Import Cobalt 19.master.0.203780

Includes the following patches:
  https://cobalt-review.googlesource.com/c/cobalt/+/5210
    by errong.leng@samsung.com
  https://cobalt-review.googlesource.com/c/cobalt/+/5270
    by linus.wang@samsung.com
diff --git a/src/third_party/llvm-project/clang-tools-extra/.arcconfig b/src/third_party/llvm-project/clang-tools-extra/.arcconfig
new file mode 100644
index 0000000..d4a0016
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/.arcconfig
@@ -0,0 +1,4 @@
+{
+  "repository.callsign" : "CTE",
+  "conduit_uri" : "https://reviews.llvm.org/"
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/CMakeLists.txt
new file mode 100644
index 0000000..c434682
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/CMakeLists.txt
@@ -0,0 +1,29 @@
+add_subdirectory(clang-apply-replacements)
+add_subdirectory(clang-reorder-fields)
+add_subdirectory(modularize)
+if(CLANG_ENABLE_STATIC_ANALYZER)
+add_subdirectory(clang-tidy)
+add_subdirectory(clang-tidy-vs)
+endif()
+
+add_subdirectory(change-namespace)
+add_subdirectory(clang-doc)
+add_subdirectory(clang-query)
+add_subdirectory(clang-move)
+add_subdirectory(clangd)
+add_subdirectory(include-fixer)
+add_subdirectory(pp-trace)
+add_subdirectory(tool-template)
+
+# Add the common testsuite after all the tools.
+if(CLANG_INCLUDE_TESTS)
+add_subdirectory(test)
+add_subdirectory(unittests)
+endif()
+
+option(CLANG_TOOLS_EXTRA_INCLUDE_DOCS "Generate build targets for the Clang Extra Tools docs."
+  ${LLVM_INCLUDE_DOCS})
+if( CLANG_TOOLS_EXTRA_INCLUDE_DOCS )
+  add_subdirectory(docs)
+endif()
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/CODE_OWNERS.TXT b/src/third_party/llvm-project/clang-tools-extra/CODE_OWNERS.TXT
new file mode 100644
index 0000000..af8beb4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/CODE_OWNERS.TXT
@@ -0,0 +1,21 @@
+This file is a list of the people responsible for ensuring that patches for a
+particular tool are reviewed, either by themself or by someone else. They are
+also the gatekeepers for their part of Clang, with the final word on what goes
+in or not.
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts.  The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Peter Collingbourne
+E: peter@pcc.me.uk
+D: clang-query
+
+N: Manuel Klimek
+E: klimek@google.com
+D: clang-rename, all parts of clang-tools-extra not covered by someone else
+
+N: Alexander Kornienko
+E: alexfh@google.com
+D: clang-tidy
diff --git a/src/third_party/llvm-project/clang-tools-extra/LICENSE.TXT b/src/third_party/llvm-project/clang-tools-extra/LICENSE.TXT
new file mode 100644
index 0000000..b886535
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/LICENSE.TXT
@@ -0,0 +1,63 @@
+==============================================================================
+LLVM Release License
+==============================================================================
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2007-2018 University of Illinois at Urbana-Champaign.
+All rights reserved.
+
+Developed by:
+
+    LLVM Team
+
+    University of Illinois at Urbana-Champaign
+
+    http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, University of Illinois at
+      Urbana-Champaign, nor the names of its contributors may be used to
+      endorse or promote products derived from this Software without specific
+      prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+The LLVM software contains code written by third parties.  Such software will
+have its own individual LICENSE.TXT file in the directory in which it appears.
+This file will describe the copyrights, license, and restrictions which apply
+to that code.
+
+The disclaimer of warranty in the University of Illinois Open Source License
+applies to all code in the LLVM Distribution, and nothing in any of the
+other licenses gives permission to use the names of the LLVM Team or the
+University of Illinois to endorse or promote products derived from this
+Software.
+
+The following pieces of software have additional or alternate copyrights,
+licenses, and/or restrictions:
+
+Program             Directory
+-------             ---------
+clang-tidy          clang-tidy/cert
+clang-tidy          clang-tidy/hicpp
diff --git a/src/third_party/llvm-project/clang-tools-extra/README.txt b/src/third_party/llvm-project/clang-tools-extra/README.txt
new file mode 100644
index 0000000..9809cc3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/README.txt
@@ -0,0 +1,22 @@
+//===----------------------------------------------------------------------===//
+// Clang Tools repository
+//===----------------------------------------------------------------------===//
+
+Welcome to the repository of extra Clang Tools.  This repository holds tools
+that are developed as part of the LLVM compiler infrastructure project and the
+Clang frontend.  These tools are kept in a separate "extra" repository to
+allow lighter weight checkouts of the core Clang codebase.
+
+This repository is only intended to be checked out inside of a full LLVM+Clang
+tree, and in the 'tools/extra' subdirectory of the Clang checkout.
+
+All discussion regarding Clang, Clang-based tools, and code in this repository
+should be held using the standard Clang mailing lists:
+  http://lists.llvm.org/mailman/listinfo/cfe-dev
+
+Code review for this tree should take place on the standard Clang patch and
+commit lists:
+  http://lists.llvm.org/mailman/listinfo/cfe-commits
+
+If you find a bug in these tools, please file it in the LLVM bug tracker:
+  http://llvm.org/bugs/
diff --git a/src/third_party/llvm-project/clang-tools-extra/change-namespace/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/change-namespace/CMakeLists.txt
new file mode 100644
index 0000000..1c8aba9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/change-namespace/CMakeLists.txt
@@ -0,0 +1,19 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  )
+
+add_clang_library(clangChangeNamespace
+  ChangeNamespace.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFormat
+  clangFrontend
+  clangLex
+  clangTooling
+  clangToolingCore
+  )
+
+add_subdirectory(tool)
diff --git a/src/third_party/llvm-project/clang-tools-extra/change-namespace/ChangeNamespace.cpp b/src/third_party/llvm-project/clang-tools-extra/change-namespace/ChangeNamespace.cpp
new file mode 100644
index 0000000..35c321a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/change-namespace/ChangeNamespace.cpp
@@ -0,0 +1,1015 @@
+//===-- ChangeNamespace.cpp - Change namespace implementation -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "ChangeNamespace.h"
+#include "clang/Format/Format.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace change_namespace {
+
+namespace {
+
+inline std::string
+joinNamespaces(const llvm::SmallVectorImpl<StringRef> &Namespaces) {
+  if (Namespaces.empty())
+    return "";
+  std::string Result = Namespaces.front();
+  for (auto I = Namespaces.begin() + 1, E = Namespaces.end(); I != E; ++I)
+    Result += ("::" + *I).str();
+  return Result;
+}
+
+// Given "a::b::c", returns {"a", "b", "c"}.
+llvm::SmallVector<llvm::StringRef, 4> splitSymbolName(llvm::StringRef Name) {
+  llvm::SmallVector<llvm::StringRef, 4> Splitted;
+  Name.split(Splitted, "::", /*MaxSplit=*/-1,
+             /*KeepEmpty=*/false);
+  return Splitted;
+}
+
+SourceLocation startLocationForType(TypeLoc TLoc) {
+  // For elaborated types (e.g. `struct a::A`) we want the portion after the
+  // `struct` but including the namespace qualifier, `a::`.
+  if (TLoc.getTypeLocClass() == TypeLoc::Elaborated) {
+    NestedNameSpecifierLoc NestedNameSpecifier =
+        TLoc.castAs<ElaboratedTypeLoc>().getQualifierLoc();
+    if (NestedNameSpecifier.getNestedNameSpecifier())
+      return NestedNameSpecifier.getBeginLoc();
+    TLoc = TLoc.getNextTypeLoc();
+  }
+  return TLoc.getLocStart();
+}
+
+SourceLocation endLocationForType(TypeLoc TLoc) {
+  // Dig past any namespace or keyword qualifications.
+  while (TLoc.getTypeLocClass() == TypeLoc::Elaborated ||
+         TLoc.getTypeLocClass() == TypeLoc::Qualified)
+    TLoc = TLoc.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 (TLoc.getTypeLocClass() == TypeLoc::TemplateSpecialization)
+    return TLoc.castAs<TemplateSpecializationTypeLoc>()
+        .getLAngleLoc()
+        .getLocWithOffset(-1);
+  return TLoc.getEndLoc();
+}
+
+// Returns the containing namespace of `InnerNs` by skipping `PartialNsName`.
+// If the `InnerNs` does not have `PartialNsName` as suffix, or `PartialNsName`
+// is empty, nullptr is returned.
+// For example, if `InnerNs` is "a::b::c" and `PartialNsName` is "b::c", then
+// the NamespaceDecl of namespace "a" will be returned.
+const NamespaceDecl *getOuterNamespace(const NamespaceDecl *InnerNs,
+                                       llvm::StringRef PartialNsName) {
+  if (!InnerNs || PartialNsName.empty())
+    return nullptr;
+  const auto *CurrentContext = llvm::cast<DeclContext>(InnerNs);
+  const auto *CurrentNs = InnerNs;
+  auto PartialNsNameSplitted = splitSymbolName(PartialNsName);
+  while (!PartialNsNameSplitted.empty()) {
+    // Get the inner-most namespace in CurrentContext.
+    while (CurrentContext && !llvm::isa<NamespaceDecl>(CurrentContext))
+      CurrentContext = CurrentContext->getParent();
+    if (!CurrentContext)
+      return nullptr;
+    CurrentNs = llvm::cast<NamespaceDecl>(CurrentContext);
+    if (PartialNsNameSplitted.back() != CurrentNs->getNameAsString())
+      return nullptr;
+    PartialNsNameSplitted.pop_back();
+    CurrentContext = CurrentContext->getParent();
+  }
+  return CurrentNs;
+}
+
+static std::unique_ptr<Lexer>
+getLexerStartingFromLoc(SourceLocation Loc, const SourceManager &SM,
+                        const LangOptions &LangOpts) {
+  if (Loc.isMacroID() &&
+      !Lexer::isAtEndOfMacroExpansion(Loc, SM, LangOpts, &Loc))
+    return nullptr;
+  // Break down the source location.
+  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+  // Try to load the file buffer.
+  bool InvalidTemp = false;
+  llvm::StringRef File = SM.getBufferData(LocInfo.first, &InvalidTemp);
+  if (InvalidTemp)
+    return nullptr;
+
+  const char *TokBegin = File.data() + LocInfo.second;
+  // Lex from the start of the given location.
+  return llvm::make_unique<Lexer>(SM.getLocForStartOfFile(LocInfo.first),
+                                  LangOpts, File.begin(), TokBegin, File.end());
+}
+
+// FIXME: get rid of this helper function if this is supported in clang-refactor
+// library.
+static SourceLocation getStartOfNextLine(SourceLocation Loc,
+                                         const SourceManager &SM,
+                                         const LangOptions &LangOpts) {
+  std::unique_ptr<Lexer> Lex = getLexerStartingFromLoc(Loc, SM, LangOpts);
+  if (!Lex.get())
+    return SourceLocation();
+  llvm::SmallVector<char, 16> Line;
+  // FIXME: this is a bit hacky to get ReadToEndOfLine work.
+  Lex->setParsingPreprocessorDirective(true);
+  Lex->ReadToEndOfLine(&Line);
+  auto End = Loc.getLocWithOffset(Line.size());
+  return SM.getLocForEndOfFile(SM.getDecomposedLoc(Loc).first) == End
+             ? End
+             : End.getLocWithOffset(1);
+}
+
+// Returns `R` with new range that refers to code after `Replaces` being
+// applied.
+tooling::Replacement
+getReplacementInChangedCode(const tooling::Replacements &Replaces,
+                            const tooling::Replacement &R) {
+  unsigned NewStart = Replaces.getShiftedCodePosition(R.getOffset());
+  unsigned NewEnd =
+      Replaces.getShiftedCodePosition(R.getOffset() + R.getLength());
+  return tooling::Replacement(R.getFilePath(), NewStart, NewEnd - NewStart,
+                              R.getReplacementText());
+}
+
+// Adds a replacement `R` into `Replaces` or merges it into `Replaces` by
+// applying all existing Replaces first if there is conflict.
+void addOrMergeReplacement(const tooling::Replacement &R,
+                           tooling::Replacements *Replaces) {
+  auto Err = Replaces->add(R);
+  if (Err) {
+    llvm::consumeError(std::move(Err));
+    auto Replace = getReplacementInChangedCode(*Replaces, R);
+    *Replaces = Replaces->merge(tooling::Replacements(Replace));
+  }
+}
+
+tooling::Replacement createReplacement(SourceLocation Start, SourceLocation End,
+                                       llvm::StringRef ReplacementText,
+                                       const SourceManager &SM) {
+  if (!Start.isValid() || !End.isValid()) {
+    llvm::errs() << "start or end location were invalid\n";
+    return tooling::Replacement();
+  }
+  if (SM.getDecomposedLoc(Start).first != SM.getDecomposedLoc(End).first) {
+    llvm::errs()
+        << "start or end location were in different macro expansions\n";
+    return tooling::Replacement();
+  }
+  Start = SM.getSpellingLoc(Start);
+  End = SM.getSpellingLoc(End);
+  if (SM.getFileID(Start) != SM.getFileID(End)) {
+    llvm::errs() << "start or end location were in different files\n";
+    return tooling::Replacement();
+  }
+  return tooling::Replacement(
+      SM, CharSourceRange::getTokenRange(SM.getSpellingLoc(Start),
+                                         SM.getSpellingLoc(End)),
+      ReplacementText);
+}
+
+void addReplacementOrDie(
+    SourceLocation Start, SourceLocation End, llvm::StringRef ReplacementText,
+    const SourceManager &SM,
+    std::map<std::string, tooling::Replacements> *FileToReplacements) {
+  const auto R = createReplacement(Start, End, ReplacementText, SM);
+  auto Err = (*FileToReplacements)[R.getFilePath()].add(R);
+  if (Err)
+    llvm_unreachable(llvm::toString(std::move(Err)).c_str());
+}
+
+tooling::Replacement createInsertion(SourceLocation Loc,
+                                     llvm::StringRef InsertText,
+                                     const SourceManager &SM) {
+  if (Loc.isInvalid()) {
+    llvm::errs() << "insert Location is invalid.\n";
+    return tooling::Replacement();
+  }
+  Loc = SM.getSpellingLoc(Loc);
+  return tooling::Replacement(SM, Loc, 0, InsertText);
+}
+
+// Returns the shortest qualified name for declaration `DeclName` in the
+// namespace `NsName`. For example, if `DeclName` is "a::b::X" and `NsName`
+// is "a::c::d", then "b::X" will be returned.
+// Note that if `DeclName` is `::b::X` and `NsName` is `::a::b`, this returns
+// "::b::X" instead of "b::X" since there will be a name conflict otherwise.
+// \param DeclName A fully qualified name, "::a::b::X" or "a::b::X".
+// \param NsName A fully qualified name, "::a::b" or "a::b". Global namespace
+//        will have empty name.
+std::string getShortestQualifiedNameInNamespace(llvm::StringRef DeclName,
+                                                llvm::StringRef NsName) {
+  DeclName = DeclName.ltrim(':');
+  NsName = NsName.ltrim(':');
+  if (DeclName.find(':') == llvm::StringRef::npos)
+    return DeclName;
+
+  auto NsNameSplitted = splitSymbolName(NsName);
+  auto DeclNsSplitted = splitSymbolName(DeclName);
+  llvm::StringRef UnqualifiedDeclName = DeclNsSplitted.pop_back_val();
+  // If the Decl is in global namespace, there is no need to shorten it.
+  if (DeclNsSplitted.empty())
+    return UnqualifiedDeclName;
+  // If NsName is the global namespace, we can simply use the DeclName sans
+  // leading "::".
+  if (NsNameSplitted.empty())
+    return DeclName;
+
+  if (NsNameSplitted.front() != DeclNsSplitted.front()) {
+    // The DeclName must be fully-qualified, but we still need to decide if a
+    // leading "::" is necessary. For example, if `NsName` is "a::b::c" and the
+    // `DeclName` is "b::X", then the reference must be qualified as "::b::X"
+    // to avoid conflict.
+    if (llvm::is_contained(NsNameSplitted, DeclNsSplitted.front()))
+      return ("::" + DeclName).str();
+    return DeclName;
+  }
+  // Since there is already an overlap namespace, we know that `DeclName` can be
+  // shortened, so we reduce the longest common prefix.
+  auto DeclI = DeclNsSplitted.begin();
+  auto DeclE = DeclNsSplitted.end();
+  auto NsI = NsNameSplitted.begin();
+  auto NsE = NsNameSplitted.end();
+  for (; DeclI != DeclE && NsI != NsE && *DeclI == *NsI; ++DeclI, ++NsI) {
+  }
+  return (DeclI == DeclE)
+             ? UnqualifiedDeclName.str()
+             : (llvm::join(DeclI, DeclE, "::") + "::" + UnqualifiedDeclName)
+                   .str();
+}
+
+std::string wrapCodeInNamespace(StringRef NestedNs, std::string Code) {
+  if (Code.back() != '\n')
+    Code += "\n";
+  auto NsSplitted = splitSymbolName(NestedNs);
+  while (!NsSplitted.empty()) {
+    // FIXME: consider code style for comments.
+    Code = ("namespace " + NsSplitted.back() + " {\n" + Code +
+            "} // namespace " + NsSplitted.back() + "\n")
+               .str();
+    NsSplitted.pop_back();
+  }
+  return Code;
+}
+
+// Returns true if \p D is a nested DeclContext in \p Context
+bool isNestedDeclContext(const DeclContext *D, const DeclContext *Context) {
+  while (D) {
+    if (D == Context)
+      return true;
+    D = D->getParent();
+  }
+  return false;
+}
+
+// Returns true if \p D is visible at \p Loc with DeclContext \p DeclCtx.
+bool isDeclVisibleAtLocation(const SourceManager &SM, const Decl *D,
+                             const DeclContext *DeclCtx, SourceLocation Loc) {
+  SourceLocation DeclLoc = SM.getSpellingLoc(D->getLocStart());
+  Loc = SM.getSpellingLoc(Loc);
+  return SM.isBeforeInTranslationUnit(DeclLoc, Loc) &&
+         (SM.getFileID(DeclLoc) == SM.getFileID(Loc) &&
+          isNestedDeclContext(DeclCtx, D->getDeclContext()));
+}
+
+// Given a qualified symbol name, returns true if the symbol will be
+// incorrectly qualified without leading "::".
+bool conflictInNamespace(llvm::StringRef QualifiedSymbol,
+                         llvm::StringRef Namespace) {
+  auto SymbolSplitted = splitSymbolName(QualifiedSymbol.trim(":"));
+  assert(!SymbolSplitted.empty());
+  SymbolSplitted.pop_back();  // We are only interested in namespaces.
+
+  if (SymbolSplitted.size() > 1 && !Namespace.empty()) {
+    auto NsSplitted = splitSymbolName(Namespace.trim(":"));
+    assert(!NsSplitted.empty());
+    // We do not check the outermost namespace since it would not be a conflict
+    // if it equals to the symbol's outermost namespace and the symbol name
+    // would have been shortened.
+    for (auto I = NsSplitted.begin() + 1, E = NsSplitted.end(); I != E; ++I) {
+      if (*I == SymbolSplitted.front())
+        return true;
+    }
+  }
+  return false;
+}
+
+AST_MATCHER(EnumDecl, isScoped) {
+    return Node.isScoped();
+}
+
+bool isTemplateParameter(TypeLoc Type) {
+  while (!Type.isNull()) {
+    if (Type.getTypeLocClass() == TypeLoc::SubstTemplateTypeParm)
+      return true;
+    Type = Type.getNextTypeLoc();
+  }
+  return false;
+}
+
+} // anonymous namespace
+
+ChangeNamespaceTool::ChangeNamespaceTool(
+    llvm::StringRef OldNs, llvm::StringRef NewNs, llvm::StringRef FilePattern,
+    llvm::ArrayRef<std::string> WhiteListedSymbolPatterns,
+    std::map<std::string, tooling::Replacements> *FileToReplacements,
+    llvm::StringRef FallbackStyle)
+    : FallbackStyle(FallbackStyle), FileToReplacements(*FileToReplacements),
+      OldNamespace(OldNs.ltrim(':')), NewNamespace(NewNs.ltrim(':')),
+      FilePattern(FilePattern), FilePatternRE(FilePattern) {
+  FileToReplacements->clear();
+  auto OldNsSplitted = splitSymbolName(OldNamespace);
+  auto NewNsSplitted = splitSymbolName(NewNamespace);
+  // Calculates `DiffOldNamespace` and `DiffNewNamespace`.
+  while (!OldNsSplitted.empty() && !NewNsSplitted.empty() &&
+         OldNsSplitted.front() == NewNsSplitted.front()) {
+    OldNsSplitted.erase(OldNsSplitted.begin());
+    NewNsSplitted.erase(NewNsSplitted.begin());
+  }
+  DiffOldNamespace = joinNamespaces(OldNsSplitted);
+  DiffNewNamespace = joinNamespaces(NewNsSplitted);
+
+  for (const auto &Pattern : WhiteListedSymbolPatterns)
+    WhiteListedSymbolRegexes.emplace_back(Pattern);
+}
+
+void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
+  std::string FullOldNs = "::" + OldNamespace;
+  // Prefix is the outer-most namespace in DiffOldNamespace. For example, if the
+  // OldNamespace is "a::b::c" and DiffOldNamespace is "b::c", then Prefix will
+  // be "a::b". Declarations in this namespace will not be visible in the new
+  // namespace. If DiffOldNamespace is empty, Prefix will be a invalid name "-".
+  llvm::SmallVector<llvm::StringRef, 4> DiffOldNsSplitted;
+  llvm::StringRef(DiffOldNamespace)
+      .split(DiffOldNsSplitted, "::", /*MaxSplit=*/-1,
+             /*KeepEmpty=*/false);
+  std::string Prefix = "-";
+  if (!DiffOldNsSplitted.empty())
+    Prefix = (StringRef(FullOldNs).drop_back(DiffOldNamespace.size()) +
+              DiffOldNsSplitted.front())
+                 .str();
+  auto IsInMovedNs =
+      allOf(hasAncestor(namespaceDecl(hasName(FullOldNs)).bind("ns_decl")),
+            isExpansionInFileMatching(FilePattern));
+  auto IsVisibleInNewNs = anyOf(
+      IsInMovedNs, unless(hasAncestor(namespaceDecl(hasName(Prefix)))));
+  // Match using declarations.
+  Finder->addMatcher(
+      usingDecl(isExpansionInFileMatching(FilePattern), IsVisibleInNewNs)
+          .bind("using"),
+      this);
+  // Match using namespace declarations.
+  Finder->addMatcher(usingDirectiveDecl(isExpansionInFileMatching(FilePattern),
+                                        IsVisibleInNewNs)
+                         .bind("using_namespace"),
+                     this);
+  // Match namespace alias declarations.
+  Finder->addMatcher(namespaceAliasDecl(isExpansionInFileMatching(FilePattern),
+                                        IsVisibleInNewNs)
+                         .bind("namespace_alias"),
+                     this);
+
+  // Match old namespace blocks.
+  Finder->addMatcher(
+      namespaceDecl(hasName(FullOldNs), isExpansionInFileMatching(FilePattern))
+          .bind("old_ns"),
+      this);
+
+  // Match class forward-declarations in the old namespace.
+  // Note that forward-declarations in classes are not matched.
+  Finder->addMatcher(cxxRecordDecl(unless(anyOf(isImplicit(), isDefinition())),
+                                   IsInMovedNs, hasParent(namespaceDecl()))
+                         .bind("class_fwd_decl"),
+                     this);
+
+  // Match template class forward-declarations in the old namespace.
+  Finder->addMatcher(
+      classTemplateDecl(unless(hasDescendant(cxxRecordDecl(isDefinition()))),
+                        IsInMovedNs, hasParent(namespaceDecl()))
+          .bind("template_class_fwd_decl"),
+      this);
+
+  // Match references to types that are not defined in the old namespace.
+  // Forward-declarations in the old namespace are also matched since they will
+  // be moved back to the old namespace.
+  auto DeclMatcher = namedDecl(
+      hasAncestor(namespaceDecl()),
+      unless(anyOf(
+          isImplicit(), hasAncestor(namespaceDecl(isAnonymous())),
+          hasAncestor(cxxRecordDecl()),
+          allOf(IsInMovedNs, unless(cxxRecordDecl(unless(isDefinition())))))));
+
+  // Using shadow declarations in classes always refers to base class, which
+  // does not need to be qualified since it can be inferred from inheritance.
+  // Note that this does not match using alias declarations.
+  auto UsingShadowDeclInClass =
+      usingDecl(hasAnyUsingShadowDecl(decl()), hasParent(cxxRecordDecl()));
+
+  // Match TypeLocs on the declaration. Carefully match only the outermost
+  // TypeLoc and template specialization arguments (which are not outermost)
+  // that are directly linked to types matching `DeclMatcher`. Nested name
+  // specifier locs are handled separately below.
+  Finder->addMatcher(
+      typeLoc(IsInMovedNs,
+              loc(qualType(hasDeclaration(DeclMatcher.bind("from_decl")))),
+              unless(anyOf(hasParent(typeLoc(loc(qualType(
+                               allOf(hasDeclaration(DeclMatcher),
+                                     unless(templateSpecializationType())))))),
+                           hasParent(nestedNameSpecifierLoc()),
+                           hasAncestor(isImplicit()),
+                           hasAncestor(UsingShadowDeclInClass),
+                           hasAncestor(functionDecl(isDefaulted())))),
+              hasAncestor(decl().bind("dc")))
+          .bind("type"),
+      this);
+
+  // Types in `UsingShadowDecl` is not matched by `typeLoc` above, so we need to
+  // special case it.
+  // Since using declarations inside classes must have the base class in the
+  // nested name specifier, we leave it to the nested name specifier matcher.
+  Finder->addMatcher(usingDecl(IsInMovedNs, hasAnyUsingShadowDecl(decl()),
+                               unless(UsingShadowDeclInClass))
+                         .bind("using_with_shadow"),
+                     this);
+
+  // Handle types in nested name specifier. Specifiers that are in a TypeLoc
+  // matched above are not matched, e.g. "A::" in "A::A" is not matched since
+  // "A::A" would have already been fixed.
+  Finder->addMatcher(
+      nestedNameSpecifierLoc(
+          hasAncestor(decl(IsInMovedNs).bind("dc")),
+          loc(nestedNameSpecifier(
+              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"),
+      this);
+
+  // Matches base class initializers in constructors. TypeLocs of base class
+  // initializers do not need to be fixed. For example,
+  //    class X : public a::b::Y {
+  //      public:
+  //        X() : Y::Y() {} // Y::Y do not need namespace specifier.
+  //    };
+  Finder->addMatcher(
+      cxxCtorInitializer(isBaseInitializer()).bind("base_initializer"), this);
+
+  // Handle function.
+  // Only handle functions that are defined in a namespace excluding member
+  // function, static methods (qualified by nested specifier), and functions
+  // defined in the global namespace.
+  // Note that the matcher does not exclude calls to out-of-line static method
+  // definitions, so we need to exclude them in the callback handler.
+  auto FuncMatcher =
+      functionDecl(unless(anyOf(cxxMethodDecl(), IsInMovedNs,
+                                hasAncestor(namespaceDecl(isAnonymous())),
+                                hasAncestor(cxxRecordDecl()))),
+                   hasParent(namespaceDecl()));
+  Finder->addMatcher(
+      expr(allOf(hasAncestor(decl().bind("dc")), IsInMovedNs,
+                 unless(hasAncestor(isImplicit())),
+                 anyOf(callExpr(callee(FuncMatcher)).bind("call"),
+                       declRefExpr(to(FuncMatcher.bind("func_decl")))
+                           .bind("func_ref")))),
+      this);
+
+  auto GlobalVarMatcher = varDecl(
+      hasGlobalStorage(), hasParent(namespaceDecl()),
+      unless(anyOf(IsInMovedNs, hasAncestor(namespaceDecl(isAnonymous())))));
+  Finder->addMatcher(declRefExpr(IsInMovedNs, hasAncestor(decl().bind("dc")),
+                                 to(GlobalVarMatcher.bind("var_decl")))
+                         .bind("var_ref"),
+                     this);
+
+  // Handle unscoped enum constant.
+  auto UnscopedEnumMatcher = enumConstantDecl(hasParent(enumDecl(
+      hasParent(namespaceDecl()),
+      unless(anyOf(isScoped(), IsInMovedNs, hasAncestor(cxxRecordDecl()),
+                   hasAncestor(namespaceDecl(isAnonymous())))))));
+  Finder->addMatcher(
+      declRefExpr(IsInMovedNs, hasAncestor(decl().bind("dc")),
+                  to(UnscopedEnumMatcher.bind("enum_const_decl")))
+          .bind("enum_const_ref"),
+      this);
+}
+
+void ChangeNamespaceTool::run(
+    const ast_matchers::MatchFinder::MatchResult &Result) {
+  if (const auto *Using = Result.Nodes.getNodeAs<UsingDecl>("using")) {
+    UsingDecls.insert(Using);
+  } else if (const auto *UsingNamespace =
+                 Result.Nodes.getNodeAs<UsingDirectiveDecl>(
+                     "using_namespace")) {
+    UsingNamespaceDecls.insert(UsingNamespace);
+  } else if (const auto *NamespaceAlias =
+                 Result.Nodes.getNodeAs<NamespaceAliasDecl>(
+                     "namespace_alias")) {
+    NamespaceAliasDecls.insert(NamespaceAlias);
+  } else if (const auto *NsDecl =
+                 Result.Nodes.getNodeAs<NamespaceDecl>("old_ns")) {
+    moveOldNamespace(Result, NsDecl);
+  } else if (const auto *FwdDecl =
+                 Result.Nodes.getNodeAs<CXXRecordDecl>("class_fwd_decl")) {
+    moveClassForwardDeclaration(Result, cast<NamedDecl>(FwdDecl));
+  } else if (const auto *TemplateFwdDecl =
+                 Result.Nodes.getNodeAs<ClassTemplateDecl>(
+                     "template_class_fwd_decl")) {
+    moveClassForwardDeclaration(Result, cast<NamedDecl>(TemplateFwdDecl));
+  } else if (const auto *UsingWithShadow =
+                 Result.Nodes.getNodeAs<UsingDecl>("using_with_shadow")) {
+    fixUsingShadowDecl(Result, UsingWithShadow);
+  } else if (const auto *Specifier =
+                 Result.Nodes.getNodeAs<NestedNameSpecifierLoc>(
+                     "nested_specifier_loc")) {
+    SourceLocation Start = Specifier->getBeginLoc();
+    SourceLocation End = endLocationForType(Specifier->getTypeLoc());
+    fixTypeLoc(Result, Start, End, Specifier->getTypeLoc());
+  } else if (const auto *BaseInitializer =
+                 Result.Nodes.getNodeAs<CXXCtorInitializer>(
+                     "base_initializer")) {
+    BaseCtorInitializerTypeLocs.push_back(
+        BaseInitializer->getTypeSourceInfo()->getTypeLoc());
+  } else if (const auto *TLoc = Result.Nodes.getNodeAs<TypeLoc>("type")) {
+    // This avoids fixing types with record types as qualifier, which is not
+    // filtered by matchers in some cases, e.g. the type is templated. We should
+    // handle the record type qualifier instead.
+    TypeLoc Loc = *TLoc;
+    while (Loc.getTypeLocClass() == TypeLoc::Qualified)
+      Loc = Loc.getNextTypeLoc();
+    if (Loc.getTypeLocClass() == TypeLoc::Elaborated) {
+      NestedNameSpecifierLoc NestedNameSpecifier =
+          Loc.castAs<ElaboratedTypeLoc>().getQualifierLoc();
+      // This happens for friend declaration of a base class with injected class
+      // name.
+      if (!NestedNameSpecifier.getNestedNameSpecifier())
+        return;
+      const Type *SpecifierType =
+          NestedNameSpecifier.getNestedNameSpecifier()->getAsType();
+      if (SpecifierType && SpecifierType->isRecordType())
+        return;
+    }
+    fixTypeLoc(Result, startLocationForType(Loc), endLocationForType(Loc), Loc);
+  } else if (const auto *VarRef =
+                 Result.Nodes.getNodeAs<DeclRefExpr>("var_ref")) {
+    const auto *Var = Result.Nodes.getNodeAs<VarDecl>("var_decl");
+    assert(Var);
+    if (Var->getCanonicalDecl()->isStaticDataMember())
+      return;
+    const auto *Context = Result.Nodes.getNodeAs<Decl>("dc");
+    assert(Context && "Empty decl context.");
+    fixDeclRefExpr(Result, Context->getDeclContext(),
+                   llvm::cast<NamedDecl>(Var), VarRef);
+  } else if (const auto *EnumConstRef =
+                 Result.Nodes.getNodeAs<DeclRefExpr>("enum_const_ref")) {
+    // Do not rename the reference if it is already scoped by the EnumDecl name.
+    if (EnumConstRef->hasQualifier() &&
+        EnumConstRef->getQualifier()->getKind() ==
+            NestedNameSpecifier::SpecifierKind::TypeSpec &&
+        EnumConstRef->getQualifier()->getAsType()->isEnumeralType())
+      return;
+    const auto *EnumConstDecl =
+        Result.Nodes.getNodeAs<EnumConstantDecl>("enum_const_decl");
+    assert(EnumConstDecl);
+    const auto *Context = Result.Nodes.getNodeAs<Decl>("dc");
+    assert(Context && "Empty decl context.");
+    // FIXME: this would qualify "ns::VALUE" as "ns::EnumValue::VALUE". Fix it
+    // if it turns out to be an issue.
+    fixDeclRefExpr(Result, Context->getDeclContext(),
+                   llvm::cast<NamedDecl>(EnumConstDecl), EnumConstRef);
+  } else if (const auto *FuncRef =
+                 Result.Nodes.getNodeAs<DeclRefExpr>("func_ref")) {
+    // If this reference has been processed as a function call, we do not
+    // process it again.
+    if (ProcessedFuncRefs.count(FuncRef))
+      return;
+    ProcessedFuncRefs.insert(FuncRef);
+    const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func_decl");
+    assert(Func);
+    const auto *Context = Result.Nodes.getNodeAs<Decl>("dc");
+    assert(Context && "Empty decl context.");
+    fixDeclRefExpr(Result, Context->getDeclContext(),
+                   llvm::cast<NamedDecl>(Func), FuncRef);
+  } else {
+    const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
+    assert(Call != nullptr && "Expecting callback for CallExpr.");
+    const auto *CalleeFuncRef =
+        llvm::cast<DeclRefExpr>(Call->getCallee()->IgnoreImplicit());
+    ProcessedFuncRefs.insert(CalleeFuncRef);
+    const FunctionDecl *Func = Call->getDirectCallee();
+    assert(Func != nullptr);
+    // FIXME: ignore overloaded operators. This would miss cases where operators
+    // are called by qualified names (i.e. "ns::operator <"). Ignore such
+    // cases for now.
+    if (Func->isOverloadedOperator())
+      return;
+    // Ignore out-of-line static methods since they will be handled by nested
+    // name specifiers.
+    if (Func->getCanonicalDecl()->getStorageClass() ==
+            StorageClass::SC_Static &&
+        Func->isOutOfLine())
+      return;
+    const auto *Context = Result.Nodes.getNodeAs<Decl>("dc");
+    assert(Context && "Empty decl context.");
+    SourceRange CalleeRange = Call->getCallee()->getSourceRange();
+    replaceQualifiedSymbolInDeclContext(
+        Result, Context->getDeclContext(), CalleeRange.getBegin(),
+        CalleeRange.getEnd(), llvm::cast<NamedDecl>(Func));
+  }
+}
+
+static SourceLocation getLocAfterNamespaceLBrace(const NamespaceDecl *NsDecl,
+                                                 const SourceManager &SM,
+                                                 const LangOptions &LangOpts) {
+  std::unique_ptr<Lexer> Lex =
+      getLexerStartingFromLoc(NsDecl->getLocStart(), SM, LangOpts);
+  assert(Lex.get() &&
+         "Failed to create lexer from the beginning of namespace.");
+  if (!Lex.get())
+    return SourceLocation();
+  Token Tok;
+  while (!Lex->LexFromRawLexer(Tok) && Tok.isNot(tok::TokenKind::l_brace)) {
+  }
+  return Tok.isNot(tok::TokenKind::l_brace)
+             ? SourceLocation()
+             : Tok.getEndLoc().getLocWithOffset(1);
+}
+
+// Stores information about a moved namespace in `MoveNamespaces` and leaves
+// the actual movement to `onEndOfTranslationUnit()`.
+void ChangeNamespaceTool::moveOldNamespace(
+    const ast_matchers::MatchFinder::MatchResult &Result,
+    const NamespaceDecl *NsDecl) {
+  // If the namespace is empty, do nothing.
+  if (Decl::castToDeclContext(NsDecl)->decls_empty())
+    return;
+
+  const SourceManager &SM = *Result.SourceManager;
+  // Get the range of the code in the old namespace.
+  SourceLocation Start =
+      getLocAfterNamespaceLBrace(NsDecl, SM, Result.Context->getLangOpts());
+  assert(Start.isValid() && "Can't find l_brace for namespace.");
+  MoveNamespace MoveNs;
+  MoveNs.Offset = SM.getFileOffset(Start);
+  // The range of the moved namespace is from the location just past the left
+  // brace to the location right before the right brace.
+  MoveNs.Length = SM.getFileOffset(NsDecl->getRBraceLoc()) - MoveNs.Offset;
+
+  // Insert the new namespace after `DiffOldNamespace`. For example, if
+  // `OldNamespace` is "a::b::c" and `NewNamespace` is `a::x::y`, then
+  // "x::y" will be inserted inside the existing namespace "a" and after "a::b".
+  // `OuterNs` is the first namespace in `DiffOldNamespace`, e.g. "namespace b"
+  // in the above example.
+  // If there is no outer namespace (i.e. DiffOldNamespace is empty), the new
+  // namespace will be a nested namespace in the old namespace.
+  const NamespaceDecl *OuterNs = getOuterNamespace(NsDecl, DiffOldNamespace);
+  SourceLocation InsertionLoc = Start;
+  if (OuterNs) {
+    SourceLocation LocAfterNs = getStartOfNextLine(
+        OuterNs->getRBraceLoc(), SM, Result.Context->getLangOpts());
+    assert(LocAfterNs.isValid() &&
+           "Failed to get location after DiffOldNamespace");
+    InsertionLoc = LocAfterNs;
+  }
+  MoveNs.InsertionOffset = SM.getFileOffset(SM.getSpellingLoc(InsertionLoc));
+  MoveNs.FID = SM.getFileID(Start);
+  MoveNs.SourceMgr = Result.SourceManager;
+  MoveNamespaces[SM.getFilename(Start)].push_back(MoveNs);
+}
+
+// Removes a class forward declaration from the code in the moved namespace and
+// creates an `InsertForwardDeclaration` to insert the forward declaration back
+// into the old namespace after moving code from the old namespace to the new
+// namespace.
+// For example, changing "a" to "x":
+// Old code:
+//   namespace a {
+//   class FWD;
+//   class A { FWD *fwd; }
+//   }  // a
+// New code:
+//   namespace a {
+//   class FWD;
+//   }  // a
+//   namespace x {
+//   class A { a::FWD *fwd; }
+//   }  // x
+void ChangeNamespaceTool::moveClassForwardDeclaration(
+    const ast_matchers::MatchFinder::MatchResult &Result,
+    const NamedDecl *FwdDecl) {
+  SourceLocation Start = FwdDecl->getLocStart();
+  SourceLocation End = FwdDecl->getLocEnd();
+  const SourceManager &SM = *Result.SourceManager;
+  SourceLocation AfterSemi = Lexer::findLocationAfterToken(
+      End, tok::semi, SM, Result.Context->getLangOpts(),
+      /*SkipTrailingWhitespaceAndNewLine=*/true);
+  if (AfterSemi.isValid())
+    End = AfterSemi.getLocWithOffset(-1);
+  // Delete the forward declaration from the code to be moved.
+  addReplacementOrDie(Start, End, "", SM, &FileToReplacements);
+  llvm::StringRef Code = Lexer::getSourceText(
+      CharSourceRange::getTokenRange(SM.getSpellingLoc(Start),
+                                     SM.getSpellingLoc(End)),
+      SM, Result.Context->getLangOpts());
+  // Insert the forward declaration back into the old namespace after moving the
+  // code from old namespace to new namespace.
+  // Insertion information is stored in `InsertFwdDecls` and actual
+  // insertion will be performed in `onEndOfTranslationUnit`.
+  // Get the (old) namespace that contains the forward declaration.
+  const auto *NsDecl = Result.Nodes.getNodeAs<NamespaceDecl>("ns_decl");
+  // The namespace contains the forward declaration, so it must not be empty.
+  assert(!NsDecl->decls_empty());
+  const auto Insertion = createInsertion(
+      getLocAfterNamespaceLBrace(NsDecl, SM, Result.Context->getLangOpts()),
+      Code, SM);
+  InsertForwardDeclaration InsertFwd;
+  InsertFwd.InsertionOffset = Insertion.getOffset();
+  InsertFwd.ForwardDeclText = Insertion.getReplacementText().str();
+  InsertFwdDecls[Insertion.getFilePath()].push_back(InsertFwd);
+}
+
+// Replaces a qualified symbol (in \p DeclCtx) that refers to a declaration \p
+// FromDecl with the shortest qualified name possible when the reference is in
+// `NewNamespace`.
+void ChangeNamespaceTool::replaceQualifiedSymbolInDeclContext(
+    const ast_matchers::MatchFinder::MatchResult &Result,
+    const DeclContext *DeclCtx, SourceLocation Start, SourceLocation End,
+    const NamedDecl *FromDecl) {
+  const auto *NsDeclContext = DeclCtx->getEnclosingNamespaceContext();
+  if (llvm::isa<TranslationUnitDecl>(NsDeclContext)) {
+    // This should not happen in usual unless the TypeLoc is in function type
+    // parameters, e.g `std::function<void(T)>`. In this case, DeclContext of
+    // `T` will be the translation unit. We simply use fully-qualified name
+    // here.
+    // Note that `FromDecl` must not be defined in the old namespace (according
+    // to `DeclMatcher`), so its fully-qualified name will not change after
+    // changing the namespace.
+    addReplacementOrDie(Start, End, FromDecl->getQualifiedNameAsString(),
+                        *Result.SourceManager, &FileToReplacements);
+    return;
+  }
+  const auto *NsDecl = llvm::cast<NamespaceDecl>(NsDeclContext);
+  // Calculate the name of the `NsDecl` after it is moved to new namespace.
+  std::string OldNs = NsDecl->getQualifiedNameAsString();
+  llvm::StringRef Postfix = OldNs;
+  bool Consumed = Postfix.consume_front(OldNamespace);
+  assert(Consumed && "Expect OldNS to start with OldNamespace.");
+  (void)Consumed;
+  const std::string NewNs = (NewNamespace + Postfix).str();
+
+  llvm::StringRef NestedName = Lexer::getSourceText(
+      CharSourceRange::getTokenRange(
+          Result.SourceManager->getSpellingLoc(Start),
+          Result.SourceManager->getSpellingLoc(End)),
+      *Result.SourceManager, Result.Context->getLangOpts());
+  std::string FromDeclName = FromDecl->getQualifiedNameAsString();
+  for (llvm::Regex &RE : WhiteListedSymbolRegexes)
+    if (RE.match(FromDeclName))
+      return;
+  std::string ReplaceName =
+      getShortestQualifiedNameInNamespace(FromDeclName, NewNs);
+  // Checks if there is any using namespace declarations that can shorten the
+  // qualified name.
+  for (const auto *UsingNamespace : UsingNamespaceDecls) {
+    if (!isDeclVisibleAtLocation(*Result.SourceManager, UsingNamespace, DeclCtx,
+                                 Start))
+      continue;
+    StringRef FromDeclNameRef = FromDeclName;
+    if (FromDeclNameRef.consume_front(UsingNamespace->getNominatedNamespace()
+                                          ->getQualifiedNameAsString())) {
+      FromDeclNameRef = FromDeclNameRef.drop_front(2);
+      if (FromDeclNameRef.size() < ReplaceName.size())
+        ReplaceName = FromDeclNameRef;
+    }
+  }
+  // Checks if there is any namespace alias declarations that can shorten the
+  // qualified name.
+  for (const auto *NamespaceAlias : NamespaceAliasDecls) {
+    if (!isDeclVisibleAtLocation(*Result.SourceManager, NamespaceAlias, DeclCtx,
+                                 Start))
+      continue;
+    StringRef FromDeclNameRef = FromDeclName;
+    if (FromDeclNameRef.consume_front(
+            NamespaceAlias->getNamespace()->getQualifiedNameAsString() +
+            "::")) {
+      std::string AliasName = NamespaceAlias->getNameAsString();
+      std::string AliasQualifiedName =
+          NamespaceAlias->getQualifiedNameAsString();
+      // We only consider namespace aliases define in the global namepspace or
+      // in namespaces that are directly visible from the reference, i.e.
+      // ancestor of the `OldNs`. Note that declarations in ancestor namespaces
+      // but not visible in the new namespace is filtered out by
+      // "IsVisibleInNewNs" matcher.
+      if (AliasQualifiedName != AliasName) {
+        // The alias is defined in some namespace.
+        assert(StringRef(AliasQualifiedName).endswith("::" + AliasName));
+        llvm::StringRef AliasNs =
+            StringRef(AliasQualifiedName).drop_back(AliasName.size() + 2);
+        if (!llvm::StringRef(OldNs).startswith(AliasNs))
+          continue;
+      }
+      std::string NameWithAliasNamespace =
+          (AliasName + "::" + FromDeclNameRef).str();
+      if (NameWithAliasNamespace.size() < ReplaceName.size())
+        ReplaceName = NameWithAliasNamespace;
+    }
+  }
+  // Checks if there is any using shadow declarations that can shorten the
+  // qualified name.
+  bool Matched = false;
+  for (const UsingDecl *Using : UsingDecls) {
+    if (Matched)
+      break;
+    if (isDeclVisibleAtLocation(*Result.SourceManager, Using, DeclCtx, Start)) {
+      for (const auto *UsingShadow : Using->shadows()) {
+        const auto *TargetDecl = UsingShadow->getTargetDecl();
+        if (TargetDecl->getQualifiedNameAsString() ==
+            FromDecl->getQualifiedNameAsString()) {
+          ReplaceName = FromDecl->getNameAsString();
+          Matched = true;
+          break;
+        }
+      }
+    }
+  }
+  // If the new nested name in the new namespace is the same as it was in the
+  // old namespace, we don't create replacement.
+  if (NestedName == ReplaceName ||
+      (NestedName.startswith("::") && NestedName.drop_front(2) == ReplaceName))
+    return;
+  // If the reference need to be fully-qualified, add a leading "::" unless
+  // NewNamespace is the global namespace.
+  if (ReplaceName == FromDeclName && !NewNamespace.empty() &&
+      conflictInNamespace(ReplaceName, NewNamespace))
+    ReplaceName = "::" + ReplaceName;
+  addReplacementOrDie(Start, End, ReplaceName, *Result.SourceManager,
+                      &FileToReplacements);
+}
+
+// Replace the [Start, End] of `Type` with the shortest qualified name when the
+// `Type` is in `NewNamespace`.
+void ChangeNamespaceTool::fixTypeLoc(
+    const ast_matchers::MatchFinder::MatchResult &Result, SourceLocation Start,
+    SourceLocation End, TypeLoc Type) {
+  // FIXME: do not rename template parameter.
+  if (Start.isInvalid() || End.isInvalid())
+    return;
+  // Types of CXXCtorInitializers do not need to be fixed.
+  if (llvm::is_contained(BaseCtorInitializerTypeLocs, Type))
+    return;
+  if (isTemplateParameter(Type))
+    return;
+  // The declaration which this TypeLoc refers to.
+  const auto *FromDecl = Result.Nodes.getNodeAs<NamedDecl>("from_decl");
+  // `hasDeclaration` gives underlying declaration, but if the type is
+  // a typedef type, we need to use the typedef type instead.
+  auto IsInMovedNs = [&](const NamedDecl *D) {
+    if (!llvm::StringRef(D->getQualifiedNameAsString())
+             .startswith(OldNamespace + "::"))
+      return false;
+    auto ExpansionLoc = Result.SourceManager->getExpansionLoc(D->getLocStart());
+    if (ExpansionLoc.isInvalid())
+      return false;
+    llvm::StringRef Filename = Result.SourceManager->getFilename(ExpansionLoc);
+    return FilePatternRE.match(Filename);
+  };
+  // Make `FromDecl` the immediate declaration that `Type` refers to, i.e. if
+  // `Type` is an alias type, we make `FromDecl` the type alias declaration.
+  // Also, don't fix the \p Type if it refers to a type alias decl in the moved
+  // namespace since the alias decl will be moved along with the type reference.
+  if (auto *Typedef = Type.getType()->getAs<TypedefType>()) {
+    FromDecl = Typedef->getDecl();
+    if (IsInMovedNs(FromDecl))
+      return;
+  } else if (auto *TemplateType =
+                 Type.getType()->getAs<TemplateSpecializationType>()) {
+    if (TemplateType->isTypeAlias()) {
+      FromDecl = TemplateType->getTemplateName().getAsTemplateDecl();
+      if (IsInMovedNs(FromDecl))
+        return;
+    }
+  }
+  const auto *DeclCtx = Result.Nodes.getNodeAs<Decl>("dc");
+  assert(DeclCtx && "Empty decl context.");
+  replaceQualifiedSymbolInDeclContext(Result, DeclCtx->getDeclContext(), Start,
+                                      End, FromDecl);
+}
+
+void ChangeNamespaceTool::fixUsingShadowDecl(
+    const ast_matchers::MatchFinder::MatchResult &Result,
+    const UsingDecl *UsingDeclaration) {
+  SourceLocation Start = UsingDeclaration->getLocStart();
+  SourceLocation End = UsingDeclaration->getLocEnd();
+  if (Start.isInvalid() || End.isInvalid())
+    return;
+
+  assert(UsingDeclaration->shadow_size() > 0);
+  // FIXME: it might not be always accurate to use the first using-decl.
+  const NamedDecl *TargetDecl =
+      UsingDeclaration->shadow_begin()->getTargetDecl();
+  std::string TargetDeclName = TargetDecl->getQualifiedNameAsString();
+  // FIXME: check if target_decl_name is in moved ns, which doesn't make much
+  // sense. If this happens, we need to use name with the new namespace.
+  // Use fully qualified name in UsingDecl for now.
+  addReplacementOrDie(Start, End, "using ::" + TargetDeclName,
+                      *Result.SourceManager, &FileToReplacements);
+}
+
+void ChangeNamespaceTool::fixDeclRefExpr(
+    const ast_matchers::MatchFinder::MatchResult &Result,
+    const DeclContext *UseContext, const NamedDecl *From,
+    const DeclRefExpr *Ref) {
+  SourceRange RefRange = Ref->getSourceRange();
+  replaceQualifiedSymbolInDeclContext(Result, UseContext, RefRange.getBegin(),
+                                      RefRange.getEnd(), From);
+}
+
+void ChangeNamespaceTool::onEndOfTranslationUnit() {
+  // Move namespace blocks and insert forward declaration to old namespace.
+  for (const auto &FileAndNsMoves : MoveNamespaces) {
+    auto &NsMoves = FileAndNsMoves.second;
+    if (NsMoves.empty())
+      continue;
+    const std::string &FilePath = FileAndNsMoves.first;
+    auto &Replaces = FileToReplacements[FilePath];
+    auto &SM = *NsMoves.begin()->SourceMgr;
+    llvm::StringRef Code = SM.getBufferData(NsMoves.begin()->FID);
+    auto ChangedCode = tooling::applyAllReplacements(Code, Replaces);
+    if (!ChangedCode) {
+      llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n";
+      continue;
+    }
+    // Replacements on the changed code for moving namespaces and inserting
+    // forward declarations to old namespaces.
+    tooling::Replacements NewReplacements;
+    // Cut the changed code from the old namespace and paste the code in the new
+    // namespace.
+    for (const auto &NsMove : NsMoves) {
+      // Calculate the range of the old namespace block in the changed
+      // code.
+      const unsigned NewOffset = Replaces.getShiftedCodePosition(NsMove.Offset);
+      const unsigned NewLength =
+          Replaces.getShiftedCodePosition(NsMove.Offset + NsMove.Length) -
+          NewOffset;
+      tooling::Replacement Deletion(FilePath, NewOffset, NewLength, "");
+      std::string MovedCode = ChangedCode->substr(NewOffset, NewLength);
+      std::string MovedCodeWrappedInNewNs =
+          wrapCodeInNamespace(DiffNewNamespace, MovedCode);
+      // Calculate the new offset at which the code will be inserted in the
+      // changed code.
+      unsigned NewInsertionOffset =
+          Replaces.getShiftedCodePosition(NsMove.InsertionOffset);
+      tooling::Replacement Insertion(FilePath, NewInsertionOffset, 0,
+                                     MovedCodeWrappedInNewNs);
+      addOrMergeReplacement(Deletion, &NewReplacements);
+      addOrMergeReplacement(Insertion, &NewReplacements);
+    }
+    // After moving namespaces, insert forward declarations back to old
+    // namespaces.
+    const auto &FwdDeclInsertions = InsertFwdDecls[FilePath];
+    for (const auto &FwdDeclInsertion : FwdDeclInsertions) {
+      unsigned NewInsertionOffset =
+          Replaces.getShiftedCodePosition(FwdDeclInsertion.InsertionOffset);
+      tooling::Replacement Insertion(FilePath, NewInsertionOffset, 0,
+                                     FwdDeclInsertion.ForwardDeclText);
+      addOrMergeReplacement(Insertion, &NewReplacements);
+    }
+    // Add replacements referring to the changed code to existing replacements,
+    // which refers to the original code.
+    Replaces = Replaces.merge(NewReplacements);
+    auto Style = format::getStyle("file", FilePath, FallbackStyle);
+    if (!Style) {
+      llvm::errs() << llvm::toString(Style.takeError()) << "\n";
+      continue;
+    }
+    // Clean up old namespaces if there is nothing in it after moving.
+    auto CleanReplacements =
+        format::cleanupAroundReplacements(Code, Replaces, *Style);
+    if (!CleanReplacements) {
+      llvm::errs() << llvm::toString(CleanReplacements.takeError()) << "\n";
+      continue;
+    }
+    FileToReplacements[FilePath] = *CleanReplacements;
+  }
+
+  // Make sure we don't generate replacements for files that do not match
+  // FilePattern.
+  for (auto &Entry : FileToReplacements)
+    if (!FilePatternRE.match(Entry.first))
+      Entry.second.clear();
+}
+
+} // namespace change_namespace
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/change-namespace/ChangeNamespace.h b/src/third_party/llvm-project/clang-tools-extra/change-namespace/ChangeNamespace.h
new file mode 100644
index 0000000..cfe3cbc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/change-namespace/ChangeNamespace.h
@@ -0,0 +1,176 @@
+//===-- ChangeNamespace.h -- Change namespace  ------------------*- 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_CHANGE_NAMESPACE_CHANGENAMESPACE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CHANGE_NAMESPACE_CHANGENAMESPACE_H
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Format/Format.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/Support/Regex.h"
+#include <string>
+
+namespace clang {
+namespace change_namespace {
+
+// This tool can be used to change the surrounding namespaces of class/function
+// definitions. Classes/functions in the moved namespace will have new
+// namespaces while references to symbols (e.g. types, functions) which are not
+// defined in the changed namespace will be correctly qualified by prepending
+// namespace specifiers before them.
+// This will try to add shortest namespace specifiers possible. When a symbol
+// reference needs to be fully-qualified, this adds a "::" prefix to the
+// namespace specifiers unless the new namespace is the global namespace.
+// For classes, only classes that are declared/defined in the given namespace in
+// speficifed files will be moved: forward declarations will remain in the old
+// namespace.
+// For example, changing "a" to "x":
+// Old code:
+//   namespace a {
+//   class FWD;
+//   class A { FWD *fwd; }
+//   }  // a
+// New code:
+//   namespace a {
+//   class FWD;
+//   }  // a
+//   namespace x {
+//   class A { ::a::FWD *fwd; }
+//   }  // x
+// FIXME: support moving typedef, enums across namespaces.
+class ChangeNamespaceTool : public ast_matchers::MatchFinder::MatchCallback {
+public:
+  // Moves code in the old namespace `OldNs` to the new namespace `NewNs` in
+  // files matching `FilePattern`.
+  ChangeNamespaceTool(
+      llvm::StringRef OldNs, llvm::StringRef NewNs, llvm::StringRef FilePattern,
+      llvm::ArrayRef<std::string> WhiteListedSymbolPatterns,
+      std::map<std::string, tooling::Replacements> *FileToReplacements,
+      llvm::StringRef FallbackStyle = "LLVM");
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder);
+
+  void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+  // Moves the changed code in old namespaces but leaves class forward
+  // declarations behind.
+  void onEndOfTranslationUnit() override;
+
+private:
+  void moveOldNamespace(const ast_matchers::MatchFinder::MatchResult &Result,
+                        const NamespaceDecl *NsDecl);
+
+  void moveClassForwardDeclaration(
+      const ast_matchers::MatchFinder::MatchResult &Result,
+      const NamedDecl *FwdDecl);
+
+  void replaceQualifiedSymbolInDeclContext(
+      const ast_matchers::MatchFinder::MatchResult &Result,
+      const DeclContext *DeclContext, SourceLocation Start, SourceLocation End,
+      const NamedDecl *FromDecl);
+
+  void fixTypeLoc(const ast_matchers::MatchFinder::MatchResult &Result,
+                  SourceLocation Start, SourceLocation End, TypeLoc Type);
+
+  void fixUsingShadowDecl(const ast_matchers::MatchFinder::MatchResult &Result,
+                          const UsingDecl *UsingDeclaration);
+
+  void fixDeclRefExpr(const ast_matchers::MatchFinder::MatchResult &Result,
+                      const DeclContext *UseContext, const NamedDecl *From,
+                      const DeclRefExpr *Ref);
+
+  // Information about moving an old namespace.
+  struct MoveNamespace {
+    // The start offset of the namespace block being moved in the original
+    // code.
+    unsigned Offset;
+    // The length of the namespace block in the original code.
+    unsigned Length;
+    // The offset at which the new namespace block will be inserted in the
+    // original code.
+    unsigned InsertionOffset;
+    // The file in which the namespace is declared.
+    FileID FID;
+    SourceManager *SourceMgr;
+  };
+
+  // Information about inserting a class forward declaration.
+  struct InsertForwardDeclaration {
+    // The offset at while the forward declaration will be inserted in the
+    // original code.
+    unsigned InsertionOffset;
+    // The code to be inserted.
+    std::string ForwardDeclText;
+  };
+
+  std::string FallbackStyle;
+  // In match callbacks, this contains replacements for replacing `typeLoc`s in
+  // and deleting forward declarations in the moved namespace blocks.
+  // In `onEndOfTranslationUnit` callback, the previous added replacements are
+  // applied (on the moved namespace blocks), and then changed code in old
+  // namespaces re moved to new namespaces, and previously deleted forward
+  // declarations are inserted back to old namespaces, from which they are
+  // deleted.
+  std::map<std::string, tooling::Replacements> &FileToReplacements;
+  // A fully qualified name of the old namespace without "::" prefix, e.g.
+  // "a::b::c".
+  std::string OldNamespace;
+  // A fully qualified name of the new namespace without "::" prefix, e.g.
+  // "x::y::z".
+  std::string NewNamespace;
+  // The longest suffix in the old namespace that does not overlap the new
+  // namespace.
+  // For example, if `OldNamespace` is "a::b::c" and `NewNamespace` is
+  // "a::x::y", then `DiffOldNamespace` will be "b::c".
+  std::string DiffOldNamespace;
+  // The longest suffix in the new namespace that does not overlap the old
+  // namespace.
+  // For example, if `OldNamespace` is "a::b::c" and `NewNamespace` is
+  // "a::x::y", then `DiffNewNamespace` will be "x::y".
+  std::string DiffNewNamespace;
+  // A regex pattern that matches files to be processed.
+  std::string FilePattern;
+  llvm::Regex FilePatternRE;
+  // Information about moved namespaces grouped by file.
+  // Since we are modifying code in old namespaces (e.g. add namespace
+  // spedifiers) as well as moving them, we store information about namespaces
+  // to be moved and only move them after all modifications are finished (i.e.
+  // in `onEndOfTranslationUnit`).
+  std::map<std::string, std::vector<MoveNamespace>> MoveNamespaces;
+  // Information about forward declaration insertions grouped by files.
+  // A class forward declaration is not moved, so it will be deleted from the
+  // moved code block and inserted back into the old namespace. The insertion
+  // will be done after removing the code from the old namespace and before
+  // inserting it to the new namespace.
+  std::map<std::string, std::vector<InsertForwardDeclaration>> InsertFwdDecls;
+  // Records all using declarations, which can be used to shorten namespace
+  // specifiers.
+  llvm::SmallPtrSet<const UsingDecl *, 8> UsingDecls;
+  // Records all using namespace declarations, which can be used to shorten
+  // namespace specifiers.
+  llvm::SmallPtrSet<const UsingDirectiveDecl *, 8> UsingNamespaceDecls;
+  // Records all namespace alias declarations, which can be used to shorten
+  // namespace specifiers.
+  llvm::SmallPtrSet<const NamespaceAliasDecl *, 8> NamespaceAliasDecls;
+  // TypeLocs of CXXCtorInitializer. Types of CXXCtorInitializers do not need to
+  // be fixed.
+  llvm::SmallVector<TypeLoc, 8> BaseCtorInitializerTypeLocs;
+  // Since a DeclRefExpr for a function call can be matched twice (one as
+  // CallExpr and one as DeclRefExpr), we record all DeclRefExpr's that have
+  // been processed so that we don't handle them twice.
+  llvm::SmallPtrSet<const clang::DeclRefExpr*, 16> ProcessedFuncRefs;
+  // Patterns of symbol names whose references are not expected to be updated
+  // when changing namespaces around them.
+  std::vector<llvm::Regex> WhiteListedSymbolRegexes;
+};
+
+} // namespace change_namespace
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CHANGE_NAMESPACE_CHANGENAMESPACE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/change-namespace/tool/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/change-namespace/tool/CMakeLists.txt
new file mode 100644
index 0000000..f1d8ddb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/change-namespace/tool/CMakeLists.txt
@@ -0,0 +1,24 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
+
+set(LLVM_LINK_COMPONENTS
+  Support
+  )
+
+add_clang_executable(clang-change-namespace
+  ClangChangeNamespace.cpp
+  )
+target_link_libraries(clang-change-namespace
+  PRIVATE
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangChangeNamespace
+  clangFormat
+  clangFrontend
+  clangRewrite
+  clangTooling
+  clangToolingCore
+  )
+
+install(TARGETS clang-change-namespace
+  RUNTIME DESTINATION bin)
diff --git a/src/third_party/llvm-project/clang-tools-extra/change-namespace/tool/ClangChangeNamespace.cpp b/src/third_party/llvm-project/clang-tools-extra/change-namespace/tool/ClangChangeNamespace.cpp
new file mode 100644
index 0000000..180e8c3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/change-namespace/tool/ClangChangeNamespace.cpp
@@ -0,0 +1,178 @@
+//===-- ClangIncludeFixer.cpp - Standalone change namespace ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This tool can be used to change the surrounding namespaces of class/function
+// definitions.
+//
+// Example: test.cc
+//    namespace na {
+//    class X {};
+//    namespace nb {
+//    class Y { X x; };
+//    } // namespace nb
+//    } // namespace na
+// To move the definition of class Y from namespace "na::nb" to "x::y", run:
+//    clang-change-namespace --old_namespace "na::nb" \
+//      --new_namespace "x::y" --file_pattern "test.cc" test.cc --
+// Output:
+//    namespace na {
+//    class X {};
+//    } // namespace na
+//    namespace x {
+//    namespace y {
+//    class Y { na::X x; };
+//    } // namespace y
+//    } // namespace x
+
+#include "ChangeNamespace.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/FrontendActions.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/Tooling.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/YAMLTraits.h"
+
+using namespace clang;
+using namespace llvm;
+
+namespace {
+
+cl::OptionCategory ChangeNamespaceCategory("Change namespace.");
+
+cl::opt<std::string> OldNamespace("old_namespace", cl::Required,
+                                  cl::desc("Old namespace."),
+                                  cl::cat(ChangeNamespaceCategory));
+
+cl::opt<std::string> NewNamespace("new_namespace", cl::Required,
+                                  cl::desc("New namespace."),
+                                  cl::cat(ChangeNamespaceCategory));
+
+cl::opt<std::string> FilePattern(
+    "file_pattern", cl::Required,
+    cl::desc("Only rename namespaces in files that match the given pattern."),
+    cl::cat(ChangeNamespaceCategory));
+
+cl::opt<bool> Inplace("i", cl::desc("Inplace edit <file>s, if specified."),
+                      cl::cat(ChangeNamespaceCategory));
+
+cl::opt<bool>
+    DumpYAML("dump_result",
+         cl::desc("Dump new file contents in YAML, if specified."),
+         cl::cat(ChangeNamespaceCategory));
+
+cl::opt<std::string> Style("style",
+                           cl::desc("The style name used for reformatting."),
+                           cl::init("LLVM"), cl::cat(ChangeNamespaceCategory));
+
+cl::opt<std::string> WhiteListFile(
+    "whitelist_file",
+    cl::desc("A file containing regexes of symbol names that are not expected "
+             "to be updated when changing namespaces around them."),
+    cl::init(""), cl::cat(ChangeNamespaceCategory));
+
+llvm::ErrorOr<std::vector<std::string>> GetWhiteListedSymbolPatterns() {
+  std::vector<std::string> Patterns;
+  if (WhiteListFile.empty())
+    return Patterns;
+
+  llvm::SmallVector<StringRef, 8> Lines;
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
+      llvm::MemoryBuffer::getFile(WhiteListFile);
+  if (!File)
+    return File.getError();
+  llvm::StringRef Content = File.get()->getBuffer();
+  Content.split(Lines, '\n', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+  for (auto Line : Lines)
+    Patterns.push_back(Line.trim());
+  return Patterns;
+}
+
+} // anonymous namespace
+
+int main(int argc, const char **argv) {
+  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+  tooling::CommonOptionsParser OptionsParser(argc, argv,
+                                             ChangeNamespaceCategory);
+  const auto &Files = OptionsParser.getSourcePathList();
+  tooling::RefactoringTool Tool(OptionsParser.getCompilations(), Files);
+  llvm::ErrorOr<std::vector<std::string>> WhiteListPatterns =
+      GetWhiteListedSymbolPatterns();
+  if (!WhiteListPatterns) {
+    llvm::errs() << "Failed to open whitelist file " << WhiteListFile << ". "
+                 << WhiteListPatterns.getError().message() << "\n";
+    return 1;
+  }
+  change_namespace::ChangeNamespaceTool NamespaceTool(
+      OldNamespace, NewNamespace, FilePattern, *WhiteListPatterns,
+      &Tool.getReplacements(), Style);
+  ast_matchers::MatchFinder Finder;
+  NamespaceTool.registerMatchers(&Finder);
+  std::unique_ptr<tooling::FrontendActionFactory> Factory =
+      tooling::newFrontendActionFactory(&Finder);
+
+  if (int Result = Tool.run(Factory.get()))
+    return Result;
+  LangOptions DefaultLangOptions;
+  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+  clang::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);
+
+  if (!formatAndApplyAllReplacements(Tool.getReplacements(), Rewrite, Style)) {
+    llvm::errs() << "Failed applying all replacements.\n";
+    return 1;
+  }
+  if (Inplace)
+    return Rewrite.overwriteChangedFiles();
+
+  std::set<llvm::StringRef> ChangedFiles;
+  for (const auto &it : Tool.getReplacements())
+    ChangedFiles.insert(it.first);
+
+  if (DumpYAML) {
+    auto WriteToYAML = [&](llvm::raw_ostream &OS) {
+      OS << "[\n";
+      for (auto I = ChangedFiles.begin(), E = ChangedFiles.end(); I != E; ++I) {
+        OS << "  {\n";
+        OS << "    \"FilePath\": \"" << *I << "\",\n";
+        const auto *Entry = FileMgr.getFile(*I);
+        auto ID = Sources.getOrCreateFileID(Entry, SrcMgr::C_User);
+        std::string Content;
+        llvm::raw_string_ostream ContentStream(Content);
+        Rewrite.getEditBuffer(ID).write(ContentStream);
+        OS << "    \"SourceText\": \""
+           << llvm::yaml::escape(ContentStream.str()) << "\"\n";
+        OS << "  }";
+        if (I != std::prev(E))
+          OS << ",\n";
+      }
+      OS << "\n]\n";
+    };
+    WriteToYAML(llvm::outs());
+    return 0;
+  }
+
+  for (const auto &File : ChangedFiles) {
+    const auto *Entry = FileMgr.getFile(File);
+
+    auto ID = Sources.getOrCreateFileID(Entry, SrcMgr::C_User);
+    outs() << "============== " << File << " ==============\n";
+    Rewrite.getEditBuffer(ID).write(llvm::outs());
+    outs() << "\n============================================\n";
+  }
+
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-apply-replacements/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-apply-replacements/CMakeLists.txt
new file mode 100644
index 0000000..02da085
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-apply-replacements/CMakeLists.txt
@@ -0,0 +1,20 @@
+set(LLVM_LINK_COMPONENTS
+  Support
+  )
+
+add_clang_library(clangApplyReplacements
+  lib/Tooling/ApplyReplacements.cpp
+
+  LINK_LIBS
+  clangAST
+  clangBasic
+  clangRewrite
+  clangToolingCore
+  clangToolingRefactor
+  )
+
+include_directories(
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  include
+  )
+add_subdirectory(tool)
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h b/src/third_party/llvm-project/clang-tools-extra/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h
new file mode 100644
index 0000000..da9ae0c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h
@@ -0,0 +1,123 @@
+//===-- ApplyReplacements.h - Deduplicate and apply replacements -- C++ -*-===//
+//
+//                     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 provides the interface for deduplicating, detecting
+/// conflicts in, and applying collections of Replacements.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_APPLYREPLACEMENTS_H
+#define LLVM_CLANG_APPLYREPLACEMENTS_H
+
+#include "clang/Tooling/Core/Diagnostic.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Refactoring/AtomicChange.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+#include <system_error>
+#include <vector>
+
+namespace clang {
+
+class DiagnosticsEngine;
+class Rewriter;
+
+namespace replace {
+
+/// \brief Collection of TranslationUnitReplacements.
+typedef std::vector<clang::tooling::TranslationUnitReplacements> TUReplacements;
+
+/// \brief Collection of TranslationUnitReplacement files.
+typedef std::vector<std::string> TUReplacementFiles;
+
+/// \brief Collection of TranslationUniDiagnostics.
+typedef std::vector<clang::tooling::TranslationUnitDiagnostics> TUDiagnostics;
+
+/// \brief Map mapping file name to a set of AtomicChange targeting that file.
+typedef llvm::DenseMap<const clang::FileEntry *,
+                       std::vector<tooling::AtomicChange>>
+    FileToChangesMap;
+
+/// \brief Recursively descends through a directory structure rooted at \p
+/// Directory and attempts to deserialize *.yaml files as
+/// TranslationUnitReplacements. All docs that successfully deserialize are
+/// added to \p TUs.
+///
+/// Directories starting with '.' are ignored during traversal.
+///
+/// \param[in] Directory Directory to begin search for serialized
+/// TranslationUnitReplacements.
+/// \param[out] TUs Collection of all found and deserialized
+/// TranslationUnitReplacements or TranslationUnitDiagnostics.
+/// \param[out] TUFiles Collection of all TranslationUnitReplacement files
+/// found in \c Directory.
+/// \param[in] Diagnostics DiagnosticsEngine used for error output.
+///
+/// \returns An error_code indicating success or failure in navigating the
+/// directory structure.
+std::error_code collectReplacementsFromDirectory(
+    const llvm::StringRef Directory, TUReplacements &TUs,
+    TUReplacementFiles &TUFiles, clang::DiagnosticsEngine &Diagnostics);
+
+std::error_code collectReplacementsFromDirectory(
+    const llvm::StringRef Directory, TUDiagnostics &TUs,
+    TUReplacementFiles &TUFiles, clang::DiagnosticsEngine &Diagnostics);
+
+/// \brief Deduplicate, check for conflicts, and extract all Replacements stored
+/// in \c TUs. Conflicting replacements are skipped.
+///
+/// \post For all (key,value) in FileChanges, value[i].getOffset() <=
+/// value[i+1].getOffset().
+///
+/// \param[in] TUs Collection of TranslationUnitReplacements or
+/// TranslationUnitDiagnostics to merge, deduplicate, and test for conflicts.
+/// \param[out] FileChanges Container grouping all changes by the
+/// file they target. Only non conflicting replacements are kept into
+/// FileChanges.
+/// \param[in] SM SourceManager required for conflict reporting.
+///
+/// \returns \parblock
+///          \li true If all changes were converted successfully.
+///          \li false If there were conflicts.
+bool mergeAndDeduplicate(const TUReplacements &TUs, const TUDiagnostics &TUDs,
+                         FileToChangesMap &FileChanges,
+                         clang::SourceManager &SM);
+
+/// \brief Apply \c AtomicChange on File and rewrite it.
+///
+/// \param[in] File Path of the file where to apply AtomicChange.
+/// \param[in] Changes to apply.
+/// \param[in] Spec For code cleanup and formatting.
+/// \param[in] Diagnostics DiagnosticsEngine used for error output.
+///
+/// \returns The changed code if all changes are applied successfully;
+/// otherwise, an llvm::Error carrying llvm::StringError or an error_code.
+llvm::Expected<std::string>
+applyChanges(StringRef File, const std::vector<tooling::AtomicChange> &Changes,
+             const tooling::ApplyChangesSpec &Spec,
+             DiagnosticsEngine &Diagnostics);
+
+/// \brief Delete the replacement files.
+///
+/// \param[in] Files Replacement files to delete.
+/// \param[in] Diagnostics DiagnosticsEngine used for error output.
+///
+/// \returns \parblock
+///          \li true If all files have been deleted successfully.
+///          \li false If at least one or more failures occur when deleting
+/// files.
+bool deleteReplacementFiles(const TUReplacementFiles &Files,
+                            clang::DiagnosticsEngine &Diagnostics);
+
+} // end namespace replace
+} // end namespace clang
+
+#endif // LLVM_CLANG_APPLYREPLACEMENTS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
new file mode 100644
index 0000000..1970d05
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
@@ -0,0 +1,249 @@
+//===-- ApplyReplacements.cpp - Apply and deduplicate replacements --------===//
+//
+//                     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 provides the implementation for deduplicating, detecting
+/// conflicts in, and applying collections of Replacements.
+///
+/// FIXME: Use Diagnostics for output instead of llvm::errs().
+///
+//===----------------------------------------------------------------------===//
+#include "clang-apply-replacements/Tooling/ApplyReplacements.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Format/Format.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/DiagnosticsYaml.h"
+#include "clang/Tooling/ReplacementsYaml.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace clang;
+
+static void eatDiagnostics(const SMDiagnostic &, void *) {}
+
+namespace clang {
+namespace replace {
+
+std::error_code collectReplacementsFromDirectory(
+    const llvm::StringRef Directory, TUReplacements &TUs,
+    TUReplacementFiles &TUFiles, clang::DiagnosticsEngine &Diagnostics) {
+  using namespace llvm::sys::fs;
+  using namespace llvm::sys::path;
+
+  std::error_code ErrorCode;
+
+  for (recursive_directory_iterator I(Directory, ErrorCode), E;
+       I != E && !ErrorCode; I.increment(ErrorCode)) {
+    if (filename(I->path())[0] == '.') {
+      // Indicate not to descend into directories beginning with '.'
+      I.no_push();
+      continue;
+    }
+
+    if (extension(I->path()) != ".yaml")
+      continue;
+
+    TUFiles.push_back(I->path());
+
+    ErrorOr<std::unique_ptr<MemoryBuffer>> Out =
+        MemoryBuffer::getFile(I->path());
+    if (std::error_code BufferError = Out.getError()) {
+      errs() << "Error reading " << I->path() << ": " << BufferError.message()
+             << "\n";
+      continue;
+    }
+
+    yaml::Input YIn(Out.get()->getBuffer(), nullptr, &eatDiagnostics);
+    tooling::TranslationUnitReplacements TU;
+    YIn >> TU;
+    if (YIn.error()) {
+      // File doesn't appear to be a header change description. Ignore it.
+      continue;
+    }
+
+    // Only keep files that properly parse.
+    TUs.push_back(TU);
+  }
+
+  return ErrorCode;
+}
+
+std::error_code collectReplacementsFromDirectory(
+    const llvm::StringRef Directory, TUDiagnostics &TUs,
+    TUReplacementFiles &TUFiles, clang::DiagnosticsEngine &Diagnostics) {
+  using namespace llvm::sys::fs;
+  using namespace llvm::sys::path;
+
+  std::error_code ErrorCode;
+
+  for (recursive_directory_iterator I(Directory, ErrorCode), E;
+       I != E && !ErrorCode; I.increment(ErrorCode)) {
+    if (filename(I->path())[0] == '.') {
+      // Indicate not to descend into directories beginning with '.'
+      I.no_push();
+      continue;
+    }
+
+    if (extension(I->path()) != ".yaml")
+      continue;
+
+    TUFiles.push_back(I->path());
+
+    ErrorOr<std::unique_ptr<MemoryBuffer>> Out =
+        MemoryBuffer::getFile(I->path());
+    if (std::error_code BufferError = Out.getError()) {
+      errs() << "Error reading " << I->path() << ": " << BufferError.message()
+             << "\n";
+      continue;
+    }
+
+    yaml::Input YIn(Out.get()->getBuffer(), nullptr, &eatDiagnostics);
+    tooling::TranslationUnitDiagnostics TU;
+    YIn >> TU;
+    if (YIn.error()) {
+      // File doesn't appear to be a header change description. Ignore it.
+      continue;
+    }
+
+    // Only keep files that properly parse.
+    TUs.push_back(TU);
+  }
+
+  return ErrorCode;
+}
+
+/// \brief Extract replacements from collected TranslationUnitReplacements and
+/// TranslationUnitDiagnostics and group them per file.
+///
+/// \param[in] TUs Collection of all found and deserialized
+/// TranslationUnitReplacements.
+/// \param[in] TUDs Collection of all found and deserialized
+/// TranslationUnitDiagnostics.
+/// \param[in] SM Used to deduplicate paths.
+///
+/// \returns A map mapping FileEntry to a set of Replacement targeting that
+/// file.
+static llvm::DenseMap<const FileEntry *, std::vector<tooling::Replacement>>
+groupReplacements(const TUReplacements &TUs, const TUDiagnostics &TUDs,
+                  const clang::SourceManager &SM) {
+  std::set<StringRef> Warned;
+  llvm::DenseMap<const FileEntry *, std::vector<tooling::Replacement>>
+      GroupedReplacements;
+
+  auto AddToGroup = [&](const tooling::Replacement &R) {
+    // Use the file manager to deduplicate paths. FileEntries are
+    // automatically canonicalized.
+    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";
+    }
+  };
+
+  for (const auto &TU : TUs)
+    for (const tooling::Replacement &R : TU.Replacements)
+      AddToGroup(R);
+
+  for (const auto &TU : TUDs)
+    for (const auto &D : TU.Diagnostics)
+      for (const auto &Fix : D.Fix)
+        for (const tooling::Replacement &R : Fix.second)
+          AddToGroup(R);
+
+  // Sort replacements per file to keep consistent behavior when
+  // clang-apply-replacements run on differents machine.
+  for (auto &FileAndReplacements : GroupedReplacements) {
+    llvm::sort(FileAndReplacements.second.begin(),
+               FileAndReplacements.second.end());
+  }
+
+  return GroupedReplacements;
+}
+
+bool mergeAndDeduplicate(const TUReplacements &TUs, const TUDiagnostics &TUDs,
+                         FileToChangesMap &FileChanges,
+                         clang::SourceManager &SM) {
+  auto GroupedReplacements = groupReplacements(TUs, TUDs, SM);
+  bool ConflictDetected = false;
+
+  // To report conflicting replacements on corresponding file, all replacements
+  // are stored into 1 big AtomicChange.
+  for (const auto &FileAndReplacements : GroupedReplacements) {
+    const FileEntry *Entry = FileAndReplacements.first;
+    const SourceLocation BeginLoc =
+        SM.getLocForStartOfFile(SM.getOrCreateFileID(Entry, SrcMgr::C_User));
+    tooling::AtomicChange FileChange(Entry->getName(), Entry->getName());
+    for (const auto &R : FileAndReplacements.second) {
+      llvm::Error Err =
+          FileChange.replace(SM, BeginLoc.getLocWithOffset(R.getOffset()),
+                             R.getLength(), R.getReplacementText());
+      if (Err) {
+        // FIXME: This will report conflicts by pair using a file+offset format
+        // which is not so much human readable.
+        // A first improvement could be to translate offset to line+col. For
+        // this and without loosing error message some modifications arround
+        // `tooling::ReplacementError` are need (access to
+        // `getReplacementErrString`).
+        // A better strategy could be to add a pretty printer methods for
+        // conflict reporting. Methods that could be parameterized to report a
+        // conflict in different format, file+offset, file+line+col, or even
+        // more human readable using VCS conflict markers.
+        // For now, printing directly the error reported by `AtomicChange` is
+        // the easiest solution.
+        errs() << llvm::toString(std::move(Err)) << "\n";
+        ConflictDetected = true;
+      }
+    }
+    FileChanges.try_emplace(Entry,
+                            std::vector<tooling::AtomicChange>{FileChange});
+  }
+
+  return !ConflictDetected;
+}
+
+llvm::Expected<std::string>
+applyChanges(StringRef File, const std::vector<tooling::AtomicChange> &Changes,
+             const tooling::ApplyChangesSpec &Spec,
+             DiagnosticsEngine &Diagnostics) {
+  FileManager Files((FileSystemOptions()));
+  SourceManager SM(Diagnostics, Files);
+
+  llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
+      SM.getFileManager().getBufferForFile(File);
+  if (!Buffer)
+    return errorCodeToError(Buffer.getError());
+  return tooling::applyAtomicChanges(File, Buffer.get()->getBuffer(), Changes,
+                                     Spec);
+}
+
+bool deleteReplacementFiles(const TUReplacementFiles &Files,
+                            clang::DiagnosticsEngine &Diagnostics) {
+  bool Success = true;
+  for (const auto &Filename : Files) {
+    std::error_code Error = llvm::sys::fs::remove(Filename);
+    if (Error) {
+      Success = false;
+      // FIXME: Use Diagnostics for outputting errors.
+      errs() << "Error deleting file: " << Filename << "\n";
+      errs() << Error.message() << "\n";
+      errs() << "Please delete the file manually\n";
+    }
+  }
+  return Success;
+}
+
+} // end namespace replace
+} // end namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-apply-replacements/tool/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-apply-replacements/tool/CMakeLists.txt
new file mode 100644
index 0000000..945b486
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-apply-replacements/tool/CMakeLists.txt
@@ -0,0 +1,19 @@
+set(LLVM_LINK_COMPONENTS
+  Support
+  )
+
+add_clang_tool(clang-apply-replacements
+  ClangApplyReplacementsMain.cpp
+  )
+target_link_libraries(clang-apply-replacements
+  PRIVATE
+  clangApplyReplacements
+  clangBasic
+  clangFormat
+  clangRewrite
+  clangToolingCore
+  clangToolingRefactor
+  )
+
+install(TARGETS clang-apply-replacements
+  RUNTIME DESTINATION bin)
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp
new file mode 100644
index 0000000..24a430f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp
@@ -0,0 +1,165 @@
+//===-- ClangApplyReplacementsMain.cpp - Main file for the 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 provides the main function for the
+/// clang-apply-replacements tool.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang-apply-replacements/Tooling/ApplyReplacements.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Version.h"
+#include "clang/Format/Format.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/CommandLine.h"
+
+using namespace llvm;
+using namespace clang;
+using namespace clang::replace;
+
+static cl::opt<std::string> Directory(cl::Positional, cl::Required,
+                                      cl::desc("<Search Root Directory>"));
+
+static cl::OptionCategory ReplacementCategory("Replacement Options");
+static cl::OptionCategory FormattingCategory("Formatting Options");
+
+const cl::OptionCategory *VisibleCategories[] = {&ReplacementCategory,
+                                                 &FormattingCategory};
+
+static cl::opt<bool> RemoveTUReplacementFiles(
+    "remove-change-desc-files",
+    cl::desc("Remove the change description files regardless of successful\n"
+             "merging/replacing."),
+    cl::init(false), cl::cat(ReplacementCategory));
+
+static cl::opt<bool> DoFormat(
+    "format",
+    cl::desc("Enable formatting of code changed by applying replacements.\n"
+             "Use -style to choose formatting style.\n"),
+    cl::cat(FormattingCategory));
+
+// FIXME: Consider making the default behaviour for finding a style
+// configuration file to start the search anew for every file being changed to
+// handle situations where the style is different for different parts of a
+// project.
+
+static cl::opt<std::string> FormatStyleConfig(
+    "style-config",
+    cl::desc("Path to a directory containing a .clang-format file\n"
+             "describing a formatting style to use for formatting\n"
+             "code when -style=file.\n"),
+    cl::init(""), cl::cat(FormattingCategory));
+
+static cl::opt<std::string>
+    FormatStyleOpt("style", cl::desc(format::StyleOptionHelpDescription),
+                   cl::init("LLVM"), cl::cat(FormattingCategory));
+
+namespace {
+// Helper object to remove the TUReplacement and TUDiagnostic (triggered by
+// "remove-change-desc-files" command line option) when exiting current scope.
+class ScopedFileRemover {
+public:
+  ScopedFileRemover(const TUReplacementFiles &Files,
+                    clang::DiagnosticsEngine &Diagnostics)
+      : TURFiles(Files), Diag(Diagnostics) {}
+
+  ~ScopedFileRemover() { deleteReplacementFiles(TURFiles, Diag); }
+
+private:
+  const TUReplacementFiles &TURFiles;
+  clang::DiagnosticsEngine &Diag;
+};
+} // namespace
+
+static void printVersion(raw_ostream &OS) {
+  OS << "clang-apply-replacements version " CLANG_VERSION_STRING << "\n";
+}
+
+int main(int argc, char **argv) {
+  cl::HideUnrelatedOptions(makeArrayRef(VisibleCategories));
+
+  cl::SetVersionPrinter(printVersion);
+  cl::ParseCommandLineOptions(argc, argv);
+
+  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions());
+  DiagnosticsEngine Diagnostics(
+      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), DiagOpts.get());
+
+  // Determine a formatting style from options.
+  auto FormatStyleOrError =
+      format::getStyle(FormatStyleOpt, FormatStyleConfig, "LLVM");
+  if (!FormatStyleOrError) {
+    llvm::errs() << llvm::toString(FormatStyleOrError.takeError()) << "\n";
+    return 1;
+  }
+  format::FormatStyle FormatStyle = std::move(*FormatStyleOrError);
+
+  TUReplacements TURs;
+  TUReplacementFiles TUFiles;
+
+  std::error_code ErrorCode =
+      collectReplacementsFromDirectory(Directory, TURs, TUFiles, Diagnostics);
+
+  TUDiagnostics TUDs;
+  TUFiles.clear();
+  ErrorCode =
+      collectReplacementsFromDirectory(Directory, TUDs, TUFiles, Diagnostics);
+
+  if (ErrorCode) {
+    errs() << "Trouble iterating over directory '" << Directory
+           << "': " << ErrorCode.message() << "\n";
+    return 1;
+  }
+
+  // Remove the TUReplacementFiles (triggered by "remove-change-desc-files"
+  // command line option) when exiting main().
+  std::unique_ptr<ScopedFileRemover> Remover;
+  if (RemoveTUReplacementFiles)
+    Remover.reset(new ScopedFileRemover(TUFiles, Diagnostics));
+
+  FileManager Files((FileSystemOptions()));
+  SourceManager SM(Diagnostics, Files);
+
+  FileToChangesMap Changes;
+  if (!mergeAndDeduplicate(TURs, TUDs, Changes, SM))
+    return 1;
+
+  tooling::ApplyChangesSpec Spec;
+  Spec.Cleanup = true;
+  Spec.Style = FormatStyle;
+  Spec.Format = DoFormat ? tooling::ApplyChangesSpec::kAll
+                         : tooling::ApplyChangesSpec::kNone;
+
+  for (const auto &FileChange : Changes) {
+    const FileEntry *Entry = FileChange.first;
+    StringRef FileName = Entry->getName();
+    llvm::Expected<std::string> NewFileData =
+        applyChanges(FileName, FileChange.second, Spec, Diagnostics);
+    if (!NewFileData) {
+      errs() << llvm::toString(NewFileData.takeError()) << "\n";
+      continue;
+    }
+
+    // Write new file to disk
+    std::error_code EC;
+    llvm::raw_fd_ostream FileStream(FileName, EC, llvm::sys::fs::F_None);
+    if (EC) {
+      llvm::errs() << "Could not open " << FileName << " for writing\n";
+      continue;
+    }
+    FileStream << *NewFileData;
+  }
+
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/BitcodeReader.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-doc/BitcodeReader.cpp
new file mode 100644
index 0000000..fa51d01
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -0,0 +1,622 @@
+//===--  BitcodeReader.cpp - ClangDoc Bitcode Reader ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "BitcodeReader.h"
+#include "llvm/ADT/IndexedMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace doc {
+
+using Record = llvm::SmallVector<uint64_t, 1024>;
+
+bool decodeRecord(Record R, llvm::SmallVectorImpl<char> &Field,
+                  llvm::StringRef Blob) {
+  Field.assign(Blob.begin(), Blob.end());
+  return true;
+}
+
+bool decodeRecord(Record R, SymbolID &Field, llvm::StringRef Blob) {
+  if (R[0] != BitCodeConstants::USRHashSize)
+    return false;
+
+  // First position in the record is the length of the following array, so we
+  // copy the following elements to the field.
+  for (int I = 0, E = R[0]; I < E; ++I)
+    Field[I] = R[I + 1];
+  return true;
+}
+
+bool decodeRecord(Record R, bool &Field, llvm::StringRef Blob) {
+  Field = R[0] != 0;
+  return true;
+}
+
+bool decodeRecord(Record R, int &Field, llvm::StringRef Blob) {
+  if (R[0] > INT_MAX)
+    return false;
+  Field = (int)R[0];
+  return true;
+}
+
+bool decodeRecord(Record R, AccessSpecifier &Field, llvm::StringRef Blob) {
+  switch (R[0]) {
+  case AS_public:
+  case AS_private:
+  case AS_protected:
+  case AS_none:
+    Field = (AccessSpecifier)R[0];
+    return true;
+  default:
+    return false;
+  }
+}
+
+bool decodeRecord(Record R, TagTypeKind &Field, llvm::StringRef Blob) {
+  switch (R[0]) {
+  case TTK_Struct:
+  case TTK_Interface:
+  case TTK_Union:
+  case TTK_Class:
+  case TTK_Enum:
+    Field = (TagTypeKind)R[0];
+    return true;
+  default:
+    return false;
+  }
+}
+
+bool decodeRecord(Record R, llvm::Optional<Location> &Field,
+                  llvm::StringRef Blob) {
+  if (R[0] > INT_MAX)
+    return false;
+  Field.emplace((int)R[0], Blob);
+  return true;
+}
+
+bool decodeRecord(Record R, InfoType &Field, llvm::StringRef Blob) {
+  switch (auto IT = static_cast<InfoType>(R[0])) {
+  case InfoType::IT_namespace:
+  case InfoType::IT_record:
+  case InfoType::IT_function:
+  case InfoType::IT_default:
+  case InfoType::IT_enum:
+    Field = IT;
+    return true;
+  }
+  return false;
+}
+
+bool decodeRecord(Record R, FieldId &Field, llvm::StringRef Blob) {
+  switch (auto F = static_cast<FieldId>(R[0])) {
+  case FieldId::F_namespace:
+  case FieldId::F_parent:
+  case FieldId::F_vparent:
+  case FieldId::F_type:
+  case FieldId::F_default:
+    Field = F;
+    return true;
+  }
+  return false;
+}
+
+bool decodeRecord(Record R, llvm::SmallVectorImpl<llvm::SmallString<16>> &Field,
+                  llvm::StringRef Blob) {
+  Field.push_back(Blob);
+  return true;
+}
+
+bool decodeRecord(Record R, llvm::SmallVectorImpl<Location> &Field,
+                  llvm::StringRef Blob) {
+  if (R[0] > INT_MAX)
+    return false;
+  Field.emplace_back((int)R[0], Blob);
+  return true;
+}
+
+bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob,
+                 const unsigned VersionNo) {
+  if (ID == VERSION && R[0] == VersionNo)
+    return true;
+  return false;
+}
+
+bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob,
+                 NamespaceInfo *I) {
+  switch (ID) {
+  case NAMESPACE_USR:
+    return decodeRecord(R, I->USR, Blob);
+  case NAMESPACE_NAME:
+    return decodeRecord(R, I->Name, Blob);
+  default:
+    return false;
+  }
+}
+
+bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, RecordInfo *I) {
+  switch (ID) {
+  case RECORD_USR:
+    return decodeRecord(R, I->USR, Blob);
+  case RECORD_NAME:
+    return decodeRecord(R, I->Name, Blob);
+  case RECORD_DEFLOCATION:
+    return decodeRecord(R, I->DefLoc, Blob);
+  case RECORD_LOCATION:
+    return decodeRecord(R, I->Loc, Blob);
+  case RECORD_TAG_TYPE:
+    return decodeRecord(R, I->TagType, Blob);
+  default:
+    return false;
+  }
+}
+
+bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, EnumInfo *I) {
+  switch (ID) {
+  case ENUM_USR:
+    return decodeRecord(R, I->USR, Blob);
+  case ENUM_NAME:
+    return decodeRecord(R, I->Name, Blob);
+  case ENUM_DEFLOCATION:
+    return decodeRecord(R, I->DefLoc, Blob);
+  case ENUM_LOCATION:
+    return decodeRecord(R, I->Loc, Blob);
+  case ENUM_MEMBER:
+    return decodeRecord(R, I->Members, Blob);
+  case ENUM_SCOPED:
+    return decodeRecord(R, I->Scoped, Blob);
+  default:
+    return false;
+  }
+}
+
+bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, FunctionInfo *I) {
+  switch (ID) {
+  case FUNCTION_USR:
+    return decodeRecord(R, I->USR, Blob);
+  case FUNCTION_NAME:
+    return decodeRecord(R, I->Name, Blob);
+  case FUNCTION_DEFLOCATION:
+    return decodeRecord(R, I->DefLoc, Blob);
+  case FUNCTION_LOCATION:
+    return decodeRecord(R, I->Loc, Blob);
+  case FUNCTION_ACCESS:
+    return decodeRecord(R, I->Access, Blob);
+  case FUNCTION_IS_METHOD:
+    return decodeRecord(R, I->IsMethod, Blob);
+  default:
+    return false;
+  }
+}
+
+bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, TypeInfo *I) {
+  return true;
+}
+
+bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob,
+                 FieldTypeInfo *I) {
+  switch (ID) {
+  case FIELD_TYPE_NAME:
+    return decodeRecord(R, I->Name, Blob);
+  default:
+    return false;
+  }
+}
+
+bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob,
+                 MemberTypeInfo *I) {
+  switch (ID) {
+  case MEMBER_TYPE_NAME:
+    return decodeRecord(R, I->Name, Blob);
+  case MEMBER_TYPE_ACCESS:
+    return decodeRecord(R, I->Access, Blob);
+  default:
+    return false;
+  }
+}
+
+bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, CommentInfo *I) {
+  switch (ID) {
+  case COMMENT_KIND:
+    return decodeRecord(R, I->Kind, Blob);
+  case COMMENT_TEXT:
+    return decodeRecord(R, I->Text, Blob);
+  case COMMENT_NAME:
+    return decodeRecord(R, I->Name, Blob);
+  case COMMENT_DIRECTION:
+    return decodeRecord(R, I->Direction, Blob);
+  case COMMENT_PARAMNAME:
+    return decodeRecord(R, I->ParamName, Blob);
+  case COMMENT_CLOSENAME:
+    return decodeRecord(R, I->CloseName, Blob);
+  case COMMENT_ATTRKEY:
+    return decodeRecord(R, I->AttrKeys, Blob);
+  case COMMENT_ATTRVAL:
+    return decodeRecord(R, I->AttrValues, Blob);
+  case COMMENT_ARG:
+    return decodeRecord(R, I->Args, Blob);
+  case COMMENT_SELFCLOSING:
+    return decodeRecord(R, I->SelfClosing, Blob);
+  case COMMENT_EXPLICIT:
+    return decodeRecord(R, I->Explicit, Blob);
+  default:
+    return false;
+  }
+}
+
+bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, Reference *I,
+                 FieldId &F) {
+  switch (ID) {
+  case REFERENCE_USR:
+    return decodeRecord(R, I->USR, Blob);
+  case REFERENCE_NAME:
+    return decodeRecord(R, I->Name, Blob);
+  case REFERENCE_TYPE:
+    return decodeRecord(R, I->RefType, Blob);
+  case REFERENCE_FIELD:
+    return decodeRecord(R, F, Blob);
+  default:
+    return false;
+  }
+}
+
+template <typename T> CommentInfo *getCommentInfo(T I) {
+  llvm::errs() << "Cannot have comment subblock.\n";
+  exit(1);
+}
+
+template <> CommentInfo *getCommentInfo(FunctionInfo *I) {
+  I->Description.emplace_back();
+  return &I->Description.back();
+}
+
+template <> CommentInfo *getCommentInfo(NamespaceInfo *I) {
+  I->Description.emplace_back();
+  return &I->Description.back();
+}
+
+template <> CommentInfo *getCommentInfo(RecordInfo *I) {
+  I->Description.emplace_back();
+  return &I->Description.back();
+}
+
+template <> CommentInfo *getCommentInfo(EnumInfo *I) {
+  I->Description.emplace_back();
+  return &I->Description.back();
+}
+
+template <> CommentInfo *getCommentInfo(CommentInfo *I) {
+  I->Children.emplace_back(llvm::make_unique<CommentInfo>());
+  return I->Children.back().get();
+}
+
+template <> CommentInfo *getCommentInfo(std::unique_ptr<CommentInfo> &I) {
+  return getCommentInfo(I.get());
+}
+
+template <typename T, typename TTypeInfo>
+void addTypeInfo(T I, TTypeInfo &&TI) {
+  llvm::errs() << "Invalid type for info.\n";
+  exit(1);
+}
+
+template <> void addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) {
+  I->Members.emplace_back(std::move(T));
+}
+
+template <> void addTypeInfo(FunctionInfo *I, TypeInfo &&T) {
+  I->ReturnType = std::move(T);
+}
+
+template <> void addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) {
+  I->Params.emplace_back(std::move(T));
+}
+
+template <typename T> void addReference(T I, Reference &&R, FieldId F) {
+  llvm::errs() << "Invalid field type for info.\n";
+  exit(1);
+}
+
+template <> void addReference(TypeInfo *I, Reference &&R, FieldId F) {
+  switch (F) {
+  case FieldId::F_type:
+    I->Type = std::move(R);
+    break;
+  default:
+    llvm::errs() << "Invalid field type for info.\n";
+    exit(1);
+  }
+}
+
+template <> void addReference(FieldTypeInfo *I, Reference &&R, FieldId F) {
+  switch (F) {
+  case FieldId::F_type:
+    I->Type = std::move(R);
+    break;
+  default:
+    llvm::errs() << "Invalid field type for info.\n";
+    exit(1);
+  }
+}
+
+template <> void addReference(MemberTypeInfo *I, Reference &&R, FieldId F) {
+  switch (F) {
+  case FieldId::F_type:
+    I->Type = std::move(R);
+    break;
+  default:
+    llvm::errs() << "Invalid field type for info.\n";
+    exit(1);
+  }
+}
+
+template <> void addReference(EnumInfo *I, Reference &&R, FieldId F) {
+  switch (F) {
+  case FieldId::F_namespace:
+    I->Namespace.emplace_back(std::move(R));
+    break;
+  default:
+    llvm::errs() << "Invalid field type for info.\n";
+    exit(1);
+  }
+}
+
+template <> void addReference(NamespaceInfo *I, Reference &&R, FieldId F) {
+  switch (F) {
+  case FieldId::F_namespace:
+    I->Namespace.emplace_back(std::move(R));
+    break;
+  default:
+    llvm::errs() << "Invalid field type for info.\n";
+    exit(1);
+  }
+}
+
+template <> void addReference(FunctionInfo *I, Reference &&R, FieldId F) {
+  switch (F) {
+  case FieldId::F_namespace:
+    I->Namespace.emplace_back(std::move(R));
+    break;
+  case FieldId::F_parent:
+    I->Parent = std::move(R);
+    break;
+  default:
+    llvm::errs() << "Invalid field type for info.\n";
+    exit(1);
+  }
+}
+
+template <> void addReference(RecordInfo *I, Reference &&R, FieldId F) {
+  switch (F) {
+  case FieldId::F_namespace:
+    I->Namespace.emplace_back(std::move(R));
+    break;
+  case FieldId::F_parent:
+    I->Parents.emplace_back(std::move(R));
+    break;
+  case FieldId::F_vparent:
+    I->VirtualParents.emplace_back(std::move(R));
+    break;
+  default:
+    llvm::errs() << "Invalid field type for info.\n";
+    exit(1);
+  }
+}
+
+// Read records from bitcode into a given info.
+template <typename T> bool ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
+  Record R;
+  llvm::StringRef Blob;
+  unsigned RecID = Stream.readRecord(ID, R, &Blob);
+  return parseRecord(R, RecID, Blob, I);
+}
+
+template <> bool ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
+  Record R;
+  llvm::StringRef Blob;
+  unsigned RecID = Stream.readRecord(ID, R, &Blob);
+  return parseRecord(R, RecID, Blob, I, CurrentReferenceField);
+}
+
+// Read a block of records into a single info.
+template <typename T> bool ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
+  if (Stream.EnterSubBlock(ID))
+    return false;
+
+  while (true) {
+    unsigned BlockOrCode = 0;
+    Cursor Res = skipUntilRecordOrBlock(BlockOrCode);
+
+    switch (Res) {
+    case Cursor::BadBlock:
+      return false;
+    case Cursor::BlockEnd:
+      return true;
+    case Cursor::BlockBegin:
+      if (readSubBlock(BlockOrCode, I))
+        continue;
+      if (!Stream.SkipBlock())
+        return false;
+      continue;
+    case Cursor::Record:
+      break;
+    }
+    if (!readRecord(BlockOrCode, I))
+      return false;
+  }
+}
+
+template <typename T>
+bool ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
+  switch (ID) {
+  // Blocks can only have Comment, Reference, or TypeInfo subblocks
+  case BI_COMMENT_BLOCK_ID:
+    if (readBlock(ID, getCommentInfo(I)))
+      return true;
+    return false;
+  case BI_TYPE_BLOCK_ID: {
+    TypeInfo TI;
+    if (readBlock(ID, &TI)) {
+      addTypeInfo(I, std::move(TI));
+      return true;
+    }
+    return false;
+  }
+  case BI_FIELD_TYPE_BLOCK_ID: {
+    FieldTypeInfo TI;
+    if (readBlock(ID, &TI)) {
+      addTypeInfo(I, std::move(TI));
+      return true;
+    }
+    return false;
+  }
+  case BI_MEMBER_TYPE_BLOCK_ID: {
+    MemberTypeInfo TI;
+    if (readBlock(ID, &TI)) {
+      addTypeInfo(I, std::move(TI));
+      return true;
+    }
+    return false;
+  }
+  case BI_REFERENCE_BLOCK_ID: {
+    Reference R;
+    if (readBlock(ID, &R)) {
+      addReference(I, std::move(R), CurrentReferenceField);
+      return true;
+    }
+    return false;
+  }
+  default:
+    llvm::errs() << "Invalid subblock type.\n";
+    return false;
+  }
+}
+
+ClangDocBitcodeReader::Cursor
+ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) {
+  BlockOrRecordID = 0;
+
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+
+    switch ((llvm::bitc::FixedAbbrevIDs)Code) {
+    case llvm::bitc::ENTER_SUBBLOCK:
+      BlockOrRecordID = Stream.ReadSubBlockID();
+      return Cursor::BlockBegin;
+    case llvm::bitc::END_BLOCK:
+      if (Stream.ReadBlockEnd())
+        return Cursor::BadBlock;
+      return Cursor::BlockEnd;
+    case llvm::bitc::DEFINE_ABBREV:
+      Stream.ReadAbbrevRecord();
+      continue;
+    case llvm::bitc::UNABBREV_RECORD:
+      return Cursor::BadBlock;
+    default:
+      BlockOrRecordID = Code;
+      return Cursor::Record;
+    }
+  }
+  llvm_unreachable("Premature stream end.");
+}
+
+bool ClangDocBitcodeReader::validateStream() {
+  if (Stream.AtEndOfStream())
+    return false;
+
+  // Sniff for the signature.
+  if (Stream.Read(8) != BitCodeConstants::Signature[0] ||
+      Stream.Read(8) != BitCodeConstants::Signature[1] ||
+      Stream.Read(8) != BitCodeConstants::Signature[2] ||
+      Stream.Read(8) != BitCodeConstants::Signature[3])
+    return false;
+  return true;
+}
+
+bool ClangDocBitcodeReader::readBlockInfoBlock() {
+  BlockInfo = Stream.ReadBlockInfoBlock();
+  if (!BlockInfo)
+    return false;
+  Stream.setBlockInfo(&*BlockInfo);
+  return true;
+}
+
+template <typename T>
+std::unique_ptr<Info> ClangDocBitcodeReader::createInfo(unsigned ID) {
+  std::unique_ptr<Info> I = llvm::make_unique<T>();
+  if (readBlock(ID, static_cast<T *>(I.get())))
+    return I;
+  llvm::errs() << "Error reading from block.\n";
+  return nullptr;
+}
+
+std::unique_ptr<Info> ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
+  switch (ID) {
+  case BI_NAMESPACE_BLOCK_ID:
+    return createInfo<NamespaceInfo>(ID);
+  case BI_RECORD_BLOCK_ID:
+    return createInfo<RecordInfo>(ID);
+  case BI_ENUM_BLOCK_ID:
+    return createInfo<EnumInfo>(ID);
+  case BI_FUNCTION_BLOCK_ID:
+    return createInfo<FunctionInfo>(ID);
+  default:
+    llvm::errs() << "Error reading from block.\n";
+    return nullptr;
+  }
+}
+
+// Entry point
+std::vector<std::unique_ptr<Info>> ClangDocBitcodeReader::readBitcode() {
+  std::vector<std::unique_ptr<Info>> Infos;
+  if (!validateStream())
+    return Infos;
+
+  // Read the top level blocks.
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+    if (Code != llvm::bitc::ENTER_SUBBLOCK)
+      return Infos;
+
+    unsigned ID = Stream.ReadSubBlockID();
+    switch (ID) {
+    // NamedType and Comment blocks should not appear at the top level
+    case BI_TYPE_BLOCK_ID:
+    case BI_FIELD_TYPE_BLOCK_ID:
+    case BI_MEMBER_TYPE_BLOCK_ID:
+    case BI_COMMENT_BLOCK_ID:
+    case BI_REFERENCE_BLOCK_ID:
+      llvm::errs() << "Invalid top level block.\n";
+      return Infos;
+    case BI_NAMESPACE_BLOCK_ID:
+    case BI_RECORD_BLOCK_ID:
+    case BI_ENUM_BLOCK_ID:
+    case BI_FUNCTION_BLOCK_ID:
+      if (std::unique_ptr<Info> I = readBlockToInfo(ID)) {
+        Infos.emplace_back(std::move(I));
+      }
+      return Infos;
+    case BI_VERSION_BLOCK_ID:
+      if (readBlock(ID, VersionNumber))
+        continue;
+      return Infos;
+    case llvm::bitc::BLOCKINFO_BLOCK_ID:
+      if (readBlockInfoBlock())
+        continue;
+      return Infos;
+    default:
+      if (!Stream.SkipBlock())
+        continue;
+    }
+  }
+  return Infos;
+}
+
+} // namespace doc
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/BitcodeReader.h b/src/third_party/llvm-project/clang-tools-extra/clang-doc/BitcodeReader.h
new file mode 100644
index 0000000..c0cf24a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/BitcodeReader.h
@@ -0,0 +1,73 @@
+//===--  BitcodeReader.h - ClangDoc Bitcode Reader --------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a reader for parsing the clang-doc internal
+// representation from LLVM bitcode. The reader takes in a stream of bits and
+// generates the set of infos that it represents.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEREADER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEREADER_H
+
+#include "BitcodeWriter.h"
+#include "Representation.h"
+#include "clang/AST/AST.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+
+namespace clang {
+namespace doc {
+
+// Class to read bitstream into an InfoSet collection
+class ClangDocBitcodeReader {
+public:
+  ClangDocBitcodeReader(llvm::BitstreamCursor &Stream) : Stream(Stream) {}
+
+  // Main entry point, calls readBlock to read each block in the given stream.
+  std::vector<std::unique_ptr<Info>> readBitcode();
+
+private:
+  enum class Cursor { BadBlock = 1, Record, BlockEnd, BlockBegin };
+
+  // Top level parsing
+  bool validateStream();
+  bool readVersion();
+  bool readBlockInfoBlock();
+
+  // Read a block of records into a single Info struct, calls readRecord on each
+  // record found.
+  template <typename T> bool readBlock(unsigned ID, T I);
+
+  // Step through a block of records to find the next data field.
+  template <typename T> bool readSubBlock(unsigned ID, T I);
+
+  // Read record data into the given Info data field, calling the appropriate
+  // parseRecord functions to parse and store the data.
+  template <typename T> bool readRecord(unsigned ID, T I);
+
+  // Allocate the relevant type of info and add read data to the object.
+  template <typename T> std::unique_ptr<Info> createInfo(unsigned ID);
+
+  // Helper function to step through blocks to find and dispatch the next record
+  // or block to be read.
+  Cursor skipUntilRecordOrBlock(unsigned &BlockOrRecordID);
+
+  // Helper function to set up the approriate type of Info.
+  std::unique_ptr<Info> readBlockToInfo(unsigned ID);
+
+  llvm::BitstreamCursor &Stream;
+  Optional<llvm::BitstreamBlockInfo> BlockInfo;
+  FieldId CurrentReferenceField;
+};
+
+} // namespace doc
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEREADER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-doc/BitcodeWriter.cpp
new file mode 100644
index 0000000..623ed1a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/BitcodeWriter.cpp
@@ -0,0 +1,518 @@
+//===--  BitcodeWriter.cpp - ClangDoc Bitcode Writer ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "BitcodeWriter.h"
+#include "llvm/ADT/IndexedMap.h"
+#include <initializer_list>
+
+namespace clang {
+namespace doc {
+
+// Empty SymbolID for comparison, so we don't have to construct one every time.
+static const SymbolID EmptySID = SymbolID();
+
+// Since id enums are not zero-indexed, we need to transform the given id into
+// its associated index.
+struct BlockIdToIndexFunctor {
+  using argument_type = unsigned;
+  unsigned operator()(unsigned ID) const { return ID - BI_FIRST; }
+};
+
+struct RecordIdToIndexFunctor {
+  using argument_type = unsigned;
+  unsigned operator()(unsigned ID) const { return ID - RI_FIRST; }
+};
+
+using AbbrevDsc = void (*)(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev);
+
+static void AbbrevGen(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev,
+                      const std::initializer_list<llvm::BitCodeAbbrevOp> Ops) {
+  for (const auto &Op : Ops)
+    Abbrev->Add(Op);
+}
+
+static void BoolAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
+  AbbrevGen(Abbrev,
+            {// 0. Boolean
+             llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
+                                   BitCodeConstants::BoolSize)});
+}
+
+static void IntAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
+  AbbrevGen(Abbrev,
+            {// 0. Fixed-size integer
+             llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
+                                   BitCodeConstants::IntSize)});
+}
+
+static void SymbolIDAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
+  AbbrevGen(Abbrev,
+            {// 0. Fixed-size integer (length of the sha1'd USR)
+             llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
+                                   BitCodeConstants::USRLengthSize),
+             // 1. Fixed-size array of Char6 (USR)
+             llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array),
+             llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
+                                   BitCodeConstants::USRBitLengthSize)});
+}
+
+static void StringAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
+  AbbrevGen(Abbrev,
+            {// 0. Fixed-size integer (length of the following string)
+             llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
+                                   BitCodeConstants::StringLengthSize),
+             // 1. The string blob
+             llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)});
+}
+
+// Assumes that the file will not have more than 65535 lines.
+static void LocationAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
+  AbbrevGen(
+      Abbrev,
+      {// 0. Fixed-size integer (line number)
+       llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
+                             BitCodeConstants::LineNumberSize),
+       // 1. Fixed-size integer (length of the following string (filename))
+       llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
+                             BitCodeConstants::StringLengthSize),
+       // 2. The string blob
+       llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)});
+}
+
+struct RecordIdDsc {
+  llvm::StringRef Name;
+  AbbrevDsc Abbrev = nullptr;
+
+  RecordIdDsc() = default;
+  RecordIdDsc(llvm::StringRef Name, AbbrevDsc Abbrev)
+      : Name(Name), Abbrev(Abbrev) {}
+
+  // Is this 'description' valid?
+  operator bool() const {
+    return Abbrev != nullptr && Name.data() != nullptr && !Name.empty();
+  }
+};
+
+static const llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor>
+    BlockIdNameMap = []() {
+      llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor> BlockIdNameMap;
+      BlockIdNameMap.resize(BlockIdCount);
+
+      // There is no init-list constructor for the IndexedMap, so have to
+      // improvise
+      static const std::vector<std::pair<BlockId, const char *const>> Inits = {
+          {BI_VERSION_BLOCK_ID, "VersionBlock"},
+          {BI_NAMESPACE_BLOCK_ID, "NamespaceBlock"},
+          {BI_ENUM_BLOCK_ID, "EnumBlock"},
+          {BI_TYPE_BLOCK_ID, "TypeBlock"},
+          {BI_FIELD_TYPE_BLOCK_ID, "FieldTypeBlock"},
+          {BI_MEMBER_TYPE_BLOCK_ID, "MemberTypeBlock"},
+          {BI_RECORD_BLOCK_ID, "RecordBlock"},
+          {BI_FUNCTION_BLOCK_ID, "FunctionBlock"},
+          {BI_COMMENT_BLOCK_ID, "CommentBlock"},
+          {BI_REFERENCE_BLOCK_ID, "ReferenceBlock"}};
+      assert(Inits.size() == BlockIdCount);
+      for (const auto &Init : Inits)
+        BlockIdNameMap[Init.first] = Init.second;
+      assert(BlockIdNameMap.size() == BlockIdCount);
+      return BlockIdNameMap;
+    }();
+
+static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor>
+    RecordIdNameMap = []() {
+      llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor> RecordIdNameMap;
+      RecordIdNameMap.resize(RecordIdCount);
+
+      // There is no init-list constructor for the IndexedMap, so have to
+      // improvise
+      static const std::vector<std::pair<RecordId, RecordIdDsc>> Inits = {
+          {VERSION, {"Version", &IntAbbrev}},
+          {COMMENT_KIND, {"Kind", &StringAbbrev}},
+          {COMMENT_TEXT, {"Text", &StringAbbrev}},
+          {COMMENT_NAME, {"Name", &StringAbbrev}},
+          {COMMENT_DIRECTION, {"Direction", &StringAbbrev}},
+          {COMMENT_PARAMNAME, {"ParamName", &StringAbbrev}},
+          {COMMENT_CLOSENAME, {"CloseName", &StringAbbrev}},
+          {COMMENT_SELFCLOSING, {"SelfClosing", &BoolAbbrev}},
+          {COMMENT_EXPLICIT, {"Explicit", &BoolAbbrev}},
+          {COMMENT_ATTRKEY, {"AttrKey", &StringAbbrev}},
+          {COMMENT_ATTRVAL, {"AttrVal", &StringAbbrev}},
+          {COMMENT_ARG, {"Arg", &StringAbbrev}},
+          {FIELD_TYPE_NAME, {"Name", &StringAbbrev}},
+          {MEMBER_TYPE_NAME, {"Name", &StringAbbrev}},
+          {MEMBER_TYPE_ACCESS, {"Access", &IntAbbrev}},
+          {NAMESPACE_USR, {"USR", &SymbolIDAbbrev}},
+          {NAMESPACE_NAME, {"Name", &StringAbbrev}},
+          {ENUM_USR, {"USR", &SymbolIDAbbrev}},
+          {ENUM_NAME, {"Name", &StringAbbrev}},
+          {ENUM_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
+          {ENUM_LOCATION, {"Location", &LocationAbbrev}},
+          {ENUM_MEMBER, {"Member", &StringAbbrev}},
+          {ENUM_SCOPED, {"Scoped", &BoolAbbrev}},
+          {RECORD_USR, {"USR", &SymbolIDAbbrev}},
+          {RECORD_NAME, {"Name", &StringAbbrev}},
+          {RECORD_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
+          {RECORD_LOCATION, {"Location", &LocationAbbrev}},
+          {RECORD_TAG_TYPE, {"TagType", &IntAbbrev}},
+          {FUNCTION_USR, {"USR", &SymbolIDAbbrev}},
+          {FUNCTION_NAME, {"Name", &StringAbbrev}},
+          {FUNCTION_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
+          {FUNCTION_LOCATION, {"Location", &LocationAbbrev}},
+          {FUNCTION_ACCESS, {"Access", &IntAbbrev}},
+          {FUNCTION_IS_METHOD, {"IsMethod", &BoolAbbrev}},
+          {REFERENCE_USR, {"USR", &SymbolIDAbbrev}},
+          {REFERENCE_NAME, {"Name", &StringAbbrev}},
+          {REFERENCE_TYPE, {"RefType", &IntAbbrev}},
+          {REFERENCE_FIELD, {"Field", &IntAbbrev}}};
+      assert(Inits.size() == RecordIdCount);
+      for (const auto &Init : Inits) {
+        RecordIdNameMap[Init.first] = Init.second;
+        assert((Init.second.Name.size() + 1) <= BitCodeConstants::RecordSize);
+      }
+      assert(RecordIdNameMap.size() == RecordIdCount);
+      return RecordIdNameMap;
+    }();
+
+static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
+    RecordsByBlock{
+        // Version Block
+        {BI_VERSION_BLOCK_ID, {VERSION}},
+        // Comment Block
+        {BI_COMMENT_BLOCK_ID,
+         {COMMENT_KIND, COMMENT_TEXT, COMMENT_NAME, COMMENT_DIRECTION,
+          COMMENT_PARAMNAME, COMMENT_CLOSENAME, COMMENT_SELFCLOSING,
+          COMMENT_EXPLICIT, COMMENT_ATTRKEY, COMMENT_ATTRVAL, COMMENT_ARG}},
+        // Type Block
+        {BI_TYPE_BLOCK_ID, {}},
+        // FieldType Block
+        {BI_FIELD_TYPE_BLOCK_ID, {FIELD_TYPE_NAME}},
+        // MemberType Block
+        {BI_MEMBER_TYPE_BLOCK_ID, {MEMBER_TYPE_NAME, MEMBER_TYPE_ACCESS}},
+        // Enum Block
+        {BI_ENUM_BLOCK_ID,
+         {ENUM_USR, ENUM_NAME, ENUM_DEFLOCATION, ENUM_LOCATION, ENUM_MEMBER,
+          ENUM_SCOPED}},
+        // Namespace Block
+        {BI_NAMESPACE_BLOCK_ID, {NAMESPACE_USR, NAMESPACE_NAME}},
+        // Record Block
+        {BI_RECORD_BLOCK_ID,
+         {RECORD_USR, RECORD_NAME, RECORD_DEFLOCATION, RECORD_LOCATION,
+          RECORD_TAG_TYPE}},
+        // Function Block
+        {BI_FUNCTION_BLOCK_ID,
+         {FUNCTION_USR, FUNCTION_NAME, FUNCTION_DEFLOCATION, FUNCTION_LOCATION,
+          FUNCTION_ACCESS, FUNCTION_IS_METHOD}},
+        // Reference Block
+        {BI_REFERENCE_BLOCK_ID,
+         {REFERENCE_USR, REFERENCE_NAME, REFERENCE_TYPE, REFERENCE_FIELD}}};
+
+// AbbreviationMap
+
+constexpr char BitCodeConstants::Signature[];
+
+void ClangDocBitcodeWriter::AbbreviationMap::add(RecordId RID,
+                                                 unsigned AbbrevID) {
+  assert(RecordIdNameMap[RID] && "Unknown RecordId.");
+  assert(Abbrevs.find(RID) == Abbrevs.end() && "Abbreviation already added.");
+  Abbrevs[RID] = AbbrevID;
+}
+
+unsigned ClangDocBitcodeWriter::AbbreviationMap::get(RecordId RID) const {
+  assert(RecordIdNameMap[RID] && "Unknown RecordId.");
+  assert(Abbrevs.find(RID) != Abbrevs.end() && "Unknown abbreviation.");
+  return Abbrevs.lookup(RID);
+}
+
+// Validation and Overview Blocks
+
+/// \brief Emits the magic number header to check that its the right format,
+/// in this case, 'DOCS'.
+void ClangDocBitcodeWriter::emitHeader() {
+  for (char C : BitCodeConstants::Signature)
+    Stream.Emit((unsigned)C, BitCodeConstants::SignatureBitSize);
+}
+
+void ClangDocBitcodeWriter::emitVersionBlock() {
+  StreamSubBlockGuard Block(Stream, BI_VERSION_BLOCK_ID);
+  emitRecord(VersionNumber, VERSION);
+}
+
+/// \brief Emits a block ID and the block name to the BLOCKINFO block.
+void ClangDocBitcodeWriter::emitBlockID(BlockId BID) {
+  const auto &BlockIdName = BlockIdNameMap[BID];
+  assert(BlockIdName.data() && BlockIdName.size() && "Unknown BlockId.");
+
+  Record.clear();
+  Record.push_back(BID);
+  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
+  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
+                    ArrayRef<unsigned char>(BlockIdName.bytes_begin(),
+                                            BlockIdName.bytes_end()));
+}
+
+/// \brief Emits a record name to the BLOCKINFO block.
+void ClangDocBitcodeWriter::emitRecordID(RecordId ID) {
+  assert(RecordIdNameMap[ID] && "Unknown RecordId.");
+  prepRecordData(ID);
+  Record.append(RecordIdNameMap[ID].Name.begin(),
+                RecordIdNameMap[ID].Name.end());
+  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
+}
+
+// Abbreviations
+
+void ClangDocBitcodeWriter::emitAbbrev(RecordId ID, BlockId Block) {
+  assert(RecordIdNameMap[ID] && "Unknown abbreviation.");
+  auto Abbrev = std::make_shared<llvm::BitCodeAbbrev>();
+  Abbrev->Add(llvm::BitCodeAbbrevOp(ID));
+  RecordIdNameMap[ID].Abbrev(Abbrev);
+  Abbrevs.add(ID, Stream.EmitBlockInfoAbbrev(Block, std::move(Abbrev)));
+}
+
+// Records
+
+void ClangDocBitcodeWriter::emitRecord(const SymbolID &Sym, RecordId ID) {
+  assert(RecordIdNameMap[ID] && "Unknown RecordId.");
+  assert(RecordIdNameMap[ID].Abbrev == &SymbolIDAbbrev &&
+         "Abbrev type mismatch.");
+  if (!prepRecordData(ID, Sym != EmptySID))
+    return;
+  assert(Sym.size() == 20);
+  Record.push_back(Sym.size());
+  Record.append(Sym.begin(), Sym.end());
+  Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
+}
+
+void ClangDocBitcodeWriter::emitRecord(llvm::StringRef Str, RecordId ID) {
+  assert(RecordIdNameMap[ID] && "Unknown RecordId.");
+  assert(RecordIdNameMap[ID].Abbrev == &StringAbbrev &&
+         "Abbrev type mismatch.");
+  if (!prepRecordData(ID, !Str.empty()))
+    return;
+  assert(Str.size() < (1U << BitCodeConstants::StringLengthSize));
+  Record.push_back(Str.size());
+  Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Str);
+}
+
+void ClangDocBitcodeWriter::emitRecord(const Location &Loc, RecordId ID) {
+  assert(RecordIdNameMap[ID] && "Unknown RecordId.");
+  assert(RecordIdNameMap[ID].Abbrev == &LocationAbbrev &&
+         "Abbrev type mismatch.");
+  if (!prepRecordData(ID, true))
+    return;
+  // FIXME: Assert that the line number is of the appropriate size.
+  Record.push_back(Loc.LineNumber);
+  assert(Loc.Filename.size() < (1U << BitCodeConstants::StringLengthSize));
+  // Record.push_back(Loc.Filename.size());
+  // Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Loc.Filename);
+  Record.push_back(4);
+  Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, "test");
+}
+
+void ClangDocBitcodeWriter::emitRecord(bool Val, RecordId ID) {
+  assert(RecordIdNameMap[ID] && "Unknown RecordId.");
+  assert(RecordIdNameMap[ID].Abbrev == &BoolAbbrev && "Abbrev type mismatch.");
+  if (!prepRecordData(ID, Val))
+    return;
+  Record.push_back(Val);
+  Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
+}
+
+void ClangDocBitcodeWriter::emitRecord(int Val, RecordId ID) {
+  assert(RecordIdNameMap[ID] && "Unknown RecordId.");
+  assert(RecordIdNameMap[ID].Abbrev == &IntAbbrev && "Abbrev type mismatch.");
+  if (!prepRecordData(ID, Val))
+    return;
+  // FIXME: Assert that the integer is of the appropriate size.
+  Record.push_back(Val);
+  Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
+}
+
+void ClangDocBitcodeWriter::emitRecord(unsigned Val, RecordId ID) {
+  assert(RecordIdNameMap[ID] && "Unknown RecordId.");
+  assert(RecordIdNameMap[ID].Abbrev == &IntAbbrev && "Abbrev type mismatch.");
+  if (!prepRecordData(ID, Val))
+    return;
+  assert(Val < (1U << BitCodeConstants::IntSize));
+  Record.push_back(Val);
+  Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
+}
+
+bool ClangDocBitcodeWriter::prepRecordData(RecordId ID, bool ShouldEmit) {
+  assert(RecordIdNameMap[ID] && "Unknown RecordId.");
+  if (!ShouldEmit)
+    return false;
+  Record.clear();
+  Record.push_back(ID);
+  return true;
+}
+
+// BlockInfo Block
+
+void ClangDocBitcodeWriter::emitBlockInfoBlock() {
+  Stream.EnterBlockInfoBlock();
+  for (const auto &Block : RecordsByBlock) {
+    assert(Block.second.size() < (1U << BitCodeConstants::SubblockIDSize));
+    emitBlockInfo(Block.first, Block.second);
+  }
+  Stream.ExitBlock();
+}
+
+void ClangDocBitcodeWriter::emitBlockInfo(BlockId BID,
+                                          const std::vector<RecordId> &RIDs) {
+  assert(RIDs.size() < (1U << BitCodeConstants::SubblockIDSize));
+  emitBlockID(BID);
+  for (RecordId RID : RIDs) {
+    emitRecordID(RID);
+    emitAbbrev(RID, BID);
+  }
+}
+
+// Block emission
+
+void ClangDocBitcodeWriter::emitBlock(const Reference &R, FieldId Field) {
+  if (R.USR == EmptySID && R.Name.empty())
+    return;
+  StreamSubBlockGuard Block(Stream, BI_REFERENCE_BLOCK_ID);
+  emitRecord(R.USR, REFERENCE_USR);
+  emitRecord(R.Name, REFERENCE_NAME);
+  emitRecord((unsigned)R.RefType, REFERENCE_TYPE);
+  emitRecord((unsigned)Field, REFERENCE_FIELD);
+}
+
+void ClangDocBitcodeWriter::emitBlock(const TypeInfo &T) {
+  StreamSubBlockGuard Block(Stream, BI_TYPE_BLOCK_ID);
+  emitBlock(T.Type, FieldId::F_type);
+}
+
+void ClangDocBitcodeWriter::emitBlock(const FieldTypeInfo &T) {
+  StreamSubBlockGuard Block(Stream, BI_FIELD_TYPE_BLOCK_ID);
+  emitBlock(T.Type, FieldId::F_type);
+  emitRecord(T.Name, FIELD_TYPE_NAME);
+}
+
+void ClangDocBitcodeWriter::emitBlock(const MemberTypeInfo &T) {
+  StreamSubBlockGuard Block(Stream, BI_MEMBER_TYPE_BLOCK_ID);
+  emitBlock(T.Type, FieldId::F_type);
+  emitRecord(T.Name, MEMBER_TYPE_NAME);
+  emitRecord(T.Access, MEMBER_TYPE_ACCESS);
+}
+
+void ClangDocBitcodeWriter::emitBlock(const CommentInfo &I) {
+  StreamSubBlockGuard Block(Stream, BI_COMMENT_BLOCK_ID);
+  for (const auto &L : std::vector<std::pair<llvm::StringRef, RecordId>>{
+           {I.Kind, COMMENT_KIND},
+           {I.Text, COMMENT_TEXT},
+           {I.Name, COMMENT_NAME},
+           {I.Direction, COMMENT_DIRECTION},
+           {I.ParamName, COMMENT_PARAMNAME},
+           {I.CloseName, COMMENT_CLOSENAME}})
+    emitRecord(L.first, L.second);
+  emitRecord(I.SelfClosing, COMMENT_SELFCLOSING);
+  emitRecord(I.Explicit, COMMENT_EXPLICIT);
+  for (const auto &A : I.AttrKeys)
+    emitRecord(A, COMMENT_ATTRKEY);
+  for (const auto &A : I.AttrValues)
+    emitRecord(A, COMMENT_ATTRVAL);
+  for (const auto &A : I.Args)
+    emitRecord(A, COMMENT_ARG);
+  for (const auto &C : I.Children)
+    emitBlock(*C);
+}
+
+void ClangDocBitcodeWriter::emitBlock(const NamespaceInfo &I) {
+  StreamSubBlockGuard Block(Stream, BI_NAMESPACE_BLOCK_ID);
+  emitRecord(I.USR, NAMESPACE_USR);
+  emitRecord(I.Name, NAMESPACE_NAME);
+  for (const auto &N : I.Namespace)
+    emitBlock(N, FieldId::F_namespace);
+  for (const auto &CI : I.Description)
+    emitBlock(CI);
+}
+
+void ClangDocBitcodeWriter::emitBlock(const EnumInfo &I) {
+  StreamSubBlockGuard Block(Stream, BI_ENUM_BLOCK_ID);
+  emitRecord(I.USR, ENUM_USR);
+  emitRecord(I.Name, ENUM_NAME);
+  for (const auto &N : I.Namespace)
+    emitBlock(N, FieldId::F_namespace);
+  for (const auto &CI : I.Description)
+    emitBlock(CI);
+  if (I.DefLoc)
+    emitRecord(I.DefLoc.getValue(), ENUM_DEFLOCATION);
+  for (const auto &L : I.Loc)
+    emitRecord(L, ENUM_LOCATION);
+  emitRecord(I.Scoped, ENUM_SCOPED);
+  for (const auto &N : I.Members)
+    emitRecord(N, ENUM_MEMBER);
+}
+
+void ClangDocBitcodeWriter::emitBlock(const RecordInfo &I) {
+  StreamSubBlockGuard Block(Stream, BI_RECORD_BLOCK_ID);
+  emitRecord(I.USR, RECORD_USR);
+  emitRecord(I.Name, RECORD_NAME);
+  for (const auto &N : I.Namespace)
+    emitBlock(N, FieldId::F_namespace);
+  for (const auto &CI : I.Description)
+    emitBlock(CI);
+  if (I.DefLoc)
+    emitRecord(I.DefLoc.getValue(), RECORD_DEFLOCATION);
+  for (const auto &L : I.Loc)
+    emitRecord(L, RECORD_LOCATION);
+  emitRecord(I.TagType, RECORD_TAG_TYPE);
+  for (const auto &N : I.Members)
+    emitBlock(N);
+  for (const auto &P : I.Parents)
+    emitBlock(P, FieldId::F_parent);
+  for (const auto &P : I.VirtualParents)
+    emitBlock(P, FieldId::F_vparent);
+}
+
+void ClangDocBitcodeWriter::emitBlock(const FunctionInfo &I) {
+  StreamSubBlockGuard Block(Stream, BI_FUNCTION_BLOCK_ID);
+  emitRecord(I.USR, FUNCTION_USR);
+  emitRecord(I.Name, FUNCTION_NAME);
+  for (const auto &N : I.Namespace)
+    emitBlock(N, FieldId::F_namespace);
+  for (const auto &CI : I.Description)
+    emitBlock(CI);
+  emitRecord(I.IsMethod, FUNCTION_IS_METHOD);
+  if (I.DefLoc)
+    emitRecord(I.DefLoc.getValue(), FUNCTION_DEFLOCATION);
+  for (const auto &L : I.Loc)
+    emitRecord(L, FUNCTION_LOCATION);
+  emitBlock(I.Parent, FieldId::F_parent);
+  emitBlock(I.ReturnType);
+  for (const auto &N : I.Params)
+    emitBlock(N);
+}
+
+bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) {
+  switch (I->IT) {
+  case InfoType::IT_namespace:
+    emitBlock(*static_cast<clang::doc::NamespaceInfo *>(I));
+    break;
+  case InfoType::IT_record:
+    emitBlock(*static_cast<clang::doc::RecordInfo *>(I));
+    break;
+  case InfoType::IT_enum:
+    emitBlock(*static_cast<clang::doc::EnumInfo *>(I));
+    break;
+  case InfoType::IT_function:
+    emitBlock(*static_cast<clang::doc::FunctionInfo *>(I));
+    break;
+  default:
+    llvm::errs() << "Unexpected info, unable to write.\n";
+    return true;
+  }
+  return false;
+}
+
+} // namespace doc
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/BitcodeWriter.h b/src/third_party/llvm-project/clang-tools-extra/clang-doc/BitcodeWriter.h
new file mode 100644
index 0000000..3d8a68f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/BitcodeWriter.h
@@ -0,0 +1,201 @@
+//===--  BitcodeWriter.h - ClangDoc Bitcode Writer --------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a writer for serializing the clang-doc internal
+// representation to LLVM bitcode. The writer takes in a stream and emits the
+// generated bitcode to that stream.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H
+
+#include "Representation.h"
+#include "clang/AST/AST.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include <initializer_list>
+#include <vector>
+
+namespace clang {
+namespace doc {
+
+// Current version number of clang-doc bitcode.
+// Should be bumped when removing or changing BlockIds, RecordIds, or
+// BitCodeConstants, though they can be added without breaking it.
+static const unsigned VersionNumber = 2;
+
+struct BitCodeConstants {
+  static constexpr unsigned RecordSize = 32U;
+  static constexpr unsigned SignatureBitSize = 8U;
+  static constexpr unsigned SubblockIDSize = 4U;
+  static constexpr unsigned BoolSize = 1U;
+  static constexpr unsigned IntSize = 16U;
+  static constexpr unsigned StringLengthSize = 16U;
+  static constexpr unsigned FilenameLengthSize = 16U;
+  static constexpr unsigned LineNumberSize = 16U;
+  static constexpr unsigned ReferenceTypeSize = 8U;
+  static constexpr unsigned USRLengthSize = 6U;
+  static constexpr unsigned USRBitLengthSize = 8U;
+  static constexpr char Signature[4] = {'D', 'O', 'C', 'S'};
+  static constexpr int USRHashSize = 20;
+};
+
+// New Ids need to be added to both the enum here and the relevant IdNameMap in
+// the implementation file.
+enum BlockId {
+  BI_VERSION_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
+  BI_NAMESPACE_BLOCK_ID,
+  BI_ENUM_BLOCK_ID,
+  BI_TYPE_BLOCK_ID,
+  BI_FIELD_TYPE_BLOCK_ID,
+  BI_MEMBER_TYPE_BLOCK_ID,
+  BI_RECORD_BLOCK_ID,
+  BI_FUNCTION_BLOCK_ID,
+  BI_COMMENT_BLOCK_ID,
+  BI_REFERENCE_BLOCK_ID,
+  BI_LAST,
+  BI_FIRST = BI_VERSION_BLOCK_ID
+};
+
+// New Ids need to be added to the enum here, and to the relevant IdNameMap and
+// initialization list in the implementation file.
+#define INFORECORDS(X) X##_USR, X##_NAME
+
+enum RecordId {
+  VERSION = 1,
+  INFORECORDS(FUNCTION),
+  FUNCTION_DEFLOCATION,
+  FUNCTION_LOCATION,
+  FUNCTION_ACCESS,
+  FUNCTION_IS_METHOD,
+  COMMENT_KIND,
+  COMMENT_TEXT,
+  COMMENT_NAME,
+  COMMENT_DIRECTION,
+  COMMENT_PARAMNAME,
+  COMMENT_CLOSENAME,
+  COMMENT_SELFCLOSING,
+  COMMENT_EXPLICIT,
+  COMMENT_ATTRKEY,
+  COMMENT_ATTRVAL,
+  COMMENT_ARG,
+  FIELD_TYPE_NAME,
+  MEMBER_TYPE_NAME,
+  MEMBER_TYPE_ACCESS,
+  INFORECORDS(NAMESPACE),
+  INFORECORDS(ENUM),
+  ENUM_DEFLOCATION,
+  ENUM_LOCATION,
+  ENUM_MEMBER,
+  ENUM_SCOPED,
+  INFORECORDS(RECORD),
+  RECORD_DEFLOCATION,
+  RECORD_LOCATION,
+  RECORD_TAG_TYPE,
+  REFERENCE_USR,
+  REFERENCE_NAME,
+  REFERENCE_TYPE,
+  REFERENCE_FIELD,
+  RI_LAST,
+  RI_FIRST = VERSION
+};
+
+static constexpr unsigned BlockIdCount = BI_LAST - BI_FIRST;
+static constexpr unsigned RecordIdCount = RI_LAST - RI_FIRST;
+
+#undef INFORECORDS
+
+// Identifiers for differentiating between subblocks
+enum class FieldId { F_default, F_namespace, F_parent, F_vparent, F_type };
+
+class ClangDocBitcodeWriter {
+public:
+  ClangDocBitcodeWriter(llvm::BitstreamWriter &Stream) : Stream(Stream) {
+    emitHeader();
+    emitBlockInfoBlock();
+    emitVersionBlock();
+  }
+
+  // Write a specific info to a bitcode stream.
+  bool dispatchInfoForWrite(Info *I);
+
+  // Block emission of different info types.
+  void emitBlock(const NamespaceInfo &I);
+  void emitBlock(const RecordInfo &I);
+  void emitBlock(const FunctionInfo &I);
+  void emitBlock(const EnumInfo &I);
+  void emitBlock(const TypeInfo &B);
+  void emitBlock(const FieldTypeInfo &B);
+  void emitBlock(const MemberTypeInfo &B);
+  void emitBlock(const CommentInfo &B);
+  void emitBlock(const Reference &B, FieldId F);
+
+private:
+  class AbbreviationMap {
+    llvm::DenseMap<unsigned, unsigned> Abbrevs;
+
+  public:
+    AbbreviationMap() : Abbrevs(RecordIdCount) {}
+
+    void add(RecordId RID, unsigned AbbrevID);
+    unsigned get(RecordId RID) const;
+  };
+
+  class StreamSubBlockGuard {
+    llvm::BitstreamWriter &Stream;
+
+  public:
+    StreamSubBlockGuard(llvm::BitstreamWriter &Stream_, BlockId ID)
+        : Stream(Stream_) {
+      // NOTE: SubBlockIDSize could theoretically be calculated on the fly,
+      // based on the initialization list of records in each block.
+      Stream.EnterSubblock(ID, BitCodeConstants::SubblockIDSize);
+    }
+
+    StreamSubBlockGuard(const StreamSubBlockGuard &) = delete;
+    StreamSubBlockGuard &operator=(const StreamSubBlockGuard &) = delete;
+
+    ~StreamSubBlockGuard() { Stream.ExitBlock(); }
+  };
+
+  // Emission of validation and overview blocks.
+  void emitHeader();
+  void emitVersionBlock();
+  void emitRecordID(RecordId ID);
+  void emitBlockID(BlockId ID);
+  void emitBlockInfoBlock();
+  void emitBlockInfo(BlockId BID, const std::vector<RecordId> &RIDs);
+
+  // Emission of individual record types.
+  void emitRecord(StringRef Str, RecordId ID);
+  void emitRecord(const SymbolID &Str, RecordId ID);
+  void emitRecord(const Location &Loc, RecordId ID);
+  void emitRecord(const Reference &Ref, RecordId ID);
+  void emitRecord(bool Value, RecordId ID);
+  void emitRecord(int Value, RecordId ID);
+  void emitRecord(unsigned Value, RecordId ID);
+  bool prepRecordData(RecordId ID, bool ShouldEmit = true);
+
+  // Emission of appropriate abbreviation type.
+  void emitAbbrev(RecordId ID, BlockId Block);
+
+  // Static size is the maximum length of the block/record names we're pushing
+  // to this + 1. Longest is currently `MemberTypeBlock` at 15 chars.
+  SmallVector<uint32_t, BitCodeConstants::RecordSize> Record;
+  llvm::BitstreamWriter &Stream;
+  AbbreviationMap Abbrevs;
+};
+
+} // namespace doc
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-doc/CMakeLists.txt
new file mode 100644
index 0000000..eaebf61
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/CMakeLists.txt
@@ -0,0 +1,29 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  BitReader
+  BitWriter
+  )
+
+add_clang_library(clangDoc
+  BitcodeReader.cpp
+  BitcodeWriter.cpp
+  ClangDoc.cpp
+  Generators.cpp
+  Mapper.cpp
+  Representation.cpp
+  Serialize.cpp
+  YAMLGenerator.cpp
+
+  LINK_LIBS
+  clangAnalysis
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFrontend
+  clangIndex
+  clangLex
+  clangTooling
+  clangToolingCore
+  )
+
+add_subdirectory(tool)
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/ClangDoc.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-doc/ClangDoc.cpp
new file mode 100644
index 0000000..a11c584
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/ClangDoc.cpp
@@ -0,0 +1,62 @@
+//===-- ClangDoc.cpp - ClangDoc ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the main entry point for the clang-doc tool. It runs
+// the clang-doc mapper on a given set of source code files using a
+// FrontendActionFactory.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangDoc.h"
+#include "Mapper.h"
+#include "Representation.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Frontend/ASTConsumers.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+
+namespace clang {
+namespace doc {
+
+class MapperActionFactory : public tooling::FrontendActionFactory {
+public:
+  MapperActionFactory(ClangDocContext CDCtx) : CDCtx(CDCtx) {}
+  clang::FrontendAction *create() override;
+
+private:
+  ClangDocContext CDCtx;
+};
+
+clang::FrontendAction *MapperActionFactory::create() {
+  class ClangDocAction : public clang::ASTFrontendAction {
+  public:
+    ClangDocAction(ClangDocContext CDCtx) : CDCtx(CDCtx) {}
+
+    std::unique_ptr<clang::ASTConsumer>
+    CreateASTConsumer(clang::CompilerInstance &Compiler,
+                      llvm::StringRef InFile) override {
+      return llvm::make_unique<MapASTVisitor>(&Compiler.getASTContext(), CDCtx);
+    }
+
+  private:
+    ClangDocContext CDCtx;
+  };
+  return new ClangDocAction(CDCtx);
+}
+
+std::unique_ptr<tooling::FrontendActionFactory>
+newMapperActionFactory(ClangDocContext CDCtx) {
+  return llvm::make_unique<MapperActionFactory>(CDCtx);
+}
+
+} // namespace doc
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/ClangDoc.h b/src/third_party/llvm-project/clang-tools-extra/clang-doc/ClangDoc.h
new file mode 100644
index 0000000..59e9a92
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/ClangDoc.h
@@ -0,0 +1,34 @@
+//===-- ClangDoc.h - ClangDoc -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file exposes a method to craete the FrontendActionFactory for the
+// clang-doc tool. The factory runs the clang-doc mapper on a given set of
+// source code files, storing the results key-value pairs in its
+// ExecutionContext.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_CLANGDOC_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_CLANGDOC_H
+
+#include "Representation.h"
+#include "clang/Tooling/Execution.h"
+#include "clang/Tooling/StandaloneExecution.h"
+#include "clang/Tooling/Tooling.h"
+
+namespace clang {
+namespace doc {
+
+std::unique_ptr<tooling::FrontendActionFactory>
+newMapperActionFactory(ClangDocContext CDCtx);
+
+} // namespace doc
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_CLANGDOC_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/Generators.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Generators.cpp
new file mode 100644
index 0000000..fe01d61
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Generators.cpp
@@ -0,0 +1,36 @@
+//===---- Generator.cpp - Generator Registry ---------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Generators.h"
+
+LLVM_INSTANTIATE_REGISTRY(clang::doc::GeneratorRegistry)
+
+namespace clang {
+namespace doc {
+
+llvm::Expected<std::unique_ptr<Generator>>
+findGeneratorByName(llvm::StringRef Format) {
+  for (auto I = GeneratorRegistry::begin(), E = GeneratorRegistry::end();
+       I != E; ++I) {
+    if (I->getName() != Format)
+      continue;
+    return I->instantiate();
+  }
+  return llvm::make_error<llvm::StringError>("Can't find generator: " + Format,
+                                             llvm::inconvertibleErrorCode());
+}
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the generators.
+extern volatile int YAMLGeneratorAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED YAMLGeneratorAnchorDest =
+    YAMLGeneratorAnchorSource;
+
+} // namespace doc
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/Generators.h b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Generators.h
new file mode 100644
index 0000000..9106d2c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Generators.h
@@ -0,0 +1,41 @@
+//===-- Generators.h - ClangDoc Generator ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Generator classes for converting declaration information into documentation
+// in a specified format.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_GENERATOR_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_GENERATOR_H
+
+#include "Representation.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Registry.h"
+
+namespace clang {
+namespace doc {
+
+// Abstract base class for generators.
+// This is expected to be implemented and exposed via the GeneratorRegistry.
+class Generator {
+public:
+  virtual ~Generator() = default;
+
+  // Write out the decl info in the specified format.
+  virtual bool generateDocForInfo(Info *I, llvm::raw_ostream &OS) = 0;
+};
+
+typedef llvm::Registry<Generator> GeneratorRegistry;
+
+llvm::Expected<std::unique_ptr<Generator>>
+findGeneratorByName(llvm::StringRef Format);
+
+} // namespace doc
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_GENERATOR_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/Mapper.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Mapper.cpp
new file mode 100644
index 0000000..fb0b42a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Mapper.cpp
@@ -0,0 +1,90 @@
+//===-- Mapper.cpp - ClangDoc Mapper ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Mapper.h"
+#include "BitcodeWriter.h"
+#include "Serialize.h"
+#include "clang/AST/Comment.h"
+#include "clang/Index/USRGeneration.h"
+#include "llvm/ADT/StringExtras.h"
+
+using clang::comments::FullComment;
+
+namespace clang {
+namespace doc {
+
+void MapASTVisitor::HandleTranslationUnit(ASTContext &Context) {
+  TraverseDecl(Context.getTranslationUnitDecl());
+}
+
+template <typename T> bool MapASTVisitor::mapDecl(const T *D) {
+  // If we're looking a decl not in user files, skip this decl.
+  if (D->getASTContext().getSourceManager().isInSystemHeader(D->getLocation()))
+    return true;
+
+  llvm::SmallString<128> USR;
+  // If there is an error generating a USR for the decl, skip this decl.
+  if (index::generateUSRForDecl(D, USR))
+    return true;
+
+  std::string info = serialize::emitInfo(
+      D, getComment(D, D->getASTContext()), getLine(D, D->getASTContext()),
+      getFile(D, D->getASTContext()), CDCtx.PublicOnly);
+
+  if (info != "")
+    CDCtx.ECtx->reportResult(
+        llvm::toHex(llvm::toStringRef(serialize::hashUSR(USR))), info);
+
+  return true;
+}
+
+bool MapASTVisitor::VisitNamespaceDecl(const NamespaceDecl *D) {
+  return mapDecl(D);
+}
+
+bool MapASTVisitor::VisitRecordDecl(const RecordDecl *D) { return mapDecl(D); }
+
+bool MapASTVisitor::VisitEnumDecl(const EnumDecl *D) { return mapDecl(D); }
+
+bool MapASTVisitor::VisitCXXMethodDecl(const CXXMethodDecl *D) {
+  return mapDecl(D);
+}
+
+bool MapASTVisitor::VisitFunctionDecl(const FunctionDecl *D) {
+  // Don't visit CXXMethodDecls twice
+  if (dyn_cast<CXXMethodDecl>(D))
+    return true;
+  return mapDecl(D);
+}
+
+comments::FullComment *
+MapASTVisitor::getComment(const NamedDecl *D, const ASTContext &Context) const {
+  RawComment *Comment = Context.getRawCommentForDeclNoCache(D);
+  // FIXME: Move setAttached to the initial comment parsing.
+  if (Comment) {
+    Comment->setAttached();
+    return Comment->parse(Context, nullptr, D);
+  }
+  return nullptr;
+}
+
+int MapASTVisitor::getLine(const NamedDecl *D,
+                           const ASTContext &Context) const {
+  return Context.getSourceManager().getPresumedLoc(D->getLocStart()).getLine();
+}
+
+llvm::StringRef MapASTVisitor::getFile(const NamedDecl *D,
+                                       const ASTContext &Context) const {
+  return Context.getSourceManager()
+      .getPresumedLoc(D->getLocStart())
+      .getFilename();
+}
+
+} // namespace doc
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/Mapper.h b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Mapper.h
new file mode 100644
index 0000000..a0b1ac2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Mapper.h
@@ -0,0 +1,58 @@
+//===-- Mapper.h - ClangDoc Mapper ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Mapper piece of the clang-doc tool. It implements
+// a RecursiveASTVisitor to look at each declaration and populate the info
+// into the internal representation. Each seen declaration is serialized to
+// to bitcode and written out to the ExecutionContext as a KV pair where the
+// key is the declaration's USR and the value is the serialized bitcode.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_MAPPER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_MAPPER_H
+
+#include "Representation.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Tooling/Execution.h"
+
+using namespace clang::comments;
+using namespace clang::tooling;
+
+namespace clang {
+namespace doc {
+
+class MapASTVisitor : public clang::RecursiveASTVisitor<MapASTVisitor>,
+                      public ASTConsumer {
+public:
+  explicit MapASTVisitor(ASTContext *Ctx, ClangDocContext CDCtx)
+      : CDCtx(CDCtx) {}
+
+  void HandleTranslationUnit(ASTContext &Context) override;
+  bool VisitNamespaceDecl(const NamespaceDecl *D);
+  bool VisitRecordDecl(const RecordDecl *D);
+  bool VisitEnumDecl(const EnumDecl *D);
+  bool VisitCXXMethodDecl(const CXXMethodDecl *D);
+  bool VisitFunctionDecl(const FunctionDecl *D);
+
+private:
+  template <typename T> bool mapDecl(const T *D);
+
+  int getLine(const NamedDecl *D, const ASTContext &Context) const;
+  StringRef getFile(const NamedDecl *D, const ASTContext &Context) const;
+  comments::FullComment *getComment(const NamedDecl *D,
+                                    const ASTContext &Context) const;
+
+  ClangDocContext CDCtx;
+};
+
+} // namespace doc
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_MAPPER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/Representation.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Representation.cpp
new file mode 100644
index 0000000..6107b98
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Representation.cpp
@@ -0,0 +1,131 @@
+///===-- Representation.cpp - ClangDoc Representation -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the merging of different types of infos. The data in the
+// calling Info is preserved during a merge unless that field is empty or
+// default. In that case, the data from the parameter Info is used to replace
+// the empty or default data.
+//
+// For most fields, the first decl seen provides the data. Exceptions to this
+// include the location and description fields, which are collections of data on
+// all decls related to a given definition. All other fields are ignored in new
+// decls unless the first seen decl didn't, for whatever reason, incorporate
+// data on that field (e.g. a forward declared class wouldn't have information
+// on members on the forward declaration, but would have the class name).
+//
+//===----------------------------------------------------------------------===//
+#include "Representation.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace doc {
+
+static const SymbolID EmptySID = SymbolID();
+
+template <typename T>
+std::unique_ptr<Info> reduce(std::vector<std::unique_ptr<Info>> &Values) {
+  std::unique_ptr<Info> Merged = llvm::make_unique<T>();
+  T *Tmp = static_cast<T *>(Merged.get());
+  for (auto &I : Values)
+    Tmp->merge(std::move(*static_cast<T *>(I.get())));
+  return Merged;
+}
+
+// Dispatch function.
+llvm::Expected<std::unique_ptr<Info>>
+mergeInfos(std::vector<std::unique_ptr<Info>> &Values) {
+  if (Values.empty())
+    return llvm::make_error<llvm::StringError>("No info values to merge.\n",
+                                               llvm::inconvertibleErrorCode());
+
+  switch (Values[0]->IT) {
+  case InfoType::IT_namespace:
+    return reduce<NamespaceInfo>(Values);
+  case InfoType::IT_record:
+    return reduce<RecordInfo>(Values);
+  case InfoType::IT_enum:
+    return reduce<EnumInfo>(Values);
+  case InfoType::IT_function:
+    return reduce<FunctionInfo>(Values);
+  default:
+    return llvm::make_error<llvm::StringError>("Unexpected info type.\n",
+                                               llvm::inconvertibleErrorCode());
+  }
+}
+
+void Info::mergeBase(Info &&Other) {
+  assert(mergeable(Other));
+  if (USR == EmptySID)
+    USR = Other.USR;
+  if (Name == "")
+    Name = Other.Name;
+  if (Namespace.empty())
+    Namespace = std::move(Other.Namespace);
+  // Unconditionally extend the description, since each decl may have a comment.
+  std::move(Other.Description.begin(), Other.Description.end(),
+            std::back_inserter(Description));
+}
+
+bool Info::mergeable(const Info &Other) {
+  return IT == Other.IT && (USR == EmptySID || USR == Other.USR);
+}
+
+void SymbolInfo::merge(SymbolInfo &&Other) {
+  assert(mergeable(Other));
+  if (!DefLoc)
+    DefLoc = std::move(Other.DefLoc);
+  // Unconditionally extend the list of locations, since we want all of them.
+  std::move(Other.Loc.begin(), Other.Loc.end(), std::back_inserter(Loc));
+  mergeBase(std::move(Other));
+}
+
+void NamespaceInfo::merge(NamespaceInfo &&Other) {
+  assert(mergeable(Other));
+  mergeBase(std::move(Other));
+}
+
+void RecordInfo::merge(RecordInfo &&Other) {
+  assert(mergeable(Other));
+  if (!TagType)
+    TagType = Other.TagType;
+  if (Members.empty())
+    Members = std::move(Other.Members);
+  if (Parents.empty())
+    Parents = std::move(Other.Parents);
+  if (VirtualParents.empty())
+    VirtualParents = std::move(Other.VirtualParents);
+  SymbolInfo::merge(std::move(Other));
+}
+
+void EnumInfo::merge(EnumInfo &&Other) {
+  assert(mergeable(Other));
+  if (!Scoped)
+    Scoped = Other.Scoped;
+  if (Members.empty())
+    Members = std::move(Other.Members);
+  SymbolInfo::merge(std::move(Other));
+}
+
+void FunctionInfo::merge(FunctionInfo &&Other) {
+  assert(mergeable(Other));
+  if (!IsMethod)
+    IsMethod = Other.IsMethod;
+  if (!Access)
+    Access = Other.Access;
+  if (ReturnType.Type.USR == EmptySID && ReturnType.Type.Name == "")
+    ReturnType = std::move(Other.ReturnType);
+  if (Parent.USR == EmptySID && Parent.Name == "")
+    Parent = std::move(Other.Parent);
+  if (Params.empty())
+    Params = std::move(Other.Params);
+  SymbolInfo::merge(std::move(Other));
+}
+
+} // namespace doc
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/Representation.h b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Representation.h
new file mode 100644
index 0000000..f952954
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Representation.h
@@ -0,0 +1,251 @@
+///===-- Representation.h - ClangDoc Representation -------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the internal representations of different declaration
+// types for the clang-doc tool.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H
+
+#include "clang/AST/Type.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Tooling/StandaloneExecution.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include <array>
+#include <string>
+
+namespace clang {
+namespace doc {
+
+// SHA1'd hash of a USR.
+using SymbolID = std::array<uint8_t, 20>;
+
+struct Info;
+enum class InfoType {
+  IT_default,
+  IT_namespace,
+  IT_record,
+  IT_function,
+  IT_enum
+};
+
+// A representation of a parsed comment.
+struct CommentInfo {
+  CommentInfo() = default;
+  CommentInfo(CommentInfo &Other) = delete;
+  CommentInfo(CommentInfo &&Other) = default;
+
+  SmallString<16> Kind; // Kind of comment (TextComment, InlineCommandComment,
+                        // HTMLStartTagComment, HTMLEndTagComment,
+                        // BlockCommandComment, ParamCommandComment,
+                        // TParamCommandComment, VerbatimBlockComment,
+                        // VerbatimBlockLineComment, VerbatimLineComment).
+  SmallString<64> Text; // Text of the comment.
+  SmallString<16> Name; // Name of the comment (for Verbatim and HTML).
+  SmallString<8> Direction;  // Parameter direction (for (T)ParamCommand).
+  SmallString<16> ParamName; // Parameter name (for (T)ParamCommand).
+  SmallString<16> CloseName; // Closing tag name (for VerbatimBlock).
+  bool SelfClosing = false;  // Indicates if tag is self-closing (for HTML).
+  bool Explicit = false; // Indicates if the direction of a param is explicit
+                         // (for (T)ParamCommand).
+  llvm::SmallVector<SmallString<16>, 4>
+      AttrKeys; // List of attribute keys (for HTML).
+  llvm::SmallVector<SmallString<16>, 4>
+      AttrValues; // List of attribute values for each key (for HTML).
+  llvm::SmallVector<SmallString<16>, 4>
+      Args; // List of arguments to commands (for InlineCommand).
+  std::vector<std::unique_ptr<CommentInfo>>
+      Children; // List of child comments for this CommentInfo.
+};
+
+struct Reference {
+  Reference() = default;
+  Reference(llvm::StringRef Name) : Name(Name) {}
+  Reference(SymbolID USR, StringRef Name, InfoType IT)
+      : USR(USR), Name(Name), RefType(IT) {}
+
+  bool operator==(const Reference &Other) const {
+    return std::tie(USR, Name, RefType) ==
+           std::tie(Other.USR, Other.Name, Other.RefType);
+  }
+
+  SymbolID USR = SymbolID(); // Unique identifer for referenced decl
+  SmallString<16> Name;      // Name of type (possibly unresolved).
+  InfoType RefType = InfoType::IT_default; // Indicates the type of this
+                                           // Reference (namespace, record,
+                                           // function, enum, default).
+};
+
+// A base struct for TypeInfos
+struct TypeInfo {
+  TypeInfo() = default;
+  TypeInfo(SymbolID Type, StringRef Field, InfoType IT)
+      : Type(Type, Field, IT) {}
+  TypeInfo(llvm::StringRef RefName) : Type(RefName) {}
+
+  bool operator==(const TypeInfo &Other) const { return Type == Other.Type; }
+
+  Reference Type; // Referenced type in this info.
+};
+
+// Info for field types.
+struct FieldTypeInfo : public TypeInfo {
+  FieldTypeInfo() = default;
+  FieldTypeInfo(SymbolID Type, StringRef Field, InfoType IT,
+                llvm::StringRef Name)
+      : TypeInfo(Type, Field, IT), Name(Name) {}
+  FieldTypeInfo(llvm::StringRef RefName, llvm::StringRef Name)
+      : TypeInfo(RefName), Name(Name) {}
+
+  bool operator==(const FieldTypeInfo &Other) const {
+    return std::tie(Type, Name) == std::tie(Other.Type, Other.Name);
+  }
+
+  SmallString<16> Name; // Name associated with this info.
+};
+
+// Info for member types.
+struct MemberTypeInfo : public FieldTypeInfo {
+  MemberTypeInfo() = default;
+  MemberTypeInfo(SymbolID Type, StringRef Field, InfoType IT,
+                 llvm::StringRef Name, AccessSpecifier Access)
+      : FieldTypeInfo(Type, Field, IT, Name), Access(Access) {}
+  MemberTypeInfo(llvm::StringRef RefName, llvm::StringRef Name,
+                 AccessSpecifier Access)
+      : FieldTypeInfo(RefName, Name), Access(Access) {}
+
+  bool operator==(const MemberTypeInfo &Other) const {
+    return std::tie(Type, Name, Access) ==
+           std::tie(Other.Type, Other.Name, Other.Access);
+  }
+
+  AccessSpecifier Access = AccessSpecifier::AS_none; // Access level associated
+                                                     // with this info (public,
+                                                     // protected, private,
+                                                     // none).
+};
+
+struct Location {
+  Location() = default;
+  Location(int LineNumber, SmallString<16> Filename)
+      : LineNumber(LineNumber), Filename(std::move(Filename)) {}
+
+  bool operator==(const Location &Other) const {
+    return std::tie(LineNumber, Filename) ==
+           std::tie(Other.LineNumber, Other.Filename);
+  }
+
+  int LineNumber;           // Line number of this Location.
+  SmallString<32> Filename; // File for this Location.
+};
+
+/// A base struct for Infos.
+struct Info {
+  Info() = default;
+  Info(InfoType IT) : IT(IT) {}
+  Info(const Info &Other) = delete;
+  Info(Info &&Other) = default;
+
+  SymbolID USR =
+      SymbolID(); // Unique identifier for the decl described by this Info.
+  const InfoType IT = InfoType::IT_default; // InfoType of this particular Info.
+  SmallString<16> Name;                     // Unqualified name of the decl.
+  llvm::SmallVector<Reference, 4>
+      Namespace; // List of parent namespaces for this decl.
+  std::vector<CommentInfo> Description; // Comment description of this decl.
+
+  void mergeBase(Info &&I);
+  bool mergeable(const Info &Other);
+};
+
+// Info for namespaces.
+struct NamespaceInfo : public Info {
+  NamespaceInfo() : Info(InfoType::IT_namespace) {}
+
+  void merge(NamespaceInfo &&I);
+};
+
+// Info for symbols.
+struct SymbolInfo : public Info {
+  SymbolInfo(InfoType IT) : Info(IT) {}
+
+  void merge(SymbolInfo &&I);
+
+  llvm::Optional<Location> DefLoc;    // Location where this decl is defined.
+  llvm::SmallVector<Location, 2> Loc; // Locations where this decl is declared.
+};
+
+// TODO: Expand to allow for documenting templating and default args.
+// Info for functions.
+struct FunctionInfo : public SymbolInfo {
+  FunctionInfo() : SymbolInfo(InfoType::IT_function) {}
+
+  void merge(FunctionInfo &&I);
+
+  bool IsMethod = false; // Indicates whether this function is a class method.
+  Reference Parent;      // Reference to the parent class decl for this method.
+  TypeInfo ReturnType;   // Info about the return type of this function.
+  llvm::SmallVector<FieldTypeInfo, 4> Params; // List of parameters.
+  // Access level for this method (public, private, protected, none).
+  AccessSpecifier Access = AccessSpecifier::AS_none;
+};
+
+// TODO: Expand to allow for documenting templating, inheritance access,
+// friend classes
+// Info for types.
+struct RecordInfo : public SymbolInfo {
+  RecordInfo() : SymbolInfo(InfoType::IT_record) {}
+
+  void merge(RecordInfo &&I);
+
+  TagTypeKind TagType = TagTypeKind::TTK_Struct; // Type of this record
+                                                 // (struct, class, union,
+                                                 // interface).
+  llvm::SmallVector<MemberTypeInfo, 4>
+      Members;                             // List of info about record members.
+  llvm::SmallVector<Reference, 4> Parents; // List of base/parent records
+                                           // (does not include virtual
+                                           // parents).
+  llvm::SmallVector<Reference, 4>
+      VirtualParents; // List of virtual base/parent records.
+};
+
+// TODO: Expand to allow for documenting templating.
+// Info for types.
+struct EnumInfo : public SymbolInfo {
+  EnumInfo() : SymbolInfo(InfoType::IT_enum) {}
+
+  void merge(EnumInfo &&I);
+
+  bool Scoped =
+      false; // Indicates whether this enum is scoped (e.g. enum class).
+  llvm::SmallVector<SmallString<16>, 4> Members; // List of enum members.
+};
+
+// TODO: Add functionality to include separate markdown pages.
+
+// A standalone function to call to merge a vector of infos into one.
+// This assumes that all infos in the vector are of the same type, and will fail
+// if they are different.
+llvm::Expected<std::unique_ptr<Info>>
+mergeInfos(std::vector<std::unique_ptr<Info>> &Values);
+
+struct ClangDocContext {
+  tooling::ExecutionContext *ECtx;
+  bool PublicOnly;
+};
+
+} // namespace doc
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/Serialize.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Serialize.cpp
new file mode 100644
index 0000000..c1e6d31
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Serialize.cpp
@@ -0,0 +1,368 @@
+//===-- Serializer.cpp - ClangDoc Serializer --------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Serialize.h"
+#include "BitcodeWriter.h"
+#include "clang/AST/Comment.h"
+#include "clang/Index/USRGeneration.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/SHA1.h"
+
+using clang::comments::FullComment;
+
+namespace clang {
+namespace doc {
+namespace serialize {
+
+SymbolID hashUSR(llvm::StringRef USR) {
+  return llvm::SHA1::hash(arrayRefFromStringRef(USR));
+}
+
+class ClangDocCommentVisitor
+    : public ConstCommentVisitor<ClangDocCommentVisitor> {
+public:
+  ClangDocCommentVisitor(CommentInfo &CI) : CurrentCI(CI) {}
+
+  void parseComment(const comments::Comment *C);
+
+  void visitTextComment(const TextComment *C);
+  void visitInlineCommandComment(const InlineCommandComment *C);
+  void visitHTMLStartTagComment(const HTMLStartTagComment *C);
+  void visitHTMLEndTagComment(const HTMLEndTagComment *C);
+  void visitBlockCommandComment(const BlockCommandComment *C);
+  void visitParamCommandComment(const ParamCommandComment *C);
+  void visitTParamCommandComment(const TParamCommandComment *C);
+  void visitVerbatimBlockComment(const VerbatimBlockComment *C);
+  void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
+  void visitVerbatimLineComment(const VerbatimLineComment *C);
+
+private:
+  std::string getCommandName(unsigned CommandID) const;
+  bool isWhitespaceOnly(StringRef S) const;
+
+  CommentInfo &CurrentCI;
+};
+
+void ClangDocCommentVisitor::parseComment(const comments::Comment *C) {
+  CurrentCI.Kind = C->getCommentKindName();
+  ConstCommentVisitor<ClangDocCommentVisitor>::visit(C);
+  for (comments::Comment *Child :
+       llvm::make_range(C->child_begin(), C->child_end())) {
+    CurrentCI.Children.emplace_back(llvm::make_unique<CommentInfo>());
+    ClangDocCommentVisitor Visitor(*CurrentCI.Children.back());
+    Visitor.parseComment(Child);
+  }
+}
+
+void ClangDocCommentVisitor::visitTextComment(const TextComment *C) {
+  if (!isWhitespaceOnly(C->getText()))
+    CurrentCI.Text = C->getText();
+}
+
+void ClangDocCommentVisitor::visitInlineCommandComment(
+    const InlineCommandComment *C) {
+  CurrentCI.Name = getCommandName(C->getCommandID());
+  for (unsigned I = 0, E = C->getNumArgs(); I != E; ++I)
+    CurrentCI.Args.push_back(C->getArgText(I));
+}
+
+void ClangDocCommentVisitor::visitHTMLStartTagComment(
+    const HTMLStartTagComment *C) {
+  CurrentCI.Name = C->getTagName();
+  CurrentCI.SelfClosing = C->isSelfClosing();
+  for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I) {
+    const HTMLStartTagComment::Attribute &Attr = C->getAttr(I);
+    CurrentCI.AttrKeys.push_back(Attr.Name);
+    CurrentCI.AttrValues.push_back(Attr.Value);
+  }
+}
+
+void ClangDocCommentVisitor::visitHTMLEndTagComment(
+    const HTMLEndTagComment *C) {
+  CurrentCI.Name = C->getTagName();
+  CurrentCI.SelfClosing = true;
+}
+
+void ClangDocCommentVisitor::visitBlockCommandComment(
+    const BlockCommandComment *C) {
+  CurrentCI.Name = getCommandName(C->getCommandID());
+  for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
+    CurrentCI.Args.push_back(C->getArgText(I));
+}
+
+void ClangDocCommentVisitor::visitParamCommandComment(
+    const ParamCommandComment *C) {
+  CurrentCI.Direction =
+      ParamCommandComment::getDirectionAsString(C->getDirection());
+  CurrentCI.Explicit = C->isDirectionExplicit();
+  if (C->hasParamName())
+    CurrentCI.ParamName = C->getParamNameAsWritten();
+}
+
+void ClangDocCommentVisitor::visitTParamCommandComment(
+    const TParamCommandComment *C) {
+  if (C->hasParamName())
+    CurrentCI.ParamName = C->getParamNameAsWritten();
+}
+
+void ClangDocCommentVisitor::visitVerbatimBlockComment(
+    const VerbatimBlockComment *C) {
+  CurrentCI.Name = getCommandName(C->getCommandID());
+  CurrentCI.CloseName = C->getCloseName();
+}
+
+void ClangDocCommentVisitor::visitVerbatimBlockLineComment(
+    const VerbatimBlockLineComment *C) {
+  if (!isWhitespaceOnly(C->getText()))
+    CurrentCI.Text = C->getText();
+}
+
+void ClangDocCommentVisitor::visitVerbatimLineComment(
+    const VerbatimLineComment *C) {
+  if (!isWhitespaceOnly(C->getText()))
+    CurrentCI.Text = C->getText();
+}
+
+bool ClangDocCommentVisitor::isWhitespaceOnly(llvm::StringRef S) const {
+  return std::all_of(S.begin(), S.end(), isspace);
+}
+
+std::string ClangDocCommentVisitor::getCommandName(unsigned CommandID) const {
+  const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID);
+  if (Info)
+    return Info->Name;
+  // TODO: Add parsing for \file command.
+  return "<not a builtin command>";
+}
+
+// Serializing functions.
+
+template <typename T> static std::string serialize(T &I) {
+  SmallString<2048> Buffer;
+  llvm::BitstreamWriter Stream(Buffer);
+  ClangDocBitcodeWriter Writer(Stream);
+  Writer.emitBlock(I);
+  return Buffer.str().str();
+}
+
+static void parseFullComment(const FullComment *C, CommentInfo &CI) {
+  ClangDocCommentVisitor Visitor(CI);
+  Visitor.parseComment(C);
+}
+
+static SymbolID getUSRForDecl(const Decl *D) {
+  llvm::SmallString<128> USR;
+  if (index::generateUSRForDecl(D, USR))
+    return SymbolID();
+  return hashUSR(USR);
+}
+
+static RecordDecl *getDeclForType(const QualType &T) {
+  auto *Ty = T->getAs<RecordType>();
+  if (!Ty)
+    return nullptr;
+  return Ty->getDecl()->getDefinition();
+}
+
+static bool isPublic(const clang::AccessSpecifier AS,
+                     const clang::Linkage Link) {
+  if (AS == clang::AccessSpecifier::AS_private)
+    return false;
+  else if ((Link == clang::Linkage::ModuleLinkage) ||
+           (Link == clang::Linkage::ExternalLinkage))
+    return true;
+  return false; // otherwise, linkage is some form of internal linkage
+}
+
+static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly) {
+  for (const FieldDecl *F : D->fields()) {
+    if (PublicOnly && !isPublic(F->getAccessUnsafe(), F->getLinkageInternal()))
+      continue;
+    if (const auto *T = getDeclForType(F->getTypeSourceInfo()->getType())) {
+      // Use getAccessUnsafe so that we just get the default AS_none if it's not
+      // valid, as opposed to an assert.
+      if (const auto *N = dyn_cast<EnumDecl>(T)) {
+        I.Members.emplace_back(getUSRForDecl(T), N->getNameAsString(),
+                               InfoType::IT_enum, F->getNameAsString(),
+                               N->getAccessUnsafe());
+        continue;
+      } else if (const auto *N = dyn_cast<RecordDecl>(T)) {
+        I.Members.emplace_back(getUSRForDecl(T), N->getNameAsString(),
+                               InfoType::IT_record, F->getNameAsString(),
+                               N->getAccessUnsafe());
+        continue;
+      }
+    }
+    I.Members.emplace_back(F->getTypeSourceInfo()->getType().getAsString(),
+                           F->getNameAsString(), F->getAccessUnsafe());
+  }
+}
+
+static void parseEnumerators(EnumInfo &I, const EnumDecl *D) {
+  for (const EnumConstantDecl *E : D->enumerators())
+    I.Members.emplace_back(E->getNameAsString());
+}
+
+static void parseParameters(FunctionInfo &I, const FunctionDecl *D) {
+  for (const ParmVarDecl *P : D->parameters()) {
+    if (const auto *T = getDeclForType(P->getOriginalType())) {
+      if (const auto *N = dyn_cast<EnumDecl>(T)) {
+        I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
+                              InfoType::IT_enum, P->getNameAsString());
+        continue;
+      } else if (const auto *N = dyn_cast<RecordDecl>(T)) {
+        I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
+                              InfoType::IT_record, P->getNameAsString());
+        continue;
+      }
+    }
+    I.Params.emplace_back(P->getOriginalType().getAsString(),
+                          P->getNameAsString());
+  }
+}
+
+static void parseBases(RecordInfo &I, const CXXRecordDecl *D) {
+  for (const CXXBaseSpecifier &B : D->bases()) {
+    if (B.isVirtual())
+      continue;
+    if (const auto *P = getDeclForType(B.getType()))
+      I.Parents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
+                             InfoType::IT_record);
+    else
+      I.Parents.emplace_back(B.getType().getAsString());
+  }
+  for (const CXXBaseSpecifier &B : D->vbases()) {
+    if (const auto *P = getDeclForType(B.getType()))
+      I.VirtualParents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
+                                    InfoType::IT_record);
+    else
+      I.VirtualParents.emplace_back(B.getType().getAsString());
+  }
+}
+
+template <typename T>
+static void
+populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
+                         const T *D) {
+  const auto *DC = dyn_cast<DeclContext>(D);
+  while ((DC = DC->getParent())) {
+    if (const auto *N = dyn_cast<NamespaceDecl>(DC))
+      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
+                              InfoType::IT_namespace);
+    else if (const auto *N = dyn_cast<RecordDecl>(DC))
+      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
+                              InfoType::IT_record);
+    else if (const auto *N = dyn_cast<FunctionDecl>(DC))
+      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
+                              InfoType::IT_function);
+    else if (const auto *N = dyn_cast<EnumDecl>(DC))
+      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
+                              InfoType::IT_enum);
+  }
+}
+
+template <typename T>
+static void populateInfo(Info &I, const T *D, const FullComment *C) {
+  I.USR = getUSRForDecl(D);
+  I.Name = D->getNameAsString();
+  populateParentNamespaces(I.Namespace, D);
+  if (C) {
+    I.Description.emplace_back();
+    parseFullComment(C, I.Description.back());
+  }
+}
+
+template <typename T>
+static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C,
+                               int LineNumber, StringRef Filename) {
+  populateInfo(I, D, C);
+  if (D->isThisDeclarationADefinition())
+    I.DefLoc.emplace(LineNumber, Filename);
+  else
+    I.Loc.emplace_back(LineNumber, Filename);
+}
+
+static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
+                                 const FullComment *FC, int LineNumber,
+                                 StringRef Filename) {
+  populateSymbolInfo(I, D, FC, LineNumber, Filename);
+  if (const auto *T = getDeclForType(D->getReturnType())) {
+    if (dyn_cast<EnumDecl>(T))
+      I.ReturnType =
+          TypeInfo(getUSRForDecl(T), T->getNameAsString(), InfoType::IT_enum);
+    else if (dyn_cast<RecordDecl>(T))
+      I.ReturnType =
+          TypeInfo(getUSRForDecl(T), T->getNameAsString(), InfoType::IT_record);
+  } else {
+    I.ReturnType = TypeInfo(D->getReturnType().getAsString());
+  }
+  parseParameters(I, D);
+}
+
+std::string emitInfo(const NamespaceDecl *D, const FullComment *FC,
+                     int LineNumber, llvm::StringRef File, bool PublicOnly) {
+  if (PublicOnly && ((D->isAnonymousNamespace()) ||
+                     !isPublic(D->getAccess(), D->getLinkageInternal())))
+    return "";
+  NamespaceInfo I;
+  populateInfo(I, D, FC);
+  return serialize(I);
+}
+
+std::string emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber,
+                     llvm::StringRef File, bool PublicOnly) {
+  if (PublicOnly && !isPublic(D->getAccess(), D->getLinkageInternal()))
+    return "";
+  RecordInfo I;
+  populateSymbolInfo(I, D, FC, LineNumber, File);
+  I.TagType = D->getTagKind();
+  parseFields(I, D, PublicOnly);
+  if (const auto *C = dyn_cast<CXXRecordDecl>(D))
+    parseBases(I, C);
+  return serialize(I);
+}
+
+std::string emitInfo(const FunctionDecl *D, const FullComment *FC,
+                     int LineNumber, llvm::StringRef File, bool PublicOnly) {
+  if (PublicOnly && !isPublic(D->getAccess(), D->getLinkageInternal()))
+    return "";
+  FunctionInfo I;
+  populateFunctionInfo(I, D, FC, LineNumber, File);
+  I.Access = clang::AccessSpecifier::AS_none;
+  return serialize(I);
+}
+
+std::string emitInfo(const CXXMethodDecl *D, const FullComment *FC,
+                     int LineNumber, llvm::StringRef File, bool PublicOnly) {
+  if (PublicOnly && !isPublic(D->getAccess(), D->getLinkageInternal()))
+    return "";
+  FunctionInfo I;
+  populateFunctionInfo(I, D, FC, LineNumber, File);
+  I.IsMethod = true;
+  I.Parent = Reference{getUSRForDecl(D->getParent()),
+                       D->getParent()->getNameAsString(), InfoType::IT_record};
+  I.Access = D->getAccess();
+  return serialize(I);
+}
+
+std::string emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber,
+                     llvm::StringRef File, bool PublicOnly) {
+  if (PublicOnly && !isPublic(D->getAccess(), D->getLinkageInternal()))
+    return "";
+  EnumInfo I;
+  populateSymbolInfo(I, D, FC, LineNumber, File);
+  I.Scoped = D->isScoped();
+  parseEnumerators(I, D);
+  return serialize(I);
+}
+
+} // namespace serialize
+} // namespace doc
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/Serialize.h b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Serialize.h
new file mode 100644
index 0000000..5181cf6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/Serialize.h
@@ -0,0 +1,53 @@
+//===-- Serializer.h - ClangDoc Serializer ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the serializing functions fro the clang-doc tool. Given
+// a particular declaration, it collects the appropriate information and returns
+// a serialized bitcode string for the declaration.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_SERIALIZE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_SERIALIZE_H
+
+#include "Representation.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/CommentVisitor.h"
+#include <string>
+#include <vector>
+
+using namespace clang::comments;
+
+namespace clang {
+namespace doc {
+namespace serialize {
+
+std::string emitInfo(const NamespaceDecl *D, const FullComment *FC,
+                     int LineNumber, StringRef File, bool PublicOnly);
+std::string emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber,
+                     StringRef File, bool PublicOnly);
+std::string emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber,
+                     StringRef File, bool PublicOnly);
+std::string emitInfo(const FunctionDecl *D, const FullComment *FC,
+                     int LineNumber, StringRef File, bool PublicOnly);
+std::string emitInfo(const CXXMethodDecl *D, const FullComment *FC,
+                     int LineNumber, StringRef File, bool PublicOnly);
+
+// Function to hash a given USR value for storage.
+// As USRs (Unified Symbol Resolution) could be large, especially for functions
+// with long type arguments, we use 160-bits SHA1(USR) values to
+// guarantee the uniqueness of symbols while using a relatively small amount of
+// memory (vs storing USRs directly).
+SymbolID hashUSR(llvm::StringRef USR);
+
+} // namespace serialize
+} // namespace doc
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_SERIALIZE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/YAMLGenerator.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-doc/YAMLGenerator.cpp
new file mode 100644
index 0000000..f29b478
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/YAMLGenerator.cpp
@@ -0,0 +1,268 @@
+//===--  ClangDocYAML.cpp - ClangDoc YAML -----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Implementation of the YAML generator, converting decl info into YAML output.
+//===----------------------------------------------------------------------===//
+
+#include "Generators.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::doc;
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(FieldTypeInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(MemberTypeInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(Reference)
+LLVM_YAML_IS_SEQUENCE_VECTOR(Location)
+LLVM_YAML_IS_SEQUENCE_VECTOR(CommentInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<CommentInfo>)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::SmallString<16>)
+
+namespace llvm {
+namespace yaml {
+
+// Enumerations to YAML output.
+
+template <> struct ScalarEnumerationTraits<clang::AccessSpecifier> {
+  static void enumeration(IO &IO, clang::AccessSpecifier &Value) {
+    IO.enumCase(Value, "Public", clang::AccessSpecifier::AS_public);
+    IO.enumCase(Value, "Protected", clang::AccessSpecifier::AS_protected);
+    IO.enumCase(Value, "Private", clang::AccessSpecifier::AS_private);
+    IO.enumCase(Value, "None", clang::AccessSpecifier::AS_none);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<clang::TagTypeKind> {
+  static void enumeration(IO &IO, clang::TagTypeKind &Value) {
+    IO.enumCase(Value, "Struct", clang::TagTypeKind::TTK_Struct);
+    IO.enumCase(Value, "Interface", clang::TagTypeKind::TTK_Interface);
+    IO.enumCase(Value, "Union", clang::TagTypeKind::TTK_Union);
+    IO.enumCase(Value, "Class", clang::TagTypeKind::TTK_Class);
+    IO.enumCase(Value, "Enum", clang::TagTypeKind::TTK_Enum);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<InfoType> {
+  static void enumeration(IO &IO, InfoType &Value) {
+    IO.enumCase(Value, "Namespace", InfoType::IT_namespace);
+    IO.enumCase(Value, "Record", InfoType::IT_record);
+    IO.enumCase(Value, "Function", InfoType::IT_function);
+    IO.enumCase(Value, "Enum", InfoType::IT_enum);
+    IO.enumCase(Value, "Default", InfoType::IT_default);
+  }
+};
+
+// Scalars to YAML output.
+template <unsigned U> struct ScalarTraits<SmallString<U>> {
+
+  static void output(const SmallString<U> &S, void *, llvm::raw_ostream &OS) {
+    for (const auto &C : S)
+      OS << C;
+  }
+
+  static StringRef input(StringRef Scalar, void *, SmallString<U> &Value) {
+    Value.assign(Scalar.begin(), Scalar.end());
+    return StringRef();
+  }
+
+  static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
+};
+
+template <> struct ScalarTraits<std::array<unsigned char, 20>> {
+
+  static void output(const std::array<unsigned char, 20> &S, void *,
+                     llvm::raw_ostream &OS) {
+    OS << toHex(toStringRef(S));
+  }
+
+  static StringRef input(StringRef Scalar, void *,
+                         std::array<unsigned char, 20> &Value) {
+    if (Scalar.size() != 40)
+      return "Error: Incorrect scalar size for USR.";
+    Value = StringToSymbol(Scalar);
+    return StringRef();
+  }
+
+  static SymbolID StringToSymbol(llvm::StringRef Value) {
+    SymbolID USR;
+    std::string HexString = fromHex(Value);
+    std::copy(HexString.begin(), HexString.end(), USR.begin());
+    return SymbolID(USR);
+  }
+
+  static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
+};
+
+// Helper functions to map infos to YAML.
+
+static void TypeInfoMapping(IO &IO, TypeInfo &I) {
+  IO.mapOptional("Type", I.Type, Reference());
+}
+
+static void FieldTypeInfoMapping(IO &IO, FieldTypeInfo &I) {
+  TypeInfoMapping(IO, I);
+  IO.mapOptional("Name", I.Name, SmallString<16>());
+}
+
+static void InfoMapping(IO &IO, Info &I) {
+  IO.mapRequired("USR", I.USR);
+  IO.mapOptional("Name", I.Name, SmallString<16>());
+  IO.mapOptional("Namespace", I.Namespace, llvm::SmallVector<Reference, 4>());
+  IO.mapOptional("Description", I.Description);
+}
+
+static void SymbolInfoMapping(IO &IO, SymbolInfo &I) {
+  InfoMapping(IO, I);
+  IO.mapOptional("DefLocation", I.DefLoc, Optional<Location>());
+  IO.mapOptional("Location", I.Loc, llvm::SmallVector<Location, 2>());
+}
+
+static void CommentInfoMapping(IO &IO, CommentInfo &I) {
+  IO.mapOptional("Kind", I.Kind, SmallString<16>());
+  IO.mapOptional("Text", I.Text, SmallString<64>());
+  IO.mapOptional("Name", I.Name, SmallString<16>());
+  IO.mapOptional("Direction", I.Direction, SmallString<8>());
+  IO.mapOptional("ParamName", I.ParamName, SmallString<16>());
+  IO.mapOptional("CloseName", I.CloseName, SmallString<16>());
+  IO.mapOptional("SelfClosing", I.SelfClosing, false);
+  IO.mapOptional("Explicit", I.Explicit, false);
+  IO.mapOptional("Args", I.Args, llvm::SmallVector<SmallString<16>, 4>());
+  IO.mapOptional("AttrKeys", I.AttrKeys,
+                 llvm::SmallVector<SmallString<16>, 4>());
+  IO.mapOptional("AttrValues", I.AttrValues,
+                 llvm::SmallVector<SmallString<16>, 4>());
+  IO.mapOptional("Children", I.Children);
+}
+
+// Template specialization to YAML traits for Infos.
+
+template <> struct MappingTraits<Location> {
+  static void mapping(IO &IO, Location &Loc) {
+    IO.mapOptional("LineNumber", Loc.LineNumber, 0);
+    IO.mapOptional("Filename", Loc.Filename, SmallString<32>());
+  }
+};
+
+template <> struct MappingTraits<Reference> {
+  static void mapping(IO &IO, Reference &Ref) {
+    IO.mapOptional("Type", Ref.RefType, InfoType::IT_default);
+    IO.mapOptional("Name", Ref.Name, SmallString<16>());
+    IO.mapOptional("USR", Ref.USR, SymbolID());
+  }
+};
+
+template <> struct MappingTraits<TypeInfo> {
+  static void mapping(IO &IO, TypeInfo &I) { TypeInfoMapping(IO, I); }
+};
+
+template <> struct MappingTraits<FieldTypeInfo> {
+  static void mapping(IO &IO, FieldTypeInfo &I) {
+    TypeInfoMapping(IO, I);
+    IO.mapOptional("Name", I.Name, SmallString<16>());
+  }
+};
+
+template <> struct MappingTraits<MemberTypeInfo> {
+  static void mapping(IO &IO, MemberTypeInfo &I) {
+    FieldTypeInfoMapping(IO, I);
+    IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
+  }
+};
+
+template <> struct MappingTraits<NamespaceInfo> {
+  static void mapping(IO &IO, NamespaceInfo &I) { InfoMapping(IO, I); }
+};
+
+template <> struct MappingTraits<RecordInfo> {
+  static void mapping(IO &IO, RecordInfo &I) {
+    SymbolInfoMapping(IO, I);
+    IO.mapOptional("TagType", I.TagType, clang::TagTypeKind::TTK_Struct);
+    IO.mapOptional("Members", I.Members);
+    IO.mapOptional("Parents", I.Parents, llvm::SmallVector<Reference, 4>());
+    IO.mapOptional("VirtualParents", I.VirtualParents,
+                   llvm::SmallVector<Reference, 4>());
+  }
+};
+
+template <> struct MappingTraits<EnumInfo> {
+  static void mapping(IO &IO, EnumInfo &I) {
+    SymbolInfoMapping(IO, I);
+    IO.mapOptional("Scoped", I.Scoped, false);
+    IO.mapOptional("Members", I.Members);
+  }
+};
+
+template <> struct MappingTraits<FunctionInfo> {
+  static void mapping(IO &IO, FunctionInfo &I) {
+    SymbolInfoMapping(IO, I);
+    IO.mapOptional("IsMethod", I.IsMethod, false);
+    IO.mapOptional("Parent", I.Parent, Reference());
+    IO.mapOptional("Params", I.Params);
+    IO.mapOptional("ReturnType", I.ReturnType);
+    IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
+  }
+};
+
+template <> struct MappingTraits<CommentInfo> {
+  static void mapping(IO &IO, CommentInfo &I) { CommentInfoMapping(IO, I); }
+};
+
+template <> struct MappingTraits<std::unique_ptr<CommentInfo>> {
+  static void mapping(IO &IO, std::unique_ptr<CommentInfo> &I) {
+    if (I)
+      CommentInfoMapping(IO, *I);
+  }
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+namespace clang {
+namespace doc {
+
+/// Generator for YAML documentation.
+class YAMLGenerator : public Generator {
+public:
+  static const char *Format;
+
+  bool generateDocForInfo(Info *I, llvm::raw_ostream &OS) override;
+};
+
+const char *YAMLGenerator::Format = "yaml";
+
+bool YAMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS) {
+  llvm::yaml::Output InfoYAML(OS);
+  switch (I->IT) {
+  case InfoType::IT_namespace:
+    InfoYAML << *static_cast<clang::doc::NamespaceInfo *>(I);
+    break;
+  case InfoType::IT_record:
+    InfoYAML << *static_cast<clang::doc::RecordInfo *>(I);
+    break;
+  case InfoType::IT_enum:
+    InfoYAML << *static_cast<clang::doc::EnumInfo *>(I);
+    break;
+  case InfoType::IT_function:
+    InfoYAML << *static_cast<clang::doc::FunctionInfo *>(I);
+    break;
+  case InfoType::IT_default:
+    llvm::errs() << "Unexpected info type in index.\n";
+    return true;
+  }
+  return false;
+}
+
+static GeneratorRegistry::Add<YAMLGenerator> YAML(YAMLGenerator::Format,
+                                                  "Generator for YAML output.");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the generator.
+volatile int YAMLGeneratorAnchorSource = 0;
+
+} // namespace doc
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/gen_tests.py b/src/third_party/llvm-project/clang-tools-extra/clang-doc/gen_tests.py
new file mode 100644
index 0000000..5004892
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/gen_tests.py
@@ -0,0 +1,200 @@
+#!/usr/bin/env python3
+#
+#===- gen_tests.py - clang-doc test generator ----------------*- python -*--===#
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+"""
+clang-doc test generator
+==========================
+
+Generates tests for clang-doc given a certain set of flags, a prefix for the
+test file, and a given clang-doc binary. Please check emitted tests for
+accuracy before using.
+
+To generate all current tests:
+- Generate mapper tests:
+    gen_tests.py -flag='--dump-mapper' -flag='--doxygen' -prefix mapper
+
+- Generate reducer tests:
+    gen_tests.py -flag='--dump-intermediate' -flag='--doxygen' -prefix bc
+    
+- Generate yaml tests:
+    gen_tests.py -flag='--format=yaml' -flag='--doxygen' -prefix yaml
+    
+This script was written on/for Linux, and has not been tested on any other
+platform and so it may not work.
+
+"""
+
+import argparse
+import glob
+import os
+import shutil
+import subprocess
+
+RUN_CLANG_DOC = """
+// RUN: clang-doc {0} -p %t %t/test.cpp -output=%t/docs
+"""
+RUN = """
+// RUN: {0} %t/{1} | FileCheck %s --check-prefix CHECK-{2}
+"""
+
+CHECK = '// CHECK-{0}: '
+
+CHECK_NEXT = '// CHECK-{0}-NEXT: '
+
+
+def clear_test_prefix_files(prefix, tests_path):
+    if os.path.isdir(tests_path):
+        for root, dirs, files in os.walk(tests_path):
+            for filename in files:
+                if filename.startswith(prefix):
+                    os.remove(os.path.join(root, filename))
+
+
+def copy_to_test_file(test_case_path, test_cases_path):
+    # Copy file to 'test.cpp' to preserve file-dependent USRs
+    test_file = os.path.join(test_cases_path, 'test.cpp')
+    shutil.copyfile(test_case_path, test_file)
+    return test_file
+
+
+def run_clang_doc(args, out_dir, test_file):
+    # Run clang-doc.
+    current_cmd = [args.clangdoc]
+    current_cmd.extend(args.flags)
+    current_cmd.append('--output=' + out_dir)
+    current_cmd.append(test_file)
+    print('Running ' + ' '.join(current_cmd))
+    return_code = subprocess.call(current_cmd)
+    if return_code:
+        return 1
+    return 0
+
+
+def get_test_case_code(test_case_path, flags):
+    # Get the test case code
+    code = ''
+    with open(test_case_path, 'r') as code_file:
+        code = code_file.read()
+
+    code += RUN_CLANG_DOC.format(flags)
+    return code
+
+
+def get_output(root, out_file, case_out_path, flags, checkname, bcanalyzer):
+    output = ''
+    run_cmd = ''
+    if '--dump-mapper' in flags or '--dump-intermediate' in flags:
+        # Run llvm-bcanalyzer
+        output = subprocess.check_output(
+            [bcanalyzer, '--dump',
+             os.path.join(root, out_file)])
+        output = output[:output.find('Summary of ')].rstrip()
+        run_cmd = RUN.format('llvm-bcanalyzer --dump',
+                             os.path.join('docs', 'bc', out_file), checkname)
+    else:
+        # Run cat
+        output = subprocess.check_output(['cat', os.path.join(root, out_file)])
+        run_cmd = RUN.format(
+            'cat',
+            os.path.join('docs', os.path.relpath(root, case_out_path),
+                         out_file), checkname)
+
+    # Format output.
+    output = output.replace('blob data = \'test\'', 'blob data = \'{{.*}}\'')
+    output = CHECK.format(checkname) + output.rstrip()
+    output = run_cmd + output.replace('\n',
+                                      '\n' + CHECK_NEXT.format(checkname))
+
+    return output + '\n'
+
+
+def main():
+    parser = argparse.ArgumentParser(description='Generate clang-doc tests.')
+    parser.add_argument(
+        '-flag',
+        action='append',
+        default=[],
+        dest='flags',
+        help='Flags to pass to clang-doc.')
+    parser.add_argument(
+        '-prefix',
+        type=str,
+        default='',
+        dest='prefix',
+        help='Prefix for this test group.')
+    parser.add_argument(
+        '-clang-doc-binary',
+        dest='clangdoc',
+        metavar="PATH",
+        default='clang-doc',
+        help='path to clang-doc binary')
+    parser.add_argument(
+        '-llvm-bcanalyzer-binary',
+        dest='bcanalyzer',
+        metavar="PATH",
+        default='llvm-bcanalyzer',
+        help='path to llvm-bcanalyzer binary')
+    args = parser.parse_args()
+
+    flags = ' '.join(args.flags)
+
+    clang_doc_path = os.path.dirname(__file__)
+    tests_path = os.path.join(clang_doc_path, '..', 'test', 'clang-doc')
+    test_cases_path = os.path.join(tests_path, 'test_cases')
+
+    clear_test_prefix_files(args.prefix, tests_path)
+
+    for test_case_path in glob.glob(os.path.join(test_cases_path, '*')):
+        if test_case_path.endswith(
+                'compile_flags.txt') or test_case_path.endswith(
+                    'compile_commands.json'):
+            continue
+
+        # Name of this test case
+        case_name = os.path.basename(test_case_path).split('.')[0]
+
+        test_file = copy_to_test_file(test_case_path, test_cases_path)
+        out_dir = os.path.join(test_cases_path, case_name)
+
+        if run_clang_doc(args, out_dir, test_file):
+            return 1
+
+        # Retrieve output and format as FileCheck tests
+        all_output = ''
+        num_outputs = 0
+        for root, dirs, files in os.walk(out_dir):
+            for out_file in files:
+                # Make the file check the first 3 letters (there's a very small chance
+                # that this will collide, but the fix is to simply change the decl name)
+                usr = os.path.basename(out_file).split('.')
+                # If the usr is less than 2, this isn't one of the test files.
+                if len(usr) < 2:
+                    continue
+                all_output += get_output(root, out_file, out_dir, args.flags,
+                                         num_outputs, args.bcanalyzer)
+                num_outputs += 1
+
+        # Add test case code to test
+        all_output = get_test_case_code(test_case_path,
+                                        flags) + '\n' + all_output
+
+        # Write to test case file in /test.
+        test_out_path = os.path.join(
+            tests_path, args.prefix + '-' + os.path.basename(test_case_path))
+        with open(test_out_path, 'w+') as o:
+            o.write(all_output)
+
+        # Clean up
+        shutil.rmtree(out_dir)
+        os.remove(test_file)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/tool/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-doc/tool/CMakeLists.txt
new file mode 100644
index 0000000..d7f28cf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/tool/CMakeLists.txt
@@ -0,0 +1,17 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
+
+add_clang_executable(clang-doc
+  ClangDocMain.cpp
+  )
+
+target_link_libraries(clang-doc
+  PRIVATE
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFrontend
+  clangDoc
+  clangTooling
+  clangToolingCore
+  )
+  
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
new file mode 100644
index 0000000..9e89e85
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -0,0 +1,253 @@
+//===-- ClangDocMain.cpp - ClangDoc -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tool for generating C and C++ documenation from source code
+// and comments. Generally, it runs a LibTooling FrontendAction on source files,
+// mapping each declaration in those files to its USR and serializing relevant
+// information into LLVM bitcode. It then runs a pass over the collected
+// declaration information, reducing by USR. There is an option to dump this
+// intermediate result to bitcode. Finally, it hands the reduced information
+// off to a generator, which does the final parsing from the intermediate
+// representation to the desired output format.
+//
+//===----------------------------------------------------------------------===//
+
+#include "BitcodeReader.h"
+#include "BitcodeWriter.h"
+#include "ClangDoc.h"
+#include "Generators.h"
+#include "Representation.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchersInternal.h"
+#include "clang/Driver/Options.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Execution.h"
+#include "clang/Tooling/StandaloneExecution.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+using namespace clang::ast_matchers;
+using namespace clang::tooling;
+using namespace clang;
+
+static llvm::cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
+static llvm::cl::OptionCategory ClangDocCategory("clang-doc options");
+
+static llvm::cl::opt<std::string>
+    OutDirectory("output",
+                 llvm::cl::desc("Directory for outputting generated files."),
+                 llvm::cl::init("docs"), llvm::cl::cat(ClangDocCategory));
+
+static llvm::cl::opt<bool>
+    DumpMapperResult("dump-mapper",
+                     llvm::cl::desc("Dump mapper results to bitcode file."),
+                     llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
+
+static llvm::cl::opt<bool> DumpIntermediateResult(
+    "dump-intermediate",
+    llvm::cl::desc("Dump intermediate results to bitcode file."),
+    llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
+
+static llvm::cl::opt<bool>
+    PublicOnly("public", llvm::cl::desc("Document only public declarations."),
+               llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
+
+enum OutputFormatTy {
+  yaml,
+};
+
+static llvm::cl::opt<OutputFormatTy> FormatEnum(
+    "format", llvm::cl::desc("Format for outputted docs."),
+    llvm::cl::values(clEnumVal(yaml, "Documentation in YAML format.")),
+    llvm::cl::init(yaml), llvm::cl::cat(ClangDocCategory));
+
+static llvm::cl::opt<bool> DoxygenOnly(
+    "doxygen",
+    llvm::cl::desc("Use only doxygen-style comments to generate docs."),
+    llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
+
+bool CreateDirectory(const Twine &DirName, bool ClearDirectory = false) {
+  std::error_code OK;
+  llvm::SmallString<128> DocsRootPath;
+  if (ClearDirectory) {
+    std::error_code RemoveStatus = llvm::sys::fs::remove_directories(DirName);
+    if (RemoveStatus != OK) {
+      llvm::errs() << "Unable to remove existing documentation directory for "
+                   << DirName << ".\n";
+      return true;
+    }
+  }
+  std::error_code DirectoryStatus = llvm::sys::fs::create_directories(DirName);
+  if (DirectoryStatus != OK) {
+    llvm::errs() << "Unable to create documentation directories.\n";
+    return true;
+  }
+  return false;
+}
+
+bool DumpResultToFile(const Twine &DirName, const Twine &FileName,
+                      StringRef Buffer, bool ClearDirectory = false) {
+  std::error_code OK;
+  llvm::SmallString<128> IRRootPath;
+  llvm::sys::path::native(OutDirectory, IRRootPath);
+  llvm::sys::path::append(IRRootPath, DirName);
+  if (CreateDirectory(IRRootPath, ClearDirectory))
+    return true;
+  llvm::sys::path::append(IRRootPath, FileName);
+  std::error_code OutErrorInfo;
+  llvm::raw_fd_ostream OS(IRRootPath, OutErrorInfo, llvm::sys::fs::F_None);
+  if (OutErrorInfo != OK) {
+    llvm::errs() << "Error opening documentation file.\n";
+    return true;
+  }
+  OS << Buffer;
+  OS.close();
+  return false;
+}
+
+llvm::Expected<llvm::SmallString<128>>
+getPath(StringRef Root, StringRef Ext, StringRef Name,
+        llvm::SmallVectorImpl<doc::Reference> &Namespaces) {
+  std::error_code OK;
+  llvm::SmallString<128> Path;
+  llvm::sys::path::native(Root, Path);
+  for (auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
+    llvm::sys::path::append(Path, R->Name);
+
+  if (CreateDirectory(Path))
+    return llvm::make_error<llvm::StringError>("Unable to create directory.\n",
+                                               llvm::inconvertibleErrorCode());
+
+  llvm::sys::path::append(Path, Name + Ext);
+  return Path;
+}
+
+std::string getFormatString(OutputFormatTy Ty) {
+  switch (Ty) {
+  case yaml:
+    return "yaml";
+  }
+  llvm_unreachable("Unknown OutputFormatTy");
+}
+
+int main(int argc, const char **argv) {
+  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+  std::error_code OK;
+
+  // Fail early if an invalid format was provided.
+  std::string Format = getFormatString(FormatEnum);
+  auto G = doc::findGeneratorByName(Format);
+  if (!G) {
+    llvm::errs() << toString(G.takeError()) << "\n";
+    return 1;
+  }
+
+  auto Exec = clang::tooling::createExecutorFromCommandLineArgs(
+      argc, argv, ClangDocCategory);
+
+  if (!Exec) {
+    llvm::errs() << toString(Exec.takeError()) << "\n";
+    return 1;
+  }
+
+  ArgumentsAdjuster ArgAdjuster;
+  if (!DoxygenOnly)
+    ArgAdjuster = combineAdjusters(
+        getInsertArgumentAdjuster("-fparse-all-comments",
+                                  tooling::ArgumentInsertPosition::END),
+        ArgAdjuster);
+
+  // Mapping phase
+  llvm::outs() << "Mapping decls...\n";
+  clang::doc::ClangDocContext CDCtx = {Exec->get()->getExecutionContext(),
+                                       PublicOnly};
+  auto Err =
+      Exec->get()->execute(doc::newMapperActionFactory(CDCtx), ArgAdjuster);
+  if (Err) {
+    llvm::errs() << toString(std::move(Err)) << "\n";
+    return 1;
+  }
+
+  if (DumpMapperResult) {
+    bool Err = false;
+    Exec->get()->getToolResults()->forEachResult(
+        [&](StringRef Key, StringRef Value) {
+          Err = DumpResultToFile("bc", Key + ".bc", Value);
+        });
+    if (Err)
+      llvm::errs() << "Error dumping map results.\n";
+    return Err;
+  }
+
+  // Collect values into output by key.
+  llvm::outs() << "Collecting infos...\n";
+  llvm::StringMap<std::vector<std::unique_ptr<doc::Info>>> MapOutput;
+
+  // In ToolResults, the Key is the hashed USR and the value is the
+  // bitcode-encoded representation of the Info object.
+  Exec->get()->getToolResults()->forEachResult([&](StringRef Key,
+                                                   StringRef Value) {
+    llvm::BitstreamCursor Stream(Value);
+    doc::ClangDocBitcodeReader Reader(Stream);
+    auto Infos = Reader.readBitcode();
+    for (auto &I : Infos) {
+      auto R =
+          MapOutput.try_emplace(Key, std::vector<std::unique_ptr<doc::Info>>());
+      R.first->second.emplace_back(std::move(I));
+    }
+  });
+
+  // Reducing and generation phases
+  llvm::outs() << "Reducing " << MapOutput.size() << " infos...\n";
+  llvm::StringMap<std::unique_ptr<doc::Info>> ReduceOutput;
+  for (auto &Group : MapOutput) {
+    auto Reduced = doc::mergeInfos(Group.getValue());
+    if (!Reduced)
+      llvm::errs() << llvm::toString(Reduced.takeError());
+
+    if (DumpIntermediateResult) {
+      SmallString<4096> Buffer;
+      llvm::BitstreamWriter Stream(Buffer);
+      doc::ClangDocBitcodeWriter Writer(Stream);
+      Writer.dispatchInfoForWrite(Reduced.get().get());
+      if (DumpResultToFile("bc", Group.getKey() + ".bc", Buffer))
+        llvm::errs() << "Error dumping to bitcode.\n";
+      continue;
+    }
+
+    // Create the relevant ostream and emit the documentation for this decl.
+    doc::Info *I = Reduced.get().get();
+    auto InfoPath = getPath(OutDirectory, "." + Format, I->Name, I->Namespace);
+    if (!InfoPath) {
+      llvm::errs() << toString(InfoPath.takeError()) << "\n";
+      continue;
+    }
+    std::error_code FileErr;
+    llvm::raw_fd_ostream InfoOS(InfoPath.get(), FileErr, llvm::sys::fs::F_None);
+    if (FileErr != OK) {
+      llvm::errs() << "Error opening index file: " << FileErr.message() << "\n";
+      continue;
+    }
+
+    if (G->get()->generateDocForInfo(I, InfoOS))
+      llvm::errs() << "Unable to generate docs for info.\n";
+  }
+
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-move/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-move/CMakeLists.txt
new file mode 100644
index 0000000..84175fd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-move/CMakeLists.txt
@@ -0,0 +1,21 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  )
+
+add_clang_library(clangMove
+  ClangMove.cpp
+  HelperDeclRefGraph.cpp
+
+  LINK_LIBS
+  clangAnalysis
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFormat
+  clangFrontend
+  clangLex
+  clangTooling
+  clangToolingCore
+  )
+
+add_subdirectory(tool)
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-move/ClangMove.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-move/ClangMove.cpp
new file mode 100644
index 0000000..e126852
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-move/ClangMove.cpp
@@ -0,0 +1,954 @@
+//===-- ClangMove.cpp - Implement ClangMove functationalities ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangMove.h"
+#include "HelperDeclRefGraph.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Format/Format.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Path.h"
+
+#define DEBUG_TYPE "clang-move"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace move {
+namespace {
+
+// FIXME: Move to ASTMatchers.
+AST_MATCHER(VarDecl, isStaticDataMember) { return Node.isStaticDataMember(); }
+
+AST_MATCHER(NamedDecl, notInMacro) { return !Node.getLocation().isMacroID(); }
+
+AST_MATCHER_P(Decl, hasOutermostEnclosingClass,
+              ast_matchers::internal::Matcher<Decl>, InnerMatcher) {
+  const auto *Context = Node.getDeclContext();
+  if (!Context)
+    return false;
+  while (const auto *NextContext = Context->getParent()) {
+    if (isa<NamespaceDecl>(NextContext) ||
+        isa<TranslationUnitDecl>(NextContext))
+      break;
+    Context = NextContext;
+  }
+  return InnerMatcher.matches(*Decl::castFromDeclContext(Context), Finder,
+                              Builder);
+}
+
+AST_MATCHER_P(CXXMethodDecl, ofOutermostEnclosingClass,
+              ast_matchers::internal::Matcher<CXXRecordDecl>, InnerMatcher) {
+  const CXXRecordDecl *Parent = Node.getParent();
+  if (!Parent)
+    return false;
+  while (const auto *NextParent =
+             dyn_cast<CXXRecordDecl>(Parent->getParent())) {
+    Parent = NextParent;
+  }
+
+  return InnerMatcher.matches(*Parent, Finder, Builder);
+}
+
+std::string CleanPath(StringRef PathRef) {
+  llvm::SmallString<128> Path(PathRef);
+  llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+  // FIXME: figure out why this is necessary.
+  llvm::sys::path::native(Path);
+  return Path.str();
+}
+
+// Make the Path absolute using the CurrentDir if the Path is not an absolute
+// path. An empty Path will result in an empty string.
+std::string MakeAbsolutePath(StringRef CurrentDir, StringRef Path) {
+  if (Path.empty())
+    return "";
+  llvm::SmallString<128> InitialDirectory(CurrentDir);
+  llvm::SmallString<128> AbsolutePath(Path);
+  if (std::error_code EC =
+          llvm::sys::fs::make_absolute(InitialDirectory, AbsolutePath))
+    llvm::errs() << "Warning: could not make absolute file: '" << EC.message()
+                 << '\n';
+  return CleanPath(std::move(AbsolutePath));
+}
+
+// Make the Path absolute using the current working directory of the given
+// SourceManager if the Path is not an absolute path.
+//
+// The Path can be a path relative to the build directory, or retrieved from
+// the SourceManager.
+std::string MakeAbsolutePath(const SourceManager &SM, StringRef Path) {
+  llvm::SmallString<128> AbsolutePath(Path);
+  if (std::error_code EC =
+          SM.getFileManager().getVirtualFileSystem()->makeAbsolute(
+              AbsolutePath))
+    llvm::errs() << "Warning: could not make absolute file: '" << EC.message()
+                 << '\n';
+  // Handle symbolic link path cases.
+  // We are trying to get the real file path of the symlink.
+  const DirectoryEntry *Dir = SM.getFileManager().getDirectory(
+      llvm::sys::path::parent_path(AbsolutePath.str()));
+  if (Dir) {
+    StringRef DirName = SM.getFileManager().getCanonicalName(Dir);
+    // FIXME: getCanonicalName might fail to get real path on VFS.
+    if (llvm::sys::path::is_absolute(DirName)) {
+      SmallString<128> AbsoluteFilename;
+      llvm::sys::path::append(AbsoluteFilename, DirName,
+                              llvm::sys::path::filename(AbsolutePath.str()));
+      return CleanPath(AbsoluteFilename);
+    }
+  }
+  return CleanPath(AbsolutePath);
+}
+
+// Matches AST nodes that are expanded within the given AbsoluteFilePath.
+AST_POLYMORPHIC_MATCHER_P(isExpansionInFile,
+                          AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc),
+                          std::string, AbsoluteFilePath) {
+  auto &SourceManager = Finder->getASTContext().getSourceManager();
+  auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart());
+  if (ExpansionLoc.isInvalid())
+    return false;
+  auto FileEntry =
+      SourceManager.getFileEntryForID(SourceManager.getFileID(ExpansionLoc));
+  if (!FileEntry)
+    return false;
+  return MakeAbsolutePath(SourceManager, FileEntry->getName()) ==
+         AbsoluteFilePath;
+}
+
+class FindAllIncludes : public clang::PPCallbacks {
+public:
+  explicit FindAllIncludes(SourceManager *SM, ClangMoveTool *const MoveTool)
+      : SM(*SM), MoveTool(MoveTool) {}
+
+  void InclusionDirective(clang::SourceLocation HashLoc,
+                          const clang::Token & /*IncludeTok*/,
+                          StringRef FileName, bool IsAngled,
+                          clang::CharSourceRange FilenameRange,
+                          const clang::FileEntry * /*File*/,
+                          StringRef SearchPath, StringRef /*RelativePath*/,
+                          const clang::Module * /*Imported*/,
+                          SrcMgr::CharacteristicKind /*FileType*/) override {
+    if (const auto *FileEntry = SM.getFileEntryForID(SM.getFileID(HashLoc)))
+      MoveTool->addIncludes(FileName, IsAngled, SearchPath,
+                            FileEntry->getName(), FilenameRange, SM);
+  }
+
+private:
+  const SourceManager &SM;
+  ClangMoveTool *const MoveTool;
+};
+
+/// Add a declatration being moved to new.h/cc. Note that the declaration will
+/// also be deleted in old.h/cc.
+void MoveDeclFromOldFileToNewFile(ClangMoveTool *MoveTool, const NamedDecl *D) {
+  MoveTool->getMovedDecls().push_back(D);
+  MoveTool->addRemovedDecl(D);
+  MoveTool->getUnremovedDeclsInOldHeader().erase(D);
+}
+
+class FunctionDeclarationMatch : public MatchFinder::MatchCallback {
+public:
+  explicit FunctionDeclarationMatch(ClangMoveTool *MoveTool)
+      : MoveTool(MoveTool) {}
+
+  void run(const MatchFinder::MatchResult &Result) override {
+    const auto *FD = Result.Nodes.getNodeAs<clang::FunctionDecl>("function");
+    assert(FD);
+    const clang::NamedDecl *D = FD;
+    if (const auto *FTD = FD->getDescribedFunctionTemplate())
+      D = FTD;
+    MoveDeclFromOldFileToNewFile(MoveTool, D);
+  }
+
+private:
+  ClangMoveTool *MoveTool;
+};
+
+class VarDeclarationMatch : public MatchFinder::MatchCallback {
+public:
+  explicit VarDeclarationMatch(ClangMoveTool *MoveTool)
+      : MoveTool(MoveTool) {}
+
+  void run(const MatchFinder::MatchResult &Result) override {
+    const auto *VD = Result.Nodes.getNodeAs<clang::VarDecl>("var");
+    assert(VD);
+    MoveDeclFromOldFileToNewFile(MoveTool, VD);
+  }
+
+private:
+  ClangMoveTool *MoveTool;
+};
+
+class TypeAliasMatch : public MatchFinder::MatchCallback {
+public:
+  explicit TypeAliasMatch(ClangMoveTool *MoveTool)
+      : MoveTool(MoveTool) {}
+
+  void run(const MatchFinder::MatchResult &Result) override {
+    if (const auto *TD = Result.Nodes.getNodeAs<clang::TypedefDecl>("typedef"))
+      MoveDeclFromOldFileToNewFile(MoveTool, TD);
+    else if (const auto *TAD =
+                 Result.Nodes.getNodeAs<clang::TypeAliasDecl>("type_alias")) {
+      const NamedDecl * D = TAD;
+      if (const auto * TD = TAD->getDescribedAliasTemplate())
+        D = TD;
+      MoveDeclFromOldFileToNewFile(MoveTool, D);
+    }
+  }
+
+private:
+  ClangMoveTool *MoveTool;
+};
+
+class EnumDeclarationMatch : public MatchFinder::MatchCallback {
+public:
+  explicit EnumDeclarationMatch(ClangMoveTool *MoveTool)
+      : MoveTool(MoveTool) {}
+
+  void run(const MatchFinder::MatchResult &Result) override {
+    const auto *ED = Result.Nodes.getNodeAs<clang::EnumDecl>("enum");
+    assert(ED);
+    MoveDeclFromOldFileToNewFile(MoveTool, ED);
+  }
+
+private:
+  ClangMoveTool *MoveTool;
+};
+
+class ClassDeclarationMatch : public MatchFinder::MatchCallback {
+public:
+  explicit ClassDeclarationMatch(ClangMoveTool *MoveTool)
+      : MoveTool(MoveTool) {}
+  void run(const MatchFinder::MatchResult &Result) override {
+    clang::SourceManager* SM = &Result.Context->getSourceManager();
+    if (const auto *CMD =
+            Result.Nodes.getNodeAs<clang::CXXMethodDecl>("class_method"))
+      MatchClassMethod(CMD, SM);
+    else if (const auto *VD = Result.Nodes.getNodeAs<clang::VarDecl>(
+                   "class_static_var_decl"))
+      MatchClassStaticVariable(VD, SM);
+    else if (const auto *CD = Result.Nodes.getNodeAs<clang::CXXRecordDecl>(
+                   "moved_class"))
+      MatchClassDeclaration(CD, SM);
+  }
+
+private:
+  void MatchClassMethod(const clang::CXXMethodDecl* CMD,
+                        clang::SourceManager* SM) {
+    // Skip inline class methods. isInline() ast matcher doesn't ignore this
+    // case.
+    if (!CMD->isInlined()) {
+      MoveTool->getMovedDecls().push_back(CMD);
+      MoveTool->addRemovedDecl(CMD);
+      // Get template class method from its method declaration as
+      // UnremovedDecls stores template class method.
+      if (const auto *FTD = CMD->getDescribedFunctionTemplate())
+        MoveTool->getUnremovedDeclsInOldHeader().erase(FTD);
+      else
+        MoveTool->getUnremovedDeclsInOldHeader().erase(CMD);
+    }
+  }
+
+  void MatchClassStaticVariable(const clang::NamedDecl *VD,
+                                clang::SourceManager* SM) {
+    MoveDeclFromOldFileToNewFile(MoveTool, VD);
+  }
+
+  void MatchClassDeclaration(const clang::CXXRecordDecl *CD,
+                             clang::SourceManager* SM) {
+    // Get class template from its class declaration as UnremovedDecls stores
+    // class template.
+    if (const auto *TC = CD->getDescribedClassTemplate())
+      MoveTool->getMovedDecls().push_back(TC);
+    else
+      MoveTool->getMovedDecls().push_back(CD);
+    MoveTool->addRemovedDecl(MoveTool->getMovedDecls().back());
+    MoveTool->getUnremovedDeclsInOldHeader().erase(
+        MoveTool->getMovedDecls().back());
+  }
+
+  ClangMoveTool *MoveTool;
+};
+
+// Expand to get the end location of the line where the EndLoc of the given
+// Decl.
+SourceLocation
+getLocForEndOfDecl(const clang::Decl *D,
+                   const LangOptions &LangOpts = clang::LangOptions()) {
+  const auto &SM = D->getASTContext().getSourceManager();
+  // If the expansion range is a character range, this is the location of
+  // the first character past the end. Otherwise it's the location of the
+  // first character in the final token in the range.
+  auto EndExpansionLoc = SM.getExpansionRange(D->getLocEnd()).getEnd();
+  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(EndExpansionLoc);
+  // Try to load the file buffer.
+  bool InvalidTemp = false;
+  llvm::StringRef File = SM.getBufferData(LocInfo.first, &InvalidTemp);
+  if (InvalidTemp)
+    return SourceLocation();
+
+  const char *TokBegin = File.data() + LocInfo.second;
+  // Lex from the start of the given location.
+  Lexer Lex(SM.getLocForStartOfFile(LocInfo.first), LangOpts, File.begin(),
+            TokBegin, File.end());
+
+  llvm::SmallVector<char, 16> Line;
+  // FIXME: this is a bit hacky to get ReadToEndOfLine work.
+  Lex.setParsingPreprocessorDirective(true);
+  Lex.ReadToEndOfLine(&Line);
+  SourceLocation EndLoc = EndExpansionLoc.getLocWithOffset(Line.size());
+  // If we already reach EOF, just return the EOF SourceLocation;
+  // otherwise, move 1 offset ahead to include the trailing newline character
+  // '\n'.
+  return SM.getLocForEndOfFile(LocInfo.first) == EndLoc
+             ? EndLoc
+             : EndLoc.getLocWithOffset(1);
+}
+
+// Get full range of a Decl including the comments associated with it.
+clang::CharSourceRange
+getFullRange(const clang::Decl *D,
+             const clang::LangOptions &options = clang::LangOptions()) {
+  const auto &SM = D->getASTContext().getSourceManager();
+  clang::SourceRange Full(SM.getExpansionLoc(D->getLocStart()),
+                          getLocForEndOfDecl(D));
+  // Expand to comments that are associated with the Decl.
+  if (const auto *Comment = D->getASTContext().getRawCommentForDeclNoCache(D)) {
+    if (SM.isBeforeInTranslationUnit(Full.getEnd(), Comment->getLocEnd()))
+      Full.setEnd(Comment->getLocEnd());
+    // FIXME: Don't delete a preceding comment, if there are no other entities
+    // it could refer to.
+    if (SM.isBeforeInTranslationUnit(Comment->getLocStart(), Full.getBegin()))
+      Full.setBegin(Comment->getLocStart());
+  }
+
+  return clang::CharSourceRange::getCharRange(Full);
+}
+
+std::string getDeclarationSourceText(const clang::Decl *D) {
+  const auto &SM = D->getASTContext().getSourceManager();
+  llvm::StringRef SourceText =
+      clang::Lexer::getSourceText(getFullRange(D), SM, clang::LangOptions());
+  return SourceText.str();
+}
+
+bool isInHeaderFile(const clang::Decl *D,
+                    llvm::StringRef OriginalRunningDirectory,
+                    llvm::StringRef OldHeader) {
+  const auto &SM = D->getASTContext().getSourceManager();
+  if (OldHeader.empty())
+    return false;
+  auto ExpansionLoc = SM.getExpansionLoc(D->getLocStart());
+  if (ExpansionLoc.isInvalid())
+    return false;
+
+  if (const auto *FE = SM.getFileEntryForID(SM.getFileID(ExpansionLoc))) {
+    return MakeAbsolutePath(SM, FE->getName()) ==
+           MakeAbsolutePath(OriginalRunningDirectory, OldHeader);
+  }
+
+  return false;
+}
+
+std::vector<std::string> getNamespaces(const clang::Decl *D) {
+  std::vector<std::string> Namespaces;
+  for (const auto *Context = D->getDeclContext(); Context;
+       Context = Context->getParent()) {
+    if (llvm::isa<clang::TranslationUnitDecl>(Context) ||
+        llvm::isa<clang::LinkageSpecDecl>(Context))
+      break;
+
+    if (const auto *ND = llvm::dyn_cast<clang::NamespaceDecl>(Context))
+      Namespaces.push_back(ND->getName().str());
+  }
+  std::reverse(Namespaces.begin(), Namespaces.end());
+  return Namespaces;
+}
+
+clang::tooling::Replacements
+createInsertedReplacements(const std::vector<std::string> &Includes,
+                           const std::vector<const NamedDecl *> &Decls,
+                           llvm::StringRef FileName, bool IsHeader = false,
+                           StringRef OldHeaderInclude = "") {
+  std::string NewCode;
+  std::string GuardName(FileName);
+  if (IsHeader) {
+    for (size_t i = 0; i < GuardName.size(); ++i) {
+      if (!isAlphanumeric(GuardName[i]))
+        GuardName[i] = '_';
+    }
+    GuardName = StringRef(GuardName).upper();
+    NewCode += "#ifndef " + GuardName + "\n";
+    NewCode += "#define " + GuardName + "\n\n";
+  }
+
+  NewCode += OldHeaderInclude;
+  // Add #Includes.
+  for (const auto &Include : Includes)
+    NewCode += Include;
+
+  if (!Includes.empty())
+    NewCode += "\n";
+
+  // Add moved class definition and its related declarations. All declarations
+  // in same namespace are grouped together.
+  //
+  // Record namespaces where the current position is in.
+  std::vector<std::string> CurrentNamespaces;
+  for (const auto *MovedDecl : Decls) {
+    // The namespaces of the declaration being moved.
+    std::vector<std::string> DeclNamespaces = getNamespaces(MovedDecl);
+    auto CurrentIt = CurrentNamespaces.begin();
+    auto DeclIt = DeclNamespaces.begin();
+    // Skip the common prefix.
+    while (CurrentIt != CurrentNamespaces.end() &&
+           DeclIt != DeclNamespaces.end()) {
+      if (*CurrentIt != *DeclIt)
+        break;
+      ++CurrentIt;
+      ++DeclIt;
+    }
+    // Calculate the new namespaces after adding MovedDecl in CurrentNamespace,
+    // which is used for next iteration of this loop.
+    std::vector<std::string> NextNamespaces(CurrentNamespaces.begin(),
+                                            CurrentIt);
+    NextNamespaces.insert(NextNamespaces.end(), DeclIt, DeclNamespaces.end());
+
+
+    // End with CurrentNamespace.
+    bool HasEndCurrentNamespace = false;
+    auto RemainingSize = CurrentNamespaces.end() - CurrentIt;
+    for (auto It = CurrentNamespaces.rbegin(); RemainingSize > 0;
+         --RemainingSize, ++It) {
+      assert(It < CurrentNamespaces.rend());
+      NewCode += "} // namespace " + *It + "\n";
+      HasEndCurrentNamespace = true;
+    }
+    // Add trailing '\n' after the nested namespace definition.
+    if (HasEndCurrentNamespace)
+      NewCode += "\n";
+
+    // If the moved declaration is not in CurrentNamespace, add extra namespace
+    // definitions.
+    bool IsInNewNamespace = false;
+    while (DeclIt != DeclNamespaces.end()) {
+      NewCode += "namespace " + *DeclIt + " {\n";
+      IsInNewNamespace = true;
+      ++DeclIt;
+    }
+    // If the moved declaration is in same namespace CurrentNamespace, add
+    // a preceeding `\n' before the moved declaration.
+    // FIXME: Don't add empty lines between using declarations.
+    if (!IsInNewNamespace)
+      NewCode += "\n";
+    NewCode += getDeclarationSourceText(MovedDecl);
+    CurrentNamespaces = std::move(NextNamespaces);
+  }
+  std::reverse(CurrentNamespaces.begin(), CurrentNamespaces.end());
+  for (const auto &NS : CurrentNamespaces)
+    NewCode += "} // namespace " + NS + "\n";
+
+  if (IsHeader)
+    NewCode += "\n#endif // " + GuardName + "\n";
+  return clang::tooling::Replacements(
+      clang::tooling::Replacement(FileName, 0, 0, NewCode));
+}
+
+// Return a set of all decls which are used/referenced by the given Decls.
+// Specically, given a class member declaration, this method will return all
+// decls which are used by the whole class.
+llvm::DenseSet<const Decl *>
+getUsedDecls(const HelperDeclRefGraph *RG,
+             const std::vector<const NamedDecl *> &Decls) {
+  assert(RG);
+  llvm::DenseSet<const CallGraphNode *> Nodes;
+  for (const auto *D : Decls) {
+    auto Result = RG->getReachableNodes(
+        HelperDeclRGBuilder::getOutmostClassOrFunDecl(D));
+    Nodes.insert(Result.begin(), Result.end());
+  }
+  llvm::DenseSet<const Decl *> Results;
+  for (const auto *Node : Nodes)
+    Results.insert(Node->getDecl());
+  return Results;
+}
+
+} // namespace
+
+std::unique_ptr<clang::ASTConsumer>
+ClangMoveAction::CreateASTConsumer(clang::CompilerInstance &Compiler,
+                                   StringRef /*InFile*/) {
+  Compiler.getPreprocessor().addPPCallbacks(llvm::make_unique<FindAllIncludes>(
+      &Compiler.getSourceManager(), &MoveTool));
+  return MatchFinder.newASTConsumer();
+}
+
+ClangMoveTool::ClangMoveTool(ClangMoveContext *const Context,
+                             DeclarationReporter *const Reporter)
+    : Context(Context), Reporter(Reporter) {
+  if (!Context->Spec.NewHeader.empty())
+    CCIncludes.push_back("#include \"" + Context->Spec.NewHeader + "\"\n");
+}
+
+void ClangMoveTool::addRemovedDecl(const NamedDecl *Decl) {
+  const auto &SM = Decl->getASTContext().getSourceManager();
+  auto Loc = Decl->getLocation();
+  StringRef FilePath = SM.getFilename(Loc);
+  FilePathToFileID[FilePath] = SM.getFileID(Loc);
+  RemovedDecls.push_back(Decl);
+}
+
+void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
+  auto InOldHeader =
+      isExpansionInFile(makeAbsolutePath(Context->Spec.OldHeader));
+  auto InOldCC = isExpansionInFile(makeAbsolutePath(Context->Spec.OldCC));
+  auto InOldFiles = anyOf(InOldHeader, InOldCC);
+  auto classTemplateForwardDecls =
+      classTemplateDecl(unless(has(cxxRecordDecl(isDefinition()))));
+  auto ForwardClassDecls = namedDecl(
+      anyOf(cxxRecordDecl(unless(anyOf(isImplicit(), isDefinition()))),
+            classTemplateForwardDecls));
+  auto TopLevelDecl =
+      hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl()));
+
+  //============================================================================
+  // Matchers for old header
+  //============================================================================
+  // Match all top-level named declarations (e.g. function, variable, enum) in
+  // old header, exclude forward class declarations and namespace declarations.
+  //
+  // We consider declarations inside a class belongs to the class. So these
+  // declarations will be ignored.
+  auto AllDeclsInHeader = namedDecl(
+      unless(ForwardClassDecls), unless(namespaceDecl()),
+      unless(usingDirectiveDecl()), // using namespace decl.
+      notInMacro(),
+      InOldHeader,
+      hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl()))),
+      hasDeclContext(decl(anyOf(namespaceDecl(), translationUnitDecl()))));
+  Finder->addMatcher(AllDeclsInHeader.bind("decls_in_header"), this);
+
+  // Don't register other matchers when dumping all declarations in header.
+  if (Context->DumpDeclarations)
+    return;
+
+  // Match forward declarations in old header.
+  Finder->addMatcher(namedDecl(ForwardClassDecls, InOldHeader).bind("fwd_decl"),
+                     this);
+
+  //============================================================================
+  // Matchers for old cc
+  //============================================================================
+  auto IsOldCCTopLevelDecl = allOf(
+      hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl()))), InOldCC);
+  // Matching using decls/type alias decls which are in named/anonymous/global
+  // namespace, these decls are always copied to new.h/cc. Those in classes,
+  // functions are covered in other matchers.
+  Finder->addMatcher(namedDecl(anyOf(usingDecl(IsOldCCTopLevelDecl),
+                                     usingDirectiveDecl(IsOldCCTopLevelDecl),
+                                     typeAliasDecl(IsOldCCTopLevelDecl)),
+                               notInMacro())
+                         .bind("using_decl"),
+                     this);
+
+  // Match static functions/variable definitions which are defined in named
+  // namespaces.
+  Optional<ast_matchers::internal::Matcher<NamedDecl>> HasAnySymbolNames;
+  for (StringRef SymbolName : Context->Spec.Names) {
+    llvm::StringRef GlobalSymbolName = SymbolName.trim().ltrim(':');
+    const auto HasName = hasName(("::" + GlobalSymbolName).str());
+    HasAnySymbolNames =
+        HasAnySymbolNames ? anyOf(*HasAnySymbolNames, HasName) : HasName;
+  }
+
+  if (!HasAnySymbolNames) {
+    llvm::errs() << "No symbols being moved.\n";
+    return;
+  }
+  auto InMovedClass =
+      hasOutermostEnclosingClass(cxxRecordDecl(*HasAnySymbolNames));
+
+  // Matchers for helper declarations in old.cc.
+  auto InAnonymousNS = hasParent(namespaceDecl(isAnonymous()));
+  auto NotInMovedClass= allOf(unless(InMovedClass), InOldCC);
+  auto IsOldCCHelper =
+      allOf(NotInMovedClass, anyOf(isStaticStorageClass(), InAnonymousNS));
+  // Match helper classes separately with helper functions/variables since we
+  // want to reuse these matchers in finding helpers usage below.
+  //
+  // There could be forward declarations usage for helpers, especially for
+  // classes and functions. We need include these forward declarations.
+  //
+  // Forward declarations for variable helpers will be excluded as these
+  // declarations (with "extern") are not supposed in cpp file.
+   auto HelperFuncOrVar =
+      namedDecl(notInMacro(), anyOf(functionDecl(IsOldCCHelper),
+                                    varDecl(isDefinition(), IsOldCCHelper)));
+  auto HelperClasses =
+      cxxRecordDecl(notInMacro(), NotInMovedClass, InAnonymousNS);
+  // Save all helper declarations in old.cc.
+  Finder->addMatcher(
+      namedDecl(anyOf(HelperFuncOrVar, HelperClasses)).bind("helper_decls"),
+      this);
+
+  // Construct an AST-based call graph of helper declarations in old.cc.
+  // In the following matcheres, "dc" is a caller while "helper_decls" and
+  // "used_class" is a callee, so a new edge starting from caller to callee will
+  // be add in the graph.
+  //
+  // Find helper function/variable usages.
+  Finder->addMatcher(
+      declRefExpr(to(HelperFuncOrVar), hasAncestor(decl().bind("dc")))
+          .bind("func_ref"),
+      &RGBuilder);
+  // Find helper class usages.
+  Finder->addMatcher(
+      typeLoc(loc(recordType(hasDeclaration(HelperClasses.bind("used_class")))),
+              hasAncestor(decl().bind("dc"))),
+      &RGBuilder);
+
+  //============================================================================
+  // Matchers for old files, including old.h/old.cc
+  //============================================================================
+  // Create a MatchCallback for class declarations.
+  MatchCallbacks.push_back(llvm::make_unique<ClassDeclarationMatch>(this));
+  // Match moved class declarations.
+  auto MovedClass = cxxRecordDecl(InOldFiles, *HasAnySymbolNames,
+                                  isDefinition(), TopLevelDecl)
+                        .bind("moved_class");
+  Finder->addMatcher(MovedClass, MatchCallbacks.back().get());
+  // Match moved class methods (static methods included) which are defined
+  // outside moved class declaration.
+  Finder->addMatcher(
+      cxxMethodDecl(InOldFiles, ofOutermostEnclosingClass(*HasAnySymbolNames),
+                    isDefinition())
+          .bind("class_method"),
+      MatchCallbacks.back().get());
+  // Match static member variable definition of the moved class.
+  Finder->addMatcher(
+      varDecl(InMovedClass, InOldFiles, isDefinition(), isStaticDataMember())
+          .bind("class_static_var_decl"),
+      MatchCallbacks.back().get());
+
+  MatchCallbacks.push_back(llvm::make_unique<FunctionDeclarationMatch>(this));
+  Finder->addMatcher(functionDecl(InOldFiles, *HasAnySymbolNames, TopLevelDecl)
+                         .bind("function"),
+                     MatchCallbacks.back().get());
+
+  MatchCallbacks.push_back(llvm::make_unique<VarDeclarationMatch>(this));
+  Finder->addMatcher(
+      varDecl(InOldFiles, *HasAnySymbolNames, TopLevelDecl).bind("var"),
+      MatchCallbacks.back().get());
+
+  // Match enum definition in old.h. Enum helpers (which are defined in old.cc)
+  // will not be moved for now no matter whether they are used or not.
+  MatchCallbacks.push_back(llvm::make_unique<EnumDeclarationMatch>(this));
+  Finder->addMatcher(
+      enumDecl(InOldHeader, *HasAnySymbolNames, isDefinition(), TopLevelDecl)
+          .bind("enum"),
+      MatchCallbacks.back().get());
+
+  // Match type alias in old.h, this includes "typedef" and "using" type alias
+  // declarations. Type alias helpers (which are defined in old.cc) will not be
+  // moved for now no matter whether they are used or not.
+  MatchCallbacks.push_back(llvm::make_unique<TypeAliasMatch>(this));
+  Finder->addMatcher(namedDecl(anyOf(typedefDecl().bind("typedef"),
+                                     typeAliasDecl().bind("type_alias")),
+                               InOldHeader, *HasAnySymbolNames, TopLevelDecl),
+                     MatchCallbacks.back().get());
+}
+
+void ClangMoveTool::run(const ast_matchers::MatchFinder::MatchResult &Result) {
+  if (const auto *D =
+          Result.Nodes.getNodeAs<clang::NamedDecl>("decls_in_header")) {
+    UnremovedDeclsInOldHeader.insert(D);
+  } else if (const auto *FWD =
+                 Result.Nodes.getNodeAs<clang::CXXRecordDecl>("fwd_decl")) {
+    // Skip all forward declarations which appear after moved class declaration.
+    if (RemovedDecls.empty()) {
+      if (const auto *DCT = FWD->getDescribedClassTemplate())
+        MovedDecls.push_back(DCT);
+      else
+        MovedDecls.push_back(FWD);
+    }
+  } else if (const auto *ND =
+                 Result.Nodes.getNodeAs<clang::NamedDecl>("helper_decls")) {
+    MovedDecls.push_back(ND);
+    HelperDeclarations.push_back(ND);
+    LLVM_DEBUG(llvm::dbgs() << "Add helper : " << ND->getNameAsString() << " ("
+                            << ND << ")\n");
+  } else if (const auto *UD =
+                 Result.Nodes.getNodeAs<clang::NamedDecl>("using_decl")) {
+    MovedDecls.push_back(UD);
+  }
+}
+
+std::string ClangMoveTool::makeAbsolutePath(StringRef Path) {
+  return MakeAbsolutePath(Context->OriginalRunningDirectory, Path);
+}
+
+void ClangMoveTool::addIncludes(llvm::StringRef IncludeHeader, bool IsAngled,
+                                llvm::StringRef SearchPath,
+                                llvm::StringRef FileName,
+                                clang::CharSourceRange IncludeFilenameRange,
+                                const SourceManager &SM) {
+  SmallVector<char, 128> HeaderWithSearchPath;
+  llvm::sys::path::append(HeaderWithSearchPath, SearchPath, IncludeHeader);
+  std::string AbsoluteIncludeHeader =
+      MakeAbsolutePath(SM, llvm::StringRef(HeaderWithSearchPath.data(),
+                                           HeaderWithSearchPath.size()));
+  std::string IncludeLine =
+      IsAngled ? ("#include <" + IncludeHeader + ">\n").str()
+               : ("#include \"" + IncludeHeader + "\"\n").str();
+
+  std::string AbsoluteOldHeader = makeAbsolutePath(Context->Spec.OldHeader);
+  std::string AbsoluteCurrentFile = MakeAbsolutePath(SM, FileName);
+  if (AbsoluteOldHeader == AbsoluteCurrentFile) {
+    // Find old.h includes "old.h".
+    if (AbsoluteOldHeader == AbsoluteIncludeHeader) {
+      OldHeaderIncludeRangeInHeader = IncludeFilenameRange;
+      return;
+    }
+    HeaderIncludes.push_back(IncludeLine);
+  } else if (makeAbsolutePath(Context->Spec.OldCC) == AbsoluteCurrentFile) {
+    // Find old.cc includes "old.h".
+    if (AbsoluteOldHeader == AbsoluteIncludeHeader) {
+      OldHeaderIncludeRangeInCC = IncludeFilenameRange;
+      return;
+    }
+    CCIncludes.push_back(IncludeLine);
+  }
+}
+
+void ClangMoveTool::removeDeclsInOldFiles() {
+  if (RemovedDecls.empty()) return;
+
+  // If old_header is not specified (only move declarations from old.cc), remain
+  // all the helper function declarations in old.cc as UnremovedDeclsInOldHeader
+  // is empty in this case, there is no way to verify unused/used helpers.
+  if (!Context->Spec.OldHeader.empty()) {
+    std::vector<const NamedDecl *> UnremovedDecls;
+    for (const auto *D : UnremovedDeclsInOldHeader)
+      UnremovedDecls.push_back(D);
+
+    auto UsedDecls = getUsedDecls(RGBuilder.getGraph(), UnremovedDecls);
+
+    // We remove the helper declarations which are not used in the old.cc after
+    // moving the given declarations.
+    for (const auto *D : HelperDeclarations) {
+      LLVM_DEBUG(llvm::dbgs() << "Check helper is used: "
+                              << D->getNameAsString() << " (" << D << ")\n");
+      if (!UsedDecls.count(HelperDeclRGBuilder::getOutmostClassOrFunDecl(
+              D->getCanonicalDecl()))) {
+        LLVM_DEBUG(llvm::dbgs() << "Helper removed in old.cc: "
+                                << D->getNameAsString() << " (" << D << ")\n");
+        RemovedDecls.push_back(D);
+      }
+    }
+  }
+
+  for (const auto *RemovedDecl : RemovedDecls) {
+    const auto &SM = RemovedDecl->getASTContext().getSourceManager();
+    auto Range = getFullRange(RemovedDecl);
+    clang::tooling::Replacement RemoveReplacement(
+        SM,
+        clang::CharSourceRange::getCharRange(Range.getBegin(), Range.getEnd()),
+        "");
+    std::string FilePath = RemoveReplacement.getFilePath().str();
+    auto Err = Context->FileToReplacements[FilePath].add(RemoveReplacement);
+    if (Err)
+      llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+  }
+  const auto &SM = RemovedDecls[0]->getASTContext().getSourceManager();
+
+  // Post process of cleanup around all the replacements.
+  for (auto &FileAndReplacements : Context->FileToReplacements) {
+    StringRef FilePath = FileAndReplacements.first;
+    // Add #include of new header to old header.
+    if (Context->Spec.OldDependOnNew &&
+        MakeAbsolutePath(SM, FilePath) ==
+            makeAbsolutePath(Context->Spec.OldHeader)) {
+      // FIXME: Minimize the include path like include-fixer.
+      std::string IncludeNewH =
+          "#include \"" + Context->Spec.NewHeader + "\"\n";
+      // This replacment for inserting header will be cleaned up at the end.
+      auto Err = FileAndReplacements.second.add(
+          tooling::Replacement(FilePath, UINT_MAX, 0, IncludeNewH));
+      if (Err)
+        llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+    }
+
+    auto SI = FilePathToFileID.find(FilePath);
+    // Ignore replacements for new.h/cc.
+    if (SI == FilePathToFileID.end()) continue;
+    llvm::StringRef Code = SM.getBufferData(SI->second);
+    auto Style = format::getStyle("file", FilePath, Context->FallbackStyle);
+    if (!Style) {
+      llvm::errs() << llvm::toString(Style.takeError()) << "\n";
+      continue;
+    }
+    auto CleanReplacements = format::cleanupAroundReplacements(
+        Code, Context->FileToReplacements[FilePath], *Style);
+
+    if (!CleanReplacements) {
+      llvm::errs() << llvm::toString(CleanReplacements.takeError()) << "\n";
+      continue;
+    }
+    Context->FileToReplacements[FilePath] = *CleanReplacements;
+  }
+}
+
+void ClangMoveTool::moveDeclsToNewFiles() {
+  std::vector<const NamedDecl *> NewHeaderDecls;
+  std::vector<const NamedDecl *> NewCCDecls;
+  for (const auto *MovedDecl : MovedDecls) {
+    if (isInHeaderFile(MovedDecl, Context->OriginalRunningDirectory,
+                       Context->Spec.OldHeader))
+      NewHeaderDecls.push_back(MovedDecl);
+    else
+      NewCCDecls.push_back(MovedDecl);
+  }
+
+  auto UsedDecls = getUsedDecls(RGBuilder.getGraph(), RemovedDecls);
+  std::vector<const NamedDecl *> ActualNewCCDecls;
+
+  // Filter out all unused helpers in NewCCDecls.
+  // We only move the used helpers (including transively used helpers) and the
+  // given symbols being moved.
+  for (const auto *D : NewCCDecls) {
+    if (llvm::is_contained(HelperDeclarations, D) &&
+        !UsedDecls.count(HelperDeclRGBuilder::getOutmostClassOrFunDecl(
+            D->getCanonicalDecl())))
+      continue;
+
+    LLVM_DEBUG(llvm::dbgs() << "Helper used in new.cc: " << D->getNameAsString()
+                            << " " << D << "\n");
+    ActualNewCCDecls.push_back(D);
+  }
+
+  if (!Context->Spec.NewHeader.empty()) {
+    std::string OldHeaderInclude =
+        Context->Spec.NewDependOnOld
+            ? "#include \"" + Context->Spec.OldHeader + "\"\n"
+            : "";
+    Context->FileToReplacements[Context->Spec.NewHeader] =
+        createInsertedReplacements(HeaderIncludes, NewHeaderDecls,
+                                   Context->Spec.NewHeader, /*IsHeader=*/true,
+                                   OldHeaderInclude);
+  }
+  if (!Context->Spec.NewCC.empty())
+    Context->FileToReplacements[Context->Spec.NewCC] =
+        createInsertedReplacements(CCIncludes, ActualNewCCDecls,
+                                   Context->Spec.NewCC);
+}
+
+// Move all contents from OldFile to NewFile.
+void ClangMoveTool::moveAll(SourceManager &SM, StringRef OldFile,
+                            StringRef NewFile) {
+  const FileEntry *FE = SM.getFileManager().getFile(makeAbsolutePath(OldFile));
+  if (!FE) {
+    llvm::errs() << "Failed to get file: " << OldFile << "\n";
+    return;
+  }
+  FileID ID = SM.getOrCreateFileID(FE, SrcMgr::C_User);
+  auto Begin = SM.getLocForStartOfFile(ID);
+  auto End = SM.getLocForEndOfFile(ID);
+  clang::tooling::Replacement RemoveAll (
+      SM, clang::CharSourceRange::getCharRange(Begin, End), "");
+  std::string FilePath = RemoveAll.getFilePath().str();
+  Context->FileToReplacements[FilePath] =
+      clang::tooling::Replacements(RemoveAll);
+
+  StringRef Code = SM.getBufferData(ID);
+  if (!NewFile.empty()) {
+    auto AllCode = clang::tooling::Replacements(
+        clang::tooling::Replacement(NewFile, 0, 0, Code));
+    auto ReplaceOldInclude = [&](clang::CharSourceRange OldHeaderIncludeRange) {
+      AllCode = AllCode.merge(clang::tooling::Replacements(
+          clang::tooling::Replacement(SM, OldHeaderIncludeRange,
+                                      '"' + Context->Spec.NewHeader + '"')));
+    };
+    // Fix the case where old.h/old.cc includes "old.h", we replace the
+    // `#include "old.h"` with `#include "new.h"`.
+    if (Context->Spec.NewCC == NewFile && OldHeaderIncludeRangeInCC.isValid())
+      ReplaceOldInclude(OldHeaderIncludeRangeInCC);
+    else if (Context->Spec.NewHeader == NewFile &&
+             OldHeaderIncludeRangeInHeader.isValid())
+      ReplaceOldInclude(OldHeaderIncludeRangeInHeader);
+    Context->FileToReplacements[NewFile] = std::move(AllCode);
+  }
+}
+
+void ClangMoveTool::onEndOfTranslationUnit() {
+  if (Context->DumpDeclarations) {
+    assert(Reporter);
+    for (const auto *Decl : UnremovedDeclsInOldHeader) {
+      auto Kind = Decl->getKind();
+      const std::string QualifiedName = Decl->getQualifiedNameAsString();
+      if (Kind == Decl::Kind::Var)
+        Reporter->reportDeclaration(QualifiedName, "Variable");
+      else if (Kind == Decl::Kind::Function ||
+               Kind == Decl::Kind::FunctionTemplate)
+        Reporter->reportDeclaration(QualifiedName, "Function");
+      else if (Kind == Decl::Kind::ClassTemplate ||
+               Kind == Decl::Kind::CXXRecord)
+        Reporter->reportDeclaration(QualifiedName, "Class");
+      else if (Kind == Decl::Kind::Enum)
+        Reporter->reportDeclaration(QualifiedName, "Enum");
+      else if (Kind == Decl::Kind::Typedef ||
+               Kind == Decl::Kind::TypeAlias ||
+               Kind == Decl::Kind::TypeAliasTemplate)
+        Reporter->reportDeclaration(QualifiedName, "TypeAlias");
+    }
+    return;
+  }
+
+  if (RemovedDecls.empty())
+    return;
+  // Ignore symbols that are not supported when checking if there is unremoved
+  // symbol in old header. This makes sure that we always move old files to new
+  // files when all symbols produced from dump_decls are moved.
+  auto IsSupportedKind = [](const clang::NamedDecl *Decl) {
+    switch (Decl->getKind()) {
+    case Decl::Kind::Function:
+    case Decl::Kind::FunctionTemplate:
+    case Decl::Kind::ClassTemplate:
+    case Decl::Kind::CXXRecord:
+    case Decl::Kind::Enum:
+    case Decl::Kind::Typedef:
+    case Decl::Kind::TypeAlias:
+    case Decl::Kind::TypeAliasTemplate:
+    case Decl::Kind::Var:
+      return true;
+    default:
+      return false;
+    }
+  };
+  if (std::none_of(UnremovedDeclsInOldHeader.begin(),
+                   UnremovedDeclsInOldHeader.end(), IsSupportedKind) &&
+      !Context->Spec.OldHeader.empty()) {
+    auto &SM = RemovedDecls[0]->getASTContext().getSourceManager();
+    moveAll(SM, Context->Spec.OldHeader, Context->Spec.NewHeader);
+    moveAll(SM, Context->Spec.OldCC, Context->Spec.NewCC);
+    return;
+  }
+  LLVM_DEBUG(RGBuilder.getGraph()->dump());
+  moveDeclsToNewFiles();
+  removeDeclsInOldFiles();
+}
+
+} // namespace move
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-move/ClangMove.h b/src/third_party/llvm-project/clang-tools-extra/clang-move/ClangMove.h
new file mode 100644
index 0000000..945c6db
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-move/ClangMove.h
@@ -0,0 +1,233 @@
+//===-- ClangMove.h - Clang move  -----------------------------------------===//
+//
+//                     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_MOVE_CLANGMOVE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_MOVE_CLANGMOVE_H
+
+#include "HelperDeclRefGraph.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringMap.h"
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace move {
+
+// A reporter which collects and reports declarations in old header.
+class DeclarationReporter {
+public:
+  DeclarationReporter() = default;
+  ~DeclarationReporter() = default;
+
+  void reportDeclaration(llvm::StringRef DeclarationName,
+                         llvm::StringRef Type) {
+    DeclarationList.emplace_back(DeclarationName, Type);
+  };
+
+  // A <DeclarationName, DeclarationKind> pair.
+  // The DeclarationName is a fully qualified name for the declaration, like
+  // A::B::Foo. The DeclarationKind is a string represents the kind of the
+  // declaration, currently only "Function" and "Class" are supported.
+  typedef std::pair<std::string, std::string> DeclarationPair;
+
+  const std::vector<DeclarationPair> getDeclarationList() const {
+    return DeclarationList;
+  }
+
+private:
+  std::vector<DeclarationPair> DeclarationList;
+};
+
+// Specify declarations being moved. It contains all information of the moved
+// declarations.
+struct MoveDefinitionSpec {
+  // The list of fully qualified names, e.g. Foo, a::Foo, b::Foo.
+  SmallVector<std::string, 4> Names;
+  // The file path of old header, can be relative path and absolute path.
+  std::string OldHeader;
+  // The file path of old cc, can be relative path and absolute path.
+  std::string OldCC;
+  // The file path of new header, can be relative path and absolute path.
+  std::string NewHeader;
+  // The file path of new cc, can be relative path and absolute path.
+  std::string NewCC;
+  // Whether old.h depends on new.h. If true, #include "new.h" will be added
+  // in old.h.
+  bool OldDependOnNew = false;
+  // Whether new.h depends on old.h. If true, #include "old.h" will be added
+  // in new.h.
+  bool NewDependOnOld = false;
+};
+
+// A Context which contains extra options which are used in ClangMoveTool.
+struct ClangMoveContext {
+  MoveDefinitionSpec Spec;
+  // The Key is file path, value is the replacements being applied to the file.
+  std::map<std::string, tooling::Replacements> &FileToReplacements;
+  // The original working directory where the local clang-move binary runs.
+  //
+  // clang-move will change its current working directory to the build
+  // directory when analyzing the source file. We save the original working
+  // directory in order to get the absolute file path for the fields in Spec.
+  std::string OriginalRunningDirectory;
+  // The name of a predefined code style.
+  std::string FallbackStyle;
+  // Whether dump all declarations in old header.
+  bool DumpDeclarations;
+};
+
+// This tool is used to move class/function definitions from the given source
+// files (old.h/cc) to new files (new.h/cc).
+// The goal of this tool is to make the new/old files as compilable as possible.
+//
+// When moving a symbol,all used helper declarations (e.g. static
+// functions/variables definitions in global/named namespace,
+// functions/variables/classes definitions in anonymous namespace) used by the
+// moved symbol in old.cc are moved to the new.cc. In addition, all
+// using-declarations in old.cc are also moved to new.cc; forward class
+// declarations in old.h are also moved to new.h.
+//
+// The remaining helper declarations which are unused by non-moved symbols in
+// old.cc will be removed.
+//
+// Note: When all declarations in old header are being moved, all code in
+// old.h/cc will be moved, which means old.h/cc are empty. This ignores symbols
+// that are not supported (e.g. typedef and enum) so that we always move old
+// files to new files when all symbols produced from dump_decls are moved.
+class ClangMoveTool : public ast_matchers::MatchFinder::MatchCallback {
+public:
+  ClangMoveTool(ClangMoveContext *const Context,
+                DeclarationReporter *const Reporter);
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder);
+
+  void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+  void onEndOfTranslationUnit() override;
+
+  /// Add #includes from old.h/cc files.
+  ///
+  /// \param IncludeHeader The name of the file being included, as written in
+  /// the source code.
+  /// \param IsAngled Whether the file name was enclosed in angle brackets.
+  /// \param SearchPath The search path which was used to find the IncludeHeader
+  /// in the file system. It can be a relative path or an absolute path.
+  /// \param FileName The name of file where the IncludeHeader comes from.
+  /// \param IncludeFilenameRange The source range for the written file name in
+  /// #include (i.e. "old.h" for #include "old.h") in old.cc.
+  /// \param SM The SourceManager.
+  void addIncludes(llvm::StringRef IncludeHeader, bool IsAngled,
+                   llvm::StringRef SearchPath, llvm::StringRef FileName,
+                   clang::CharSourceRange IncludeFilenameRange,
+                   const SourceManager &SM);
+
+  std::vector<const NamedDecl *> &getMovedDecls() { return MovedDecls; }
+
+  /// Add declarations being removed from old.h/cc. For each declarations, the
+  /// method also records the mapping relationship between the corresponding
+  /// FilePath and its FileID.
+  void addRemovedDecl(const NamedDecl *Decl);
+
+  llvm::SmallPtrSet<const NamedDecl *, 8> &getUnremovedDeclsInOldHeader() {
+    return UnremovedDeclsInOldHeader;
+  }
+
+private:
+  // Make the Path absolute using the OrignalRunningDirectory if the Path is not
+  // an absolute path. An empty Path will result in an empty string.
+  std::string makeAbsolutePath(StringRef Path);
+
+  void removeDeclsInOldFiles();
+  void moveDeclsToNewFiles();
+  void moveAll(SourceManager& SM, StringRef OldFile, StringRef NewFile);
+
+  // Stores all MatchCallbacks created by this tool.
+  std::vector<std::unique_ptr<ast_matchers::MatchFinder::MatchCallback>>
+      MatchCallbacks;
+  // Store all potential declarations (decls being moved, forward decls) that
+  // might need to move to new.h/cc. It includes all helper declarations
+  // (include unused ones) by default. The unused ones will be filtered out in
+  // the last stage. Saving in an AST-visited order.
+  std::vector<const NamedDecl *> MovedDecls;
+  // The declarations that needs to be removed in old.cc/h.
+  std::vector<const NamedDecl *> RemovedDecls;
+  // The #includes in old_header.h.
+  std::vector<std::string> HeaderIncludes;
+  // The #includes in old_cc.cc.
+  std::vector<std::string> CCIncludes;
+  // Records all helper declarations (function/variable/class definitions in
+  // anonymous namespaces, static function/variable definitions in global/named
+  // namespaces) in old.cc. saving in an AST-visited order.
+  std::vector<const NamedDecl *> HelperDeclarations;
+  // The unmoved named declarations in old header.
+  llvm::SmallPtrSet<const NamedDecl*, 8> UnremovedDeclsInOldHeader;
+  /// The source range for the written file name in #include (i.e. "old.h" for
+  /// #include "old.h") in old.cc,  including the enclosing quotes or angle
+  /// brackets.
+  clang::CharSourceRange OldHeaderIncludeRangeInCC;
+  /// The source range for the written file name in #include (i.e. "old.h" for
+  /// #include "old.h") in old.h,  including the enclosing quotes or angle
+  /// brackets.
+  clang::CharSourceRange OldHeaderIncludeRangeInHeader;
+  /// Mapping from FilePath to FileID, which can be used in post processes like
+  /// cleanup around replacements.
+  llvm::StringMap<FileID> FilePathToFileID;
+  /// A context contains all running options. It is not owned.
+  ClangMoveContext *const Context;
+  /// A reporter to report all declarations from old header. It is not owned.
+  DeclarationReporter *const Reporter;
+  /// Builder for helper declarations reference graph.
+  HelperDeclRGBuilder RGBuilder;
+};
+
+class ClangMoveAction : public clang::ASTFrontendAction {
+public:
+  ClangMoveAction(ClangMoveContext *const Context,
+                  DeclarationReporter *const Reporter)
+      : MoveTool(Context, Reporter) {
+    MoveTool.registerMatchers(&MatchFinder);
+  }
+
+  ~ClangMoveAction() override = default;
+
+  std::unique_ptr<clang::ASTConsumer>
+  CreateASTConsumer(clang::CompilerInstance &Compiler,
+                    llvm::StringRef InFile) override;
+
+private:
+  ast_matchers::MatchFinder MatchFinder;
+  ClangMoveTool MoveTool;
+};
+
+class ClangMoveActionFactory : public tooling::FrontendActionFactory {
+public:
+  ClangMoveActionFactory(ClangMoveContext *const Context,
+                         DeclarationReporter *const Reporter = nullptr)
+      : Context(Context), Reporter(Reporter) {}
+
+  clang::FrontendAction *create() override {
+    return new ClangMoveAction(Context, Reporter);
+  }
+
+private:
+  // Not owned.
+  ClangMoveContext *const Context;
+  DeclarationReporter *const Reporter;
+};
+
+} // namespace move
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_MOVE_CLANGMOVE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-move/HelperDeclRefGraph.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-move/HelperDeclRefGraph.cpp
new file mode 100644
index 0000000..28200e0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-move/HelperDeclRefGraph.cpp
@@ -0,0 +1,137 @@
+//===-- UsedHelperDeclFinder.cpp - AST-based call graph for helper decls --===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "HelperDeclRefGraph.h"
+#include "ClangMove.h"
+#include "clang/AST/Decl.h"
+#include "llvm/Support/Debug.h"
+#include <vector>
+
+#define DEBUG_TYPE "clang-move"
+
+namespace clang {
+namespace move {
+
+void HelperDeclRefGraph::print(raw_ostream &OS) const {
+  OS << " --- Call graph Dump --- \n";
+  for (auto I = DeclMap.begin(); I != DeclMap.end(); ++I) {
+    const CallGraphNode *N = (I->second).get();
+
+    OS << "  Declarations: ";
+    N->print(OS);
+    OS << " (" << N << ") ";
+    OS << " calls: ";
+    for (auto CI = N->begin(), CE = N->end(); CI != CE; ++CI) {
+      (*CI)->print(OS);
+      OS << " (" << CI << ") ";
+    }
+    OS << '\n';
+  }
+  OS.flush();
+}
+
+void HelperDeclRefGraph::addEdge(const Decl *Caller, const Decl *Callee) {
+  assert(Caller);
+  assert(Callee);
+
+  // Ignore the case where Caller equals Callee. This happens in the static
+  // class member definitions in global namespace like "int CLASS::static_var =
+  // 1;", its DC is a VarDel whose outmost enclosing declaration is the "CLASS"
+  // CXXRecordDecl.
+  if (Caller == Callee) return;
+
+  // Allocate a new node, mark it as root, and process it's calls.
+  CallGraphNode *CallerNode = getOrInsertNode(const_cast<Decl *>(Caller));
+  CallGraphNode *CalleeNode = getOrInsertNode(const_cast<Decl *>(Callee));
+  CallerNode->addCallee(CalleeNode);
+}
+
+void HelperDeclRefGraph::dump() const { print(llvm::errs()); }
+
+CallGraphNode *HelperDeclRefGraph::getOrInsertNode(Decl *F) {
+  F = F->getCanonicalDecl();
+  std::unique_ptr<CallGraphNode> &Node = DeclMap[F];
+  if (Node)
+    return Node.get();
+
+  Node = llvm::make_unique<CallGraphNode>(F);
+  return Node.get();
+}
+
+CallGraphNode *HelperDeclRefGraph::getNode(const Decl *D) const {
+  auto I = DeclMap.find(D->getCanonicalDecl());
+  return I == DeclMap.end() ? nullptr : I->second.get();
+}
+
+llvm::DenseSet<const CallGraphNode *>
+HelperDeclRefGraph::getReachableNodes(const Decl *Root) const {
+  const auto *RootNode = getNode(Root);
+  if (!RootNode)
+    return {};
+  llvm::DenseSet<const CallGraphNode *> ConnectedNodes;
+  std::function<void(const CallGraphNode *)> VisitNode =
+      [&](const CallGraphNode *Node) {
+        if (ConnectedNodes.count(Node))
+          return;
+        ConnectedNodes.insert(Node);
+        for (auto It = Node->begin(), End = Node->end(); It != End; ++It)
+          VisitNode(*It);
+      };
+
+  VisitNode(RootNode);
+  return ConnectedNodes;
+}
+
+const Decl *HelperDeclRGBuilder::getOutmostClassOrFunDecl(const Decl *D) {
+  const auto *DC = D->getDeclContext();
+  const auto *Result = D;
+  while (DC) {
+    if (const auto *RD = dyn_cast<CXXRecordDecl>(DC))
+      Result = RD;
+    else if (const auto *FD = dyn_cast<FunctionDecl>(DC))
+      Result = FD;
+    DC = DC->getParent();
+  }
+  return Result;
+}
+
+void HelperDeclRGBuilder::run(
+    const ast_matchers::MatchFinder::MatchResult &Result) {
+  // Construct the graph by adding a directed edge from caller to callee.
+  //
+  // "dc" is the closest ancestor declaration of "func_ref" or "used_class", it
+  // might be not the targetted Caller Decl, we always use the outmost enclosing
+  // FunctionDecl/CXXRecordDecl of "dc". For example,
+  //
+  //   int MoveClass::F() { int a = helper(); return a; }
+  //
+  // The matched "dc" of "helper" DeclRefExpr is a VarDecl, we traverse up AST
+  // to find the outmost "MoveClass" CXXRecordDecl and use it as Caller.
+  if (const auto *FuncRef = Result.Nodes.getNodeAs<DeclRefExpr>("func_ref")) {
+    const auto *DC = Result.Nodes.getNodeAs<Decl>("dc");
+    assert(DC);
+    LLVM_DEBUG(llvm::dbgs() << "Find helper function usage: "
+                            << FuncRef->getDecl()->getNameAsString() << " ("
+                            << FuncRef->getDecl() << ")\n");
+    RG->addEdge(
+        getOutmostClassOrFunDecl(DC->getCanonicalDecl()),
+        getOutmostClassOrFunDecl(FuncRef->getDecl()->getCanonicalDecl()));
+  } else if (const auto *UsedClass =
+                 Result.Nodes.getNodeAs<CXXRecordDecl>("used_class")) {
+    const auto *DC = Result.Nodes.getNodeAs<Decl>("dc");
+    assert(DC);
+    LLVM_DEBUG(llvm::dbgs()
+               << "Find helper class usage: " << UsedClass->getNameAsString()
+               << " (" << UsedClass << ")\n");
+    RG->addEdge(getOutmostClassOrFunDecl(DC->getCanonicalDecl()), UsedClass);
+  }
+}
+
+} // namespace move
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-move/HelperDeclRefGraph.h b/src/third_party/llvm-project/clang-tools-extra/clang-move/HelperDeclRefGraph.h
new file mode 100644
index 0000000..11b3c9c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-move/HelperDeclRefGraph.h
@@ -0,0 +1,99 @@
+//===-- UsedHelperDeclFinder.h - AST-based call graph for helper decls ----===//
+//
+//                     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_MOVE_USED_HELPER_DECL_FINDER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_MOVE_USED_HELPER_DECL_FINDER_H
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Analysis/CallGraph.h"
+#include "llvm/ADT/DenseSet.h"
+#include <memory>
+#include <vector>
+
+namespace clang {
+namespace move {
+
+// A reference graph for finding used/unused helper declarations in a single
+// translation unit (e.g. old.cc). We don't reuse CallGraph in clang/Analysis
+// because that CallGraph only supports function declarations.
+//
+// Helper declarations include following types:
+//   * function/variable/class definitions in an anonymous namespace.
+//   * static function/variable definitions in a global/named namespace.
+//
+// The reference graph is a directed graph. Each node in the graph represents a
+// helper declaration in old.cc or a non-moved/moved declaration (e.g. class,
+// function) in old.h, which means each node is associated with a Decl.
+//
+// To construct the graph, we use AST matcher to find interesting Decls (usually
+// a pair of Caller and Callee), and add an edge from the Caller node to the
+// Callee node.
+//
+// Specially, for a class, it might have multiple declarations such methods
+// and member variables. We only use a single node to present this class, and
+// this node is associated with the class declaration (CXXRecordDecl).
+//
+// The graph has 3 types of edges:
+//   1. moved_decl => helper_decl
+//   2. non_moved_decl => helper_decl
+//   3. helper_decl => helper_decl
+class HelperDeclRefGraph {
+public:
+  HelperDeclRefGraph() = default;
+  ~HelperDeclRefGraph() = default;
+
+  // Add a directed edge from the caller node to the callee node.
+  // A new node will be created if the node for Caller/Callee doesn't exist.
+  //
+  // Note that, all class member declarations are represented by a single node
+  // in the graph. The corresponding Decl of this node is the class declaration.
+  void addEdge(const Decl *Caller, const Decl *Callee);
+  CallGraphNode *getNode(const Decl *D) const;
+
+  // Get all reachable nodes in the graph from the given declaration D's node,
+  // including D.
+  llvm::DenseSet<const CallGraphNode *> getReachableNodes(const Decl *D) const;
+
+  // Dump the call graph for debug purpose.
+  void dump() const;
+
+private:
+  void print(raw_ostream &OS) const;
+  // Lookup a node for the given declaration D. If not found, insert a new
+  // node into the graph.
+  CallGraphNode *getOrInsertNode(Decl *D);
+
+  typedef llvm::DenseMap<const Decl *, std::unique_ptr<CallGraphNode>>
+      DeclMapTy;
+
+  // DeclMap owns all CallGraphNodes.
+  DeclMapTy DeclMap;
+};
+
+// A builder helps to construct a call graph of helper declarations.
+class HelperDeclRGBuilder : public ast_matchers::MatchFinder::MatchCallback {
+public:
+  HelperDeclRGBuilder() : RG(new HelperDeclRefGraph) {}
+  void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  const HelperDeclRefGraph *getGraph() const { return RG.get(); }
+
+  // Find out the outmost enclosing class/function declaration of a given D.
+  // For a CXXMethodDecl, get its CXXRecordDecl; For a VarDecl/FunctionDecl, get
+  // its outmost enclosing FunctionDecl or CXXRecordDecl.
+  // Return D if not found.
+  static const Decl *getOutmostClassOrFunDecl(const Decl *D);
+
+private:
+  std::unique_ptr<HelperDeclRefGraph> RG;
+};
+
+} // namespace move
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_MOVE_USED_HELPER_DECL_FINDER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-move/tool/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-move/tool/CMakeLists.txt
new file mode 100644
index 0000000..9f678bb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-move/tool/CMakeLists.txt
@@ -0,0 +1,18 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
+
+add_clang_executable(clang-move
+  ClangMoveMain.cpp
+  )
+
+target_link_libraries(clang-move
+  PRIVATE
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFormat
+  clangFrontend
+  clangMove
+  clangRewrite
+  clangTooling
+  clangToolingCore
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-move/tool/ClangMoveMain.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-move/tool/ClangMoveMain.cpp
new file mode 100644
index 0000000..e5fee26
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-move/tool/ClangMoveMain.cpp
@@ -0,0 +1,210 @@
+//===-- ClangMoveMain.cpp - move defintion to new file ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangMove.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/ArgumentsAdjusters.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/YAMLTraits.h"
+#include <set>
+#include <string>
+
+using namespace clang;
+using namespace llvm;
+
+namespace {
+
+std::error_code CreateNewFile(const llvm::Twine &path) {
+  int fd = 0;
+  if (std::error_code ec = llvm::sys::fs::openFileForWrite(
+          path, fd, llvm::sys::fs::CD_CreateAlways, llvm::sys::fs::F_Text))
+    return ec;
+
+  return llvm::sys::Process::SafelyCloseFileDescriptor(fd);
+}
+
+cl::OptionCategory ClangMoveCategory("clang-move options");
+
+cl::list<std::string> Names("names", cl::CommaSeparated,
+                            cl::desc("The list of the names of classes being "
+                                     "moved, e.g. \"Foo,a::Foo,b::Foo\"."),
+                            cl::cat(ClangMoveCategory));
+
+cl::opt<std::string>
+    OldHeader("old_header",
+              cl::desc("The relative/absolute file path of old header."),
+              cl::cat(ClangMoveCategory));
+
+cl::opt<std::string>
+    OldCC("old_cc", cl::desc("The relative/absolute file path of old cc."),
+          cl::cat(ClangMoveCategory));
+
+cl::opt<std::string>
+    NewHeader("new_header",
+              cl::desc("The relative/absolute file path of new header."),
+              cl::cat(ClangMoveCategory));
+
+cl::opt<std::string>
+    NewCC("new_cc", cl::desc("The relative/absolute file path of new cc."),
+          cl::cat(ClangMoveCategory));
+
+cl::opt<bool>
+    OldDependOnNew("old_depend_on_new",
+                   cl::desc("Whether old header will depend on new header. If "
+                            "true, clang-move will "
+                            "add #include of new header to old header."),
+                   cl::init(false), cl::cat(ClangMoveCategory));
+
+cl::opt<bool>
+    NewDependOnOld("new_depend_on_old",
+                   cl::desc("Whether new header will depend on old header. If "
+                            "true, clang-move will "
+                            "add #include of old header to new header."),
+                   cl::init(false), cl::cat(ClangMoveCategory));
+
+cl::opt<std::string>
+    Style("style",
+          cl::desc("The style name used for reformatting. Default is \"llvm\""),
+          cl::init("llvm"), cl::cat(ClangMoveCategory));
+
+cl::opt<bool> Dump("dump_result",
+                   cl::desc("Dump results in JSON format to stdout."),
+                   cl::cat(ClangMoveCategory));
+
+cl::opt<bool> DumpDecls(
+    "dump_decls",
+    cl::desc("Dump all declarations in old header (JSON format) to stdout. If "
+             "the option is specified, other command options will be ignored. "
+             "An empty JSON will be returned if old header isn't specified."),
+    cl::cat(ClangMoveCategory));
+
+} // namespace
+
+int main(int argc, const char **argv) {
+  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+  tooling::CommonOptionsParser OptionsParser(argc, argv, ClangMoveCategory);
+
+  if (OldDependOnNew && NewDependOnOld) {
+    llvm::errs() << "Provide either --old_depend_on_new or "
+                    "--new_depend_on_old. clang-move doesn't support these two "
+                    "options at same time (It will introduce include cycle).\n";
+    return 1;
+  }
+
+  tooling::RefactoringTool Tool(OptionsParser.getCompilations(),
+                                OptionsParser.getSourcePathList());
+  // Add "-fparse-all-comments" compile option to make clang parse all comments.
+  Tool.appendArgumentsAdjuster(tooling::getInsertArgumentAdjuster(
+      "-fparse-all-comments", tooling::ArgumentInsertPosition::BEGIN));
+  move::MoveDefinitionSpec Spec;
+  Spec.Names = {Names.begin(), Names.end()};
+  Spec.OldHeader = OldHeader;
+  Spec.NewHeader = NewHeader;
+  Spec.OldCC = OldCC;
+  Spec.NewCC = NewCC;
+  Spec.OldDependOnNew = OldDependOnNew;
+  Spec.NewDependOnOld = NewDependOnOld;
+
+  llvm::SmallString<128> InitialDirectory;
+  if (std::error_code EC = llvm::sys::fs::current_path(InitialDirectory))
+    llvm::report_fatal_error("Cannot detect current path: " +
+                             Twine(EC.message()));
+
+  move::ClangMoveContext Context{Spec, Tool.getReplacements(),
+                                 InitialDirectory.str(), Style, DumpDecls};
+  move::DeclarationReporter Reporter;
+  move::ClangMoveActionFactory Factory(&Context, &Reporter);
+  
+  int CodeStatus = Tool.run(&Factory);
+  if (CodeStatus)
+    return CodeStatus;
+
+  if (DumpDecls) {
+    llvm::outs() << "[\n";
+    const auto &Declarations = Reporter.getDeclarationList();
+    for (auto I = Declarations.begin(), E = Declarations.end(); I != E; ++I) {
+      llvm::outs() << "  {\n";
+      llvm::outs() << "    \"DeclarationName\": \"" << I->first << "\",\n";
+      llvm::outs() << "    \"DeclarationType\": \"" << I->second << "\"\n";
+      llvm::outs() << "  }";
+      // Don't print trailing "," at the end of last element.
+      if (I != std::prev(E))
+        llvm::outs() << ",\n";
+    }
+    llvm::outs() << "\n]\n";
+    return 0;
+  }
+
+  if (!NewCC.empty()) {
+    std::error_code EC = CreateNewFile(NewCC);
+    if (EC) {
+      llvm::errs() << "Failed to create " << NewCC << ": " << EC.message()
+                   << "\n";
+      return EC.value();
+    }
+  }
+  if (!NewHeader.empty()) {
+    std::error_code EC = CreateNewFile(NewHeader);
+    if (EC) {
+      llvm::errs() << "Failed to create " << NewHeader << ": " << EC.message()
+                   << "\n";
+      return EC.value();
+    }
+  }
+
+  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions());
+  clang::TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts);
+  DiagnosticsEngine Diagnostics(
+      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
+      &DiagnosticPrinter, false);
+  auto &FileMgr = Tool.getFiles();
+  SourceManager SM(Diagnostics, FileMgr);
+  Rewriter Rewrite(SM, LangOptions());
+
+  if (!formatAndApplyAllReplacements(Tool.getReplacements(), Rewrite, Style)) {
+    llvm::errs() << "Failed applying all replacements.\n";
+    return 1;
+  }
+
+  if (Dump) {
+    std::set<llvm::StringRef> Files;
+    for (const auto &it : Tool.getReplacements())
+      Files.insert(it.first);
+    auto WriteToJson = [&](llvm::raw_ostream &OS) {
+      OS << "[\n";
+      for (auto I = Files.begin(), E = Files.end(); I != E; ++I) {
+        OS << "  {\n";
+        OS << "    \"FilePath\": \"" << *I << "\",\n";
+        const auto *Entry = FileMgr.getFile(*I);
+        auto ID = SM.translateFile(Entry);
+        std::string Content;
+        llvm::raw_string_ostream ContentStream(Content);
+        Rewrite.getEditBuffer(ID).write(ContentStream);
+        OS << "    \"SourceText\": \""
+           << llvm::yaml::escape(ContentStream.str()) << "\"\n";
+        OS << "  }";
+        if (I != std::prev(E))
+          OS << ",\n";
+      }
+      OS << "\n]\n";
+    };
+    WriteToJson(llvm::outs());
+    return 0;
+  }
+
+  return Rewrite.overwriteChangedFiles();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-query/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-query/CMakeLists.txt
new file mode 100644
index 0000000..46febd6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-query/CMakeLists.txt
@@ -0,0 +1,18 @@
+set(LLVM_LINK_COMPONENTS
+  lineeditor
+  support
+  )
+
+add_clang_library(clangQuery
+  Query.cpp
+  QueryParser.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangDynamicASTMatchers
+  clangFrontend
+  )
+
+add_subdirectory(tool)
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-query/Query.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-query/Query.cpp
new file mode 100644
index 0000000..072ee6b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-query/Query.cpp
@@ -0,0 +1,146 @@
+//===---- Query.cpp - clang-query query -----------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Query.h"
+#include "QuerySession.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/TextDiagnostic.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::ast_matchers;
+using namespace clang::ast_matchers::dynamic;
+
+namespace clang {
+namespace query {
+
+Query::~Query() {}
+
+bool InvalidQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
+  OS << ErrStr << "\n";
+  return false;
+}
+
+bool NoOpQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
+  return true;
+}
+
+bool HelpQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
+  OS << "Available commands:\n\n"
+        "  match MATCHER, m MATCHER          "
+        "Match the loaded ASTs against the given matcher.\n"
+        "  let NAME MATCHER, l NAME MATCHER  "
+        "Give a matcher expression a name, to be used later\n"
+        "                                    "
+        "as part of other expressions.\n"
+        "  set bind-root (true|false)        "
+        "Set whether to bind the root matcher to \"root\".\n"
+        "  set output (diag|print|dump)      "
+        "Set whether to print bindings as diagnostics,\n"
+        "                                    "
+        "AST pretty prints or AST dumps.\n"
+        "  quit                              "
+        "Terminates the query session.\n\n";
+  return true;
+}
+
+bool QuitQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
+  QS.Terminate = true;
+  return true;
+}
+
+namespace {
+
+struct CollectBoundNodes : MatchFinder::MatchCallback {
+  std::vector<BoundNodes> &Bindings;
+  CollectBoundNodes(std::vector<BoundNodes> &Bindings) : Bindings(Bindings) {}
+  void run(const MatchFinder::MatchResult &Result) override {
+    Bindings.push_back(Result.Nodes);
+  }
+};
+
+} // namespace
+
+bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
+  unsigned MatchCount = 0;
+
+  for (auto &AST : QS.ASTs) {
+    MatchFinder Finder;
+    std::vector<BoundNodes> Matches;
+    DynTypedMatcher MaybeBoundMatcher = Matcher;
+    if (QS.BindRoot) {
+      llvm::Optional<DynTypedMatcher> M = Matcher.tryBind("root");
+      if (M)
+        MaybeBoundMatcher = *M;
+    }
+    CollectBoundNodes Collect(Matches);
+    if (!Finder.addDynamicMatcher(MaybeBoundMatcher, &Collect)) {
+      OS << "Not a valid top-level matcher.\n";
+      return false;
+    }
+    Finder.matchAST(AST->getASTContext());
+
+    for (auto MI = Matches.begin(), ME = Matches.end(); MI != ME; ++MI) {
+      OS << "\nMatch #" << ++MatchCount << ":\n\n";
+
+      for (auto BI = MI->getMap().begin(), BE = MI->getMap().end(); BI != BE;
+           ++BI) {
+        switch (QS.OutKind) {
+        case OK_Diag: {
+          clang::SourceRange R = BI->second.getSourceRange();
+          if (R.isValid()) {
+            TextDiagnostic TD(OS, AST->getASTContext().getLangOpts(),
+                              &AST->getDiagnostics().getDiagnosticOptions());
+            TD.emitDiagnostic(
+                FullSourceLoc(R.getBegin(), AST->getSourceManager()),
+                DiagnosticsEngine::Note, "\"" + BI->first + "\" binds here",
+                CharSourceRange::getTokenRange(R), None);
+          }
+          break;
+        }
+        case OK_Print: {
+          OS << "Binding for \"" << BI->first << "\":\n";
+          BI->second.print(OS, AST->getASTContext().getPrintingPolicy());
+          OS << "\n";
+          break;
+        }
+        case OK_Dump: {
+          OS << "Binding for \"" << BI->first << "\":\n";
+          BI->second.dump(OS, AST->getSourceManager());
+          OS << "\n";
+          break;
+        }
+        }
+      }
+
+      if (MI->getMap().empty())
+        OS << "No bindings.\n";
+    }
+  }
+
+  OS << MatchCount << (MatchCount == 1 ? " match.\n" : " matches.\n");
+  return true;
+}
+
+bool LetQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
+  if (Value) {
+    QS.NamedValues[Name] = Value;
+  } else {
+    QS.NamedValues.erase(Name);
+  }
+  return true;
+}
+
+#ifndef _MSC_VER
+const QueryKind SetQueryKind<bool>::value;
+const QueryKind SetQueryKind<OutputKind>::value;
+#endif
+
+} // namespace query
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-query/Query.h b/src/third_party/llvm-project/clang-tools-extra/clang-query/Query.h
new file mode 100644
index 0000000..b8c59cb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-query/Query.h
@@ -0,0 +1,136 @@
+//===--- Query.h - clang-query ----------------------------------*- 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_QUERY_QUERY_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_H
+
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/Optional.h"
+#include <string>
+
+namespace clang {
+namespace query {
+
+enum OutputKind { OK_Diag, OK_Print, OK_Dump };
+
+enum QueryKind {
+  QK_Invalid,
+  QK_NoOp,
+  QK_Help,
+  QK_Let,
+  QK_Match,
+  QK_SetBool,
+  QK_SetOutputKind,
+  QK_Quit
+};
+
+class QuerySession;
+
+struct Query : llvm::RefCountedBase<Query> {
+  Query(QueryKind Kind) : Kind(Kind) {}
+  virtual ~Query();
+
+  /// Perform the query on \p QS and print output to \p OS.
+  ///
+  /// \return false if an error occurs, otherwise return true.
+  virtual bool run(llvm::raw_ostream &OS, QuerySession &QS) const = 0;
+
+  const QueryKind Kind;
+};
+
+typedef llvm::IntrusiveRefCntPtr<Query> QueryRef;
+
+/// Any query which resulted in a parse error.  The error message is in ErrStr.
+struct InvalidQuery : Query {
+  InvalidQuery(const Twine &ErrStr) : Query(QK_Invalid), ErrStr(ErrStr.str()) {}
+  bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
+
+  std::string ErrStr;
+
+  static bool classof(const Query *Q) { return Q->Kind == QK_Invalid; }
+};
+
+/// No-op query (i.e. a blank line).
+struct NoOpQuery : Query {
+  NoOpQuery() : Query(QK_NoOp) {}
+  bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
+
+  static bool classof(const Query *Q) { return Q->Kind == QK_NoOp; }
+};
+
+/// Query for "help".
+struct HelpQuery : Query {
+  HelpQuery() : Query(QK_Help) {}
+  bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
+
+  static bool classof(const Query *Q) { return Q->Kind == QK_Help; }
+};
+
+/// Query for "quit".
+struct QuitQuery : Query {
+  QuitQuery() : Query(QK_Quit) {}
+  bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
+
+  static bool classof(const Query *Q) { return Q->Kind == QK_Quit; }
+};
+
+/// Query for "match MATCHER".
+struct MatchQuery : Query {
+  MatchQuery(const ast_matchers::dynamic::DynTypedMatcher &Matcher)
+      : Query(QK_Match), Matcher(Matcher) {}
+  bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
+
+  ast_matchers::dynamic::DynTypedMatcher Matcher;
+
+  static bool classof(const Query *Q) { return Q->Kind == QK_Match; }
+};
+
+struct LetQuery : Query {
+  LetQuery(StringRef Name, const ast_matchers::dynamic::VariantValue &Value)
+      : Query(QK_Let), Name(Name), Value(Value) {}
+  bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;
+
+  std::string Name;
+  ast_matchers::dynamic::VariantValue Value;
+
+  static bool classof(const Query *Q) { return Q->Kind == QK_Let; }
+};
+
+template <typename T> struct SetQueryKind {};
+
+template <> struct SetQueryKind<bool> {
+  static const QueryKind value = QK_SetBool;
+};
+
+template <> struct SetQueryKind<OutputKind> {
+  static const QueryKind value = QK_SetOutputKind;
+};
+
+/// Query for "set VAR VALUE".
+template <typename T> struct SetQuery : Query {
+  SetQuery(T QuerySession::*Var, T Value)
+      : Query(SetQueryKind<T>::value), Var(Var), Value(Value) {}
+  bool run(llvm::raw_ostream &OS, QuerySession &QS) const override {
+    QS.*Var = Value;
+    return true;
+  }
+
+  static bool classof(const Query *Q) {
+    return Q->Kind == SetQueryKind<T>::value;
+  }
+
+  T QuerySession::*Var;
+  T Value;
+};
+
+} // namespace query
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-query/QueryParser.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-query/QueryParser.cpp
new file mode 100644
index 0000000..bb3d1b3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-query/QueryParser.cpp
@@ -0,0 +1,272 @@
+//===---- QueryParser.cpp - clang-query command parser --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "QueryParser.h"
+#include "Query.h"
+#include "QuerySession.h"
+#include "clang/ASTMatchers/Dynamic/Parser.h"
+#include "clang/Basic/CharInfo.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include <set>
+
+using namespace llvm;
+using namespace clang::ast_matchers::dynamic;
+
+namespace clang {
+namespace query {
+
+// Lex any amount of whitespace followed by a "word" (any sequence of
+// non-whitespace characters) from the start of region [Begin,End).  If no word
+// is found before End, return StringRef().  Begin is adjusted to exclude the
+// lexed region.
+StringRef QueryParser::lexWord() {
+  while (true) {
+    if (Begin == End)
+      return StringRef(Begin, 0);
+
+    if (!isWhitespace(*Begin))
+      break;
+
+    ++Begin;
+  }
+
+  const char *WordBegin = Begin;
+
+  while (true) {
+    ++Begin;
+
+    if (Begin == End || isWhitespace(*Begin))
+      return StringRef(WordBegin, Begin - WordBegin);
+  }
+}
+
+// This is the StringSwitch-alike used by lexOrCompleteWord below. See that
+// function for details.
+template <typename T> struct QueryParser::LexOrCompleteWord {
+  StringRef Word;
+  StringSwitch<T> Switch;
+
+  QueryParser *P;
+  // Set to the completion point offset in Word, or StringRef::npos if
+  // completion point not in Word.
+  size_t WordCompletionPos;
+
+  // Lexes a word and stores it in Word. Returns a LexOrCompleteWord<T> object
+  // that can be used like a llvm::StringSwitch<T>, but adds cases as possible
+  // completions if the lexed word contains the completion point.
+  LexOrCompleteWord(QueryParser *P, StringRef &OutWord)
+      : Word(P->lexWord()), Switch(Word), P(P),
+        WordCompletionPos(StringRef::npos) {
+    OutWord = Word;
+    if (P->CompletionPos && P->CompletionPos <= Word.data() + Word.size()) {
+      if (P->CompletionPos < Word.data())
+        WordCompletionPos = 0;
+      else
+        WordCompletionPos = P->CompletionPos - Word.data();
+    }
+  }
+
+  LexOrCompleteWord &Case(llvm::StringLiteral CaseStr, const T &Value,
+                          bool IsCompletion = true) {
+
+    if (WordCompletionPos == StringRef::npos)
+      Switch.Case(CaseStr, Value);
+    else if (CaseStr.size() != 0 && IsCompletion && WordCompletionPos <= CaseStr.size() &&
+             CaseStr.substr(0, WordCompletionPos) ==
+                 Word.substr(0, WordCompletionPos))
+      P->Completions.push_back(LineEditor::Completion(
+          (CaseStr.substr(WordCompletionPos) + " ").str(), CaseStr));
+    return *this;
+  }
+
+  T Default(T Value) { return Switch.Default(Value); }
+};
+
+QueryRef QueryParser::parseSetBool(bool QuerySession::*Var) {
+  StringRef ValStr;
+  unsigned Value = LexOrCompleteWord<unsigned>(this, ValStr)
+                       .Case("false", 0)
+                       .Case("true", 1)
+                       .Default(~0u);
+  if (Value == ~0u) {
+    return new InvalidQuery("expected 'true' or 'false', got '" + ValStr + "'");
+  }
+  return new SetQuery<bool>(Var, Value);
+}
+
+QueryRef QueryParser::parseSetOutputKind() {
+  StringRef ValStr;
+  unsigned OutKind = LexOrCompleteWord<unsigned>(this, ValStr)
+                         .Case("diag", OK_Diag)
+                         .Case("print", OK_Print)
+                         .Case("dump", OK_Dump)
+                         .Default(~0u);
+  if (OutKind == ~0u) {
+    return new InvalidQuery("expected 'diag', 'print' or 'dump', got '" +
+                            ValStr + "'");
+  }
+  return new SetQuery<OutputKind>(&QuerySession::OutKind, OutputKind(OutKind));
+}
+
+QueryRef QueryParser::endQuery(QueryRef Q) {
+  const char *Extra = Begin;
+  if (!lexWord().empty())
+    return new InvalidQuery("unexpected extra input: '" +
+                            StringRef(Extra, End - Extra) + "'");
+  return Q;
+}
+
+namespace {
+
+enum ParsedQueryKind {
+  PQK_Invalid,
+  PQK_NoOp,
+  PQK_Help,
+  PQK_Let,
+  PQK_Match,
+  PQK_Set,
+  PQK_Unlet,
+  PQK_Quit
+};
+
+enum ParsedQueryVariable { PQV_Invalid, PQV_Output, PQV_BindRoot };
+
+QueryRef makeInvalidQueryFromDiagnostics(const Diagnostics &Diag) {
+  std::string ErrStr;
+  llvm::raw_string_ostream OS(ErrStr);
+  Diag.printToStreamFull(OS);
+  return new InvalidQuery(OS.str());
+}
+
+} // namespace
+
+QueryRef QueryParser::completeMatcherExpression() {
+  std::vector<MatcherCompletion> Comps = Parser::completeExpression(
+      StringRef(Begin, End - Begin), CompletionPos - Begin, nullptr,
+      &QS.NamedValues);
+  for (auto I = Comps.begin(), E = Comps.end(); I != E; ++I) {
+    Completions.push_back(LineEditor::Completion(I->TypedText, I->MatcherDecl));
+  }
+  return QueryRef();
+}
+
+QueryRef QueryParser::doParse() {
+  StringRef CommandStr;
+  ParsedQueryKind QKind = LexOrCompleteWord<ParsedQueryKind>(this, CommandStr)
+                              .Case("", PQK_NoOp)
+                              .Case("help", PQK_Help)
+                              .Case("m", PQK_Match, /*IsCompletion=*/false)
+                              .Case("let", PQK_Let)
+                              .Case("match", PQK_Match)
+                              .Case("set", PQK_Set)
+                              .Case("unlet", PQK_Unlet)
+                              .Case("quit", PQK_Quit)
+                              .Default(PQK_Invalid);
+
+  switch (QKind) {
+  case PQK_NoOp:
+    return new NoOpQuery;
+
+  case PQK_Help:
+    return endQuery(new HelpQuery);
+
+  case PQK_Quit:
+    return endQuery(new QuitQuery);
+
+  case PQK_Let: {
+    StringRef Name = lexWord();
+
+    if (Name.empty())
+      return new InvalidQuery("expected variable name");
+
+    if (CompletionPos)
+      return completeMatcherExpression();
+
+    Diagnostics Diag;
+    ast_matchers::dynamic::VariantValue Value;
+    if (!Parser::parseExpression(StringRef(Begin, End - Begin), nullptr,
+                                 &QS.NamedValues, &Value, &Diag)) {
+      return makeInvalidQueryFromDiagnostics(Diag);
+    }
+
+    return new LetQuery(Name, Value);
+  }
+
+  case PQK_Match: {
+    if (CompletionPos)
+      return completeMatcherExpression();
+
+    Diagnostics Diag;
+    Optional<DynTypedMatcher> Matcher = Parser::parseMatcherExpression(
+        StringRef(Begin, End - Begin), nullptr, &QS.NamedValues, &Diag);
+    if (!Matcher) {
+      return makeInvalidQueryFromDiagnostics(Diag);
+    }
+    return new MatchQuery(*Matcher);
+  }
+
+  case PQK_Set: {
+    StringRef VarStr;
+    ParsedQueryVariable Var = LexOrCompleteWord<ParsedQueryVariable>(this,
+                                                                     VarStr)
+                                  .Case("output", PQV_Output)
+                                  .Case("bind-root", PQV_BindRoot)
+                                  .Default(PQV_Invalid);
+    if (VarStr.empty())
+      return new InvalidQuery("expected variable name");
+    if (Var == PQV_Invalid)
+      return new InvalidQuery("unknown variable: '" + VarStr + "'");
+
+    QueryRef Q;
+    switch (Var) {
+    case PQV_Output:
+      Q = parseSetOutputKind();
+      break;
+    case PQV_BindRoot:
+      Q = parseSetBool(&QuerySession::BindRoot);
+      break;
+    case PQV_Invalid:
+      llvm_unreachable("Invalid query kind");
+    }
+
+    return endQuery(Q);
+  }
+
+  case PQK_Unlet: {
+    StringRef Name = lexWord();
+
+    if (Name.empty())
+      return new InvalidQuery("expected variable name");
+
+    return endQuery(new LetQuery(Name, VariantValue()));
+  }
+
+  case PQK_Invalid:
+    return new InvalidQuery("unknown command: " + CommandStr);
+  }
+
+  llvm_unreachable("Invalid query kind");
+}
+
+QueryRef QueryParser::parse(StringRef Line, const QuerySession &QS) {
+  return QueryParser(Line, QS).doParse();
+}
+
+std::vector<LineEditor::Completion>
+QueryParser::complete(StringRef Line, size_t Pos, const QuerySession &QS) {
+  QueryParser P(Line, QS);
+  P.CompletionPos = Line.data() + Pos;
+
+  P.doParse();
+  return P.Completions;
+}
+
+} // namespace query
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-query/QueryParser.h b/src/third_party/llvm-project/clang-tools-extra/clang-query/QueryParser.h
new file mode 100644
index 0000000..67f907d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-query/QueryParser.h
@@ -0,0 +1,70 @@
+//===--- QueryParser.h - clang-query ----------------------------*- 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_QUERY_QUERY_PARSER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_PARSER_H
+
+#include "Query.h"
+#include "QuerySession.h"
+#include "llvm/LineEditor/LineEditor.h"
+#include <cstddef>
+
+namespace clang {
+namespace query {
+
+class QuerySession;
+
+class QueryParser {
+public:
+  /// Parse \a Line as a query.
+  ///
+  /// \return A QueryRef representing the query, which may be an InvalidQuery.
+  static QueryRef parse(StringRef Line, const QuerySession &QS);
+
+  /// Compute a list of completions for \a Line assuming a cursor at
+  /// \param Pos characters past the start of \a Line, ordered from most
+  /// likely to least likely.
+  ///
+  /// \return A vector of completions for \a Line.
+  static std::vector<llvm::LineEditor::Completion>
+  complete(StringRef Line, size_t Pos, const QuerySession &QS);
+
+private:
+  QueryParser(StringRef Line, const QuerySession &QS)
+      : Begin(Line.begin()), End(Line.end()), CompletionPos(nullptr), QS(QS) {}
+
+  StringRef lexWord();
+
+  template <typename T> struct LexOrCompleteWord;
+
+  QueryRef parseSetBool(bool QuerySession::*Var);
+  QueryRef parseSetOutputKind();
+  QueryRef completeMatcherExpression();
+
+  QueryRef endQuery(QueryRef Q);
+
+  /// \brief Parse [\p Begin,\p End).
+  ///
+  /// \return A reference to the parsed query object, which may be an
+  /// \c InvalidQuery if a parse error occurs.
+  QueryRef doParse();
+
+  const char *Begin;
+  const char *End;
+
+  const char *CompletionPos;
+  std::vector<llvm::LineEditor::Completion> Completions;
+
+  const QuerySession &QS;
+};
+
+} // namespace query
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_PARSER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-query/QuerySession.h b/src/third_party/llvm-project/clang-tools-extra/clang-query/QuerySession.h
new file mode 100644
index 0000000..162289f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-query/QuerySession.h
@@ -0,0 +1,40 @@
+//===--- QuerySession.h - clang-query ---------------------------*- 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_QUERY_QUERY_SESSION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_SESSION_H
+
+#include "Query.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace clang {
+
+class ASTUnit;
+
+namespace query {
+
+/// Represents the state for a particular clang-query session.
+class QuerySession {
+public:
+  QuerySession(llvm::ArrayRef<std::unique_ptr<ASTUnit>> ASTs)
+      : ASTs(ASTs), OutKind(OK_Diag), BindRoot(true), Terminate(false) {}
+
+  llvm::ArrayRef<std::unique_ptr<ASTUnit>> ASTs;
+  OutputKind OutKind;
+  bool BindRoot;
+  bool Terminate;
+  llvm::StringMap<ast_matchers::dynamic::VariantValue> NamedValues;
+};
+
+} // namespace query
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-query/tool/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-query/tool/CMakeLists.txt
new file mode 100644
index 0000000..a950931
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-query/tool/CMakeLists.txt
@@ -0,0 +1,15 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
+
+add_clang_executable(clang-query ClangQuery.cpp)
+target_link_libraries(clang-query
+  PRIVATE
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangDynamicASTMatchers
+  clangFrontend
+  clangQuery
+  clangTooling
+  )
+
+install(TARGETS clang-query RUNTIME DESTINATION bin)
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-query/tool/ClangQuery.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-query/tool/ClangQuery.cpp
new file mode 100644
index 0000000..669dc40
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-query/tool/ClangQuery.cpp
@@ -0,0 +1,116 @@
+//===---- ClangQuery.cpp - clang-query tool -------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tool is for interactive exploration of the Clang AST using AST matchers.
+// It currently allows the user to enter a matcher at an interactive prompt and
+// view the resulting bindings as diagnostics, AST pretty prints or AST dumps.
+// Example session:
+//
+// $ cat foo.c
+// void foo(void) {}
+// $ clang-query foo.c --
+// clang-query> match functionDecl()
+//
+// Match #1:
+//
+// foo.c:1:1: note: "root" binds here
+// void foo(void) {}
+// ^~~~~~~~~~~~~~~~~
+// 1 match.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Query.h"
+#include "QueryParser.h"
+#include "QuerySession.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/LineEditor/LineEditor.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Signals.h"
+#include <fstream>
+#include <string>
+
+using namespace clang;
+using namespace clang::ast_matchers;
+using namespace clang::ast_matchers::dynamic;
+using namespace clang::query;
+using namespace clang::tooling;
+using namespace llvm;
+
+static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
+static cl::OptionCategory ClangQueryCategory("clang-query options");
+
+static cl::list<std::string> Commands("c", cl::desc("Specify command to run"),
+                                      cl::value_desc("command"),
+                                      cl::cat(ClangQueryCategory));
+
+static cl::list<std::string> CommandFiles("f",
+                                          cl::desc("Read commands from file"),
+                                          cl::value_desc("file"),
+                                          cl::cat(ClangQueryCategory));
+
+int main(int argc, const char **argv) {
+  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+
+  CommonOptionsParser OptionsParser(argc, argv, ClangQueryCategory);
+
+  if (!Commands.empty() && !CommandFiles.empty()) {
+    llvm::errs() << argv[0] << ": cannot specify both -c and -f\n";
+    return 1;
+  }
+
+  ClangTool Tool(OptionsParser.getCompilations(),
+                 OptionsParser.getSourcePathList());
+  std::vector<std::unique_ptr<ASTUnit>> ASTs;
+  if (Tool.buildASTs(ASTs) != 0)
+    return 1;
+
+  QuerySession QS(ASTs);
+
+  if (!Commands.empty()) {
+    for (auto I = Commands.begin(), E = Commands.end(); I != E; ++I) {
+      QueryRef Q = QueryParser::parse(*I, QS);
+      if (!Q->run(llvm::outs(), QS))
+        return 1;
+    }
+  } else if (!CommandFiles.empty()) {
+    for (auto I = CommandFiles.begin(), E = CommandFiles.end(); I != E; ++I) {
+      std::ifstream Input(I->c_str());
+      if (!Input.is_open()) {
+        llvm::errs() << argv[0] << ": cannot open " << *I << "\n";
+        return 1;
+      }
+      while (Input.good()) {
+        std::string Line;
+        std::getline(Input, Line);
+
+        QueryRef Q = QueryParser::parse(Line, QS);
+        if (!Q->run(llvm::outs(), QS))
+          return 1;
+      }
+    }
+  } else {
+    LineEditor LE("clang-query");
+    LE.setListCompleter([&QS](StringRef Line, size_t Pos) {
+      return QueryParser::complete(Line, Pos, QS);
+    });
+    while (llvm::Optional<std::string> Line = LE.readLine()) {
+      QueryRef Q = QueryParser::parse(*Line, QS);
+      Q->run(llvm::outs(), QS);
+      llvm::outs().flush();
+      if (QS.Terminate)
+        break;
+    }
+  }
+
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-reorder-fields/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-reorder-fields/CMakeLists.txt
new file mode 100644
index 0000000..51cd4af
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-reorder-fields/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangReorderFields
+  ReorderFieldsAction.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangIndex
+  clangLex
+  clangToolingCore
+  )
+
+add_subdirectory(tool)
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-reorder-fields/ReorderFieldsAction.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-reorder-fields/ReorderFieldsAction.cpp
new file mode 100644
index 0000000..7cb8abe
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-reorder-fields/ReorderFieldsAction.cpp
@@ -0,0 +1,311 @@
+//===-- tools/extra/clang-reorder-fields/ReorderFieldsAction.cpp -*- 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 definition of the
+/// ReorderFieldsAction::newASTConsumer method
+///
+//===----------------------------------------------------------------------===//
+
+#include "ReorderFieldsAction.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/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 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;
+  }
+  if (Results.size() > 1) {
+    llvm::errs() << "The name " << RecordName
+                 << " is ambiguous, several definitions found\n";
+    return nullptr;
+  }
+  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 RecordDecl *Definition,
+                  ArrayRef<std::string> DesiredFieldsOrder) {
+  assert(Definition && "Definition is null");
+
+  llvm::StringMap<unsigned> NameToIndex;
+  for (const auto *Field : Definition->fields())
+    NameToIndex[Field->getName()] = Field->getFieldIndex();
+
+  if (DesiredFieldsOrder.size() != NameToIndex.size()) {
+    llvm::errs() << "Number of provided fields doesn't match definition.\n";
+    return {};
+  }
+  SmallVector<unsigned, 4> NewFieldsOrder;
+  for (const auto &Name : DesiredFieldsOrder) {
+    if (!NameToIndex.count(Name)) {
+      llvm::errs() << "Field " << Name << " not found in definition.\n";
+      return {};
+    }
+    NewFieldsOrder.push_back(NameToIndex[Name]);
+  }
+  assert(NewFieldsOrder.size() == NameToIndex.size());
+  return NewFieldsOrder;
+}
+
+// FIXME: error-handling
+/// \brief Replaces one range of source code by another.
+static void
+addReplacement(SourceRange Old, SourceRange New, const ASTContext &Context,
+               std::map<std::string, tooling::Replacements> &Replacements) {
+  StringRef NewText =
+      Lexer::getSourceText(CharSourceRange::getTokenRange(New),
+                           Context.getSourceManager(), Context.getLangOpts());
+  tooling::Replacement R(Context.getSourceManager(),
+                         CharSourceRange::getTokenRange(Old), NewText,
+                         Context.getLangOpts());
+  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 RecordDecl *Definition, ArrayRef<unsigned> NewFieldsOrder,
+    const ASTContext &Context,
+    std::map<std::string, tooling::Replacements> &Replacements) {
+  assert(Definition && "Definition is null");
+
+  SmallVector<const FieldDecl *, 10> Fields;
+  for (const auto *Field : Definition->fields())
+    Fields.push_back(Field);
+
+  // Check that the permutation of the fields doesn't change the accesses
+  for (const auto *Field : Definition->fields()) {
+    const auto FieldIndex = Field->getFieldIndex();
+    if (Field->getAccess() != Fields[NewFieldsOrder[FieldIndex]]->getAccess()) {
+      llvm::errs() << "Currently reodering of fields with different accesses "
+                      "is not supported\n";
+      return false;
+    }
+  }
+
+  for (const auto *Field : Definition->fields()) {
+    const auto FieldIndex = Field->getFieldIndex();
+    if (FieldIndex == NewFieldsOrder[FieldIndex])
+      continue;
+    addReplacement(Field->getSourceRange(),
+                   Fields[NewFieldsOrder[FieldIndex]]->getSourceRange(),
+                   Context, Replacements);
+  }
+  return true;
+}
+
+/// \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.
+static void reorderFieldsInConstructor(
+    const CXXConstructorDecl *CtorDecl, ArrayRef<unsigned> NewFieldsOrder,
+    ASTContext &Context,
+    std::map<std::string, tooling::Replacements> &Replacements) {
+  assert(CtorDecl && "Constructor declaration is null");
+  if (CtorDecl->isImplicit() || CtorDecl->getNumCtorInitializers() <= 1)
+    return;
+
+  // The method FunctionDecl::isThisDeclarationADefinition returns false
+  // for a defaulted function unless that function has been implicitly defined.
+  // Thus this assert needs to be after the previous checks.
+  assert(CtorDecl->isThisDeclarationADefinition() && "Not a definition");
+
+  SmallVector<unsigned, 10> NewFieldsPositions(NewFieldsOrder.size());
+  for (unsigned i = 0, e = NewFieldsOrder.size(); i < e; ++i)
+    NewFieldsPositions[NewFieldsOrder[i]] = i;
+
+  SmallVector<const CXXCtorInitializer *, 10> OldWrittenInitializersOrder;
+  SmallVector<const CXXCtorInitializer *, 10> NewWrittenInitializersOrder;
+  for (const auto *Initializer : CtorDecl->inits()) {
+    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);
+  }
+  auto ByFieldNewPosition = [&](const CXXCtorInitializer *LHS,
+                                const CXXCtorInitializer *RHS) {
+    assert(LHS && RHS);
+    return NewFieldsPositions[LHS->getMember()->getFieldIndex()] <
+           NewFieldsPositions[RHS->getMember()->getFieldIndex()];
+  };
+  std::sort(std::begin(NewWrittenInitializersOrder),
+            std::end(NewWrittenInitializersOrder), ByFieldNewPosition);
+  assert(OldWrittenInitializersOrder.size() ==
+         NewWrittenInitializersOrder.size());
+  for (unsigned i = 0, e = NewWrittenInitializersOrder.size(); i < e; ++i)
+    if (OldWrittenInitializersOrder[i] != NewWrittenInitializersOrder[i])
+      addReplacement(OldWrittenInitializersOrder[i]->getSourceRange(),
+                     NewWrittenInitializersOrder[i]->getSourceRange(), Context,
+                     Replacements);
+}
+
+/// \brief Reorders initializers in the brace initialization of an aggregate.
+///
+/// At the moment partial initialization is not supported.
+/// \returns true on success
+static bool reorderFieldsInInitListExpr(
+    const InitListExpr *InitListEx, ArrayRef<unsigned> NewFieldsOrder,
+    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.
+  // 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.
+  if (const auto *SyntacticForm = InitListEx->getSyntacticForm())
+    InitListEx = SyntacticForm;
+  // If there are no initializers we do not need to change anything.
+  if (!InitListEx->getNumInits())
+    return true;
+  if (InitListEx->getNumInits() != NewFieldsOrder.size()) {
+    llvm::errs() << "Currently only full initialization is supported\n";
+    return false;
+  }
+  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);
+  return true;
+}
+
+namespace {
+class ReorderingConsumer : public ASTConsumer {
+  StringRef RecordName;
+  ArrayRef<std::string> DesiredFieldsOrder;
+  std::map<std::string, tooling::Replacements> &Replacements;
+
+public:
+  ReorderingConsumer(StringRef RecordName,
+                     ArrayRef<std::string> DesiredFieldsOrder,
+                     std::map<std::string, tooling::Replacements> &Replacements)
+      : RecordName(RecordName), DesiredFieldsOrder(DesiredFieldsOrder),
+        Replacements(Replacements) {}
+
+  ReorderingConsumer(const ReorderingConsumer &) = delete;
+  ReorderingConsumer &operator=(const ReorderingConsumer &) = delete;
+
+  void HandleTranslationUnit(ASTContext &Context) override {
+    const RecordDecl *RD = findDefinition(RecordName, Context);
+    if (!RD)
+      return;
+    SmallVector<unsigned, 4> NewFieldsOrder =
+        getNewFieldsOrder(RD, DesiredFieldsOrder);
+    if (NewFieldsOrder.empty())
+      return;
+    if (!reorderFieldsInDefinition(RD, NewFieldsOrder, Context, Replacements))
+      return;
+
+    // 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 (!CXXRD || CXXRD->isAggregate())
+      for (auto Result :
+           match(initListExpr(hasType(equalsNode(RD))).bind("initListExpr"),
+                 Context))
+        if (!reorderFieldsInInitListExpr(
+                Result.getNodeAs<InitListExpr>("initListExpr"), NewFieldsOrder,
+                Context, Replacements)) {
+          Replacements.clear();
+          return;
+        }
+  }
+};
+} // end anonymous namespace
+
+std::unique_ptr<ASTConsumer> ReorderFieldsAction::newASTConsumer() {
+  return llvm::make_unique<ReorderingConsumer>(RecordName, DesiredFieldsOrder,
+                                               Replacements);
+}
+
+} // namespace reorder_fields
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-reorder-fields/ReorderFieldsAction.h b/src/third_party/llvm-project/clang-tools-extra/clang-reorder-fields/ReorderFieldsAction.h
new file mode 100644
index 0000000..f08c632
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-reorder-fields/ReorderFieldsAction.h
@@ -0,0 +1,47 @@
+//===-- tools/extra/clang-reorder-fields/ReorderFieldsAction.h -*- 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 declarations of the ReorderFieldsAction class and
+/// the FieldPosition struct.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_REORDER_FIELDS_ACTION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_REORDER_FIELDS_ACTION_H
+
+#include "clang/Tooling/Refactoring.h"
+
+namespace clang {
+class ASTConsumer;
+
+namespace reorder_fields {
+
+class ReorderFieldsAction {
+  llvm::StringRef RecordName;
+  llvm::ArrayRef<std::string> DesiredFieldsOrder;
+  std::map<std::string, tooling::Replacements> &Replacements;
+
+public:
+  ReorderFieldsAction(
+      llvm::StringRef RecordName,
+      llvm::ArrayRef<std::string> DesiredFieldsOrder,
+      std::map<std::string, tooling::Replacements> &Replacements)
+      : RecordName(RecordName), DesiredFieldsOrder(DesiredFieldsOrder),
+        Replacements(Replacements) {}
+
+  ReorderFieldsAction(const ReorderFieldsAction &) = delete;
+  ReorderFieldsAction &operator=(const ReorderFieldsAction &) = delete;
+
+  std::unique_ptr<ASTConsumer> newASTConsumer();
+};
+} // namespace reorder_fields
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_REORDER_FIELDS_ACTION_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-reorder-fields/tool/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-reorder-fields/tool/CMakeLists.txt
new file mode 100644
index 0000000..2de2cec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-reorder-fields/tool/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_clang_tool(clang-reorder-fields ClangReorderFields.cpp)
+
+target_link_libraries(clang-reorder-fields
+  PRIVATE
+  clangBasic
+  clangFrontend
+  clangReorderFields
+  clangRewrite
+  clangTooling
+  clangToolingCore
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp
new file mode 100644
index 0000000..077e55e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp
@@ -0,0 +1,88 @@
+//===-- tools/extra/clang-reorder-fields/tool/ClangReorderFields.cpp -*- 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 implementation of clang-reorder-fields tool
+///
+//===----------------------------------------------------------------------===//
+
+#include "../ReorderFieldsAction.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.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/Tooling.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include <cstdlib>
+#include <string>
+#include <system_error>
+
+using namespace llvm;
+using namespace clang;
+
+cl::OptionCategory ClangReorderFieldsCategory("clang-reorder-fields options");
+
+static cl::opt<std::string>
+    RecordName("record-name", cl::Required,
+               cl::desc("The name of the struct/class."),
+               cl::cat(ClangReorderFieldsCategory));
+
+static cl::list<std::string> FieldsOrder("fields-order", cl::CommaSeparated,
+                                         cl::OneOrMore,
+                                         cl::desc("The desired fields order."),
+                                         cl::cat(ClangReorderFieldsCategory));
+
+static cl::opt<bool> Inplace("i", cl::desc("Overwrite edited files."),
+                             cl::cat(ClangReorderFieldsCategory));
+
+const char Usage[] = "A tool to reorder fields in C/C++ structs/classes.\n";
+
+int main(int argc, const char **argv) {
+  tooling::CommonOptionsParser OP(argc, argv, ClangReorderFieldsCategory,
+                                  Usage);
+
+  auto Files = OP.getSourcePathList();
+  tooling::RefactoringTool Tool(OP.getCompilations(), Files);
+
+  reorder_fields::ReorderFieldsAction Action(RecordName, FieldsOrder,
+                                             Tool.getReplacements());
+
+  auto Factory = tooling::newFrontendActionFactory(&Action);
+
+  if (Inplace)
+    return Tool.runAndSave(Factory.get());
+
+  int ExitCode = Tool.run(Factory.get());
+  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());
+  }
+
+  return ExitCode;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/CMakeLists.txt
new file mode 100644
index 0000000..96381bd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/CMakeLists.txt
@@ -0,0 +1,28 @@
+option(BUILD_CLANG_TIDY_VS_PLUGIN "Build clang-tidy VS plugin" OFF)
+if (BUILD_CLANG_TIDY_VS_PLUGIN)
+  add_custom_target(clang_tidy_exe_for_vsix
+      ${CMAKE_COMMAND} -E copy_if_different
+      "${LLVM_TOOLS_BINARY_DIR}/clang-tidy.exe"
+      "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy/clang-tidy.exe"
+      DEPENDS clang-tidy)
+
+  add_custom_target(clang_tidy_license
+      ${CMAKE_COMMAND} -E copy_if_different
+      "${CLANG_SOURCE_DIR}/LICENSE.TXT"
+      "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy/license.txt")
+
+  if (NOT CLANG_TIDY_VS_VERSION)
+    set(CLANG_TIDY_VS_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}")
+  endif()
+
+  configure_file("source.extension.vsixmanifest.in"
+      "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy/source.extension.vsixmanifest")
+
+  add_custom_target(clang_tidy_vsix ALL
+      devenv "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy.sln" /Build Release
+      DEPENDS clang_tidy_exe_for_vsix "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy/source.extension.vsixmanifest"
+      COMMAND ${CMAKE_COMMAND} -E copy_if_different
+      "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy/bin/Release/ClangTidy.vsix"
+      "${LLVM_TOOLS_BINARY_DIR}/ClangTidy.vsix"
+      DEPENDS clang_tidy_exe_for_vsix clang_tidy_license)
+endif()
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy.sln b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy.sln
new file mode 100644
index 0000000..345eb83
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy.sln
@@ -0,0 +1,22 @@
+

+Microsoft Visual Studio Solution File, Format Version 12.00

+# Visual Studio 14

+VisualStudioVersion = 14.0.25123.0

+MinimumVisualStudioVersion = 10.0.40219.1

+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClangTidy", "ClangTidy\ClangTidy.csproj", "{BE261DA1-36C6-449A-95C5-4653A549170A}"

+EndProject

+Global

+	GlobalSection(SolutionConfigurationPlatforms) = preSolution

+		Debug|Any CPU = Debug|Any CPU

+		Release|Any CPU = Release|Any CPU

+	EndGlobalSection

+	GlobalSection(ProjectConfigurationPlatforms) = postSolution

+		{BE261DA1-36C6-449A-95C5-4653A549170A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

+		{BE261DA1-36C6-449A-95C5-4653A549170A}.Debug|Any CPU.Build.0 = Debug|Any CPU

+		{BE261DA1-36C6-449A-95C5-4653A549170A}.Release|Any CPU.ActiveCfg = Release|Any CPU

+		{BE261DA1-36C6-449A-95C5-4653A549170A}.Release|Any CPU.Build.0 = Release|Any CPU

+	EndGlobalSection

+	GlobalSection(SolutionProperties) = preSolution

+		HideSolutionNode = FALSE

+	EndGlobalSection

+EndGlobal

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/CategoryVerb.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/CategoryVerb.cs
new file mode 100644
index 0000000..ef07a89
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/CategoryVerb.cs
@@ -0,0 +1,70 @@
+using System;

+using System.Collections.Generic;

+using System.ComponentModel;

+using System.Globalization;

+using System.Linq;

+using System.Text;

+using System.Threading.Tasks;

+

+namespace LLVM.ClangTidy

+{

+    /// <summary>

+    /// Allows entire categories of properties to be enabled, disabled, or inherited

+    /// in one fell swoop.  We add properties to each category with the value being

+    /// this enum, and when the value is selected, we use reflection to find all other

+    /// properties in the same category and perform the corresponding action.

+    /// </summary>

+    public enum CategoryVerb

+    {

+        None,

+        Disable,

+        Enable,

+        Inherit

+    }

+

+    public class CategoryVerbConverter : EnumConverter

+    {

+        public CategoryVerbConverter() : base(typeof(CategoryVerb))

+        {

+        }

+

+        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)

+        {

+            if (value is string)

+            {

+                switch ((string)value)

+                {

+                    case "Disable Category":

+                        return CategoryVerb.Disable;

+                    case "Enable Category":

+                        return CategoryVerb.Enable;

+                    case "Inherit Category":

+                        return CategoryVerb.Inherit;

+                    case "":

+                        return CategoryVerb.None;

+                }

+            }

+            return base.ConvertFrom(context, culture, value);

+        }

+

+        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)

+        {

+            if (value is CategoryVerb && destinationType == typeof(string))

+            {

+                switch ((CategoryVerb)value)

+                {

+                    case CategoryVerb.Disable:

+                        return "Disable Category";

+                    case CategoryVerb.Enable:

+                        return "Enable Category";

+                    case CategoryVerb.Inherit:

+                        return "Inherit Category";

+                    case CategoryVerb.None:

+                        return String.Empty;

+                }

+            }

+

+            return base.ConvertTo(context, culture, value, destinationType);

+        }

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/CheckDatabase.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/CheckDatabase.cs
new file mode 100644
index 0000000..6b76688
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/CheckDatabase.cs
@@ -0,0 +1,67 @@
+using System;

+using System.Collections.Generic;

+using System.IO;

+using System.Linq;

+using System.Text;

+using YamlDotNet.Serialization;

+using YamlDotNet.Serialization.NamingConventions;

+

+namespace LLVM.ClangTidy

+{

+    public class CheckInfo

+    {

+        [YamlAlias("Name")]

+        public string Name { get; set; }

+

+        [YamlAlias("Label")]

+        public string Label { get; set; }

+

+        [YamlAlias("Description")]

+        public string Desc { get; set; }

+

+        [YamlAlias("Category")]

+        public string Category { get; set; }

+    }

+

+    /// <summary>

+    /// Reads the list of checks from Yaml and builds a description of each one.

+    /// This list of checks is then used by the PropertyGrid to determine what

+    /// items to display.

+    /// </summary>

+    public static class CheckDatabase

+    {

+        static CheckInfo[] Checks_ = null;

+

+        class CheckRoot

+        {

+            [YamlAlias("Checks")]

+            public CheckInfo[] Checks { get; set; }

+        }

+

+        static CheckDatabase()

+        {

+            using (StringReader Reader = new StringReader(Resources.ClangTidyChecks))

+            {

+                Deserializer D = new Deserializer(namingConvention: new PascalCaseNamingConvention());

+                var Root = D.Deserialize<CheckRoot>(Reader);

+                Checks_ = Root.Checks;

+

+                HashSet<string> Names = new HashSet<string>();

+                foreach (var Check in Checks_)

+                {

+                    if (Names.Contains(Check.Name))

+                        continue;

+                    Names.Add(Check.Name);

+                }

+            }

+        }

+

+        public static IEnumerable<CheckInfo> Checks

+        {

+            get

+            {

+                return Checks_;

+            }

+        }

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/CheckTree.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/CheckTree.cs
new file mode 100644
index 0000000..f3e2583
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/CheckTree.cs
@@ -0,0 +1,273 @@
+using System;

+using System.Collections.Generic;

+using System.ComponentModel;

+using System.Linq;

+using System.Text;

+

+namespace LLVM.ClangTidy

+{

+    /// <summary>

+    /// CheckTree is used to group checks into categories and subcategories.  For

+    /// example, given the following list of checks:

+    /// 

+    ///   llvm-include-order

+    ///   llvm-namespace-comment

+    ///   llvm-twine-local

+    ///   llvm-header-guard

+    ///   google-runtime-member-string-references

+    ///   google-runtime-int

+    ///   google-readability-namespace-comments

+    ///   

+    /// the corresponding CheckTree would look like this:

+    /// 

+    ///   llvm

+    ///     include-order

+    ///     namespace-comment

+    ///     twine-local

+    ///     header-guard

+    ///   google

+    ///     runtime

+    ///       member-string-references

+    ///       int

+    ///     readability

+    ///       namespace-comments

+    ///       redundant-smartptr-get

+    ///       

+    /// This is useful when serializing a set of options out to a .clang-tidy file,

+    /// because we need to decide the most efficient way to serialize the sequence

+    /// of check commands, when to use wildcards, etc.  For example, if everything

+    /// under google is inherited, we can simply leave that entry out entirely from

+    /// the .clang-tidy file.  On the other hand, if anything is inherited, we *must

+    /// not* add or remove google-* by wildcard because that, by definition, means

+    /// the property is no longer inherited.  When we can categorize the checks into

+    /// groups and subgroups like this, it is possible to efficiently serialize to

+    /// a minimal representative .clang-tidy file.

+    /// </summary>

+

+    public abstract class CheckTreeNode

+    {

+        private string Name_;

+        private CheckTreeNode Parent_;

+

+        protected CheckTreeNode(string Name, CheckTreeNode Parent)

+        {

+            Name_ = Name;

+            Parent_ = Parent;

+        }

+

+        public string Path

+        {

+            get

+            {

+                if (Parent_ == null)

+                    return null;

+                string ParentPath = Parent_.Path;

+                if (ParentPath == null)

+                    return Name_;

+                return ParentPath + "-" + Name_;

+            }

+        }

+

+        public string Name

+        {

+            get

+            {

+                return Name_;

+            }

+        }

+

+

+        public abstract int CountChecks { get; }

+        public abstract int CountExplicitlyDisabledChecks { get; }

+        public abstract int CountExplicitlyEnabledChecks { get; }

+        public abstract int CountInheritedChecks { get; }

+    }

+

+    public class CheckTree : CheckTreeNode

+    {

+        private Dictionary<string, CheckTreeNode> Children_ = new Dictionary<string, CheckTreeNode>();

+        public CheckTree()

+            : base(null, null)

+        {

+

+        }

+

+        private CheckTree(string Name, CheckTree Parent)

+            : base(Name, Parent)

+        {

+        }

+

+        private void AddLeaf(string Name, DynamicPropertyDescriptor<bool> Property)

+        {

+            Children_[Name] = new CheckLeaf(Name, this, Property);

+        }

+

+        private CheckTree AddOrCreateSubgroup(string Name)

+        {

+            CheckTreeNode Subgroup = null;

+            if (Children_.TryGetValue(Name, out Subgroup))

+            {

+                System.Diagnostics.Debug.Assert(Subgroup is CheckTree);

+                return (CheckTree)Subgroup;

+            }

+

+            CheckTree SG = new CheckTree(Name, this);

+            Children_[Name] = SG;

+            return SG;

+        }

+

+        public static CheckTree Build(ClangTidyProperties Config)

+        {

+            // Since some check names contain dashes in them, it doesn't make sense to

+            // simply split all check names by dash and construct a huge tree.  For

+            // example, in the check called google-runtime-member-string-references,

+            // we don't need each of those to be a different subgroup.  So instead we

+            // explicitly specify the common breaking points at which a user might want

+            // to use a -* and everything else falls as a leaf under one of these

+            // categories.

+            // FIXME: This should be configurable without recompilation

+            CheckTree Root = new CheckTree();

+            string[][] Groups = new string[][] {

+                new string[] {"boost"},

+                new string[] {"cert"},

+                new string[] {"clang", "diagnostic"},

+                new string[] {"cppcoreguidelines", "interfaces"},

+                new string[] {"cppcoreguidelines", "pro", "bounds"},

+                new string[] {"cppcoreguidelines", "pro", "type"},

+                new string[] {"google", "build"},

+                new string[] {"google", "readability"},

+                new string[] {"google", "runtime"},

+                new string[] {"llvm"},

+                new string[] {"misc"},

+            };

+

+            foreach (string[] Group in Groups)

+            {

+                CheckTree Subgroup = Root;

+                foreach (string Component in Group)

+                    Subgroup = Subgroup.AddOrCreateSubgroup(Component);

+            }

+

+            var Props = Config.GetProperties()

+                              .Cast<PropertyDescriptor>()

+                              .OfType<DynamicPropertyDescriptor<bool>>()

+                              .Where(x => x.Attributes.OfType<ClangTidyCheckAttribute>().Count() > 0)

+                              .Select(x => new KeyValuePair<DynamicPropertyDescriptor<bool>, string>(

+                                            x, x.Attributes.OfType<ClangTidyCheckAttribute>().First().CheckName));

+            var PropArray = Props.ToArray();

+            foreach (var CheckInfo in PropArray)

+            {

+                string LeafName = null;

+                CheckTree Tree = Root.LocateCheckLeafGroup(CheckInfo.Value, out LeafName);

+                Tree.AddLeaf(LeafName, CheckInfo.Key);

+            }

+            return Root;

+        }

+

+        private CheckTree LocateCheckLeafGroup(string Check, out string LeafName)

+        {

+            string[] Components = Check.Split('-');

+            string FirstComponent = Components.FirstOrDefault();

+            if (FirstComponent == null)

+            {

+                LeafName = Check;

+                return this;

+            }

+

+            CheckTreeNode Subgroup = null;

+            if (!Children_.TryGetValue(FirstComponent, out Subgroup))

+            {

+                LeafName = Check;

+                return this;

+            }

+            System.Diagnostics.Debug.Assert(Subgroup is CheckTree);

+            CheckTree Child = (CheckTree)Subgroup;

+            string ChildName = Check.Substring(FirstComponent.Length + 1);

+            return Child.LocateCheckLeafGroup(ChildName, out LeafName);

+        }

+

+        public override int CountChecks

+        {

+            get

+            {

+                return Children_.Aggregate(0, (X, V) => { return X + V.Value.CountChecks; });

+            }

+        }

+

+        public override int CountExplicitlyDisabledChecks

+        {

+            get

+            {

+                return Children_.Aggregate(0, (X, V) => { return X + V.Value.CountExplicitlyDisabledChecks; });

+            }

+        }

+

+        public override int CountExplicitlyEnabledChecks

+        {

+            get

+            {

+                return Children_.Aggregate(0, (X, V) => { return X + V.Value.CountExplicitlyEnabledChecks; });

+            }

+        }

+        public override int CountInheritedChecks

+        {

+            get

+            {

+                return Children_.Aggregate(0, (X, V) => { return X + V.Value.CountInheritedChecks; });

+            }

+        }

+

+        public IDictionary<string, CheckTreeNode> Children

+        {

+            get { return Children_; }

+        }

+    }

+

+    public class CheckLeaf : CheckTreeNode

+    {

+        private DynamicPropertyDescriptor<bool> Property_;

+

+        public CheckLeaf(string Name, CheckTree Parent, DynamicPropertyDescriptor<bool> Property)

+            : base(Name, Parent)

+        {

+            Property_ = Property;

+        }

+

+        public override int CountChecks

+        {

+            get

+            {

+                return 1;

+            }

+        }

+

+        public override int CountExplicitlyDisabledChecks

+        {

+            get

+            {

+                if (Property_.IsInheriting)

+                    return 0;

+                return (bool)Property_.GetValue(null) ? 0 : 1;

+            }

+        }

+

+        public override int CountExplicitlyEnabledChecks

+        {

+            get

+            {

+                if (Property_.IsInheriting)

+                    return 0;

+                return (bool)Property_.GetValue(null) ? 1 : 0;

+            }

+        }

+

+        public override int CountInheritedChecks

+        {

+            get

+            {

+                return (Property_.IsInheriting) ? 1 : 0;

+            }

+        }

+

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidy.csproj b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidy.csproj
new file mode 100644
index 0000000..bf74717
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidy.csproj
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">

+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />

+  <PropertyGroup>

+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>

+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>

+    <SchemaVersion>2.0</SchemaVersion>

+    <ProjectGuid>{BE261DA1-36C6-449A-95C5-4653A549170A}</ProjectGuid>

+    <ProjectTypeGuids>{82b43b9b-a64c-4715-b499-d71e9ca2bd60};{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

+    <OutputType>Library</OutputType>

+    <AppDesignerFolder>Properties</AppDesignerFolder>

+    <RootNamespace>LLVM.ClangTidy</RootNamespace>

+    <AssemblyName>ClangTidy</AssemblyName>

+    <SignAssembly>true</SignAssembly>

+    <AssemblyOriginatorKeyFile>Key.snk</AssemblyOriginatorKeyFile>

+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>

+    <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>

+    <FileUpgradeFlags>

+    </FileUpgradeFlags>

+    <UpgradeBackupLocation>

+    </UpgradeBackupLocation>

+    <OldToolsVersion>4.0</OldToolsVersion>

+    <PublishUrl>publish\</PublishUrl>

+    <Install>true</Install>

+    <InstallFrom>Disk</InstallFrom>

+    <UpdateEnabled>false</UpdateEnabled>

+    <UpdateMode>Foreground</UpdateMode>

+    <UpdateInterval>7</UpdateInterval>

+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>

+    <UpdatePeriodically>false</UpdatePeriodically>

+    <UpdateRequired>false</UpdateRequired>

+    <MapFileExtensions>true</MapFileExtensions>

+    <ApplicationRevision>0</ApplicationRevision>

+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>

+    <IsWebBootstrapper>false</IsWebBootstrapper>

+    <UseApplicationTrust>false</UseApplicationTrust>

+    <BootstrapperEnabled>true</BootstrapperEnabled>

+    <TargetFrameworkProfile />

+  </PropertyGroup>

+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

+    <DebugSymbols>true</DebugSymbols>

+    <DebugType>full</DebugType>

+    <Optimize>false</Optimize>

+    <OutputPath>bin\Debug\</OutputPath>

+    <DefineConstants>DEBUG;TRACE</DefineConstants>

+    <ErrorReport>prompt</ErrorReport>

+    <WarningLevel>0</WarningLevel>

+    <Prefer32Bit>false</Prefer32Bit>

+    <PlatformTarget>AnyCPU</PlatformTarget>

+  </PropertyGroup>

+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">

+    <DebugType>pdbonly</DebugType>

+    <Optimize>true</Optimize>

+    <OutputPath>bin\Release\</OutputPath>

+    <DefineConstants>TRACE</DefineConstants>

+    <ErrorReport>prompt</ErrorReport>

+    <WarningLevel>4</WarningLevel>

+    <RunCodeAnalysis>true</RunCodeAnalysis>

+    <Prefer32Bit>false</Prefer32Bit>

+  </PropertyGroup>

+  <ItemGroup>

+    <Reference Include="Microsoft.CSharp" />

+    <Reference Include="Microsoft.VisualStudio.CoreUtility, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />

+    <Reference Include="Microsoft.VisualStudio.Editor, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />

+    <Reference Include="Microsoft.VisualStudio.OLE.Interop" />

+    <Reference Include="Microsoft.VisualStudio.Settings.14.0, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=x86" />

+    <Reference Include="Microsoft.VisualStudio.Shell.14.0, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />

+    <Reference Include="Microsoft.VisualStudio.Shell.Immutable.10.0, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />

+    <Reference Include="Microsoft.VisualStudio.Shell.Immutable.14.0, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />

+    <Reference Include="Microsoft.VisualStudio.Shell.Interop" />

+    <Reference Include="Microsoft.VisualStudio.TextManager.Interop" />

+    <Reference Include="Microsoft.VisualStudio.TextManager.Interop" />

+    <Reference Include="Microsoft.VisualStudio.Utilities, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />

+    <Reference Include="System" />

+    <Reference Include="System.Core" />

+    <Reference Include="System.Data" />

+    <Reference Include="System.Design" />

+    <Reference Include="System.Drawing" />

+    <Reference Include="System.Windows.Forms" />

+    <Reference Include="System.Xml" />

+    <Reference Include="System.Xml.Linq" />

+    <Reference Include="YamlDotNet, Version=3.3.0.0, Culture=neutral, processorArchitecture=MSIL">

+      <HintPath>..\packages\YamlDotNet.3.3.0\lib\net35\YamlDotNet.dll</HintPath>

+      <Private>True</Private>

+    </Reference>

+    <Reference Include="YamlDotNet.Dynamic, Version=3.2.0.0, Culture=neutral, processorArchitecture=MSIL">

+      <HintPath>..\packages\YamlDotNet.Dynamic.3.2.3\lib\net40\YamlDotNet.Dynamic.dll</HintPath>

+      <Private>True</Private>

+    </Reference>

+  </ItemGroup>

+  <ItemGroup>

+    <COMReference Include="EnvDTE">

+      <Guid>{80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2}</Guid>

+      <VersionMajor>8</VersionMajor>

+      <VersionMinor>0</VersionMinor>

+      <Lcid>0</Lcid>

+      <WrapperTool>primary</WrapperTool>

+      <Isolated>False</Isolated>

+      <EmbedInteropTypes>False</EmbedInteropTypes>

+    </COMReference>

+    <COMReference Include="EnvDTE100">

+      <Guid>{26AD1324-4B7C-44BC-84F8-B86AED45729F}</Guid>

+      <VersionMajor>10</VersionMajor>

+      <VersionMinor>0</VersionMinor>

+      <Lcid>0</Lcid>

+      <WrapperTool>primary</WrapperTool>

+      <Isolated>False</Isolated>

+      <EmbedInteropTypes>False</EmbedInteropTypes>

+    </COMReference>

+    <COMReference Include="EnvDTE80">

+      <Guid>{1A31287A-4D7D-413E-8E32-3B374931BD89}</Guid>

+      <VersionMajor>8</VersionMajor>

+      <VersionMinor>0</VersionMinor>

+      <Lcid>0</Lcid>

+      <WrapperTool>primary</WrapperTool>

+      <Isolated>False</Isolated>

+      <EmbedInteropTypes>False</EmbedInteropTypes>

+    </COMReference>

+    <COMReference Include="EnvDTE90">

+      <Guid>{2CE2370E-D744-4936-A090-3FFFE667B0E1}</Guid>

+      <VersionMajor>9</VersionMajor>

+      <VersionMinor>0</VersionMinor>

+      <Lcid>0</Lcid>

+      <WrapperTool>primary</WrapperTool>

+      <Isolated>False</Isolated>

+      <EmbedInteropTypes>False</EmbedInteropTypes>

+    </COMReference>

+    <COMReference Include="Microsoft.VisualStudio.CommandBars">

+      <Guid>{1CBA492E-7263-47BB-87FE-639000619B15}</Guid>

+      <VersionMajor>8</VersionMajor>

+      <VersionMinor>0</VersionMinor>

+      <Lcid>0</Lcid>

+      <WrapperTool>primary</WrapperTool>

+      <Isolated>False</Isolated>

+      <EmbedInteropTypes>False</EmbedInteropTypes>

+    </COMReference>

+    <COMReference Include="stdole">

+      <Guid>{00020430-0000-0000-C000-000000000046}</Guid>

+      <VersionMajor>2</VersionMajor>

+      <VersionMinor>0</VersionMinor>

+      <Lcid>0</Lcid>

+      <WrapperTool>primary</WrapperTool>

+      <Isolated>False</Isolated>

+      <EmbedInteropTypes>False</EmbedInteropTypes>

+    </COMReference>

+  </ItemGroup>

+  <ItemGroup>

+    <Compile Include="CategoryVerb.cs" />

+    <Compile Include="CheckDatabase.cs" />

+    <Compile Include="CheckTree.cs" />

+    <Compile Include="ClangTidyCheckAttribute.cs" />

+    <Compile Include="ClangTidyConfigurationPage.cs">

+      <SubType>Component</SubType>

+    </Compile>

+    <Compile Include="ClangTidyProperties.cs">

+      <SubType>Component</SubType>

+    </Compile>

+    <Compile Include="DynamicPropertyConverter.cs" />

+    <Compile Include="DynamicPropertyDescriptor.cs" />

+    <Compile Include="ForwardingPropertyDescriptor.cs" />

+    <Compile Include="Guids.cs" />

+    <Compile Include="DynamicPropertyComponent.cs">

+      <SubType>Component</SubType>

+    </Compile>

+    <Compile Include="DynamicPropertyComponent.Designer.cs" />

+    <Compile Include="ClangTidyConfigParser.cs" />

+    <Compile Include="Resources.Designer.cs">

+      <AutoGen>True</AutoGen>

+      <DesignTime>True</DesignTime>

+      <DependentUpon>Resources.resx</DependentUpon>

+    </Compile>

+    <Compile Include="GlobalSuppressions.cs" />

+    <Compile Include="ClangTidyPackage.cs" />

+    <Compile Include="Properties\AssemblyInfo.cs" />

+    <Compile Include="PkgCmdID.cs" />

+    <Compile Include="ClangTidyPropertyGrid.cs">

+      <SubType>UserControl</SubType>

+    </Compile>

+    <Compile Include="ClangTidyPropertyGrid.Designer.cs">

+      <DependentUpon>ClangTidyPropertyGrid.cs</DependentUpon>

+    </Compile>

+    <Compile Include="Utility.cs" />

+  </ItemGroup>

+  <ItemGroup>

+    <EmbeddedResource Include="Resources.resx">

+      <Generator>ResXFileCodeGenerator</Generator>

+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>

+      <SubType>Designer</SubType>

+    </EmbeddedResource>

+    <EmbeddedResource Include="ClangTidyPropertyGrid.resx">

+      <DependentUpon>ClangTidyPropertyGrid.cs</DependentUpon>

+    </EmbeddedResource>

+    <EmbeddedResource Include="VSPackage.resx">

+      <MergeWithCTO>true</MergeWithCTO>

+      <ManifestResourceName>VSPackage</ManifestResourceName>

+    </EmbeddedResource>

+  </ItemGroup>

+  <ItemGroup>

+    <None Include="Key.snk" />

+    <None Include="packages.config" />

+    <None Include="Resources\ClangTidyChecks.yaml" />

+    <None Include="source.extension.vsixmanifest">

+      <SubType>Designer</SubType>

+    </None>

+  </ItemGroup>

+  <ItemGroup>

+    <VSCTCompile Include="ClangTidy.vsct">

+      <ResourceName>Menus.ctmenu</ResourceName>

+      <SubType>Designer</SubType>

+    </VSCTCompile>

+  </ItemGroup>

+  <ItemGroup>

+    <None Include="Resources\Images_32bit.bmp" />

+  </ItemGroup>

+  <ItemGroup>

+    <Content Include="clang-tidy.exe">

+      <IncludeInVSIX>true</IncludeInVSIX>

+    </Content>

+    <Content Include="license.txt">

+      <IncludeInVSIX>true</IncludeInVSIX>

+    </Content>

+    <Content Include="Resources\Package.ico" />

+  </ItemGroup>

+  <ItemGroup>

+    <BootstrapperPackage Include=".NETFramework,Version=v4.0">

+      <Visible>False</Visible>

+      <ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>

+      <Install>true</Install>

+    </BootstrapperPackage>

+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">

+      <Visible>False</Visible>

+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>

+      <Install>false</Install>

+    </BootstrapperPackage>

+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">

+      <Visible>False</Visible>

+      <ProductName>.NET Framework 3.5 SP1</ProductName>

+      <Install>false</Install>

+    </BootstrapperPackage>

+    <BootstrapperPackage Include="Microsoft.Windows.Installer.4.5">

+      <Visible>False</Visible>

+      <ProductName>Windows Installer 4.5</ProductName>

+      <Install>true</Install>

+    </BootstrapperPackage>

+  </ItemGroup>

+  <PropertyGroup>

+    <UseCodebase>true</UseCodebase>

+  </PropertyGroup>

+  <PropertyGroup>

+    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>

+    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

+  </PropertyGroup>

+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

+  <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" />

+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\VSSDK\Microsoft.VsSDK.targets" Condition="false" />

+  <PropertyGroup>

+    <PreBuildEvent>if not exist $(ProjectDir)Key.snk ("$(SDKToolsPath)\sn.exe" -k $(ProjectDir)Key.snk)</PreBuildEvent>

+  </PropertyGroup>

+  <Target Name="BeforeBuild">

+    <Exec ContinueOnError="false" Command="&quot;..\packages\Brutal.Dev.StrongNameSigner.1.8.0\tools\StrongNameSigner.Console.exe&quot; -in &quot;..\packages&quot; -l Summary" />

+  </Target>

+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+       Other similar extension points exist, see Microsoft.Common.targets.

+  <Target Name="AfterBuild">

+  </Target>

+  -->

+</Project>
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidy.vsct b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidy.vsct
new file mode 100644
index 0000000..8bdaeec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidy.vsct
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>

+<CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable" xmlns:xs="http://www.w3.org/2001/XMLSchema">

+

+  <!--  This is the file that defines the actual layout and type of the commands.

+        It is divided in different sections (e.g. command definition, command

+        placement, ...), with each defining a specific set of properties.

+        See the comment before each section for more details about how to

+        use it. -->

+

+  <!--  The VSCT compiler (the tool that translates this file into the binary 

+        format that VisualStudio will consume) has the ability to run a preprocessor 

+        on the vsct file; this preprocessor is (usually) the C++ preprocessor, so 

+        it is possible to define includes and macros with the same syntax used 

+        in C++ files. Using this ability of the compiler here, we include some files 

+        defining some of the constants that we will use inside the file. -->

+

+  <!--This is the file that defines the IDs for all the commands exposed by VisualStudio. -->

+  <Extern href="stdidcmd.h"/>

+

+  <!--This header contains the command ids for the menus provided by the shell. -->

+  <Extern href="vsshlids.h"/>

+

+

+

+

+  <!--The Commands section is where we the commands, menus and menu groups are defined.

+      This section uses a Guid to identify the package that provides the command defined inside it. -->

+  <Commands package="guidClangTidyPkg">

+    <!-- Inside this section we have different sub-sections: one for the menus, another  

+    for the menu groups, one for the buttons (the actual commands), one for the combos 

+    and the last one for the bitmaps used. Each element is identified by a command id that  

+    is a unique pair of guid and numeric identifier; the guid part of the identifier is usually  

+    called "command set" and is used to group different command inside a logically related  

+    group; your package should define its own command set in order to avoid collisions  

+    with command ids defined by other packages. -->

+

+    

+    <!-- In this section you can define new menu groups. A menu group is a container for 

+         other menus or buttons (commands); from a visual point of view you can see the 

+         group as the part of a menu contained between two lines. The parent of a group 

+         must be a menu. -->

+    <Groups>

+

+      <Group guid="guidClangTidyCmdSet" id="MyMenuGroup" priority="0x0600">

+        <Parent guid="guidSHLMainMenu" id="IDM_VS_MENU_TOOLS"/>

+      </Group>

+      

+

+

+    </Groups>

+    

+    <!--Buttons section. -->

+    <!--This section defines the elements the user can interact with, like a menu command or a button 

+        or combo box in a toolbar. -->

+    <Buttons>

+      <!--To define a menu group you have to specify its ID, the parent menu and its display priority. 

+          The command is visible and enabled by default. If you need to change the visibility, status, etc, you can use

+          the CommandFlag node.

+          You can add more than one CommandFlag node e.g.:

+              <CommandFlag>DefaultInvisible</CommandFlag>

+              <CommandFlag>DynamicVisibility</CommandFlag>

+          If you do not want an image next to your command, remove the Icon node /> -->

+

+      <Button guid="guidClangTidyCmdSet" id="cmdidClangTidy" priority="0x0100" type="Button">

+        <Parent guid="guidClangTidyCmdSet" id="MyMenuGroup" />

+        <Icon guid="guidImages" id="bmpPic1" />

+        <Strings>

+          <ButtonText>ClangTidy</ButtonText>

+        </Strings>

+      </Button>

+

+

+

+    </Buttons>

+   

+    <!--The bitmaps section is used to define the bitmaps that are used for the commands.-->

+    <Bitmaps>

+      <!--  The bitmap id is defined in a way that is a little bit different from the others: 

+            the declaration starts with a guid for the bitmap strip, then there is the resource id of the 

+            bitmap strip containing the bitmaps and then there are the numeric ids of the elements used 

+            inside a button definition. An important aspect of this declaration is that the element id 

+            must be the actual index (1-based) of the bitmap inside the bitmap strip. -->

+      <Bitmap guid="guidImages" href="Resources\Images_32bit.bmp" usedList="bmpPic1, bmpPic2, bmpPicSearch, bmpPicX, bmpPicArrows"/>

+      

+    </Bitmaps>

+ 

+  </Commands>

+

+

+  <KeyBindings>

+    <KeyBinding guid="guidClangTidyCmdSet" id="cmdidClangTidy" editor="guidTextEditor" key1="R" mod1="Control" key2="T" mod2="Control"/>

+  </KeyBindings>

+

+

+

+  <Symbols>

+    <!-- This is the package guid. -->

+    <GuidSymbol name="guidClangTidyPkg" value="{AE4956BE-3DB8-430E-BBAB-7E2E9A014E9C}" />

+    

+    <!-- This is the guid used to group the menu commands together -->

+    <GuidSymbol name="guidClangTidyCmdSet" value="{9E0F0493-6493-46DE-AEE1-ACD8F60F265E}">

+      <IDSymbol name="MyMenuGroup" value="0x1020" />

+      <IDSymbol name="cmdidClangTidy" value="0x0100" />

+    </GuidSymbol>

+

+    <GuidSymbol name="guidTextEditor" value="{E10FAD35-7FB8-4991-A269-EF88F12166C9}" />

+

+

+    <GuidSymbol name="guidImages" value="{942F126F-942D-428A-84B4-4AC7C523D0B2}" >

+      <IDSymbol name="bmpPic1" value="1" />

+      <IDSymbol name="bmpPic2" value="2" />

+      <IDSymbol name="bmpPicSearch" value="3" />

+      <IDSymbol name="bmpPicX" value="4" />

+      <IDSymbol name="bmpPicArrows" value="5" />

+    </GuidSymbol>

+  </Symbols>

+

+</CommandTable>

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyCheckAttribute.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyCheckAttribute.cs
new file mode 100644
index 0000000..59234d7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyCheckAttribute.cs
@@ -0,0 +1,22 @@
+using System;

+using System.Collections.Generic;

+using System.Linq;

+using System.Text;

+using System.Threading.Tasks;

+

+namespace LLVM.ClangTidy

+{

+    public class ClangTidyCheckAttribute : Attribute

+    {

+        private string CheckName_;

+        public ClangTidyCheckAttribute(string CheckName)

+        {

+            this.CheckName_ = CheckName;

+        }

+

+        public string CheckName

+        {

+            get { return CheckName_; }

+        }

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyConfigParser.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyConfigParser.cs
new file mode 100644
index 0000000..db5b055
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyConfigParser.cs
@@ -0,0 +1,214 @@
+using System;

+using System.Collections.Generic;

+using System.IO;

+using System.Linq;

+using System.Text;

+using System.Threading.Tasks;

+using YamlDotNet.Serialization;

+using YamlDotNet.Serialization.NamingConventions;

+

+namespace LLVM.ClangTidy

+{

+    static class ClangTidyConfigParser

+    {

+        public class CheckOption

+        {

+            [YamlAlias("key")]

+            public string Key { get; set; }

+

+            [YamlAlias("value")]

+            public string Value { get; set; }

+        }

+        public class ClangTidyYaml

+        {

+            [YamlAlias("Checks")]

+            public string Checks { get; set; }

+

+            [YamlAlias("CheckOptions")]

+            public List<CheckOption> CheckOptions { get; set; }

+        }

+

+        public static List<KeyValuePair<string, ClangTidyProperties>> ParseConfigurationChain(string ClangTidyFile)

+        {

+            List<KeyValuePair<string, ClangTidyProperties>> Result = new List<KeyValuePair<string, ClangTidyProperties>>();

+            Result.Add(new KeyValuePair<string, ClangTidyProperties>(null, ClangTidyProperties.RootProperties));

+

+            foreach (string P in Utility.SplitPath(ClangTidyFile).Reverse())

+            {

+                if (!Utility.HasClangTidyFile(P))

+                    continue;

+

+                string ConfigFile = Path.Combine(P, ".clang-tidy");

+

+                using (StreamReader Reader = new StreamReader(ConfigFile))

+                {

+                    Deserializer D = new Deserializer(namingConvention: new PascalCaseNamingConvention());

+                    ClangTidyYaml Y = D.Deserialize<ClangTidyYaml>(Reader);

+                    ClangTidyProperties Parent = Result[Result.Count - 1].Value;

+                    ClangTidyProperties NewProps = new ClangTidyProperties(Parent);

+                    SetPropertiesFromYaml(Y, NewProps);

+                    Result.Add(new KeyValuePair<string, ClangTidyProperties>(P, NewProps));

+                }

+            }

+            return Result;

+        }

+

+        enum TreeLevelOp

+        {

+            Enable,

+            Disable,

+            Inherit

+        }

+

+        public static void SerializeClangTidyFile(ClangTidyProperties Props, string ClangTidyFilePath)

+        {

+            List<string> CommandList = new List<string>();

+            SerializeCheckTree(CommandList, Props.GetCheckTree(), TreeLevelOp.Inherit);

+

+            CommandList.Sort((x, y) =>

+            {

+                bool LeftSub = x.StartsWith("-");

+                bool RightSub = y.StartsWith("-");

+                if (LeftSub && !RightSub)

+                    return -1;

+                if (RightSub && !LeftSub)

+                    return 1;

+                return StringComparer.CurrentCulture.Compare(x, y);

+            });

+

+            string ConfigFile = Path.Combine(ClangTidyFilePath, ".clang-tidy");

+            using (StreamWriter Writer = new StreamWriter(ConfigFile))

+            {

+                Serializer S = new Serializer(namingConvention: new PascalCaseNamingConvention());

+                ClangTidyYaml Yaml = new ClangTidyYaml();

+                Yaml.Checks = String.Join(",", CommandList.ToArray());

+                S.Serialize(Writer, Yaml);

+            }

+        }

+

+        /// <summary>

+        /// Convert the given check tree into serialized list of commands that can be written to

+        /// the Yaml.  The goal here is to determine the minimal sequence of check commands that

+        /// will produce the exact configuration displayed in the UI.  This is complicated by the

+        /// fact that an inherited True is not the same as an explicitly specified True.  If the

+        /// user has chosen to inherit a setting in a .clang-tidy file, then changing it in the

+        /// parent should show the reflected changes in the current file as well.  So we cannot

+        /// simply -* everything and then add in the checks we need, because -* immediately marks

+        /// every single check as explicitly false, thus disabling inheritance.

+        /// </summary>

+        /// <param name="CommandList">State passed through this recursive algorithm representing

+        /// the sequence of commands we have determined so far.

+        /// </param>

+        /// <param name="Tree">The check tree to serialize.  This is the parameter that will be

+        /// recursed on as successive subtrees get serialized to `CommandList`.

+        /// </param>

+        /// <param name="CurrentOp">The current state of the subtree.  For example, if the

+        /// algorithm decides to -* an entire subtree and then add back one single check,

+        /// after adding a -subtree-* command to CommandList, it would pass in a value of

+        /// CurrentOp=TreeLevelOp.Disable when it recurses down.  This allows deeper iterations

+        /// of the algorithm to know what kind of command (if any) needs to be added to CommandList

+        /// in order to put a particular check into a particular state.

+        /// </param>

+        private static void SerializeCheckTree(List<string> CommandList, CheckTree Tree, TreeLevelOp CurrentOp)

+        {

+            int NumChecks = Tree.CountChecks;

+            int NumDisabled = Tree.CountExplicitlyDisabledChecks;

+            int NumEnabled = Tree.CountExplicitlyEnabledChecks;

+            int NumInherited = Tree.CountInheritedChecks;

+

+            if (NumChecks == 0)

+                return;

+

+            if (NumInherited > 0)

+                System.Diagnostics.Debug.Assert(CurrentOp == TreeLevelOp.Inherit);

+

+            // If this entire tree is inherited, just exit, nothing about this needs to

+            // go in the clang-tidy file.

+            if (NumInherited == NumChecks)

+                return;

+

+            TreeLevelOp NewOp = CurrentOp;

+            // If there are no inherited properties in this subtree, decide whether to

+            // explicitly enable or disable this subtree.  Decide by looking at whether

+            // there is a larger proportion of disabled or enabled descendants.  If

+            // there are more disabled items in this subtree for example, disabling the

+            // subtree will lead to a smaller configuration file.

+            if (NumInherited == 0)

+            {

+                if (NumDisabled >= NumEnabled)

+                    NewOp = TreeLevelOp.Disable;

+                else

+                    NewOp = TreeLevelOp.Enable;

+            }

+

+            if (NewOp == TreeLevelOp.Disable)

+            {

+                // Only add an explicit disable command if the tree was not already disabled

+                // to begin with.

+                if (CurrentOp != TreeLevelOp.Disable)

+                {

+                    string WildcardPath = "*";

+                    if (Tree.Path != null)

+                        WildcardPath = Tree.Path + "-" + WildcardPath;

+                    CommandList.Add("-" + WildcardPath);

+                }

+                // If the entire subtree was disabled, there's no point descending.

+                if (NumDisabled == NumChecks)

+                    return;

+            }

+            else if (NewOp == TreeLevelOp.Enable)

+            {

+                // Only add an explicit enable command if the tree was not already enabled

+                // to begin with.  Note that if we're at the root, all checks are already

+                // enabled by default, so there's no need to explicitly include *

+                if (CurrentOp != TreeLevelOp.Enable && Tree.Path != null)

+                {

+                    string WildcardPath = Tree.Path + "-*";

+                    CommandList.Add(WildcardPath);

+                }

+                // If the entire subtree was enabled, there's no point descending.

+                if (NumEnabled == NumChecks)

+                    return;

+            }

+

+            foreach (var Child in Tree.Children)

+            {

+                if (Child.Value is CheckLeaf)

+                {

+                    CheckLeaf Leaf = (CheckLeaf)Child.Value;

+                    if (Leaf.CountExplicitlyEnabledChecks == 1 && NewOp != TreeLevelOp.Enable)

+                        CommandList.Add(Leaf.Path);

+                    else if (Leaf.CountExplicitlyDisabledChecks == 1 && NewOp != TreeLevelOp.Disable)

+                        CommandList.Add("-" + Leaf.Path);

+                    continue;

+                }

+

+                System.Diagnostics.Debug.Assert(Child.Value is CheckTree);

+                CheckTree ChildTree = (CheckTree)Child.Value;

+                SerializeCheckTree(CommandList, ChildTree, NewOp);

+            }

+        }

+

+        private static void SetPropertiesFromYaml(ClangTidyYaml Yaml, ClangTidyProperties Props)

+        {

+            string[] CheckCommands = Yaml.Checks.Split(',');

+            foreach (string Command in CheckCommands)

+            {

+                if (Command == null || Command.Length == 0)

+                    continue;

+                bool Add = true;

+                string Pattern = Command;

+                if (Pattern[0] == '-')

+                {

+                    Pattern = Pattern.Substring(1);

+                    Add = false;

+                }

+

+                foreach (var Match in CheckDatabase.Checks.Where(x => Utility.MatchWildcardString(x.Name, Pattern)))

+                {

+                    Props.SetDynamicValue(Match.Name, Add);

+                }

+            }

+        }

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyConfigurationPage.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyConfigurationPage.cs
new file mode 100644
index 0000000..0f7a8e9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyConfigurationPage.cs
@@ -0,0 +1,61 @@
+using Microsoft.VisualStudio;

+using Microsoft.VisualStudio.Shell;

+using Microsoft.VisualStudio.Shell.Interop;

+using System;

+using System.Collections;

+using System.Collections.Generic;

+using System.ComponentModel;

+using System.Linq;

+using System.Runtime.InteropServices;

+using System.Text;

+using System.Threading.Tasks;

+using System.Windows.Forms;

+

+namespace LLVM.ClangTidy

+{

+    [ClassInterface(ClassInterfaceType.AutoDual)]

+    [CLSCompliant(false), ComVisible(true)]

+    public class ClangTidyConfigurationPage : DialogPage

+    {

+        ClangTidyPropertyGrid Grid = null;

+        protected override IWin32Window Window

+        {

+            get

+            {

+                if (Grid == null)

+                    Grid = new ClangTidyPropertyGrid();

+                return Grid;

+            }

+        }

+

+        protected override void SaveSetting(PropertyDescriptor property)

+        {

+            base.SaveSetting(property);

+        }

+

+        public override void SaveSettingsToStorage()

+        {

+            if (Grid != null)

+                Grid.SaveSettingsToStorage();

+

+            base.SaveSettingsToStorage();

+        }

+

+        public override void ResetSettings()

+        {

+            base.ResetSettings();

+        }

+

+        protected override void LoadSettingFromStorage(PropertyDescriptor prop)

+        {

+            base.LoadSettingFromStorage(prop);

+        }

+

+        public override void LoadSettingsFromStorage()

+        {

+            if (Grid != null)

+                Grid.InitializeSettings();

+            base.LoadSettingsFromStorage();

+        }

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyPackage.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyPackage.cs
new file mode 100644
index 0000000..9a0c9b6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyPackage.cs
@@ -0,0 +1,56 @@
+//===-- ClangTidyPackages.cs - VSPackage for clang-tidy ----------*- C# -*-===//

+//

+//                     The LLVM Compiler Infrastructure

+//

+// This file is distributed under the University of Illinois Open Source

+// License. See LICENSE.TXT for details.

+//

+//===----------------------------------------------------------------------===//

+//

+// This class contains a VS extension package that runs clang-tidy over a

+// file in a VS text editor.

+//

+//===----------------------------------------------------------------------===//

+

+using Microsoft.VisualStudio.Editor;

+using Microsoft.VisualStudio.Shell;

+using Microsoft.VisualStudio.Shell.Interop;

+using Microsoft.VisualStudio.TextManager.Interop;

+using System;

+using System.Collections;

+using System.ComponentModel;

+using System.ComponentModel.Design;

+using System.IO;

+using System.Runtime.InteropServices;

+using System.Windows.Forms;

+using System.Xml.Linq;

+

+namespace LLVM.ClangTidy

+{

+    [PackageRegistration(UseManagedResourcesOnly = true)]

+    [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]

+    [ProvideMenuResource("Menus.ctmenu", 1)]

+    [Guid(GuidList.guidClangTidyPkgString)]

+    [ProvideOptionPage(typeof(ClangTidyConfigurationPage), "LLVM/Clang", "ClangTidy", 0, 0, true)]

+    public sealed class ClangTidyPackage : Package

+    {

+        #region Package Members

+        protected override void Initialize()

+        {

+            base.Initialize();

+

+            var commandService = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;

+            if (commandService != null)

+            {

+                var menuCommandID = new CommandID(GuidList.guidClangTidyCmdSet, (int)PkgCmdIDList.cmdidClangTidy);

+                var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);

+                commandService.AddCommand(menuItem);

+            }

+        }

+        #endregion

+

+        private void MenuItemCallback(object sender, EventArgs args)

+        {

+        }

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyProperties.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyProperties.cs
new file mode 100644
index 0000000..c6597c1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyProperties.cs
@@ -0,0 +1,83 @@
+using System;

+using System.Collections.Generic;

+using System.ComponentModel;

+using System.Globalization;

+using System.Linq;

+using System.Reflection;

+using System.Runtime.InteropServices;

+using System.Text;

+using System.Threading.Tasks;

+

+namespace LLVM.ClangTidy

+{

+

+    public class ClangTidyProperties : DynamicPropertyComponent

+    {

+        private static ClangTidyProperties RootProperties_ = null;

+        private CheckTree CheckTree_;

+        private bool HasUnsavedChanges_ = false;

+

+        public struct CheckMapping

+        {

+            public string CheckName;

+            public string Property;

+        }

+

+        public ClangTidyProperties()

+            : base(null)

+        {

+            AddClangCheckProperties();

+            CheckTree_ = CheckTree.Build(this);

+        }

+

+        public ClangTidyProperties(DynamicPropertyComponent Parent)

+            : base(Parent)

+        {

+            AddClangCheckProperties();

+            CheckTree_ = CheckTree.Build(this);

+        }

+

+        static ClangTidyProperties()

+        {

+            RootProperties_ = new ClangTidyProperties(null);

+        }

+

+        public static ClangTidyProperties RootProperties

+        {

+            get { return RootProperties_; }

+        }

+

+        private void AddClangCheckProperties()

+        {

+            // Add each check in the check database

+            HashSet<string> Categories = new HashSet<string>();

+            foreach (var Check in CheckDatabase.Checks)

+            {

+                string Name = Check.Name.Replace('-', '_');

+                List<Attribute> Attrs = new List<Attribute>();

+                Attrs.Add(new CategoryAttribute(Check.Category));

+                Attrs.Add(new DisplayNameAttribute(Check.Label));

+                Attrs.Add(new DefaultValueAttribute(true));

+                Attrs.Add(new DescriptionAttribute(Check.Desc));

+                Attrs.Add(new ClangTidyCheckAttribute(Check.Name));

+                Categories.Add(Check.Category);

+                AddDynamicProperty<bool>(Check.Name, Attrs.ToArray());

+            }

+

+            // Add a category verb for each unique category.

+            foreach (string Cat in Categories)

+            {

+                List<Attribute> Attrs = new List<Attribute>();

+                Attrs.Add(new CategoryAttribute(Cat));

+                Attrs.Add(new DisplayNameAttribute("(Category Verbs)"));

+                Attrs.Add(new TypeConverterAttribute(typeof(CategoryVerbConverter)));

+                Attrs.Add(new DefaultValueAttribute(CategoryVerb.None));

+                AddDynamicProperty<CategoryVerb>(Cat + "Verb", Attrs.ToArray());

+            }

+        }

+

+        public CheckTree GetCheckTree() { return CheckTree_; }

+        public bool GetHasUnsavedChanges() { return HasUnsavedChanges_; }

+        public void SetHasUnsavedChanges(bool Value) { HasUnsavedChanges_ = Value; }

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.Designer.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.Designer.cs
new file mode 100644
index 0000000..ce9324a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.Designer.cs
@@ -0,0 +1,119 @@
+namespace LLVM.ClangTidy

+{

+    partial class ClangTidyPropertyGrid

+    {

+        /// <summary> 

+        /// Required designer variable.

+        /// </summary>

+        private System.ComponentModel.IContainer components = null;

+

+        /// <summary> 

+        /// Clean up any resources being used.

+        /// </summary>

+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>

+        protected override void Dispose(bool disposing)

+        {

+            if (disposing && (components != null))

+            {

+                components.Dispose();

+            }

+            base.Dispose(disposing);

+        }

+

+        #region Component Designer generated code

+

+        /// <summary> 

+        /// Required method for Designer support - do not modify 

+        /// the contents of this method with the code editor.

+        /// </summary>

+        private void InitializeComponent()

+        {

+            this.label1 = new System.Windows.Forms.Label();

+            this.textBox1 = new System.Windows.Forms.TextBox();

+            this.button1 = new System.Windows.Forms.Button();

+            this.propertyGrid1 = new System.Windows.Forms.PropertyGrid();

+            this.clangTidyProperties1 = new LLVM.ClangTidy.ClangTidyProperties();

+            this.clangTidyConfigurationPage1 = new LLVM.ClangTidy.ClangTidyConfigurationPage();

+            this.linkLabelPath = new System.Windows.Forms.LinkLabel();

+            this.SuspendLayout();

+            // 

+            // label1

+            // 

+            this.label1.AutoSize = true;

+            this.label1.Location = new System.Drawing.Point(14, 17);

+            this.label1.Name = "label1";

+            this.label1.Size = new System.Drawing.Size(88, 13);

+            this.label1.TabIndex = 0;

+            this.label1.Text = "Configuration File";

+            // 

+            // textBox1

+            // 

+            this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 

+            | System.Windows.Forms.AnchorStyles.Right)));

+            this.textBox1.Location = new System.Drawing.Point(108, 14);

+            this.textBox1.Name = "textBox1";

+            this.textBox1.Size = new System.Drawing.Size(222, 20);

+            this.textBox1.TabIndex = 1;

+            // 

+            // button1

+            // 

+            this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));

+            this.button1.Location = new System.Drawing.Point(336, 14);

+            this.button1.Name = "button1";

+            this.button1.Size = new System.Drawing.Size(78, 20);

+            this.button1.TabIndex = 2;

+            this.button1.Text = "Browse";

+            this.button1.UseVisualStyleBackColor = true;

+            this.button1.Click += new System.EventHandler(this.button1_Click);

+            // 

+            // propertyGrid1

+            // 

+            this.propertyGrid1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 

+            | System.Windows.Forms.AnchorStyles.Left) 

+            | System.Windows.Forms.AnchorStyles.Right)));

+            this.propertyGrid1.Location = new System.Drawing.Point(20, 73);

+            this.propertyGrid1.Name = "propertyGrid1";

+            this.propertyGrid1.SelectedObject = this.clangTidyProperties1;

+            this.propertyGrid1.Size = new System.Drawing.Size(391, 384);

+            this.propertyGrid1.TabIndex = 6;

+            this.propertyGrid1.ViewBorderColor = System.Drawing.SystemColors.ControlDarkDark;

+            this.propertyGrid1.PropertyValueChanged += new System.Windows.Forms.PropertyValueChangedEventHandler(this.propertyGrid1_PropertyValueChanged);

+            // 

+            // linkLabelPath

+            // 

+            this.linkLabelPath.AutoSize = true;

+            this.linkLabelPath.Location = new System.Drawing.Point(29, 50);

+            this.linkLabelPath.Name = "linkLabelPath";

+            this.linkLabelPath.Size = new System.Drawing.Size(55, 13);

+            this.linkLabelPath.TabIndex = 7;

+            this.linkLabelPath.TabStop = true;

+            this.linkLabelPath.Text = "linkLabel1";

+            this.linkLabelPath.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelPath_LinkClicked);

+            // 

+            // ClangTidyPropertyGrid

+            // 

+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);

+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;

+            this.Controls.Add(this.linkLabelPath);

+            this.Controls.Add(this.propertyGrid1);

+            this.Controls.Add(this.button1);

+            this.Controls.Add(this.textBox1);

+            this.Controls.Add(this.label1);

+            this.Name = "ClangTidyPropertyGrid";

+            this.Size = new System.Drawing.Size(444, 469);

+            this.ResumeLayout(false);

+            this.PerformLayout();

+

+        }

+

+        #endregion

+

+        private System.Windows.Forms.Label label1;

+        private System.Windows.Forms.TextBox textBox1;

+        private System.Windows.Forms.Button button1;

+        private System.Windows.Forms.PropertyGrid propertyGrid1;

+        private ClangTidyProperties clangTidyProperties1;

+        private ClangTidyConfigurationPage clangTidyConfigurationPage1;

+        private System.Windows.Forms.LinkLabel linkLabelPath;

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.cs
new file mode 100644
index 0000000..20c8a8f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.cs
@@ -0,0 +1,208 @@
+//===-- ClangTidyPropertyGrid.cs - UI for configuring clang-tidy -*- C# -*-===//

+//

+//                     The LLVM Compiler Infrastructure

+//

+// This file is distributed under the University of Illinois Open Source

+// License. See LICENSE.TXT for details.

+//

+//===----------------------------------------------------------------------===//

+//

+// This class contains a UserControl consisting of a .NET PropertyGrid control

+// allowing configuration of checks and check options for ClangTidy.

+//

+//===----------------------------------------------------------------------===//

+using System;

+using System.Collections.Generic;

+using System.ComponentModel;

+using System.Drawing;

+using System.Data;

+using System.Linq;

+using System.Text;

+using System.Threading.Tasks;

+using System.Windows.Forms;

+using System.IO;

+using Microsoft.VisualStudio.Shell;

+

+namespace LLVM.ClangTidy

+{

+    /// <summary>

+    ///  A UserControl displaying a PropertyGrid allowing configuration of clang-tidy

+    ///  checks and check options, as well as serialization and deserialization of

+    ///  clang-tidy configuration files.  When a configuration file is loaded, the

+    ///  entire chain of configuration files is analyzed based on the file path,

+    ///  and quick access is provided to edit or view any of the files in the

+    ///  configuration chain, allowing easy visualization of where values come from

+    ///  (similar in spirit to the -explain-config option of clang-tidy).

+    /// </summary>

+    public partial class ClangTidyPropertyGrid : UserControl

+    {

+        /// <summary>

+        /// The sequence of .clang-tidy configuration files, starting from the root

+        /// of the filesystem, down to the selected file.

+        /// </summary>

+        List<KeyValuePair<string, ClangTidyProperties>> PropertyChain_ = null;

+

+        public ClangTidyPropertyGrid()

+        {

+            InitializeComponent();

+            InitializeSettings();

+        }

+

+        private enum ShouldCancel

+        {

+            Yes,

+            No,

+        }

+

+        public void SaveSettingsToStorage()

+        {

+            PersistUnsavedChanges(false);

+        }

+

+        private ShouldCancel PersistUnsavedChanges(bool PromptFirst)

+        {

+            var UnsavedResults = PropertyChain_.Where(x => x.Key != null && x.Value.GetHasUnsavedChanges());

+            if (UnsavedResults.Count() == 0)

+                return ShouldCancel.No;

+

+            bool ShouldSave = false;

+            if (PromptFirst)

+            {

+                var Response = MessageBox.Show(

+                    "You have unsaved changes!  Do you want to save before loading a new file?",

+                    "clang-tidy",

+                    MessageBoxButtons.YesNoCancel);

+

+                ShouldSave = (Response == DialogResult.Yes);

+                if (Response == DialogResult.Cancel)

+                    return ShouldCancel.Yes;

+            }

+            else

+                ShouldSave = true;

+

+            if (ShouldSave)

+            {

+                foreach (var Result in UnsavedResults)

+                {

+                    ClangTidyConfigParser.SerializeClangTidyFile(Result.Value, Result.Key);

+                    Result.Value.SetHasUnsavedChanges(false);

+                }

+            }

+            return ShouldCancel.No;

+        }

+

+        public void InitializeSettings()

+        {

+            PropertyChain_ = new List<KeyValuePair<string, ClangTidyProperties>>();

+            PropertyChain_.Add(new KeyValuePair<string, ClangTidyProperties>(null, ClangTidyProperties.RootProperties));

+            reloadPropertyChain();

+        }

+

+        private void button1_Click(object sender, EventArgs e)

+        {

+            ShouldCancel Cancel = PersistUnsavedChanges(true);

+            if (Cancel == ShouldCancel.Yes)

+                return;

+

+            using (OpenFileDialog D = new OpenFileDialog())

+            {

+                D.Filter = "Clang Tidy files|.clang-tidy";

+                D.CheckPathExists = true;

+                D.CheckFileExists = true;

+

+                if (D.ShowDialog() == DialogResult.OK)

+                {

+                    PropertyChain_.Clear();

+                    PropertyChain_ = ClangTidyConfigParser.ParseConfigurationChain(D.FileName);

+                    textBox1.Text = D.FileName;

+                    reloadPropertyChain();

+                }

+            }

+        }

+

+        private static readonly string DefaultText = "(Default)";

+        private static readonly string BrowseText = "Browse for a file to edit its properties";

+

+        /// <summary>

+        /// After a new configuration file is chosen, analyzes the directory hierarchy

+        /// and finds all .clang-tidy files in the path, parses them and updates the

+        /// PropertyGrid and quick-access LinkLabel control to reflect the new property

+        /// chain.

+        /// </summary>

+        private void reloadPropertyChain()

+        {

+            StringBuilder LinkBuilder = new StringBuilder();

+            LinkBuilder.Append(DefaultText);

+            LinkBuilder.Append(" > ");

+            int PrefixLength = LinkBuilder.Length;

+

+            if (PropertyChain_.Count == 1)

+                LinkBuilder.Append(BrowseText);

+            else

+                LinkBuilder.Append(PropertyChain_[PropertyChain_.Count - 1].Key);

+

+            linkLabelPath.Text = LinkBuilder.ToString();

+

+            // Given a path like D:\Foo\Bar\Baz, construct a LinkLabel where individual

+            // components of the path are clickable iff they contain a .clang-tidy file.

+            // Clicking one of the links then updates the PropertyGrid to display the

+            // selected .clang-tidy file.

+            ClangTidyProperties LastProps = ClangTidyProperties.RootProperties;

+            linkLabelPath.Links.Clear();

+            linkLabelPath.Links.Add(0, DefaultText.Length, LastProps);

+            foreach (var Prop in PropertyChain_.Skip(1))

+            {

+                LastProps = Prop.Value;

+                string ClangTidyFolder = Path.GetFileName(Prop.Key);

+                int ClangTidyFolderOffset = Prop.Key.Length - ClangTidyFolder.Length;

+                linkLabelPath.Links.Add(PrefixLength + ClangTidyFolderOffset, ClangTidyFolder.Length, LastProps);

+            }

+            propertyGrid1.SelectedObject = LastProps;

+        }

+

+        private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)

+        {

+            ClangTidyProperties Props = (ClangTidyProperties)propertyGrid1.SelectedObject;

+            Props.SetHasUnsavedChanges(true);

+

+            // When a CategoryVerb is selected, perform the corresponding action.

+            PropertyDescriptor Property = e.ChangedItem.PropertyDescriptor;

+            if (!(e.ChangedItem.Value is CategoryVerb))

+                return;

+

+            CategoryVerb Action = (CategoryVerb)e.ChangedItem.Value;

+            if (Action == CategoryVerb.None)

+                return;

+

+            var Category = Property.Attributes.OfType<CategoryAttribute>().FirstOrDefault();

+            if (Category == null)

+                return;

+            var SameCategoryProps = Props.GetProperties(new Attribute[] { Category });

+            foreach (PropertyDescriptor P in SameCategoryProps)

+            {

+                if (P == Property)

+                    continue;

+                switch (Action)

+                {

+                    case CategoryVerb.Disable:

+                        P.SetValue(propertyGrid1.SelectedObject, false);

+                        break;

+                    case CategoryVerb.Enable:

+                        P.SetValue(propertyGrid1.SelectedObject, true);

+                        break;

+                    case CategoryVerb.Inherit:

+                        P.ResetValue(propertyGrid1.SelectedObject);

+                        break;

+                }

+            }

+            Property.ResetValue(propertyGrid1.SelectedObject);

+            propertyGrid1.Invalidate();

+        }

+

+        private void linkLabelPath_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)

+        {

+            ClangTidyProperties Props = (ClangTidyProperties)e.Link.LinkData;

+            propertyGrid1.SelectedObject = Props;

+        }

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.resx b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.resx
new file mode 100644
index 0000000..22dfde0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.resx
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>

+<root>

+  <!-- 

+    Microsoft ResX Schema 

+    

+    Version 2.0

+    

+    The primary goals of this format is to allow a simple XML format 

+    that is mostly human readable. The generation and parsing of the 

+    various data types are done through the TypeConverter classes 

+    associated with the data types.

+    

+    Example:

+    

+    ... ado.net/XML headers & schema ...

+    <resheader name="resmimetype">text/microsoft-resx</resheader>

+    <resheader name="version">2.0</resheader>

+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>

+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>

+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>

+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>

+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">

+        <value>[base64 mime encoded serialized .NET Framework object]</value>

+    </data>

+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">

+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>

+        <comment>This is a comment</comment>

+    </data>

+                

+    There are any number of "resheader" rows that contain simple 

+    name/value pairs.

+    

+    Each data row contains a name, and value. The row also contains a 

+    type or mimetype. Type corresponds to a .NET class that support 

+    text/value conversion through the TypeConverter architecture. 

+    Classes that don't support this are serialized and stored with the 

+    mimetype set.

+    

+    The mimetype is used for serialized objects, and tells the 

+    ResXResourceReader how to depersist the object. This is currently not 

+    extensible. For a given mimetype the value must be set accordingly:

+    

+    Note - application/x-microsoft.net.object.binary.base64 is the format 

+    that the ResXResourceWriter will generate, however the reader can 

+    read any of the formats listed below.

+    

+    mimetype: application/x-microsoft.net.object.binary.base64

+    value   : The object must be serialized with 

+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter

+            : and then encoded with base64 encoding.

+    

+    mimetype: application/x-microsoft.net.object.soap.base64

+    value   : The object must be serialized with 

+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter

+            : and then encoded with base64 encoding.

+

+    mimetype: application/x-microsoft.net.object.bytearray.base64

+    value   : The object must be serialized into a byte array 

+            : using a System.ComponentModel.TypeConverter

+            : and then encoded with base64 encoding.

+    -->

+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">

+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />

+    <xsd:element name="root" msdata:IsDataSet="true">

+      <xsd:complexType>

+        <xsd:choice maxOccurs="unbounded">

+          <xsd:element name="metadata">

+            <xsd:complexType>

+              <xsd:sequence>

+                <xsd:element name="value" type="xsd:string" minOccurs="0" />

+              </xsd:sequence>

+              <xsd:attribute name="name" use="required" type="xsd:string" />

+              <xsd:attribute name="type" type="xsd:string" />

+              <xsd:attribute name="mimetype" type="xsd:string" />

+              <xsd:attribute ref="xml:space" />

+            </xsd:complexType>

+          </xsd:element>

+          <xsd:element name="assembly">

+            <xsd:complexType>

+              <xsd:attribute name="alias" type="xsd:string" />

+              <xsd:attribute name="name" type="xsd:string" />

+            </xsd:complexType>

+          </xsd:element>

+          <xsd:element name="data">

+            <xsd:complexType>

+              <xsd:sequence>

+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />

+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />

+              </xsd:sequence>

+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />

+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />

+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />

+              <xsd:attribute ref="xml:space" />

+            </xsd:complexType>

+          </xsd:element>

+          <xsd:element name="resheader">

+            <xsd:complexType>

+              <xsd:sequence>

+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />

+              </xsd:sequence>

+              <xsd:attribute name="name" type="xsd:string" use="required" />

+            </xsd:complexType>

+          </xsd:element>

+        </xsd:choice>

+      </xsd:complexType>

+    </xsd:element>

+  </xsd:schema>

+  <resheader name="resmimetype">

+    <value>text/microsoft-resx</value>

+  </resheader>

+  <resheader name="version">

+    <value>2.0</value>

+  </resheader>

+  <resheader name="reader">

+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>

+  </resheader>

+  <resheader name="writer">

+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>

+  </resheader>

+  <metadata name="clangTidyConfigurationPage1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">

+    <value>183, 17</value>

+  </metadata>

+</root>
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/DynamicPropertyComponent.Designer.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/DynamicPropertyComponent.Designer.cs
new file mode 100644
index 0000000..099f1c0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/DynamicPropertyComponent.Designer.cs
@@ -0,0 +1,42 @@
+using System;

+using System.Collections.Generic;

+using System.Linq;

+using System.Text;

+using System.Threading.Tasks;

+

+namespace LLVM.ClangTidy

+{

+    partial class DynamicPropertyComponent

+    {

+        /// <summary>

+        /// Required designer variable.

+        /// </summary>

+        private System.ComponentModel.IContainer components = null;

+

+        /// <summary> 

+        /// Clean up any resources being used.

+        /// </summary>

+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>

+        protected override void Dispose(bool disposing)

+        {

+            if (disposing && (components != null))

+            {

+                components.Dispose();

+            }

+            base.Dispose(disposing);

+        }

+

+        #region Component Designer generated code

+

+        /// <summary>

+        /// Required method for Designer support - do not modify

+        /// the contents of this method with the code editor.

+        /// </summary>

+        private void InitializeComponent()

+        {

+            components = new System.ComponentModel.Container();

+        }

+

+        #endregion

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/DynamicPropertyComponent.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/DynamicPropertyComponent.cs
new file mode 100644
index 0000000..e8843db
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/DynamicPropertyComponent.cs
@@ -0,0 +1,138 @@
+using System;

+using System.Collections.Generic;

+using System.ComponentModel;

+using System.Linq;

+using System.Text;

+using System.Threading.Tasks;

+

+namespace LLVM.ClangTidy

+{

+    /// <summary>

+    /// The goal of this class is to enable displaying of a PropertyGrid in much the

+    /// same way that Visual Studio's C++ project system does.  A project or file can

+    /// have properties which might inherit from their parent, or be overridden.

+    /// It turns out this is somewhat non-trivial.  The .NET PropertyGrid is good makes

+    /// displaying simple properties with a static notion of what constitutes a

+    /// "default" value very easy.  You simply apply an Attribute to the class that says

+    /// what the default value is and you're done.  But when you try to introduce the idea

+    /// that a property's default value depends on some other factor, things get much more

+    /// complicated due to the static nature of Attributes.

+    /// 

+    /// The solution to this is to inherit from ICustomTypeDescriptor.  This is the mechanism

+    /// by which you can inject or modify attributes or properties at runtime.  The .NET

+    /// PropertyGrid is designed in such a way that instead of using simple .NET Reflection to

+    /// look for the properties and attributes on a class, it will invoke the methods of

+    /// ICustomTypeDescriptor (if your type inherits from it), and ask those methods.  Our

+    /// implementation of ICustomTypeDescriptor works by waiting until the PropertyGrid requests

+    /// PropertyDescriptors for each of the properties, and then "decorating" them with our

+    /// own custom PropertyDescriptor implementation which understands the proeprty inheritance

+    /// model we wish to implement.

+    /// </summary>

+    public partial class DynamicPropertyComponent : Component, ICustomTypeDescriptor

+    {

+        PropertyDescriptorCollection DynamicProperties_ = new PropertyDescriptorCollection(null);

+        private DynamicPropertyComponent Parent_;

+

+        public DynamicPropertyComponent(DynamicPropertyComponent Parent)

+        {

+            Parent_ = Parent;

+        }

+

+        public DynamicPropertyComponent(DynamicPropertyComponent Parent, IContainer container)

+        {

+            Parent_ = Parent;

+

+            container.Add(this);

+            InitializeComponent();

+        }

+

+        public AttributeCollection GetAttributes()

+        {

+            return TypeDescriptor.GetAttributes(GetType());

+        }

+

+        public string GetClassName()

+        {

+            return TypeDescriptor.GetClassName(GetType());

+        }

+

+        public string GetComponentName()

+        {

+            return TypeDescriptor.GetComponentName(GetType());

+        }

+

+        public TypeConverter GetConverter()

+        {

+            return TypeDescriptor.GetConverter(GetType());

+        }

+

+        public EventDescriptor GetDefaultEvent()

+        {

+            return TypeDescriptor.GetDefaultEvent(GetType());

+        }

+

+        public PropertyDescriptor GetDefaultProperty()

+        {

+            return TypeDescriptor.GetDefaultProperty(GetType());

+        }

+

+        public object GetEditor(Type editorBaseType)

+        {

+            return TypeDescriptor.GetEditor(GetType(), editorBaseType);

+        }

+

+        public EventDescriptorCollection GetEvents()

+        {

+            return TypeDescriptor.GetEvents(GetType());

+        }

+

+        public EventDescriptorCollection GetEvents(Attribute[] attributes)

+        {

+            return TypeDescriptor.GetEvents(GetType(), attributes);

+        }

+

+        public PropertyDescriptorCollection GetProperties()

+        {

+            return DynamicProperties_;

+        }

+

+        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)

+        {

+            var Props = DynamicProperties_.OfType<PropertyDescriptor>();

+            var Filtered = Props.Where(x => x.Attributes.Contains(attributes)).ToArray();

+            return new PropertyDescriptorCollection(Filtered);

+        }

+

+        public object GetPropertyOwner(PropertyDescriptor pd)

+        {

+            return this;

+        }

+

+        public void SetDynamicValue<T>(string Name, T Value)

+        {

+            Name = Name.Replace('-', '_');

+            DynamicPropertyDescriptor<T> Descriptor = (DynamicPropertyDescriptor<T>)DynamicProperties_.Find(Name, false);

+            Descriptor.SetValue(this, Value);

+        }

+

+        public T GetDynamicValue<T>(string Name)

+        {

+            Name = Name.Replace('-', '_');

+            DynamicPropertyDescriptor<T> Descriptor = (DynamicPropertyDescriptor<T>)DynamicProperties_.Find(Name, false);

+            return (T)Descriptor.GetValue(this);

+        }

+

+        protected void AddDynamicProperty<T>(string Name, Attribute[] Attributes)

+        {

+            Name = Name.Replace('-', '_');

+

+            // If we have a parent, find the corresponding PropertyDescriptor with the same

+            // name from the parent.

+            DynamicPropertyDescriptor<T> ParentDescriptor = null;

+            if (Parent_ != null)

+                ParentDescriptor = (DynamicPropertyDescriptor<T>)Parent_.GetProperties().Find(Name, false);

+

+            DynamicProperties_.Add(new DynamicPropertyDescriptor<T>(Name, ParentDescriptor, Name, Attributes));

+        }

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/DynamicPropertyConverter.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/DynamicPropertyConverter.cs
new file mode 100644
index 0000000..9442667
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/DynamicPropertyConverter.cs
@@ -0,0 +1,139 @@
+using System;

+using System.Collections;

+using System.Collections.Generic;

+using System.ComponentModel;

+using System.Globalization;

+using System.Linq;

+using System.Text;

+using System.Threading.Tasks;

+

+namespace LLVM.ClangTidy

+{

+    class MagicInheritance

+    {

+        public static readonly string Value = "{3A27184D-1774-489B-9BB7-7191B8E8E622}";

+        public static readonly string Text = "<Inherit from project or parent>";

+    }

+

+

+    class DynamicPropertyConverter<T> : TypeConverter

+    {

+        private DynamicPropertyDescriptor<T> Descriptor_;

+        private TypeConverter Root_;

+

+        public DynamicPropertyConverter(DynamicPropertyDescriptor<T> Descriptor, TypeConverter Root)

+        {

+            Descriptor_ = Descriptor;

+            Root_ = Root;

+        }

+

+        /// <summary>

+        /// Returns true if there are specific values that can be chosen from a dropdown

+        /// for this property.  Regardless of whether standard values are supported for

+        /// the underlying type, we always support standard values because we need to

+        /// display the inheritance option.

+        /// </summary>

+        /// <returns>true</returns>

+        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)

+        {

+            return true;

+        }

+

+        /// <summary>

+        /// Get the set of all standard values that can be chosen from a dropdown for this

+        /// property.  If the underlying type supports standard values, we want to include

+        /// all those.  Additionally, we want to display the option to inherit the value,

+        /// but only if the value is not already inheriting.

+        /// </summary>

+        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)

+        {

+            List<object> Values = new List<object>();

+            if (Root_.GetStandardValuesSupported(context))

+            {

+                StandardValuesCollection RootValues = Root_.GetStandardValues(context);

+                Values.AddRange(RootValues.Cast<object>());

+            }

+            if (!Descriptor_.IsInheriting)

+                Values.Add(MagicInheritance.Value);

+            StandardValuesCollection Result = new StandardValuesCollection(Values);

+            return Result;

+        }

+

+        /// <summary>

+        /// Determines whether this property can accept values other than those specified

+        /// in the dropdown (for example by manually typing into the field).

+        /// </summary>

+        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)

+        {

+            // Although we add items to the dropdown list, we do not change whether or not

+            // the set of values are exclusive.  If the user could type into the field before

+            // they still can.  And if they couldn't before, they still can't.

+            return Root_.GetStandardValuesExclusive(context);

+        }

+

+        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)

+        {

+            return Root_.CanConvertFrom(context, sourceType);

+        }

+

+        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)

+        {

+            return Root_.CanConvertTo(context, destinationType);

+        }

+

+        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)

+        {

+            if (value.Equals(MagicInheritance.Value))

+                return MagicInheritance.Text;

+            return Root_.ConvertFrom(context, culture, value);

+        }

+

+        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)

+        {

+            if (value.GetType() == destinationType)

+                return value;

+

+            return Root_.ConvertTo(context, culture, value, destinationType);

+        }

+

+        public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)

+        {

+            return Root_.CreateInstance(context, propertyValues);

+        }

+

+        public override bool Equals(object obj)

+        {

+            return Root_.Equals(obj);

+        }

+

+        public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)

+        {

+            return Root_.GetCreateInstanceSupported(context);

+        }

+

+        public override int GetHashCode()

+        {

+            return Root_.GetHashCode();

+        }

+

+        public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)

+        {

+            return Root_.GetProperties(context, value, attributes);

+        }

+

+        public override bool GetPropertiesSupported(ITypeDescriptorContext context)

+        {

+            return Root_.GetPropertiesSupported(context);

+        }

+

+        public override bool IsValid(ITypeDescriptorContext context, object value)

+        {

+            return Root_.IsValid(context, value);

+        }

+

+        public override string ToString()

+        {

+            return Root_.ToString();

+        }

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/DynamicPropertyDescriptor.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/DynamicPropertyDescriptor.cs
new file mode 100644
index 0000000..f0d7691
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/DynamicPropertyDescriptor.cs
@@ -0,0 +1,137 @@
+using System;

+using System.Collections.Generic;

+using System.ComponentModel;

+using System.Linq;

+using System.Text;

+using System.Threading.Tasks;

+

+namespace LLVM.ClangTidy

+{

+    public class DynamicPropertyDescriptor<T> : PropertyDescriptor

+    {

+        T Value_;

+        DynamicPropertyDescriptor<T> Parent_;

+        bool IsInheriting_;

+        object Component_;

+

+        public DynamicPropertyDescriptor(object Component, DynamicPropertyDescriptor<T> Parent, string Name, Attribute[] Attrs)

+            : base(Name, Attrs)

+        {

+            foreach (DefaultValueAttribute Attr in Attrs.OfType<DefaultValueAttribute>())

+            {

+                Value_ = (T)Attr.Value;

+            }

+            Parent_ = Parent;

+            IsInheriting_ = true;

+            Component_ = Component;

+        }

+

+        public bool IsInheriting { get { return IsInheriting_; } set { IsInheriting_ = value; } }

+        public DynamicPropertyDescriptor<T> Parent { get { return Parent_; } }

+

+        /// <summary>

+        /// Determines whether this property's value should be considered "default" (e.g.

+        /// displayed in bold in the property grid).  Root properties are unmodifiable and

+        /// always default.  Non-root properties are default iff they are inheriting.

+        /// That is to say, if a property is explicitly set to False, the property should

+        /// be serialized even if the parent is also False.  It would only not be serialized

+        /// if the user had explicitly chosen to inherit it.

+        /// </summary>

+        /// <param name="component"></param>

+        /// <returns></returns>

+        public override bool ShouldSerializeValue(object component)

+        {

+            return (Parent_ != null) && !IsInheriting;

+        }

+

+        /// <summary>

+        /// Set the value back to the default.  For root properties, this essentially does

+        /// nothing as they are read-only anyway.  For non-root properties, this only means

+        /// that the property is now inheriting.

+        /// </summary>

+        /// <param name="component"></param>

+        public override void ResetValue(object component)

+        {

+            IsInheriting_ = true;

+        }

+

+        public override void SetValue(object component, object value)

+        {

+            // This is a bit of a trick.  If the user chose the inheritance option from the

+            // dropdown, we will try to set the value to that string.  So look for that and

+            // then just reset the value.

+            if (value.Equals(MagicInheritance.Text))

+                ResetValue(component);

+            else

+            {

+                // By explicitly setting the value, this property is no longer inheriting,

+                // even if the value the property is being set to is the same as that of

+                // the parent.

+                IsInheriting_ = false;

+                Value_ = (T)value;

+            }

+        }

+

+        public override TypeConverter Converter

+        {

+            get

+            {

+                // We need to return a DynamicPropertyConverter<> that can deal with our requirement

+                // to inject the inherit property option into the dropdown.  But we still need to use

+                // the "real" converter to do the actual work for the underlying type.  Therefore,

+                // we need to look for a TypeConverter<> attribute on the property, and if it is present

+                // forward an instance of that converter to the DynamicPropertyConverter<>.  Otherwise,

+                // forward an instance of the default converter for type T to the DynamicPropertyConverter<>.

+                TypeConverter UnderlyingConverter = null;

+                var ConverterAttr = this.Attributes.OfType<TypeConverterAttribute>().LastOrDefault();

+                if (ConverterAttr != null)

+                {

+                    Type ConverterType = Type.GetType(ConverterAttr.ConverterTypeName);

+                    UnderlyingConverter = (TypeConverter)Activator.CreateInstance(ConverterType);

+                }

+                else

+                    UnderlyingConverter = TypeDescriptor.GetConverter(typeof(T));

+

+                return new DynamicPropertyConverter<T>(this, UnderlyingConverter);

+            }

+        }

+

+        public override bool IsReadOnly

+        {

+            get

+            {

+                return (Parent_ == null);

+            }

+        }

+

+        public override Type ComponentType

+        {

+            get

+            {

+                return Component_.GetType();

+            }

+        }

+

+        public override object GetValue(object component)

+        {

+            // Return either this property's value or the parents value, depending on

+            // whether or not this property is inheriting.

+            if (IsInheriting_ && Parent != null)

+                return Parent.GetValue(component);

+            return Value_;

+        }

+

+        public override bool CanResetValue(object component)

+        {

+            return !IsReadOnly;

+        }

+

+        public override Type PropertyType

+        {

+            get

+            {

+                return typeof(T);

+            }

+        }

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ForwardingPropertyDescriptor.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ForwardingPropertyDescriptor.cs
new file mode 100644
index 0000000..22b08fb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/ForwardingPropertyDescriptor.cs
@@ -0,0 +1,191 @@
+using System;

+using System.Collections.Generic;

+using System.ComponentModel;

+using System.Linq;

+using System.Text;

+using System.Threading.Tasks;

+

+namespace LLVM.ClangTidy

+{

+    /// <summary>

+    /// A decorator of sorts.  Accepts a PropertyDescriptor to its constructor

+    /// and forwards all calls to the underlying PropertyDescriptor.  In this way

+    /// we can inherit from ForwardingPropertyDescriptor and override only the

+    /// few methods we need to customize the behavior of, while allowing the

+    /// underlying PropertyDescriptor to do the real work.

+    /// </summary>

+    public abstract class ForwardingPropertyDescriptor : PropertyDescriptor

+    {

+        private readonly PropertyDescriptor root;

+        protected PropertyDescriptor Root { get { return root; } }

+        protected ForwardingPropertyDescriptor(PropertyDescriptor root)

+            : base(root)

+        {

+            this.root = root;

+        }

+

+        public override void AddValueChanged(object component, EventHandler handler)

+        {

+            root.AddValueChanged(component, handler);

+        }

+

+        public override AttributeCollection Attributes

+        {

+            get

+            {

+                return root.Attributes;

+            }

+        }

+

+        public override bool CanResetValue(object component)

+        {

+            return root.CanResetValue(component);

+        }

+

+        public override string Category

+        {

+            get

+            {

+                return root.Category;

+            }

+        }

+

+        public override Type ComponentType

+        {

+            get

+            {

+                return root.ComponentType;

+            }

+        }

+

+        public override TypeConverter Converter

+        {

+            get

+            {

+                return root.Converter;

+            }

+        }

+

+        public override string Description

+        {

+            get

+            {

+                return root.Description;

+            }

+        }

+

+        public override bool DesignTimeOnly

+        {

+            get

+            {

+                return root.DesignTimeOnly;

+            }

+        }

+

+        public override string DisplayName

+        {

+            get

+            {

+                return root.DisplayName;

+            }

+        }

+

+        public override bool Equals(object obj)

+        {

+            return root.Equals(obj);

+        }

+

+        public override PropertyDescriptorCollection GetChildProperties(object instance, Attribute[] filter)

+        {

+            return root.GetChildProperties(instance, filter);

+        }

+

+        public override object GetEditor(Type editorBaseType)

+        {

+            return root.GetEditor(editorBaseType);

+        }

+

+        public override int GetHashCode()

+        {

+            return root.GetHashCode();

+        }

+

+        public override object GetValue(object component)

+        {

+            return root.GetValue(component);

+        }

+

+        public override bool IsBrowsable

+        {

+            get

+            {

+                return root.IsBrowsable;

+            }

+        }

+

+        public override bool IsLocalizable

+        {

+            get

+            {

+                return root.IsLocalizable;

+            }

+        }

+

+        public override bool IsReadOnly

+        {

+            get

+            {

+                return root.IsReadOnly;

+            }

+        }

+

+        public override string Name

+        {

+            get

+            {

+                return root.Name;

+            }

+        }

+

+        public override Type PropertyType

+        {

+            get

+            {

+                return root.PropertyType;

+            }

+        }

+

+        public override void RemoveValueChanged(object component, EventHandler handler)

+        {

+            root.RemoveValueChanged(component, handler);

+        }

+

+        public override void ResetValue(object component)

+        {

+            root.ResetValue(component);

+        }

+

+        public override void SetValue(object component, object value)

+        {

+            root.SetValue(component, value);

+        }

+

+        public override bool ShouldSerializeValue(object component)

+        {

+            return root.ShouldSerializeValue(component);

+        }

+

+        public override bool SupportsChangeEvents

+        {

+            get

+            {

+                return root.SupportsChangeEvents;

+            }

+        }

+

+        public override string ToString()

+        {

+            return root.ToString();

+        }

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/GlobalSuppressions.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/GlobalSuppressions.cs
new file mode 100644
index 0000000..175a74e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/GlobalSuppressions.cs
@@ -0,0 +1,11 @@
+// This file is used by Code Analysis to maintain SuppressMessage

+// attributes that are applied to this project. Project-level

+// suppressions either have no target or are given a specific target

+// and scoped to a namespace, type, member, etc.

+//

+// To add a suppression to this file, right-click the message in the

+// Error List, point to "Suppress Message(s)", and click "In Project

+// Suppression File". You do not need to add suppressions to this

+// file manually.

+

+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1017:MarkAssembliesWithComVisible")]

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Guids.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Guids.cs
new file mode 100644
index 0000000..0c99a6f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Guids.cs
@@ -0,0 +1,12 @@
+using System;

+

+namespace LLVM.ClangTidy

+{

+    static class GuidList

+    {

+        public const string guidClangTidyPkgString = "AE4956BE-3DB8-430E-BBAB-7E2E9A014E9C";

+        public const string guidClangTidyCmdSetString = "9E0F0493-6493-46DE-AEE1-ACD8F60F265E";

+

+        public static readonly Guid guidClangTidyCmdSet = new Guid(guidClangTidyCmdSetString);

+    };

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/PkgCmdID.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/PkgCmdID.cs
new file mode 100644
index 0000000..3faf403
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/PkgCmdID.cs
@@ -0,0 +1,7 @@
+namespace LLVM.ClangTidy

+{

+    static class PkgCmdIDList

+    {

+        public const uint cmdidClangTidy = 0x100;

+    };

+}
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Properties/AssemblyInfo.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..7105305
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+using System;

+using System.Reflection;

+using System.Resources;

+using System.Runtime.CompilerServices;

+using System.Runtime.InteropServices;

+

+// General Information about an assembly is controlled through the following 

+// set of attributes. Change these attribute values to modify the information

+// associated with an assembly.

+[assembly: AssemblyTitle("ClangFormat")]

+[assembly: AssemblyDescription("")]

+[assembly: AssemblyConfiguration("")]

+[assembly: AssemblyCompany("LLVM")]

+[assembly: AssemblyProduct("ClangFormat")]

+[assembly: AssemblyCopyright("")]

+[assembly: AssemblyTrademark("")]

+[assembly: AssemblyCulture("")]

+[assembly: ComVisible(false)]

+[assembly: CLSCompliant(false)]

+[assembly: NeutralResourcesLanguage("en-US")]

+

+// Version information for an assembly consists of the following four values:

+//

+//      Major Version

+//      Minor Version 

+//      Build Number

+//      Revision

+//

+// You can specify all the values or you can default the Revision and Build Numbers 

+// by using the '*' as shown below:

+// FIXME: Add a way to have this generated automatically by CMake

+[assembly: AssemblyVersion("1.1.0.0")]

+[assembly: AssemblyFileVersion("1.1.0.0")]

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Resources.Designer.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Resources.Designer.cs
new file mode 100644
index 0000000..b601fb3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Resources.Designer.cs
@@ -0,0 +1,81 @@
+//------------------------------------------------------------------------------

+// <auto-generated>

+//     This code was generated by a tool.

+//     Runtime Version:4.0.30319.42000

+//

+//     Changes to this file may cause incorrect behavior and will be lost if

+//     the code is regenerated.

+// </auto-generated>

+//------------------------------------------------------------------------------

+

+namespace LLVM.ClangTidy {

+    using System;

+    

+    

+    /// <summary>

+    ///   A strongly-typed resource class, for looking up localized strings, etc.

+    /// </summary>

+    // This class was auto-generated by the StronglyTypedResourceBuilder

+    // class via a tool like ResGen or Visual Studio.

+    // To add or remove a member, edit your .ResX file then rerun ResGen

+    // with the /str option, or rebuild your VS project.

+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]

+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]

+    internal class Resources {

+        

+        private static global::System.Resources.ResourceManager resourceMan;

+        

+        private static global::System.Globalization.CultureInfo resourceCulture;

+        

+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]

+        internal Resources() {

+        }

+        

+        /// <summary>

+        ///   Returns the cached ResourceManager instance used by this class.

+        /// </summary>

+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]

+        internal static global::System.Resources.ResourceManager ResourceManager {

+            get {

+                if (object.ReferenceEquals(resourceMan, null)) {

+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LLVM.ClangTidy.Resources", typeof(Resources).Assembly);

+                    resourceMan = temp;

+                }

+                return resourceMan;

+            }

+        }

+        

+        /// <summary>

+        ///   Overrides the current thread's CurrentUICulture property for all

+        ///   resource lookups using this strongly typed resource class.

+        /// </summary>

+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]

+        internal static global::System.Globalization.CultureInfo Culture {

+            get {

+                return resourceCulture;

+            }

+            set {

+                resourceCulture = value;

+            }

+        }

+        

+        /// <summary>

+        ///   Looks up a localized string similar to ---

+        ///Checks:

+        ///Checks:

+        ///  - Name:        cert-dcl54-cpp

+        ///    Label:       Overloaded allocation function pairs

+        ///    Description: Checks for violations of CERT DCL54-CPP - Overload allocation and deallocation functions as a pair in the same scope

+        ///    Category:    CERT Secure Coding Standards

+        ///  - Name:        cppcoreguidelines-interfaces-global-init

+        ///    Label:       I.22 - Complex Global Initializers

+        ///    Description: Checks for violations of Core Guideline I.22 - Avoid complex initializers of global object [rest of string was truncated]&quot;;.

+        /// </summary>

+        internal static string ClangTidyChecks {

+            get {

+                return ResourceManager.GetString("ClangTidyChecks", resourceCulture);

+            }

+        }

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Resources.resx b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Resources.resx
new file mode 100644
index 0000000..7f63475
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Resources.resx
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8"?>

+<root>

+  <!-- 

+    Microsoft ResX Schema 

+    

+    Version 2.0

+    

+    The primary goals of this format is to allow a simple XML format 

+    that is mostly human readable. The generation and parsing of the 

+    various data types are done through the TypeConverter classes 

+    associated with the data types.

+    

+    Example:

+    

+    ... ado.net/XML headers & schema ...

+    <resheader name="resmimetype">text/microsoft-resx</resheader>

+    <resheader name="version">2.0</resheader>

+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>

+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>

+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>

+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>

+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">

+        <value>[base64 mime encoded serialized .NET Framework object]</value>

+    </data>

+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">

+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>

+        <comment>This is a comment</comment>

+    </data>

+                

+    There are any number of "resheader" rows that contain simple 

+    name/value pairs.

+    

+    Each data row contains a name, and value. The row also contains a 

+    type or mimetype. Type corresponds to a .NET class that support 

+    text/value conversion through the TypeConverter architecture. 

+    Classes that don't support this are serialized and stored with the 

+    mimetype set.

+    

+    The mimetype is used for serialized objects, and tells the 

+    ResXResourceReader how to depersist the object. This is currently not 

+    extensible. For a given mimetype the value must be set accordingly:

+    

+    Note - application/x-microsoft.net.object.binary.base64 is the format 

+    that the ResXResourceWriter will generate, however the reader can 

+    read any of the formats listed below.

+    

+    mimetype: application/x-microsoft.net.object.binary.base64

+    value   : The object must be serialized with 

+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter

+            : and then encoded with base64 encoding.

+    

+    mimetype: application/x-microsoft.net.object.soap.base64

+    value   : The object must be serialized with 

+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter

+            : and then encoded with base64 encoding.

+

+    mimetype: application/x-microsoft.net.object.bytearray.base64

+    value   : The object must be serialized into a byte array 

+            : using a System.ComponentModel.TypeConverter

+            : and then encoded with base64 encoding.

+    -->

+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">

+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />

+    <xsd:element name="root" msdata:IsDataSet="true">

+      <xsd:complexType>

+        <xsd:choice maxOccurs="unbounded">

+          <xsd:element name="metadata">

+            <xsd:complexType>

+              <xsd:sequence>

+                <xsd:element name="value" type="xsd:string" minOccurs="0" />

+              </xsd:sequence>

+              <xsd:attribute name="name" use="required" type="xsd:string" />

+              <xsd:attribute name="type" type="xsd:string" />

+              <xsd:attribute name="mimetype" type="xsd:string" />

+              <xsd:attribute ref="xml:space" />

+            </xsd:complexType>

+          </xsd:element>

+          <xsd:element name="assembly">

+            <xsd:complexType>

+              <xsd:attribute name="alias" type="xsd:string" />

+              <xsd:attribute name="name" type="xsd:string" />

+            </xsd:complexType>

+          </xsd:element>

+          <xsd:element name="data">

+            <xsd:complexType>

+              <xsd:sequence>

+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />

+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />

+              </xsd:sequence>

+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />

+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />

+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />

+              <xsd:attribute ref="xml:space" />

+            </xsd:complexType>

+          </xsd:element>

+          <xsd:element name="resheader">

+            <xsd:complexType>

+              <xsd:sequence>

+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />

+              </xsd:sequence>

+              <xsd:attribute name="name" type="xsd:string" use="required" />

+            </xsd:complexType>

+          </xsd:element>

+        </xsd:choice>

+      </xsd:complexType>

+    </xsd:element>

+  </xsd:schema>

+  <resheader name="resmimetype">

+    <value>text/microsoft-resx</value>

+  </resheader>

+  <resheader name="version">

+    <value>2.0</value>

+  </resheader>

+  <resheader name="reader">

+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>

+  </resheader>

+  <resheader name="writer">

+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>

+  </resheader>

+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

+  <data name="ClangTidyChecks" type="System.Resources.ResXFileRef, System.Windows.Forms">

+    <value>Resources\ClangTidyChecks.yaml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>

+  </data>

+</root>
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Resources/ClangTidyChecks.yaml b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Resources/ClangTidyChecks.yaml
new file mode 100644
index 0000000..7b06aba
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Resources/ClangTidyChecks.yaml
@@ -0,0 +1,317 @@
+---

+Checks:

+   # This file should be updated when new checks are added, and eventually we should

+   # generate this file automatically from the .rst files in clang-tidy.

+  - Category:    CERT Secure Coding Standards

+    Label:       Overloaded allocation function pairs

+    Description: Checks for violations of CERT DCL54-CPP - Overload allocation and deallocation functions as a pair in the same scope

+    Name:        cert-dcl54-cpp

+  - Category:    C++ Core Guidelines

+    Label:       I.22 - Complex Global Initializers

+    Description: Checks for violations of Core Guideline I.22 - Avoid complex initializers of global objects

+    Name:        cppcoreguidelines-interfaces-global-init

+  - Category:    CERT Secure Coding Standards

+    Label:       DCL50-CPP

+    Description: Checks for violations of CERT DCL50-CPP - Do not define a C-style variadic function

+    Name:        cert-dcl50-cpp

+  - Category:    C++ Core Guidelines

+    Label:       Bounds.1 - No pointer arithmetic

+    Description: Checks for violations of Core Guideline Bounds.3 - Don't use pointer arithmetic.  Use span<> instead.

+    Name:        cppcoreguidelines-pro-bounds-pointer-arithmetic

+  - Category:    C++ Core Guidelines

+    Label:       Bounds.2 - Constant array indices

+    Description: Checks for violations of Core Bounds.2 - Only index into arrays using constant expressions.

+    Name:        cppcoreguidelines-pro-bounds-constant-array-index

+  - Category:    C++ Core Guidelines

+    Label:       Bounds.3 - Array to Pointer Decay

+    Description: Checks for violations of Core Guideline Bounds.3 - No array-to-pointer decay

+    Name:        cppcoreguidelines-pro-bounds-array-to-pointer-decay

+  - Category:    C++ Core Guidelines

+    Label:       const_cast (Type.3)

+    Description: Checks for violations of Core Guideline Type.3 - Don't use const_cast to cast away const

+    Name:        cppcoreguidelines-pro-type-const-cast

+  - Category:    C++ Core Guidelines

+    Label: C style casts (Type.4)

+    Description: Checks for violations of Core Guideline Type.3 - Don't use C-style (T)expression casts that would perform a static downcast, const_cast, or reinterpret_cast

+    Name:        cppcoreguidelines-pro-type-cstyle-cast

+  - Category:    C++ Core Guidelines

+    Label:       reinterpret_cast (Type.1)

+    Description: Checks for violations of Core Guideline Type.1 - Don't use reinterpret_cast.

+    Name:        cppcoreguidelines-pro-type-reinterpret-cast

+  - Category:    C++ Core Guidelines

+    Label:       Prefer dynamic_cast (Type.2)

+    Description: Checks for violations of Core Guideline Type.2 - Don't use static_cast downcasts.  Use dynamic_cast instead.

+    Name:        cppcoreguidelines-pro-type-static-cast-downcast

+  - Category:    C++ Core Guidelines

+    Label:       Member variable initialization (Type.6)

+    Description: Checks for violations of Core Guideline Type.6 - Always initialize a member variable.

+    Name:        cppcoreguidelines-pro-type-member-init

+  - Category:    C++ Core Guidelines

+    Label:       Avoid unions (Type.7)

+    Description: Checks for violations of Core Guideline Type.7 - Avoid accessing members of raw unions.  Use variant instead.

+    Name:        cppcoreguidelines-pro-type-union-access

+  - Category:    C++ Core Guidelines

+    Label:       Don't use varargs (Type.8)

+    Description: Checks for violations of Core Guideline Type.8 - Avoid reading varargs or passing vararg arguments.  Prefer variadic templates instead.

+    Name:        cppcoreguidelines-pro-type-vararg

+  - Category:    C++ Core Guidelines

+    Label:       Don't slice (ES.63 & C.145)

+    Description: Checks for violations of Core Guidelines ES.63 (Don't slice) and C.145 (Access polymorphic objects through pointers and references)

+    Name:        cppcoreguidelines-slicing

+  - Category:    C++ Core Guidelines

+    Label:       Detect unsafe special functions (C.21)

+    Description: Checks for violations of Core Guidelines C.21 - If you define or =delete any default operation, define or =delete them all.

+    Name:        cppcoreguidelines-special-member-functions

+  - Category:    Google Style Guide

+    Label:       Forbid explicitly parameterized make_pair

+    Description: 

+    Name:        google-build-explicit-make-pair

+  - Category:    Google Style Guide

+    Label:       Anonymous namespace in headers

+    Description: 

+    Name:        google-build-namespaces

+  - Category:    Google Style Guide

+    Label:       Find using namespace directives

+    Description: 

+    Name:        google-build-using-namespace

+  - Category:    Google Style Guide

+    Label:       Default arguments in virtual methods

+    Description: 

+    Name:        google-default-arguments

+  - Category:    Google Style Guide

+    Label:       explicit constructors

+    Description: 

+    Name:        google-explicit-constructor

+  - Category:    Google Style Guide

+    Label:       Global namespace pollution in headers

+    Description: 

+    Name:        google-global-names-in-headers

+  - Category:    Google Style Guide

+    Label:       Braces around statements

+    Description: 

+    Name:        google-readability-braces-around-statements

+  - Category:    Google Style Guide

+    Label:       No C-style casts

+    Description: 

+    Name:        google-readability-casting

+  - Category:    Google Style Guide

+    Label:       Find large functions

+    Description: 

+    Name:        google-readability-function-size

+  - Category:    Google Style Guide

+    Label:       Namespace closing comments

+    Description: 

+    Name:        google-readability-namespace-comments

+  - Category:    Google Style Guide

+    Label:       Find unnecessary calls to .get()

+    Description: 

+    Name:        google-readability-redundant-smartptr-get

+  - Category:    Google Style Guide

+    Label:       Find noncomformant TODO comments

+    Description: 

+    Name:        google-readability-todo

+  - Category:    Google Style Guide

+    Label:       Find implementation-specific integral types

+    Description: 

+    Name:        google-runtime-int

+  - Category:    Google Style Guide

+    Label:       Find zero-length memsets

+    Description: 

+    Name:        google-runtime-memset

+  - Category:    Google Style Guide

+    Label:       Find overloads of operator&

+    Description: 

+    Name:        google-runtime-operator

+  - Category:    Google Style Guide

+    Label:       Check usage of non-const references

+    Description: 

+    Name:        google-runtime-references

+  - Category:    LLVM Style Guide

+    Label:       LLVM header guards

+    Description: 

+    Name:        llvm-header-guard

+  - Category:    LLVM Style Guide

+    Label:       LLVM include order

+    Description: 

+    Name:        llvm-include-order

+  - Category:    LLVM Style Guide

+    Label:       LLVM namespace comments

+    Description: 

+    Name:        llvm-namespace-comment

+  - Category:    LLVM Style Guide

+    Label:       Find local twines

+    Description: 

+    Name:        llvm-twine-local

+  - Category:    Clang Diagnostics

+    Label:       Warnings

+    Description: 

+    Name:        clang-diagnostic-warning

+  - Category:    Clang Diagnostics

+    Label:       Errors

+    Description: 

+    Name:        clang-diagnostic-error

+  - Category:    Clang Diagnostics

+    Label:       Unknown

+    Description: 

+    Name:        clang-diagnostic-unknown

+  - Category:    Miscellaneous

+    Label:       Validate argument comments

+    Description: 

+    Name:        misc-argument-comment

+  - Category:    Miscellaneous

+    Label:       Side effects in assert()

+    Description: 

+    Name:        misc-assert-side-effect

+  - Category:    Miscellaneous

+    Label:       bool / pointer implicit conversions

+    Description: 

+    Name:        misc-bool-pointer-implicit-conversion

+  - Category:    Miscellaneous

+    Label:       Dangling handles

+    Description: 

+    Name:        misc-dangling-handle

+  - Category:    Miscellaneous

+    Label:       Definitions in headers

+    Description: 

+    Name:        misc-definitions-in-headers

+  - Category:    Miscellaneous

+    Label:       Type mismatch in fold operations

+    Description: 

+    Name:        misc-fold-init-type

+  - Category:    Miscellaneous

+    Label:       Forward declaration namespace

+    Description: 

+    Name:        misc-forward-declaration-namespace

+  - Category:    Miscellaneous

+    Label:       Inaccurate erase

+    Description: 

+    Name:        misc-inaccurate-erase

+  - Category:    Miscellaneous

+    Label:       Incorrect rounding

+    Description: 

+    Name:        misc-incorrect-roundings

+  - Category:    Miscellaneous

+    Label:       Inefficient STL algorithms

+    Description: 

+    Name:        misc-inefficient-algorithm

+  - Category:    Miscellaneous

+    Label:       Macro parentheses

+    Description: 

+    Name:        misc-macro-parentheses

+  - Category:    Miscellaneous

+    Label:       Macro repeated side effects

+    Description: 

+    Name:        misc-macro-repeated-side-effects

+  - Category:    Miscellaneous

+    Label:       Misplaced const

+    Description: 

+    Name:        misc-misplaced-const

+  - Category:    Miscellaneous

+    Label:       Misplaced widening casts

+    Description: 

+    Name:        misc-misplaced-widening-cast

+  - Category:    Miscellaneous

+    Label:       Move constructor const arguments

+    Description: 

+    Name:        misc-move-const-arg

+  - Category:    Miscellaneous

+    Label:       Move constructor initialization

+    Description: 

+    Name:        misc-move-constructor-init

+  - Category:    Miscellaneous

+    Label:       Multi-statement macros

+    Description: 

+    Name:        misc-multiple-statement-macro

+  - Category:    Miscellaneous

+    Label:       Verify new / delete overloads

+    Description: 

+    Name:        misc-new-delete-overloads

+  - Category:    Miscellaneous

+    Label:       Ensure move constructors are noexcept

+    Description: 

+    Name:        misc-noexcept-move-constructor

+  - Category:    Miscellaneous

+    Label:       Copying of non-copyable objects

+    Description: 

+    Name:        misc-non-copyable-objects

+  - Category:    Miscellaneous

+    Label:       Find redundant expressions

+    Description: 

+    Name:        misc-redundant-expression

+  - Category:    Miscellaneous

+    Label:       sizeof() on stl containers

+    Description: 

+    Name:        misc-sizeof-container

+  - Category:    Miscellaneous

+    Label:       Suspicious sizeof() usage

+    Description: 

+    Name:        misc-sizeof-expression

+  - Category:    Miscellaneous

+    Label:       Replace assert with static_assert

+    Description: 

+    Name:        misc-static-assert

+  - Category:    Miscellaneous

+    Label:       Suspicious string constructor

+    Description: 

+    Name:        misc-string-constructor

+  - Category:    Miscellaneous

+    Label:       String integer assignment

+    Description: 

+    Name:        misc-string-integer-assignment

+  - Category:    Miscellaneous

+    Label:       String literal with embedded null

+    Description: 

+    Name:        misc-string-literal-with-embedded-nul

+  - Category:    Miscellaneous

+    Label:       Suspicious missing comma

+    Description: 

+    Name:        misc-suspicious-missing-comma

+  - Category:    Miscellaneous

+    Label:       Suspicious semicolon

+    Description: 

+    Name:        misc-suspicious-semicolon

+  - Category:    Miscellaneous

+    Label:       Suspicious string compare

+    Description: 

+    Name:        misc-suspicious-string-compare

+  - Category:    Miscellaneous

+    Label:       Swapped arguments

+    Description: 

+    Name:        misc-swapped-arguments

+  - Category:    Miscellaneous

+    Label:       Throw by value / catch by reference

+    Description: 

+    Name:        misc-throw-by-value-catch-by-reference

+  - Category:    Miscellaneous

+    Label:       Unconventional operator=()

+    Description: 

+    Name:        misc-unconventional-assign-operator

+  - Category:    Miscellaneous

+    Label:       Undelegated constructor

+    Description: 

+    Name:        misc-undelegated-constructor

+  - Category:    Miscellaneous

+    Label:       unique_ptr<> reset / release

+    Description: 

+    Name:        misc-uniqueptr-reset-release

+  - Category:    Miscellaneous

+    Label:       Unused Alias Decls

+    Description: 

+    Name:        misc-unused-alias-decls

+  - Category:    Miscellaneous

+    Label:       Unused Params

+    Description: 

+    Name:        misc-unused-parameters

+  - Category:    Miscellaneous

+    Label:       Unused Raii

+    Description: 

+    Name:        misc-unused-raii

+  - Category:    Miscellaneous

+    Label:       Unused Using Decls

+    Description: 

+    Name:        misc-unused-using-decls

+  - Category:    Miscellaneous

+    Label:       Virtual Near Miss

+    Description: 

+    Name:        misc-virtual-near-miss

+...

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Resources/Images_32bit.bmp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Resources/Images_32bit.bmp
new file mode 100644
index 0000000..2fa7ab0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Resources/Images_32bit.bmp
Binary files differ
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Resources/Package.ico b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Resources/Package.ico
new file mode 100644
index 0000000..ea3b23f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Resources/Package.ico
Binary files differ
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Utility.cs b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Utility.cs
new file mode 100644
index 0000000..5a220e6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/Utility.cs
@@ -0,0 +1,35 @@
+using System;

+using System.Collections.Generic;

+using System.IO;

+using System.Linq;

+using System.Text;

+using System.Text.RegularExpressions;

+using System.Threading.Tasks;

+

+namespace LLVM.ClangTidy

+{

+    static class Utility

+    {

+        public static IEnumerable<string> SplitPath(string FileOrDir)

+        {

+            string P = Path.GetDirectoryName(FileOrDir);

+            do

+            {

+                yield return P;

+                P = Path.GetDirectoryName(P);

+            } while (P != null);

+        }

+

+        public static bool HasClangTidyFile(string Folder)

+        {

+            string ClangTidy = Path.Combine(Folder, ".clang-tidy");

+            return File.Exists(ClangTidy);

+        }

+

+        public static bool MatchWildcardString(string Value, string Pattern)

+        {

+            string RE = Regex.Escape(Pattern).Replace(@"\*", ".*");

+            return Regex.IsMatch(Value, RE);

+        }

+    }

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/VSPackage.resx b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/VSPackage.resx
new file mode 100644
index 0000000..932b062
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/VSPackage.resx
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8"?>

+<root>

+  <!-- 

+    Microsoft ResX Schema 

+    

+    Version 2.0

+    

+    The primary goals of this format is to allow a simple XML format 

+    that is mostly human readable. The generation and parsing of the 

+    various data types are done through the TypeConverter classes 

+    associated with the data types.

+    

+    Example:

+    

+    ... ado.net/XML headers & schema ...

+    <resheader name="resmimetype">text/microsoft-resx</resheader>

+    <resheader name="version">2.0</resheader>

+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>

+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>

+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>

+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>

+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">

+        <value>[base64 mime encoded serialized .NET Framework object]</value>

+    </data>

+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">

+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>

+        <comment>This is a comment</comment>

+    </data>

+                

+    There are any number of "resheader" rows that contain simple 

+    name/value pairs.

+    

+    Each data row contains a name, and value. The row also contains a 

+    type or mimetype. Type corresponds to a .NET class that support 

+    text/value conversion through the TypeConverter architecture. 

+    Classes that don't support this are serialized and stored with the 

+    mimetype set.

+    

+    The mimetype is used for serialized objects, and tells the 

+    ResXResourceReader how to depersist the object. This is currently not 

+    extensible. For a given mimetype the value must be set accordingly:

+    

+    Note - application/x-microsoft.net.object.binary.base64 is the format 

+    that the ResXResourceWriter will generate, however the reader can 

+    read any of the formats listed below.

+    

+    mimetype: application/x-microsoft.net.object.binary.base64

+    value   : The object must be serialized with 

+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter

+            : and then encoded with base64 encoding.

+    

+    mimetype: application/x-microsoft.net.object.soap.base64

+    value   : The object must be serialized with 

+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter

+            : and then encoded with base64 encoding.

+

+    mimetype: application/x-microsoft.net.object.bytearray.base64

+    value   : The object must be serialized into a byte array 

+            : using a System.ComponentModel.TypeConverter

+            : and then encoded with base64 encoding.

+    -->

+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">

+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />

+    <xsd:element name="root" msdata:IsDataSet="true">

+      <xsd:complexType>

+        <xsd:choice maxOccurs="unbounded">

+          <xsd:element name="metadata">

+            <xsd:complexType>

+              <xsd:sequence>

+                <xsd:element name="value" type="xsd:string" minOccurs="0" />

+              </xsd:sequence>

+              <xsd:attribute name="name" use="required" type="xsd:string" />

+              <xsd:attribute name="type" type="xsd:string" />

+              <xsd:attribute name="mimetype" type="xsd:string" />

+              <xsd:attribute ref="xml:space" />

+            </xsd:complexType>

+          </xsd:element>

+          <xsd:element name="assembly">

+            <xsd:complexType>

+              <xsd:attribute name="alias" type="xsd:string" />

+              <xsd:attribute name="name" type="xsd:string" />

+            </xsd:complexType>

+          </xsd:element>

+          <xsd:element name="data">

+            <xsd:complexType>

+              <xsd:sequence>

+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />

+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />

+              </xsd:sequence>

+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />

+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />

+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />

+              <xsd:attribute ref="xml:space" />

+            </xsd:complexType>

+          </xsd:element>

+          <xsd:element name="resheader">

+            <xsd:complexType>

+              <xsd:sequence>

+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />

+              </xsd:sequence>

+              <xsd:attribute name="name" type="xsd:string" use="required" />

+            </xsd:complexType>

+          </xsd:element>

+        </xsd:choice>

+      </xsd:complexType>

+    </xsd:element>

+  </xsd:schema>

+  <resheader name="resmimetype">

+    <value>text/microsoft-resx</value>

+  </resheader>

+  <resheader name="version">

+    <value>2.0</value>

+  </resheader>

+  <resheader name="reader">

+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>

+  </resheader>

+  <resheader name="writer">

+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>

+  </resheader>

+  <data name="110" xml:space="preserve">

+    <value>ClangTidy</value>

+  </data>

+  <data name="112" xml:space="preserve">

+    <value>Analyzes code by calling the clang-tidy executable.</value>

+  </data>

+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

+  <data name="400" type="System.Resources.ResXFileRef, System.Windows.Forms">

+    <value>Resources\Package.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>

+  </data>

+</root>
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/license.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/license.txt
new file mode 100644
index 0000000..547f6a4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/license.txt
@@ -0,0 +1,63 @@
+==============================================================================
+LLVM Release License
+==============================================================================
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2007-2018 University of Illinois at Urbana-Champaign.
+All rights reserved.
+
+Developed by:
+
+    LLVM Team
+
+    University of Illinois at Urbana-Champaign
+
+    http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, University of Illinois at
+      Urbana-Champaign, nor the names of its contributors may be used to
+      endorse or promote products derived from this Software without specific
+      prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+The LLVM software contains code written by third parties.  Such software will
+have its own individual LICENSE.TXT file in the directory in which it appears.
+This file will describe the copyrights, license, and restrictions which apply
+to that code.
+
+The disclaimer of warranty in the University of Illinois Open Source License
+applies to all code in the LLVM Distribution, and nothing in any of the
+other licenses gives permission to use the names of the LLVM Team or the
+University of Illinois to endorse or promote products derived from this
+Software.
+
+The following pieces of software have additional or alternate copyrights,
+licenses, and/or restrictions:
+
+Program             Directory
+-------             ---------
+<none yet>
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/packages.config b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/packages.config
new file mode 100644
index 0000000..75d7faf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/packages.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>

+<packages>

+  <package id="Brutal.Dev.StrongNameSigner" version="1.8.0" targetFramework="net45" />

+  <package id="YamlDotNet" version="3.3.0" targetFramework="net45" />

+  <package id="YamlDotNet.Dynamic" version="3.2.3" targetFramework="net45" />

+</packages>
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/source.extension.vsixmanifest b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/source.extension.vsixmanifest
new file mode 100644
index 0000000..cd0e863
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/ClangTidy/source.extension.vsixmanifest
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Vsix Version="1.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2010">

+  <Identifier Id="405594C3-042A-4155-B9A6-E25DAB8B1924">

+    <Name>ClangFormat</Name>

+    <Author>LLVM</Author>

+    <Version>4.0.0</Version>

+    <Description xml:space="preserve">A static analysis tool for C/C++ code.</Description>

+    <Locale>1033</Locale>

+    <MoreInfoUrl>http://clang.llvm.org/extra/clang-tidy/</MoreInfoUrl>

+    <License>license.txt</License>

+    <InstalledByMsi>false</InstalledByMsi>

+    <SupportedProducts>

+      <VisualStudio Version="10.0">

+        <Edition>Pro</Edition>

+      </VisualStudio>

+      <VisualStudio Version="11.0">

+        <Edition>Pro</Edition>

+      </VisualStudio>

+      <VisualStudio Version="12.0">

+        <Edition>Pro</Edition>

+      </VisualStudio>

+      <VisualStudio Version="14.0">

+        <Edition>Pro</Edition>

+      </VisualStudio>

+    </SupportedProducts>

+    <SupportedFrameworkRuntimeEdition MinVersion="4.0" MaxVersion="4.0" />

+  </Identifier>

+  <References>

+        <Reference Id="Microsoft.VisualStudio.MPF" MinVersion="10.0">

+            <Name>Visual Studio MPF</Name>

+        </Reference>

+  </References>

+  <Content>

+    <VsPackage>|%CurrentProject%;PkgdefProjectOutputGroup|</VsPackage>

+  </Content>

+</Vsix>

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/README.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/README.txt
new file mode 100644
index 0000000..d8785c9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/README.txt
@@ -0,0 +1,17 @@
+This directory contains a VSPackage project to generate a Visual Studio extension

+for clang-tidy.

+

+Build prerequisites are:

+- Visual Studio 2013 Professional

+- Visual Studio 2013 SDK

+- Visual Studio 2010 Professional (?)

+- Visual Studio 2010 SDK (?)

+

+The extension is built using CMake by setting BUILD_CLANG_TIDY_VS_PLUGIN=ON

+when configuring a Clang build, and building the clang_tidy_vsix target.

+

+The CMake build will copy clang-tidy.exe and LICENSE.TXT into the ClangTidy/

+directory so they can be bundled with the plug-in, as well as creating

+ClangTidy/source.extension.vsixmanifest. Once the plug-in has been built with

+CMake once, it can be built manually from the ClangTidy.sln solution in Visual

+Studio.

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/source.extension.vsixmanifest.in b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/source.extension.vsixmanifest.in
new file mode 100644
index 0000000..86ee571
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy-vs/source.extension.vsixmanifest.in
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Vsix Version="1.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2010">

+  <Identifier Id="405594C3-042A-4155-B9A6-E25DAB8B1924">

+    <Name>ClangTidy</Name>

+    <Author>LLVM</Author>

+    <Version>@CLANG_TIDY_VS_VERSION@</Version>

+    <Description xml:space="preserve">A static analysis tool for C/C++ code.</Description>

+    <Locale>1033</Locale>

+    <MoreInfoUrl>http://clang.llvm.org/extra/clang-tidy/</MoreInfoUrl>

+    <License>license.txt</License>

+    <InstalledByMsi>false</InstalledByMsi>

+    <SupportedProducts>

+      <VisualStudio Version="10.0">

+        <Edition>Pro</Edition>

+      </VisualStudio>

+      <VisualStudio Version="11.0">

+        <Edition>Pro</Edition>

+      </VisualStudio>

+      <VisualStudio Version="12.0">

+        <Edition>Pro</Edition>

+      </VisualStudio>

+      <VisualStudio Version="14.0">

+        <Edition>Pro</Edition>

+      </VisualStudio>

+    </SupportedProducts>

+    <SupportedFrameworkRuntimeEdition MinVersion="4.0" MaxVersion="4.0" />

+  </Identifier>

+  <References>

+        <Reference Id="Microsoft.VisualStudio.MPF" MinVersion="10.0">

+            <Name>Visual Studio MPF</Name>

+        </Reference>

+  </References>

+  <Content>

+    <VsPackage>|%CurrentProject%;PkgdefProjectOutputGroup|</VsPackage>

+  </Content>

+</Vsix>

diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/CMakeLists.txt
new file mode 100644
index 0000000..a872469
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/CMakeLists.txt
@@ -0,0 +1,50 @@
+set(LLVM_LINK_COMPONENTS
+  Support
+  )
+
+add_clang_library(clangTidy
+  ClangTidy.cpp
+  ClangTidyModule.cpp
+  ClangTidyDiagnosticConsumer.cpp
+  ClangTidyOptions.cpp
+  ClangTidyProfiling.cpp
+
+  DEPENDS
+  ClangSACheckers
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFormat
+  clangFrontend
+  clangLex
+  clangRewrite
+  clangSema
+  clangStaticAnalyzerCore
+  clangStaticAnalyzerFrontend
+  clangTooling
+  clangToolingCore
+  )
+
+add_subdirectory(android)
+add_subdirectory(abseil)
+add_subdirectory(boost)
+add_subdirectory(bugprone)
+add_subdirectory(cert)
+add_subdirectory(cppcoreguidelines)
+add_subdirectory(fuchsia)
+add_subdirectory(google)
+add_subdirectory(hicpp)
+add_subdirectory(llvm)
+add_subdirectory(misc)
+add_subdirectory(modernize)
+add_subdirectory(mpi)
+add_subdirectory(objc)
+add_subdirectory(performance)
+add_subdirectory(plugin)
+add_subdirectory(portability)
+add_subdirectory(readability)
+add_subdirectory(tool)
+add_subdirectory(utils)
+add_subdirectory(zircon)
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidy.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidy.cpp
new file mode 100644
index 0000000..f497fd7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidy.cpp
@@ -0,0 +1,621 @@
+//===--- tools/extra/clang-tidy/ClangTidy.cpp - Clang tidy tool -----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+///  \file This file implements a clang-tidy tool.
+///
+///  This tool uses the Clang Tooling infrastructure, see
+///    http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
+///  for details on setting it up with LLVM source tree.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ClangTidy.h"
+#include "ClangTidyDiagnosticConsumer.h"
+#include "ClangTidyModuleRegistry.h"
+#include "ClangTidyProfiling.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Format/Format.h"
+#include "clang/Frontend/ASTConsumers.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Rewrite/Frontend/FixItRewriter.h"
+#include "clang/Rewrite/Frontend/FrontendActions.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
+#include "clang/Tooling/DiagnosticsYaml.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/ReplacementsYaml.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Signals.h"
+#include <algorithm>
+#include <utility>
+
+using namespace clang::ast_matchers;
+using namespace clang::driver;
+using namespace clang::tooling;
+using namespace llvm;
+
+LLVM_INSTANTIATE_REGISTRY(clang::tidy::ClangTidyModuleRegistry)
+
+namespace clang {
+namespace tidy {
+
+namespace {
+static const char *AnalyzerCheckNamePrefix = "clang-analyzer-";
+
+class AnalyzerDiagnosticConsumer : public ento::PathDiagnosticConsumer {
+public:
+  AnalyzerDiagnosticConsumer(ClangTidyContext &Context) : Context(Context) {}
+
+  void FlushDiagnosticsImpl(std::vector<const ento::PathDiagnostic *> &Diags,
+                            FilesMade *filesMade) override {
+    for (const ento::PathDiagnostic *PD : Diags) {
+      SmallString<64> CheckName(AnalyzerCheckNamePrefix);
+      CheckName += PD->getCheckName();
+      Context.diag(CheckName, PD->getLocation().asLocation(),
+                   PD->getShortDescription())
+          << PD->path.back()->getRanges();
+
+      for (const auto &DiagPiece :
+           PD->path.flatten(/*ShouldFlattenMacros=*/true)) {
+        Context.diag(CheckName, DiagPiece->getLocation().asLocation(),
+                     DiagPiece->getString(), DiagnosticIDs::Note)
+            << DiagPiece->getRanges();
+      }
+    }
+  }
+
+  StringRef getName() const override { return "ClangTidyDiags"; }
+  bool supportsLogicalOpControlFlow() const override { return true; }
+  bool supportsCrossFileDiagnostics() const override { return true; }
+
+private:
+  ClangTidyContext &Context;
+};
+
+class ErrorReporter {
+public:
+  ErrorReporter(ClangTidyContext &Context, bool ApplyFixes,
+                llvm::IntrusiveRefCntPtr<vfs::FileSystem> BaseFS)
+      : Files(FileSystemOptions(), BaseFS), DiagOpts(new DiagnosticOptions()),
+        DiagPrinter(new TextDiagnosticPrinter(llvm::outs(), &*DiagOpts)),
+        Diags(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts,
+              DiagPrinter),
+        SourceMgr(Diags, Files), Context(Context), ApplyFixes(ApplyFixes),
+        TotalFixes(0), AppliedFixes(0), WarningsAsErrors(0) {
+    DiagOpts->ShowColors = llvm::sys::Process::StandardOutHasColors();
+    DiagPrinter->BeginSourceFile(LangOpts);
+  }
+
+  SourceManager &getSourceManager() { return SourceMgr; }
+
+  void reportDiagnostic(const ClangTidyError &Error) {
+    const tooling::DiagnosticMessage &Message = Error.Message;
+    SourceLocation Loc = getLocation(Message.FilePath, Message.FileOffset);
+    // Contains a pair for each attempted fix: location and whether the fix was
+    // applied successfully.
+    SmallVector<std::pair<SourceLocation, bool>, 4> FixLocations;
+    {
+      auto Level = static_cast<DiagnosticsEngine::Level>(Error.DiagLevel);
+      std::string Name = Error.DiagnosticName;
+      if (Error.IsWarningAsError) {
+        Name += ",-warnings-as-errors";
+        Level = DiagnosticsEngine::Error;
+        WarningsAsErrors++;
+      }
+      auto Diag = Diags.Report(Loc, Diags.getCustomDiagID(Level, "%0 [%1]"))
+                  << Message.Message << Name;
+      for (const auto &FileAndReplacements : Error.Fix) {
+        for (const auto &Repl : FileAndReplacements.second) {
+          // Retrieve the source range for applicable fixes. Macro definitions
+          // on the command line have locations in a virtual buffer and don't
+          // have valid file paths and are therefore not applicable.
+          SourceRange Range;
+          SourceLocation FixLoc;
+          ++TotalFixes;
+          bool CanBeApplied = false;
+          if (Repl.isApplicable()) {
+            SmallString<128> FixAbsoluteFilePath = Repl.getFilePath();
+            Files.makeAbsolutePath(FixAbsoluteFilePath);
+            if (ApplyFixes) {
+              tooling::Replacement R(FixAbsoluteFilePath, Repl.getOffset(),
+                                     Repl.getLength(),
+                                     Repl.getReplacementText());
+              Replacements &Replacements = FileReplacements[R.getFilePath()];
+              llvm::Error Err = Replacements.add(R);
+              if (Err) {
+                // FIXME: Implement better conflict handling.
+                llvm::errs() << "Trying to resolve conflict: "
+                             << llvm::toString(std::move(Err)) << "\n";
+                unsigned NewOffset =
+                    Replacements.getShiftedCodePosition(R.getOffset());
+                unsigned NewLength = Replacements.getShiftedCodePosition(
+                                         R.getOffset() + R.getLength()) -
+                                     NewOffset;
+                if (NewLength == R.getLength()) {
+                  R = Replacement(R.getFilePath(), NewOffset, NewLength,
+                                  R.getReplacementText());
+                  Replacements = Replacements.merge(tooling::Replacements(R));
+                  CanBeApplied = true;
+                  ++AppliedFixes;
+                } else {
+                  llvm::errs()
+                      << "Can't resolve conflict, skipping the replacement.\n";
+                }
+
+              } else {
+                CanBeApplied = true;
+                ++AppliedFixes;
+              }
+            }
+            FixLoc = getLocation(FixAbsoluteFilePath, Repl.getOffset());
+            SourceLocation FixEndLoc =
+                FixLoc.getLocWithOffset(Repl.getLength());
+            Range = SourceRange(FixLoc, FixEndLoc);
+            Diag << FixItHint::CreateReplacement(Range,
+                                                 Repl.getReplacementText());
+          }
+
+          if (ApplyFixes)
+            FixLocations.push_back(std::make_pair(FixLoc, CanBeApplied));
+        }
+      }
+    }
+    for (auto Fix : FixLocations) {
+      Diags.Report(Fix.first, Fix.second ? diag::note_fixit_applied
+                                         : diag::note_fixit_failed);
+    }
+    for (const auto &Note : Error.Notes)
+      reportNote(Note);
+  }
+
+  void Finish() {
+    if (ApplyFixes && TotalFixes > 0) {
+      Rewriter Rewrite(SourceMgr, LangOpts);
+      for (const auto &FileAndReplacements : FileReplacements) {
+        StringRef File = FileAndReplacements.first();
+        llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
+            SourceMgr.getFileManager().getBufferForFile(File);
+        if (!Buffer) {
+          llvm::errs() << "Can't get buffer for file " << File << ": "
+                       << Buffer.getError().message() << "\n";
+          // FIXME: Maybe don't apply fixes for other files as well.
+          continue;
+        }
+        StringRef Code = Buffer.get()->getBuffer();
+        auto Style = format::getStyle(
+            *Context.getOptionsForFile(File).FormatStyle, File, "none");
+        if (!Style) {
+          llvm::errs() << llvm::toString(Style.takeError()) << "\n";
+          continue;
+        }
+        llvm::Expected<tooling::Replacements> Replacements =
+            format::cleanupAroundReplacements(Code, FileAndReplacements.second,
+                                              *Style);
+        if (!Replacements) {
+          llvm::errs() << llvm::toString(Replacements.takeError()) << "\n";
+          continue;
+        }
+        if (llvm::Expected<tooling::Replacements> FormattedReplacements =
+                format::formatReplacements(Code, *Replacements, *Style)) {
+          Replacements = std::move(FormattedReplacements);
+          if (!Replacements)
+            llvm_unreachable("!Replacements");
+        } else {
+          llvm::errs() << llvm::toString(FormattedReplacements.takeError())
+                       << ". Skipping formatting.\n";
+        }
+        if (!tooling::applyAllReplacements(Replacements.get(), Rewrite)) {
+          llvm::errs() << "Can't apply replacements for file " << File << "\n";
+        }
+      }
+      if (Rewrite.overwriteChangedFiles()) {
+        llvm::errs() << "clang-tidy failed to apply suggested fixes.\n";
+      } else {
+        llvm::errs() << "clang-tidy applied " << AppliedFixes << " of "
+                     << TotalFixes << " suggested fixes.\n";
+      }
+    }
+  }
+
+  unsigned getWarningsAsErrorsCount() const { return WarningsAsErrors; }
+
+private:
+  SourceLocation getLocation(StringRef FilePath, unsigned Offset) {
+    if (FilePath.empty())
+      return SourceLocation();
+
+    const FileEntry *File = SourceMgr.getFileManager().getFile(FilePath);
+    FileID ID = SourceMgr.getOrCreateFileID(File, SrcMgr::C_User);
+    return SourceMgr.getLocForStartOfFile(ID).getLocWithOffset(Offset);
+  }
+
+  void reportNote(const tooling::DiagnosticMessage &Message) {
+    SourceLocation Loc = getLocation(Message.FilePath, Message.FileOffset);
+    Diags.Report(Loc, Diags.getCustomDiagID(DiagnosticsEngine::Note, "%0"))
+        << Message.Message;
+  }
+
+  FileManager Files;
+  LangOptions LangOpts; // FIXME: use langopts from each original file
+  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
+  DiagnosticConsumer *DiagPrinter;
+  DiagnosticsEngine Diags;
+  SourceManager SourceMgr;
+  llvm::StringMap<Replacements> FileReplacements;
+  ClangTidyContext &Context;
+  bool ApplyFixes;
+  unsigned TotalFixes;
+  unsigned AppliedFixes;
+  unsigned WarningsAsErrors;
+};
+
+class ClangTidyASTConsumer : public MultiplexConsumer {
+public:
+  ClangTidyASTConsumer(std::vector<std::unique_ptr<ASTConsumer>> Consumers,
+                       std::unique_ptr<ClangTidyProfiling> Profiling,
+                       std::unique_ptr<ast_matchers::MatchFinder> Finder,
+                       std::vector<std::unique_ptr<ClangTidyCheck>> Checks)
+      : MultiplexConsumer(std::move(Consumers)),
+        Profiling(std::move(Profiling)), Finder(std::move(Finder)),
+        Checks(std::move(Checks)) {}
+
+private:
+  // Destructor order matters! Profiling must be destructed last.
+  // Or at least after Finder.
+  std::unique_ptr<ClangTidyProfiling> Profiling;
+  std::unique_ptr<ast_matchers::MatchFinder> Finder;
+  std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
+};
+
+} // namespace
+
+ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory(
+    ClangTidyContext &Context)
+    : Context(Context), CheckFactories(new ClangTidyCheckFactories) {
+  for (ClangTidyModuleRegistry::iterator I = ClangTidyModuleRegistry::begin(),
+                                         E = ClangTidyModuleRegistry::end();
+       I != E; ++I) {
+    std::unique_ptr<ClangTidyModule> Module(I->instantiate());
+    Module->addCheckFactories(*CheckFactories);
+  }
+}
+
+static void setStaticAnalyzerCheckerOpts(const ClangTidyOptions &Opts,
+                                         AnalyzerOptionsRef AnalyzerOptions) {
+  StringRef AnalyzerPrefix(AnalyzerCheckNamePrefix);
+  for (const auto &Opt : Opts.CheckOptions) {
+    StringRef OptName(Opt.first);
+    if (!OptName.startswith(AnalyzerPrefix))
+      continue;
+    AnalyzerOptions->Config[OptName.substr(AnalyzerPrefix.size())] = Opt.second;
+  }
+}
+
+typedef std::vector<std::pair<std::string, bool>> CheckersList;
+
+static CheckersList getCheckersControlList(ClangTidyContext &Context,
+                                           bool IncludeExperimental) {
+  CheckersList List;
+
+  const auto &RegisteredCheckers =
+      AnalyzerOptions::getRegisteredCheckers(IncludeExperimental);
+  bool AnalyzerChecksEnabled = false;
+  for (StringRef CheckName : RegisteredCheckers) {
+    std::string ClangTidyCheckName((AnalyzerCheckNamePrefix + CheckName).str());
+    AnalyzerChecksEnabled |= Context.isCheckEnabled(ClangTidyCheckName);
+  }
+
+  if (!AnalyzerChecksEnabled)
+    return List;
+
+  // List all static analyzer checkers that our filter enables.
+  //
+  // Always add all core checkers if any other static analyzer check is enabled.
+  // This is currently necessary, as other path sensitive checks rely on the
+  // core checkers.
+  for (StringRef CheckName : RegisteredCheckers) {
+    std::string ClangTidyCheckName((AnalyzerCheckNamePrefix + CheckName).str());
+
+    if (CheckName.startswith("core") ||
+        Context.isCheckEnabled(ClangTidyCheckName)) {
+      List.emplace_back(CheckName, true);
+    }
+  }
+  return List;
+}
+
+std::unique_ptr<clang::ASTConsumer>
+ClangTidyASTConsumerFactory::CreateASTConsumer(
+    clang::CompilerInstance &Compiler, StringRef File) {
+  // FIXME: Move this to a separate method, so that CreateASTConsumer doesn't
+  // modify Compiler.
+  Context.setSourceManager(&Compiler.getSourceManager());
+  Context.setCurrentFile(File);
+  Context.setASTContext(&Compiler.getASTContext());
+
+  auto WorkingDir = Compiler.getSourceManager()
+                        .getFileManager()
+                        .getVirtualFileSystem()
+                        ->getCurrentWorkingDirectory();
+  if (WorkingDir)
+    Context.setCurrentBuildDirectory(WorkingDir.get());
+
+  std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
+  CheckFactories->createChecks(&Context, Checks);
+
+  ast_matchers::MatchFinder::MatchFinderOptions FinderOptions;
+
+  std::unique_ptr<ClangTidyProfiling> Profiling;
+  if (Context.getEnableProfiling()) {
+    Profiling = llvm::make_unique<ClangTidyProfiling>(
+        Context.getProfileStorageParams());
+    FinderOptions.CheckProfiling.emplace(Profiling->Records);
+  }
+
+  std::unique_ptr<ast_matchers::MatchFinder> Finder(
+      new ast_matchers::MatchFinder(std::move(FinderOptions)));
+
+  for (auto &Check : Checks) {
+    Check->registerMatchers(&*Finder);
+    Check->registerPPCallbacks(Compiler);
+  }
+
+  std::vector<std::unique_ptr<ASTConsumer>> Consumers;
+  if (!Checks.empty())
+    Consumers.push_back(Finder->newASTConsumer());
+
+  AnalyzerOptionsRef AnalyzerOptions = Compiler.getAnalyzerOpts();
+  AnalyzerOptions->CheckersControlList =
+      getCheckersControlList(Context, Context.canEnableAnalyzerAlphaCheckers());
+  if (!AnalyzerOptions->CheckersControlList.empty()) {
+    setStaticAnalyzerCheckerOpts(Context.getOptions(), AnalyzerOptions);
+    AnalyzerOptions->AnalysisStoreOpt = RegionStoreModel;
+    AnalyzerOptions->AnalysisDiagOpt = PD_NONE;
+    AnalyzerOptions->AnalyzeNestedBlocks = true;
+    AnalyzerOptions->eagerlyAssumeBinOpBifurcation = true;
+    std::unique_ptr<ento::AnalysisASTConsumer> AnalysisConsumer =
+        ento::CreateAnalysisConsumer(Compiler);
+    AnalysisConsumer->AddDiagnosticConsumer(
+        new AnalyzerDiagnosticConsumer(Context));
+    Consumers.push_back(std::move(AnalysisConsumer));
+  }
+  return llvm::make_unique<ClangTidyASTConsumer>(
+      std::move(Consumers), std::move(Profiling), std::move(Finder),
+      std::move(Checks));
+}
+
+std::vector<std::string> ClangTidyASTConsumerFactory::getCheckNames() {
+  std::vector<std::string> CheckNames;
+  for (const auto &CheckFactory : *CheckFactories) {
+    if (Context.isCheckEnabled(CheckFactory.first))
+      CheckNames.push_back(CheckFactory.first);
+  }
+
+  for (const auto &AnalyzerCheck : getCheckersControlList(
+           Context, Context.canEnableAnalyzerAlphaCheckers()))
+    CheckNames.push_back(AnalyzerCheckNamePrefix + AnalyzerCheck.first);
+
+  std::sort(CheckNames.begin(), CheckNames.end());
+  return CheckNames;
+}
+
+ClangTidyOptions::OptionMap ClangTidyASTConsumerFactory::getCheckOptions() {
+  ClangTidyOptions::OptionMap Options;
+  std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
+  CheckFactories->createChecks(&Context, Checks);
+  for (const auto &Check : Checks)
+    Check->storeOptions(Options);
+  return Options;
+}
+
+DiagnosticBuilder ClangTidyCheck::diag(SourceLocation Loc, StringRef Message,
+                                       DiagnosticIDs::Level Level) {
+  return Context->diag(CheckName, Loc, Message, Level);
+}
+
+void ClangTidyCheck::run(const ast_matchers::MatchFinder::MatchResult &Result) {
+  Context->setSourceManager(Result.SourceManager);
+  check(Result);
+}
+
+OptionsView::OptionsView(StringRef CheckName,
+                         const ClangTidyOptions::OptionMap &CheckOptions)
+    : NamePrefix(CheckName.str() + "."), CheckOptions(CheckOptions) {}
+
+std::string OptionsView::get(StringRef LocalName, StringRef Default) const {
+  const auto &Iter = CheckOptions.find(NamePrefix + LocalName.str());
+  if (Iter != CheckOptions.end())
+    return Iter->second;
+  return Default;
+}
+
+std::string OptionsView::getLocalOrGlobal(StringRef LocalName,
+                                          StringRef Default) const {
+  auto Iter = CheckOptions.find(NamePrefix + LocalName.str());
+  if (Iter != CheckOptions.end())
+    return Iter->second;
+  // Fallback to global setting, if present.
+  Iter = CheckOptions.find(LocalName.str());
+  if (Iter != CheckOptions.end())
+    return Iter->second;
+  return Default;
+}
+
+void OptionsView::store(ClangTidyOptions::OptionMap &Options,
+                        StringRef LocalName, StringRef Value) const {
+  Options[NamePrefix + LocalName.str()] = Value;
+}
+
+void OptionsView::store(ClangTidyOptions::OptionMap &Options,
+                        StringRef LocalName, int64_t Value) const {
+  store(Options, LocalName, llvm::itostr(Value));
+}
+
+std::vector<std::string>
+getCheckNames(const ClangTidyOptions &Options,
+              bool AllowEnablingAnalyzerAlphaCheckers) {
+  clang::tidy::ClangTidyContext Context(
+      llvm::make_unique<DefaultOptionsProvider>(ClangTidyGlobalOptions(),
+                                                Options),
+      AllowEnablingAnalyzerAlphaCheckers);
+  ClangTidyASTConsumerFactory Factory(Context);
+  return Factory.getCheckNames();
+}
+
+ClangTidyOptions::OptionMap
+getCheckOptions(const ClangTidyOptions &Options,
+                bool AllowEnablingAnalyzerAlphaCheckers) {
+  clang::tidy::ClangTidyContext Context(
+      llvm::make_unique<DefaultOptionsProvider>(ClangTidyGlobalOptions(),
+                                                Options),
+      AllowEnablingAnalyzerAlphaCheckers);
+  ClangTidyASTConsumerFactory Factory(Context);
+  return Factory.getCheckOptions();
+}
+
+void runClangTidy(clang::tidy::ClangTidyContext &Context,
+                  const CompilationDatabase &Compilations,
+                  ArrayRef<std::string> InputFiles,
+                  llvm::IntrusiveRefCntPtr<vfs::FileSystem> BaseFS,
+                  bool EnableCheckProfile, llvm::StringRef StoreCheckProfile) {
+  ClangTool Tool(Compilations, InputFiles,
+                 std::make_shared<PCHContainerOperations>(), BaseFS);
+
+  // Add extra arguments passed by the clang-tidy command-line.
+  ArgumentsAdjuster PerFileExtraArgumentsInserter =
+      [&Context](const CommandLineArguments &Args, StringRef Filename) {
+        ClangTidyOptions Opts = Context.getOptionsForFile(Filename);
+        CommandLineArguments AdjustedArgs = Args;
+        if (Opts.ExtraArgsBefore) {
+          auto I = AdjustedArgs.begin();
+          if (I != AdjustedArgs.end() && !StringRef(*I).startswith("-"))
+            ++I; // Skip compiler binary name, if it is there.
+          AdjustedArgs.insert(I, Opts.ExtraArgsBefore->begin(),
+                              Opts.ExtraArgsBefore->end());
+        }
+        if (Opts.ExtraArgs)
+          AdjustedArgs.insert(AdjustedArgs.end(), Opts.ExtraArgs->begin(),
+                              Opts.ExtraArgs->end());
+        return AdjustedArgs;
+      };
+
+  // Remove plugins arguments.
+  ArgumentsAdjuster PluginArgumentsRemover =
+      [](const CommandLineArguments &Args, StringRef Filename) {
+        CommandLineArguments AdjustedArgs;
+        for (size_t I = 0, E = Args.size(); I < E; ++I) {
+          if (I + 4 < Args.size() && Args[I] == "-Xclang" &&
+              (Args[I + 1] == "-load" || Args[I + 1] == "-add-plugin" ||
+               StringRef(Args[I + 1]).startswith("-plugin-arg-")) &&
+              Args[I + 2] == "-Xclang") {
+            I += 3;
+          } else
+            AdjustedArgs.push_back(Args[I]);
+        }
+        return AdjustedArgs;
+      };
+
+  Tool.appendArgumentsAdjuster(PerFileExtraArgumentsInserter);
+  Tool.appendArgumentsAdjuster(PluginArgumentsRemover);
+  Context.setEnableProfiling(EnableCheckProfile);
+  Context.setProfileStoragePrefix(StoreCheckProfile);
+
+  ClangTidyDiagnosticConsumer DiagConsumer(Context);
+
+  Tool.setDiagnosticConsumer(&DiagConsumer);
+
+  class ActionFactory : public FrontendActionFactory {
+  public:
+    ActionFactory(ClangTidyContext &Context) : ConsumerFactory(Context) {}
+    FrontendAction *create() override { return new Action(&ConsumerFactory); }
+
+    bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
+                       FileManager *Files,
+                       std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+                       DiagnosticConsumer *DiagConsumer) override {
+      // Explicitly set ProgramAction to RunAnalysis to make the preprocessor
+      // define __clang_analyzer__ macro. The frontend analyzer action will not
+      // be called here.
+      Invocation->getFrontendOpts().ProgramAction = frontend::RunAnalysis;
+      return FrontendActionFactory::runInvocation(
+          Invocation, Files, PCHContainerOps, DiagConsumer);
+    }
+
+  private:
+    class Action : public ASTFrontendAction {
+    public:
+      Action(ClangTidyASTConsumerFactory *Factory) : Factory(Factory) {}
+      std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
+                                                     StringRef File) override {
+        return Factory->CreateASTConsumer(Compiler, File);
+      }
+
+    private:
+      ClangTidyASTConsumerFactory *Factory;
+    };
+
+    ClangTidyASTConsumerFactory ConsumerFactory;
+  };
+
+  ActionFactory Factory(Context);
+  Tool.run(&Factory);
+}
+
+void handleErrors(ClangTidyContext &Context, bool Fix,
+                  unsigned &WarningsAsErrorsCount,
+                  llvm::IntrusiveRefCntPtr<vfs::FileSystem> BaseFS) {
+  ErrorReporter Reporter(Context, Fix, BaseFS);
+  vfs::FileSystem &FileSystem =
+      *Reporter.getSourceManager().getFileManager().getVirtualFileSystem();
+  auto InitialWorkingDir = FileSystem.getCurrentWorkingDirectory();
+  if (!InitialWorkingDir)
+    llvm::report_fatal_error("Cannot get current working path.");
+
+  for (const ClangTidyError &Error : Context.getErrors()) {
+    if (!Error.BuildDirectory.empty()) {
+      // By default, the working directory of file system is the current
+      // clang-tidy running directory.
+      //
+      // Change the directory to the one used during the analysis.
+      FileSystem.setCurrentWorkingDirectory(Error.BuildDirectory);
+    }
+    Reporter.reportDiagnostic(Error);
+    // Return to the initial directory to correctly resolve next Error.
+    FileSystem.setCurrentWorkingDirectory(InitialWorkingDir.get());
+  }
+  Reporter.Finish();
+  WarningsAsErrorsCount += Reporter.getWarningsAsErrorsCount();
+}
+
+void exportReplacements(const llvm::StringRef MainFilePath,
+                        const std::vector<ClangTidyError> &Errors,
+                        raw_ostream &OS) {
+  TranslationUnitDiagnostics TUD;
+  TUD.MainSourceFile = MainFilePath;
+  for (const auto &Error : Errors) {
+    tooling::Diagnostic Diag = Error;
+    TUD.Diagnostics.insert(TUD.Diagnostics.end(), Diag);
+  }
+
+  yaml::Output YAML(OS);
+  YAML << TUD;
+}
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidy.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidy.h
new file mode 100644
index 0000000..0ea9a70
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidy.h
@@ -0,0 +1,259 @@
+//===--- ClangTidy.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_CLANGTIDY_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDY_H
+
+#include "ClangTidyDiagnosticConsumer.h"
+#include "ClangTidyOptions.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Tooling/Refactoring.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
+#include <type_traits>
+#include <vector>
+
+namespace clang {
+
+class CompilerInstance;
+namespace tooling {
+class CompilationDatabase;
+}
+
+namespace tidy {
+
+/// \brief Provides access to the ``ClangTidyCheck`` options via check-local
+/// names.
+///
+/// Methods of this class prepend ``CheckName + "."`` to translate check-local
+/// option names to global option names.
+class OptionsView {
+public:
+  /// \brief Initializes the instance using \p CheckName + "." as a prefix.
+  OptionsView(StringRef CheckName,
+              const ClangTidyOptions::OptionMap &CheckOptions);
+
+  /// \brief Read a named option from the ``Context``.
+  ///
+  /// Reads the option with the check-local name \p LocalName from the
+  /// ``CheckOptions``. If the corresponding key is not present, returns
+  /// \p Default.
+  std::string get(StringRef LocalName, StringRef Default) const;
+
+  /// \brief Read a named option from the ``Context``.
+  ///
+  /// Reads the option with the check-local name \p LocalName from local or
+  /// global ``CheckOptions``. Gets local option first. If local is not present,
+  /// falls back to get global option. If global option is not present either,
+  /// returns Default.
+  std::string getLocalOrGlobal(StringRef LocalName, StringRef Default) const;
+
+  /// \brief Read a named option from the ``Context`` and parse it as an
+  /// integral type ``T``.
+  ///
+  /// Reads the option with the check-local name \p LocalName from the
+  /// ``CheckOptions``. If the corresponding key is not present, returns
+  /// \p Default.
+  template <typename T>
+  typename std::enable_if<std::is_integral<T>::value, T>::type
+  get(StringRef LocalName, T Default) const {
+    std::string Value = get(LocalName, "");
+    T Result = Default;
+    if (!Value.empty())
+      StringRef(Value).getAsInteger(10, Result);
+    return Result;
+  }
+
+  /// \brief Read a named option from the ``Context`` and parse it as an
+  /// integral type ``T``.
+  ///
+  /// Reads the option with the check-local name \p LocalName from local or
+  /// global ``CheckOptions``. Gets local option first. If local is not present,
+  /// falls back to get global option. If global option is not present either,
+  /// returns Default.
+  template <typename T>
+  typename std::enable_if<std::is_integral<T>::value, T>::type
+  getLocalOrGlobal(StringRef LocalName, T Default) const {
+    std::string Value = getLocalOrGlobal(LocalName, "");
+    T Result = Default;
+    if (!Value.empty())
+      StringRef(Value).getAsInteger(10, Result);
+    return Result;
+  }
+
+  /// \brief Stores an option with the check-local name \p LocalName with string
+  /// value \p Value to \p Options.
+  void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName,
+             StringRef Value) const;
+
+  /// \brief Stores an option with the check-local name \p LocalName with
+  /// ``int64_t`` value \p Value to \p Options.
+  void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName,
+             int64_t Value) const;
+
+private:
+  std::string NamePrefix;
+  const ClangTidyOptions::OptionMap &CheckOptions;
+};
+
+/// \brief Base class for all clang-tidy checks.
+///
+/// To implement a ``ClangTidyCheck``, write a subclass and override some of the
+/// base class's methods. E.g. to implement a check that validates namespace
+/// declarations, override ``registerMatchers``:
+///
+/// ~~~{.cpp}
+/// void registerMatchers(ast_matchers::MatchFinder *Finder) override {
+///   Finder->addMatcher(namespaceDecl().bind("namespace"), this);
+/// }
+/// ~~~
+///
+/// and then override ``check(const MatchResult &Result)`` to do the actual
+/// check for each match.
+///
+/// A new ``ClangTidyCheck`` instance is created per translation unit.
+///
+/// FIXME: Figure out whether carrying information from one TU to another is
+/// useful/necessary.
+class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
+public:
+  /// \brief Initializes the check with \p CheckName and \p Context.
+  ///
+  /// Derived classes must implement the constructor with this signature or
+  /// delegate it. If a check needs to read options, it can do this in the
+  /// constructor using the Options.get() methods below.
+  ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context)
+      : CheckName(CheckName), Context(Context),
+        Options(CheckName, Context->getOptions().CheckOptions) {
+    assert(Context != nullptr);
+    assert(!CheckName.empty());
+  }
+
+  /// \brief Override this to register ``PPCallbacks`` with ``Compiler``.
+  ///
+  /// This should be used for clang-tidy checks that analyze preprocessor-
+  /// dependent properties, e.g. the order of include directives.
+  virtual void registerPPCallbacks(CompilerInstance &Compiler) {}
+
+  /// \brief Override this to register AST matchers with \p Finder.
+  ///
+  /// This should be used by clang-tidy checks that analyze code properties that
+  /// dependent on AST knowledge.
+  ///
+  /// You can register as many matchers as necessary with \p Finder. Usually,
+  /// "this" will be used as callback, but you can also specify other callback
+  /// classes. Thereby, different matchers can trigger different callbacks.
+  ///
+  /// If you need to merge information between the different matchers, you can
+  /// store these as members of the derived class. However, note that all
+  /// matches occur in the order of the AST traversal.
+  virtual void registerMatchers(ast_matchers::MatchFinder *Finder) {}
+
+  /// \brief ``ClangTidyChecks`` that register ASTMatchers should do the actual
+  /// work in here.
+  virtual void check(const ast_matchers::MatchFinder::MatchResult &Result) {}
+
+  /// \brief Add a diagnostic with the check's name.
+  DiagnosticBuilder diag(SourceLocation Loc, StringRef Description,
+                         DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
+
+  /// \brief Should store all options supported by this check with their
+  /// current values or default values for options that haven't been overridden.
+  ///
+  /// The check should use ``Options.store()`` to store each option it supports
+  /// whether it has the default value or it has been overridden.
+  virtual void storeOptions(ClangTidyOptions::OptionMap &Options) {}
+
+private:
+  void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  StringRef getID() const override { return CheckName; }
+  std::string CheckName;
+  ClangTidyContext *Context;
+
+protected:
+  OptionsView Options;
+  /// \brief Returns the main file name of the current translation unit.
+  StringRef getCurrentMainFile() const { return Context->getCurrentFile(); }
+  /// \brief Returns the language options from the context.
+  LangOptions getLangOpts() const { return Context->getLangOpts(); }
+};
+
+class ClangTidyCheckFactories;
+
+class ClangTidyASTConsumerFactory {
+public:
+  ClangTidyASTConsumerFactory(ClangTidyContext &Context);
+
+  /// \brief Returns an ASTConsumer that runs the specified clang-tidy checks.
+  std::unique_ptr<clang::ASTConsumer>
+  CreateASTConsumer(clang::CompilerInstance &Compiler, StringRef File);
+
+  /// \brief Get the list of enabled checks.
+  std::vector<std::string> getCheckNames();
+
+  /// \brief Get the union of options from all checks.
+  ClangTidyOptions::OptionMap getCheckOptions();
+
+private:
+  ClangTidyContext &Context;
+  std::unique_ptr<ClangTidyCheckFactories> CheckFactories;
+};
+
+/// \brief Fills the list of check names that are enabled when the provided
+/// filters are applied.
+std::vector<std::string> getCheckNames(const ClangTidyOptions &Options,
+                                       bool AllowEnablingAnalyzerAlphaCheckers);
+
+/// \brief Returns the effective check-specific options.
+///
+/// The method configures ClangTidy with the specified \p Options and collects
+/// effective options from all created checks. The returned set of options
+/// includes default check-specific options for all keys not overridden by \p
+/// Options.
+ClangTidyOptions::OptionMap
+getCheckOptions(const ClangTidyOptions &Options,
+                bool AllowEnablingAnalyzerAlphaCheckers);
+
+/// \brief Run a set of clang-tidy checks on a set of files.
+///
+/// \param EnableCheckProfile If provided, it enables check profile collection
+/// in MatchFinder, and will contain the result of the profile.
+/// \param StoreCheckProfile If provided, and EnableCheckProfile is true,
+/// the profile will not be output to stderr, but will instead be stored
+/// as a JSON file in the specified directory.
+void runClangTidy(clang::tidy::ClangTidyContext &Context,
+                  const tooling::CompilationDatabase &Compilations,
+                  ArrayRef<std::string> InputFiles,
+                  llvm::IntrusiveRefCntPtr<vfs::FileSystem> BaseFS,
+                  bool EnableCheckProfile = false,
+                  llvm::StringRef StoreCheckProfile = StringRef());
+
+// FIXME: This interface will need to be significantly extended to be useful.
+// FIXME: Implement confidence levels for displaying/fixing errors.
+//
+/// \brief Displays the found \p Errors to the users. If \p Fix is true, \p
+/// Errors containing fixes are automatically applied and reformatted. If no
+/// clang-format configuration file is found, the given \P FormatStyle is used.
+void handleErrors(ClangTidyContext &Context, bool Fix,
+                  unsigned &WarningsAsErrorsCount,
+                  llvm::IntrusiveRefCntPtr<vfs::FileSystem> BaseFS);
+
+/// \brief Serializes replacements into YAML and writes them to the specified
+/// output stream.
+void exportReplacements(StringRef MainFilePath,
+                        const std::vector<ClangTidyError> &Errors,
+                        raw_ostream &OS);
+
+} // end namespace tidy
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDY_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
new file mode 100644
index 0000000..a1c76fb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -0,0 +1,690 @@
+//===--- tools/extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp ----------=== //
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+///  \file This file implements ClangTidyDiagnosticConsumer, ClangTidyContext
+///  and ClangTidyError classes.
+///
+///  This tool uses the Clang Tooling infrastructure, see
+///    http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
+///  for details on setting it up with LLVM source tree.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ClangTidyDiagnosticConsumer.h"
+#include "ClangTidyOptions.h"
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Frontend/DiagnosticRenderer.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include <tuple>
+#include <vector>
+using namespace clang;
+using namespace tidy;
+
+namespace {
+class ClangTidyDiagnosticRenderer : public DiagnosticRenderer {
+public:
+  ClangTidyDiagnosticRenderer(const LangOptions &LangOpts,
+                              DiagnosticOptions *DiagOpts,
+                              ClangTidyError &Error)
+      : DiagnosticRenderer(LangOpts, DiagOpts), Error(Error) {}
+
+protected:
+  void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
+                             DiagnosticsEngine::Level Level, StringRef Message,
+                             ArrayRef<CharSourceRange> Ranges,
+                             DiagOrStoredDiag Info) override {
+    // Remove check name from the message.
+    // FIXME: Remove this once there's a better way to pass check names than
+    // appending the check name to the message in ClangTidyContext::diag and
+    // using getCustomDiagID.
+    std::string CheckNameInMessage = " [" + Error.DiagnosticName + "]";
+    if (Message.endswith(CheckNameInMessage))
+      Message = Message.substr(0, Message.size() - CheckNameInMessage.size());
+
+    auto TidyMessage =
+        Loc.isValid()
+            ? tooling::DiagnosticMessage(Message, Loc.getManager(), Loc)
+            : tooling::DiagnosticMessage(Message);
+    if (Level == DiagnosticsEngine::Note) {
+      Error.Notes.push_back(TidyMessage);
+      return;
+    }
+    assert(Error.Message.Message.empty() && "Overwriting a diagnostic message");
+    Error.Message = TidyMessage;
+  }
+
+  void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
+                         DiagnosticsEngine::Level Level,
+                         ArrayRef<CharSourceRange> Ranges) override {}
+
+  void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
+                       SmallVectorImpl<CharSourceRange> &Ranges,
+                       ArrayRef<FixItHint> Hints) override {
+    assert(Loc.isValid());
+    for (const auto &FixIt : Hints) {
+      CharSourceRange Range = FixIt.RemoveRange;
+      assert(Range.getBegin().isValid() && Range.getEnd().isValid() &&
+             "Invalid range in the fix-it hint.");
+      assert(Range.getBegin().isFileID() && Range.getEnd().isFileID() &&
+             "Only file locations supported in fix-it hints.");
+
+      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).
+      if (Err) {
+        llvm::errs() << "Fix conflicts with existing fix! "
+                     << llvm::toString(std::move(Err)) << "\n";
+        assert(false && "Fix conflicts with existing fix!");
+      }
+    }
+  }
+
+  void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override {}
+
+  void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc,
+                          StringRef ModuleName) override {}
+
+  void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc,
+                                  StringRef ModuleName) override {}
+
+  void endDiagnostic(DiagOrStoredDiag D,
+                     DiagnosticsEngine::Level Level) override {
+    assert(!Error.Message.Message.empty() && "Message has not been set");
+  }
+
+private:
+  ClangTidyError &Error;
+};
+} // end anonymous namespace
+
+ClangTidyError::ClangTidyError(StringRef CheckName,
+                               ClangTidyError::Level DiagLevel,
+                               StringRef BuildDirectory, bool IsWarningAsError)
+    : tooling::Diagnostic(CheckName, DiagLevel, BuildDirectory),
+      IsWarningAsError(IsWarningAsError) {}
+
+// Returns true if GlobList starts with the negative indicator ('-'), removes it
+// from the GlobList.
+static bool ConsumeNegativeIndicator(StringRef &GlobList) {
+  GlobList = GlobList.trim(" \r\n");
+  if (GlobList.startswith("-")) {
+    GlobList = GlobList.substr(1);
+    return true;
+  }
+  return false;
+}
+// Converts first glob from the comma-separated list of globs to Regex and
+// removes it and the trailing comma from the GlobList.
+static llvm::Regex ConsumeGlob(StringRef &GlobList) {
+  StringRef UntrimmedGlob = GlobList.substr(0, GlobList.find(','));
+  StringRef Glob = UntrimmedGlob.trim(' ');
+  GlobList = GlobList.substr(UntrimmedGlob.size() + 1);
+  SmallString<128> RegexText("^");
+  StringRef MetaChars("()^$|*+?.[]\\{}");
+  for (char C : Glob) {
+    if (C == '*')
+      RegexText.push_back('.');
+    else if (MetaChars.find(C) != StringRef::npos)
+      RegexText.push_back('\\');
+    RegexText.push_back(C);
+  }
+  RegexText.push_back('$');
+  return llvm::Regex(RegexText);
+}
+
+GlobList::GlobList(StringRef Globs)
+    : Positive(!ConsumeNegativeIndicator(Globs)), Regex(ConsumeGlob(Globs)),
+      NextGlob(Globs.empty() ? nullptr : new GlobList(Globs)) {}
+
+bool GlobList::contains(StringRef S, bool Contains) {
+  if (Regex.match(S))
+    Contains = Positive;
+
+  if (NextGlob)
+    Contains = NextGlob->contains(S, Contains);
+  return Contains;
+}
+
+class ClangTidyContext::CachedGlobList {
+public:
+  CachedGlobList(StringRef Globs) : Globs(Globs) {}
+
+  bool contains(StringRef S) {
+    switch (auto &Result = Cache[S]) {
+      case Yes: return true;
+      case No: return false;
+      case None:
+        Result = Globs.contains(S) ? Yes : No;
+        return Result == Yes;
+    }
+    llvm_unreachable("invalid enum");
+  }
+
+private:
+  GlobList Globs;
+  enum Tristate { None, Yes, No };
+  llvm::StringMap<Tristate> Cache;
+};
+
+ClangTidyContext::ClangTidyContext(
+    std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
+    bool AllowEnablingAnalyzerAlphaCheckers)
+    : DiagEngine(nullptr), OptionsProvider(std::move(OptionsProvider)),
+      Profile(false),
+      AllowEnablingAnalyzerAlphaCheckers(AllowEnablingAnalyzerAlphaCheckers) {
+  // Before the first translation unit we can get errors related to command-line
+  // parsing, use empty string for the file name in this case.
+  setCurrentFile("");
+}
+
+ClangTidyContext::~ClangTidyContext() = default;
+
+DiagnosticBuilder ClangTidyContext::diag(
+    StringRef CheckName, SourceLocation Loc, StringRef Description,
+    DiagnosticIDs::Level Level /* = DiagnosticIDs::Warning*/) {
+  assert(Loc.isValid());
+  unsigned ID = DiagEngine->getDiagnosticIDs()->getCustomDiagID(
+      Level, (Description + " [" + CheckName + "]").str());
+  CheckNamesByDiagnosticID.try_emplace(ID, CheckName);
+  return DiagEngine->Report(Loc, ID);
+}
+
+void ClangTidyContext::setDiagnosticsEngine(DiagnosticsEngine *Engine) {
+  DiagEngine = Engine;
+}
+
+void ClangTidyContext::setSourceManager(SourceManager *SourceMgr) {
+  DiagEngine->setSourceManager(SourceMgr);
+}
+
+void ClangTidyContext::setCurrentFile(StringRef File) {
+  CurrentFile = File;
+  CurrentOptions = getOptionsForFile(CurrentFile);
+  CheckFilter = llvm::make_unique<CachedGlobList>(*getOptions().Checks);
+  WarningAsErrorFilter =
+      llvm::make_unique<CachedGlobList>(*getOptions().WarningsAsErrors);
+}
+
+void ClangTidyContext::setASTContext(ASTContext *Context) {
+  DiagEngine->SetArgToStringFn(&FormatASTNodeDiagnosticArgument, Context);
+  LangOpts = Context->getLangOpts();
+}
+
+const ClangTidyGlobalOptions &ClangTidyContext::getGlobalOptions() const {
+  return OptionsProvider->getGlobalOptions();
+}
+
+const ClangTidyOptions &ClangTidyContext::getOptions() const {
+  return CurrentOptions;
+}
+
+ClangTidyOptions ClangTidyContext::getOptionsForFile(StringRef File) const {
+  // Merge options on top of getDefaults() as a safeguard against options with
+  // unset values.
+  return ClangTidyOptions::getDefaults().mergeWith(
+      OptionsProvider->getOptions(File));
+}
+
+void ClangTidyContext::setEnableProfiling(bool P) { Profile = P; }
+
+void ClangTidyContext::setProfileStoragePrefix(StringRef Prefix) {
+  ProfilePrefix = Prefix;
+}
+
+llvm::Optional<ClangTidyProfiling::StorageParams>
+ClangTidyContext::getProfileStorageParams() const {
+  if (ProfilePrefix.empty())
+    return llvm::None;
+
+  return ClangTidyProfiling::StorageParams(ProfilePrefix, CurrentFile);
+}
+
+bool ClangTidyContext::isCheckEnabled(StringRef CheckName) const {
+  assert(CheckFilter != nullptr);
+  return CheckFilter->contains(CheckName);
+}
+
+bool ClangTidyContext::treatAsError(StringRef CheckName) const {
+  assert(WarningAsErrorFilter != nullptr);
+  return WarningAsErrorFilter->contains(CheckName);
+}
+
+/// \brief Store a \c ClangTidyError.
+void ClangTidyContext::storeError(const ClangTidyError &Error) {
+  Errors.push_back(Error);
+}
+
+StringRef ClangTidyContext::getCheckName(unsigned DiagnosticID) const {
+  llvm::DenseMap<unsigned, std::string>::const_iterator I =
+      CheckNamesByDiagnosticID.find(DiagnosticID);
+  if (I != CheckNamesByDiagnosticID.end())
+    return I->second;
+  return "";
+}
+
+ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
+    ClangTidyContext &Ctx, bool RemoveIncompatibleErrors)
+    : Context(Ctx), RemoveIncompatibleErrors(RemoveIncompatibleErrors),
+      LastErrorRelatesToUserCode(false), LastErrorPassesLineFilter(false),
+      LastErrorWasIgnored(false) {
+  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+  Diags = llvm::make_unique<DiagnosticsEngine>(
+      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts, this,
+      /*ShouldOwnClient=*/false);
+  Context.setDiagnosticsEngine(Diags.get());
+}
+
+void ClangTidyDiagnosticConsumer::finalizeLastError() {
+  if (!Errors.empty()) {
+    ClangTidyError &Error = Errors.back();
+    if (!Context.isCheckEnabled(Error.DiagnosticName) &&
+        Error.DiagLevel != ClangTidyError::Error) {
+      ++Context.Stats.ErrorsIgnoredCheckFilter;
+      Errors.pop_back();
+    } else if (!LastErrorRelatesToUserCode) {
+      ++Context.Stats.ErrorsIgnoredNonUserCode;
+      Errors.pop_back();
+    } else if (!LastErrorPassesLineFilter) {
+      ++Context.Stats.ErrorsIgnoredLineFilter;
+      Errors.pop_back();
+    } else {
+      ++Context.Stats.ErrorsDisplayed;
+    }
+  }
+  LastErrorRelatesToUserCode = false;
+  LastErrorPassesLineFilter = false;
+}
+
+static bool IsNOLINTFound(StringRef NolintDirectiveText, StringRef Line,
+                          unsigned DiagID, const ClangTidyContext &Context) {
+  const size_t NolintIndex = Line.find(NolintDirectiveText);
+  if (NolintIndex == StringRef::npos)
+    return false;
+
+  size_t BracketIndex = NolintIndex + NolintDirectiveText.size();
+  // Check if the specific checks are specified in brackets.
+  if (BracketIndex < Line.size() && Line[BracketIndex] == '(') {
+    ++BracketIndex;
+    const size_t BracketEndIndex = Line.find(')', BracketIndex);
+    if (BracketEndIndex != StringRef::npos) {
+      StringRef ChecksStr =
+          Line.substr(BracketIndex, BracketEndIndex - BracketIndex);
+      // Allow disabling all the checks with "*".
+      if (ChecksStr != "*") {
+        StringRef CheckName = Context.getCheckName(DiagID);
+        // Allow specifying a few check names, delimited with comma.
+        SmallVector<StringRef, 1> Checks;
+        ChecksStr.split(Checks, ',', -1, false);
+        llvm::transform(Checks, Checks.begin(),
+                        [](StringRef S) { return S.trim(); });
+        return llvm::find(Checks, CheckName) != Checks.end();
+      }
+    }
+  }
+  return true;
+}
+
+static bool LineIsMarkedWithNOLINT(SourceManager &SM, SourceLocation Loc,
+                                   unsigned DiagID,
+                                   const ClangTidyContext &Context) {
+  bool Invalid;
+  const char *CharacterData = SM.getCharacterData(Loc, &Invalid);
+  if (Invalid)
+    return false;
+
+  // Check if there's a NOLINT on this line.
+  const char *P = CharacterData;
+  while (*P != '\0' && *P != '\r' && *P != '\n')
+    ++P;
+  StringRef RestOfLine(CharacterData, P - CharacterData + 1);
+  if (IsNOLINTFound("NOLINT", RestOfLine, DiagID, Context))
+    return true;
+
+  // Check if there's a NOLINTNEXTLINE on the previous line.
+  const char *BufBegin =
+      SM.getCharacterData(SM.getLocForStartOfFile(SM.getFileID(Loc)), &Invalid);
+  if (Invalid || P == BufBegin)
+    return false;
+
+  // Scan backwards over the current line.
+  P = CharacterData;
+  while (P != BufBegin && *P != '\n')
+    --P;
+
+  // If we reached the begin of the file there is no line before it.
+  if (P == BufBegin)
+    return false;
+
+  // Skip over the newline.
+  --P;
+  const char *LineEnd = P;
+
+  // Now we're on the previous line. Skip to the beginning of it.
+  while (P != BufBegin && *P != '\n')
+    --P;
+
+  RestOfLine = StringRef(P, LineEnd - P + 1);
+  if (IsNOLINTFound("NOLINTNEXTLINE", RestOfLine, DiagID, Context))
+    return true;
+
+  return false;
+}
+
+static bool LineIsMarkedWithNOLINTinMacro(SourceManager &SM, SourceLocation Loc,
+                                          unsigned DiagID,
+                                          const ClangTidyContext &Context) {
+  while (true) {
+    if (LineIsMarkedWithNOLINT(SM, Loc, DiagID, Context))
+      return true;
+    if (!Loc.isMacroID())
+      return false;
+    Loc = SM.getImmediateExpansionRange(Loc).getBegin();
+  }
+  return false;
+}
+
+void ClangTidyDiagnosticConsumer::HandleDiagnostic(
+    DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
+  if (LastErrorWasIgnored && DiagLevel == DiagnosticsEngine::Note)
+    return;
+
+  if (Info.getLocation().isValid() && DiagLevel != DiagnosticsEngine::Error &&
+      DiagLevel != DiagnosticsEngine::Fatal &&
+      LineIsMarkedWithNOLINTinMacro(Diags->getSourceManager(),
+                                    Info.getLocation(), Info.getID(),
+                                    Context)) {
+    ++Context.Stats.ErrorsIgnoredNOLINT;
+    // Ignored a warning, should ignore related notes as well
+    LastErrorWasIgnored = true;
+    return;
+  }
+
+  LastErrorWasIgnored = false;
+  // Count warnings/errors.
+  DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
+
+  if (DiagLevel == DiagnosticsEngine::Note) {
+    assert(!Errors.empty() &&
+           "A diagnostic note can only be appended to a message.");
+  } else {
+    finalizeLastError();
+    StringRef WarningOption =
+        Context.DiagEngine->getDiagnosticIDs()->getWarningOptionForDiag(
+            Info.getID());
+    std::string CheckName = !WarningOption.empty()
+                                ? ("clang-diagnostic-" + WarningOption).str()
+                                : Context.getCheckName(Info.getID()).str();
+
+    if (CheckName.empty()) {
+      // This is a compiler diagnostic without a warning option. Assign check
+      // name based on its level.
+      switch (DiagLevel) {
+      case DiagnosticsEngine::Error:
+      case DiagnosticsEngine::Fatal:
+        CheckName = "clang-diagnostic-error";
+        break;
+      case DiagnosticsEngine::Warning:
+        CheckName = "clang-diagnostic-warning";
+        break;
+      default:
+        CheckName = "clang-diagnostic-unknown";
+        break;
+      }
+    }
+
+    ClangTidyError::Level Level = ClangTidyError::Warning;
+    if (DiagLevel == DiagnosticsEngine::Error ||
+        DiagLevel == DiagnosticsEngine::Fatal) {
+      // Force reporting of Clang errors regardless of filters and non-user
+      // code.
+      Level = ClangTidyError::Error;
+      LastErrorRelatesToUserCode = true;
+      LastErrorPassesLineFilter = true;
+    }
+    bool IsWarningAsError = DiagLevel == DiagnosticsEngine::Warning &&
+                            Context.treatAsError(CheckName);
+    Errors.emplace_back(CheckName, Level, Context.getCurrentBuildDirectory(),
+                        IsWarningAsError);
+  }
+
+  ClangTidyDiagnosticRenderer Converter(
+      Context.getLangOpts(), &Context.DiagEngine->getDiagnosticOptions(),
+      Errors.back());
+  SmallString<100> Message;
+  Info.FormatDiagnostic(Message);
+  FullSourceLoc Loc =
+      (Info.getLocation().isInvalid())
+          ? FullSourceLoc()
+          : FullSourceLoc(Info.getLocation(), Info.getSourceManager());
+  Converter.emitDiagnostic(Loc, DiagLevel, Message, Info.getRanges(),
+                           Info.getFixItHints());
+
+  checkFilters(Info.getLocation());
+}
+
+bool ClangTidyDiagnosticConsumer::passesLineFilter(StringRef FileName,
+                                                   unsigned LineNumber) const {
+  if (Context.getGlobalOptions().LineFilter.empty())
+    return true;
+  for (const FileFilter &Filter : Context.getGlobalOptions().LineFilter) {
+    if (FileName.endswith(Filter.Name)) {
+      if (Filter.LineRanges.empty())
+        return true;
+      for (const FileFilter::LineRange &Range : Filter.LineRanges) {
+        if (Range.first <= LineNumber && LineNumber <= Range.second)
+          return true;
+      }
+      return false;
+    }
+  }
+  return false;
+}
+
+void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location) {
+  // Invalid location may mean a diagnostic in a command line, don't skip these.
+  if (!Location.isValid()) {
+    LastErrorRelatesToUserCode = true;
+    LastErrorPassesLineFilter = true;
+    return;
+  }
+
+  const SourceManager &Sources = Diags->getSourceManager();
+  if (!*Context.getOptions().SystemHeaders &&
+      Sources.isInSystemHeader(Location))
+    return;
+
+  // FIXME: We start with a conservative approach here, but the actual type of
+  // location needed depends on the check (in particular, where this check wants
+  // to apply fixes).
+  FileID FID = Sources.getDecomposedExpansionLoc(Location).first;
+  const FileEntry *File = Sources.getFileEntryForID(FID);
+
+  // -DMACRO definitions on the command line have locations in a virtual buffer
+  // that doesn't have a FileEntry. Don't skip these as well.
+  if (!File) {
+    LastErrorRelatesToUserCode = true;
+    LastErrorPassesLineFilter = true;
+    return;
+  }
+
+  StringRef FileName(File->getName());
+  LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
+                               Sources.isInMainFile(Location) ||
+                               getHeaderFilter()->match(FileName);
+
+  unsigned LineNumber = Sources.getExpansionLineNumber(Location);
+  LastErrorPassesLineFilter =
+      LastErrorPassesLineFilter || passesLineFilter(FileName, LineNumber);
+}
+
+llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
+  if (!HeaderFilter)
+    HeaderFilter =
+        llvm::make_unique<llvm::Regex>(*Context.getOptions().HeaderFilterRegex);
+  return HeaderFilter.get();
+}
+
+void ClangTidyDiagnosticConsumer::removeIncompatibleErrors(
+    SmallVectorImpl<ClangTidyError> &Errors) const {
+  // Each error is modelled as the set of intervals in which it applies
+  // replacements. To detect overlapping replacements, we use a sweep line
+  // algorithm over these sets of intervals.
+  // An event here consists of the opening or closing of an interval. During the
+  // process, we maintain a counter with the amount of open intervals. If we
+  // find an endpoint of an interval and this counter is different from 0, it
+  // means that this interval overlaps with another one, so we set it as
+  // inapplicable.
+  struct Event {
+    // An event can be either the begin or the end of an interval.
+    enum EventType {
+      ET_Begin = 1,
+      ET_End = -1,
+    };
+
+    Event(unsigned Begin, unsigned End, EventType Type, unsigned ErrorId,
+          unsigned ErrorSize)
+        : Type(Type), ErrorId(ErrorId) {
+      // The events are going to be sorted by their position. In case of draw:
+      //
+      // * If an interval ends at the same position at which other interval
+      //   begins, this is not an overlapping, so we want to remove the ending
+      //   interval before adding the starting one: end events have higher
+      //   priority than begin events.
+      //
+      // * If we have several begin points at the same position, we will mark as
+      //   inapplicable the ones that we process later, so the first one has to
+      //   be the one with the latest end point, because this one will contain
+      //   all the other intervals. For the same reason, if we have several end
+      //   points in the same position, the last one has to be the one with the
+      //   earliest begin point. In both cases, we sort non-increasingly by the
+      //   position of the complementary.
+      //
+      // * In case of two equal intervals, the one whose error is bigger can
+      //   potentially contain the other one, so we want to process its begin
+      //   points before and its end points later.
+      //
+      // * Finally, if we have two equal intervals whose errors have the same
+      //   size, none of them will be strictly contained inside the other.
+      //   Sorting by ErrorId will guarantee that the begin point of the first
+      //   one will be processed before, disallowing the second one, and the
+      //   end point of the first one will also be processed before,
+      //   disallowing the first one.
+      if (Type == ET_Begin)
+        Priority = std::make_tuple(Begin, Type, -End, -ErrorSize, ErrorId);
+      else
+        Priority = std::make_tuple(End, Type, -Begin, ErrorSize, ErrorId);
+    }
+
+    bool operator<(const Event &Other) const {
+      return Priority < Other.Priority;
+    }
+
+    // Determines if this event is the begin or the end of an interval.
+    EventType Type;
+    // The index of the error to which the interval that generated this event
+    // belongs.
+    unsigned ErrorId;
+    // The events will be sorted based on this field.
+    std::tuple<unsigned, EventType, int, int, unsigned> Priority;
+  };
+
+  // Compute error sizes.
+  std::vector<int> Sizes;
+  for (const auto &Error : Errors) {
+    int Size = 0;
+    for (const auto &FileAndReplaces : Error.Fix) {
+      for (const auto &Replace : FileAndReplaces.second)
+        Size += Replace.getLength();
+    }
+    Sizes.push_back(Size);
+  }
+
+  // Build events from error intervals.
+  std::map<std::string, std::vector<Event>> FileEvents;
+  for (unsigned I = 0; I < Errors.size(); ++I) {
+    for (const auto &FileAndReplace : Errors[I].Fix) {
+      for (const auto &Replace : FileAndReplace.second) {
+        unsigned Begin = Replace.getOffset();
+        unsigned End = Begin + Replace.getLength();
+        const std::string &FilePath = Replace.getFilePath();
+        // FIXME: Handle empty intervals, such as those from insertions.
+        if (Begin == End)
+          continue;
+        auto &Events = FileEvents[FilePath];
+        Events.emplace_back(Begin, End, Event::ET_Begin, I, Sizes[I]);
+        Events.emplace_back(Begin, End, Event::ET_End, I, Sizes[I]);
+      }
+    }
+  }
+
+  std::vector<bool> Apply(Errors.size(), true);
+  for (auto &FileAndEvents : FileEvents) {
+    std::vector<Event> &Events = FileAndEvents.second;
+    // Sweep.
+    std::sort(Events.begin(), Events.end());
+    int OpenIntervals = 0;
+    for (const auto &Event : Events) {
+      if (Event.Type == Event::ET_End)
+        --OpenIntervals;
+      // This has to be checked after removing the interval from the count if it
+      // is an end event, or before adding it if it is a begin event.
+      if (OpenIntervals != 0)
+        Apply[Event.ErrorId] = false;
+      if (Event.Type == Event::ET_Begin)
+        ++OpenIntervals;
+    }
+    assert(OpenIntervals == 0 && "Amount of begin/end points doesn't match");
+  }
+
+  for (unsigned I = 0; I < Errors.size(); ++I) {
+    if (!Apply[I]) {
+      Errors[I].Fix.clear();
+      Errors[I].Notes.emplace_back(
+          "this fix will not be applied because it overlaps with another fix");
+    }
+  }
+}
+
+namespace {
+struct LessClangTidyError {
+  bool operator()(const ClangTidyError &LHS, const ClangTidyError &RHS) const {
+    const tooling::DiagnosticMessage &M1 = LHS.Message;
+    const tooling::DiagnosticMessage &M2 = RHS.Message;
+
+    return std::tie(M1.FilePath, M1.FileOffset, M1.Message) <
+           std::tie(M2.FilePath, M2.FileOffset, M2.Message);
+  }
+};
+struct EqualClangTidyError {
+  bool operator()(const ClangTidyError &LHS, const ClangTidyError &RHS) const {
+    LessClangTidyError Less;
+    return !Less(LHS, RHS) && !Less(RHS, LHS);
+  }
+};
+} // end anonymous namespace
+
+// Flushes the internal diagnostics buffer to the ClangTidyContext.
+void ClangTidyDiagnosticConsumer::finish() {
+  finalizeLastError();
+
+  std::sort(Errors.begin(), Errors.end(), LessClangTidyError());
+  Errors.erase(std::unique(Errors.begin(), Errors.end(), EqualClangTidyError()),
+               Errors.end());
+
+  if (RemoveIncompatibleErrors)
+    removeIncompatibleErrors(Errors);
+
+  for (const ClangTidyError &Error : Errors)
+    Context.storeError(Error);
+  Errors.clear();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
new file mode 100644
index 0000000..ae25013
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -0,0 +1,276 @@
+//===--- ClangTidyDiagnosticConsumer.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_CLANGTIDYDIAGNOSTICCONSUMER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H
+
+#include "ClangTidyOptions.h"
+#include "ClangTidyProfiling.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Tooling/Core/Diagnostic.h"
+#include "clang/Tooling/Refactoring.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/Timer.h"
+
+namespace clang {
+
+class ASTContext;
+class CompilerInstance;
+namespace ast_matchers {
+class MatchFinder;
+}
+namespace tooling {
+class CompilationDatabase;
+}
+
+namespace tidy {
+
+/// \brief A detected error complete with information to display diagnostic and
+/// automatic fix.
+///
+/// This is used as an intermediate format to transport Diagnostics without a
+/// dependency on a SourceManager.
+///
+/// FIXME: Make Diagnostics flexible enough to support this directly.
+struct ClangTidyError : tooling::Diagnostic {
+  ClangTidyError(StringRef CheckName, Level DiagLevel, StringRef BuildDirectory,
+                 bool IsWarningAsError);
+
+  bool IsWarningAsError;
+};
+
+/// \brief Read-only set of strings represented as a list of positive and
+/// negative globs. Positive globs add all matched strings to the set, negative
+/// globs remove them in the order of appearance in the list.
+class GlobList {
+public:
+  /// \brief \p GlobList is a comma-separated list of globs (only '*'
+  /// metacharacter is supported) with optional '-' prefix to denote exclusion.
+  GlobList(StringRef Globs);
+
+  /// \brief Returns \c true if the pattern matches \p S. The result is the last
+  /// matching glob's Positive flag.
+  bool contains(StringRef S) { return contains(S, false); }
+
+private:
+  bool contains(StringRef S, bool Contains);
+
+  bool Positive;
+  llvm::Regex Regex;
+  std::unique_ptr<GlobList> NextGlob;
+};
+
+/// \brief Contains displayed and ignored diagnostic counters for a ClangTidy
+/// run.
+struct ClangTidyStats {
+  ClangTidyStats()
+      : ErrorsDisplayed(0), ErrorsIgnoredCheckFilter(0), ErrorsIgnoredNOLINT(0),
+        ErrorsIgnoredNonUserCode(0), ErrorsIgnoredLineFilter(0) {}
+
+  unsigned ErrorsDisplayed;
+  unsigned ErrorsIgnoredCheckFilter;
+  unsigned ErrorsIgnoredNOLINT;
+  unsigned ErrorsIgnoredNonUserCode;
+  unsigned ErrorsIgnoredLineFilter;
+
+  unsigned errorsIgnored() const {
+    return ErrorsIgnoredNOLINT + ErrorsIgnoredCheckFilter +
+           ErrorsIgnoredNonUserCode + ErrorsIgnoredLineFilter;
+  }
+};
+
+/// \brief Every \c ClangTidyCheck reports errors through a \c DiagnosticsEngine
+/// provided by this context.
+///
+/// A \c ClangTidyCheck always has access to the active context to report
+/// warnings like:
+/// \code
+/// Context->Diag(Loc, "Single-argument constructors must be explicit")
+///     << FixItHint::CreateInsertion(Loc, "explicit ");
+/// \endcode
+class ClangTidyContext {
+public:
+  /// \brief Initializes \c ClangTidyContext instance.
+  ClangTidyContext(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
+                   bool AllowEnablingAnalyzerAlphaCheckers = false);
+
+  ~ClangTidyContext();
+
+  /// \brief Report any errors detected using this method.
+  ///
+  /// This is still under heavy development and will likely change towards using
+  /// tablegen'd diagnostic IDs.
+  /// FIXME: Figure out a way to manage ID spaces.
+  DiagnosticBuilder diag(StringRef CheckName, SourceLocation Loc,
+                         StringRef Message,
+                         DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
+
+  /// \brief Sets the \c SourceManager of the used \c DiagnosticsEngine.
+  ///
+  /// This is called from the \c ClangTidyCheck base class.
+  void setSourceManager(SourceManager *SourceMgr);
+
+  /// \brief Should be called when starting to process new translation unit.
+  void setCurrentFile(StringRef File);
+
+  /// \brief Returns the main file name of the current translation unit.
+  StringRef getCurrentFile() const { return CurrentFile; }
+
+  /// \brief Sets ASTContext for the current translation unit.
+  void setASTContext(ASTContext *Context);
+
+  /// \brief Gets the language options from the AST context.
+  const LangOptions &getLangOpts() const { return LangOpts; }
+
+  /// \brief Returns the name of the clang-tidy check which produced this
+  /// diagnostic ID.
+  StringRef getCheckName(unsigned DiagnosticID) const;
+
+  /// \brief Returns \c true if the check is enabled for the \c CurrentFile.
+  ///
+  /// The \c CurrentFile can be changed using \c setCurrentFile.
+  bool isCheckEnabled(StringRef CheckName) const;
+
+  /// \brief Returns \c true if the check should be upgraded to error for the
+  /// \c CurrentFile.
+  bool treatAsError(StringRef CheckName) const;
+
+  /// \brief Returns global options.
+  const ClangTidyGlobalOptions &getGlobalOptions() const;
+
+  /// \brief Returns options for \c CurrentFile.
+  ///
+  /// The \c CurrentFile can be changed using \c setCurrentFile.
+  const ClangTidyOptions &getOptions() const;
+
+  /// \brief Returns options for \c File. Does not change or depend on
+  /// \c CurrentFile.
+  ClangTidyOptions getOptionsForFile(StringRef File) const;
+
+  /// \brief Returns \c ClangTidyStats containing issued and ignored diagnostic
+  /// counters.
+  const ClangTidyStats &getStats() const { return Stats; }
+
+  /// \brief Returns all collected errors.
+  ArrayRef<ClangTidyError> getErrors() const { return Errors; }
+
+  /// \brief Clears collected errors.
+  void clearErrors() { Errors.clear(); }
+
+  /// \brief Control profile collection in clang-tidy.
+  void setEnableProfiling(bool Profile);
+  bool getEnableProfiling() const { return Profile; }
+
+  /// \brief Control storage of profile date.
+  void setProfileStoragePrefix(StringRef ProfilePrefix);
+  llvm::Optional<ClangTidyProfiling::StorageParams>
+  getProfileStorageParams() const;
+
+  /// \brief Should be called when starting to process new translation unit.
+  void setCurrentBuildDirectory(StringRef BuildDirectory) {
+    CurrentBuildDirectory = BuildDirectory;
+  }
+
+  /// \brief Returns build directory of the current translation unit.
+  const std::string &getCurrentBuildDirectory() {
+    return CurrentBuildDirectory;
+  }
+
+  /// \brief If the experimental alpha checkers from the static analyzer can be
+  /// enabled.
+  bool canEnableAnalyzerAlphaCheckers() const {
+    return AllowEnablingAnalyzerAlphaCheckers;
+  }
+
+private:
+  // Calls setDiagnosticsEngine() and storeError().
+  friend class ClangTidyDiagnosticConsumer;
+  friend class ClangTidyPluginAction;
+
+  /// \brief Sets the \c DiagnosticsEngine so that Diagnostics can be generated
+  /// correctly.
+  void setDiagnosticsEngine(DiagnosticsEngine *Engine);
+
+  /// \brief Store an \p Error.
+  void storeError(const ClangTidyError &Error);
+
+  std::vector<ClangTidyError> Errors;
+  DiagnosticsEngine *DiagEngine;
+  std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider;
+
+  std::string CurrentFile;
+  ClangTidyOptions CurrentOptions;
+  class CachedGlobList;
+  std::unique_ptr<CachedGlobList> CheckFilter;
+  std::unique_ptr<CachedGlobList> WarningAsErrorFilter;
+
+  LangOptions LangOpts;
+
+  ClangTidyStats Stats;
+
+  std::string CurrentBuildDirectory;
+
+  llvm::DenseMap<unsigned, std::string> CheckNamesByDiagnosticID;
+
+  bool Profile;
+  std::string ProfilePrefix;
+
+  bool AllowEnablingAnalyzerAlphaCheckers;
+};
+
+/// \brief A diagnostic consumer that turns each \c Diagnostic into a
+/// \c SourceManager-independent \c ClangTidyError.
+//
+// FIXME: If we move away from unit-tests, this can be moved to a private
+// implementation file.
+class ClangTidyDiagnosticConsumer : public DiagnosticConsumer {
+public:
+  ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx,
+                              bool RemoveIncompatibleErrors = true);
+
+  // FIXME: The concept of converting between FixItHints and Replacements is
+  // more generic and should be pulled out into a more useful Diagnostics
+  // library.
+  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+                        const Diagnostic &Info) override;
+
+  /// \brief Flushes the internal diagnostics buffer to the ClangTidyContext.
+  void finish() override;
+
+private:
+  void finalizeLastError();
+
+  void removeIncompatibleErrors(SmallVectorImpl<ClangTidyError> &Errors) const;
+
+  /// \brief Returns the \c HeaderFilter constructed for the options set in the
+  /// context.
+  llvm::Regex *getHeaderFilter();
+
+  /// \brief Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
+  /// according to the diagnostic \p Location.
+  void checkFilters(SourceLocation Location);
+  bool passesLineFilter(StringRef FileName, unsigned LineNumber) const;
+
+  ClangTidyContext &Context;
+  bool RemoveIncompatibleErrors;
+  std::unique_ptr<DiagnosticsEngine> Diags;
+  SmallVector<ClangTidyError, 8> Errors;
+  std::unique_ptr<llvm::Regex> HeaderFilter;
+  bool LastErrorRelatesToUserCode;
+  bool LastErrorPassesLineFilter;
+  bool LastErrorWasIgnored;
+};
+
+} // end namespace tidy
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyModule.cpp
new file mode 100644
index 0000000..9dbf016
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyModule.cpp
@@ -0,0 +1,38 @@
+//===--- tools/extra/clang-tidy/ClangTidyModule.cpp - Clang tidy tool -----===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+///  \file Implements classes required to build clang-tidy modules.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ClangTidyModule.h"
+
+namespace clang {
+namespace tidy {
+
+void ClangTidyCheckFactories::registerCheckFactory(StringRef Name,
+                                                   CheckFactory Factory) {
+  Factories[Name] = std::move(Factory);
+}
+
+void ClangTidyCheckFactories::createChecks(
+    ClangTidyContext *Context,
+    std::vector<std::unique_ptr<ClangTidyCheck>> &Checks) {
+  for (const auto &Factory : Factories) {
+    if (Context->isCheckEnabled(Factory.first))
+      Checks.emplace_back(Factory.second(Factory.first, Context));
+  }
+}
+
+ClangTidyOptions ClangTidyModule::getModuleOptions() {
+  return ClangTidyOptions();
+}
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyModule.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyModule.h
new file mode 100644
index 0000000..4721636
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyModule.h
@@ -0,0 +1,99 @@
+//===--- ClangTidyModule.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_CLANGTIDYMODULE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULE_H
+
+#include "ClangTidy.h"
+#include "llvm/ADT/StringRef.h"
+#include <functional>
+#include <map>
+#include <string>
+#include <utility>
+
+namespace clang {
+namespace tidy {
+
+/// \brief A collection of \c ClangTidyCheckFactory instances.
+///
+/// All clang-tidy modules register their check factories with an instance of
+/// this object.
+class ClangTidyCheckFactories {
+public:
+  typedef std::function<ClangTidyCheck *(StringRef Name,
+                                         ClangTidyContext *Context)>
+      CheckFactory;
+
+  /// \brief Registers check \p Factory with name \p Name.
+  ///
+  /// For all checks that have default constructors, use \c registerCheck.
+  void registerCheckFactory(StringRef Name, CheckFactory Factory);
+
+  /// \brief Registers the \c CheckType with the name \p Name.
+  ///
+  /// This method should be used for all \c ClangTidyChecks that don't require
+  /// constructor parameters.
+  ///
+  /// For example, if have a clang-tidy check like:
+  /// \code
+  /// class MyTidyCheck : public ClangTidyCheck {
+  ///   void registerMatchers(ast_matchers::MatchFinder *Finder) override {
+  ///     ..
+  ///   }
+  /// };
+  /// \endcode
+  /// you can register it with:
+  /// \code
+  /// class MyModule : public ClangTidyModule {
+  ///   void addCheckFactories(ClangTidyCheckFactories &Factories) override {
+  ///     Factories.registerCheck<MyTidyCheck>("myproject-my-check");
+  ///   }
+  /// };
+  /// \endcode
+  template <typename CheckType> void registerCheck(StringRef CheckName) {
+    registerCheckFactory(CheckName,
+                         [](StringRef Name, ClangTidyContext *Context) {
+                           return new CheckType(Name, Context);
+                         });
+  }
+
+  /// \brief Create instances of all checks matching \p CheckRegexString and
+  /// store them in \p Checks.
+  ///
+  /// The caller takes ownership of the return \c ClangTidyChecks.
+  void createChecks(ClangTidyContext *Context,
+                    std::vector<std::unique_ptr<ClangTidyCheck>> &Checks);
+
+  typedef std::map<std::string, CheckFactory> FactoryMap;
+  FactoryMap::const_iterator begin() const { return Factories.begin(); }
+  FactoryMap::const_iterator end() const { return Factories.end(); }
+  bool empty() const { return Factories.empty(); }
+
+private:
+  FactoryMap Factories;
+};
+
+/// \brief A clang-tidy module groups a number of \c ClangTidyChecks and gives
+/// them a prefixed name.
+class ClangTidyModule {
+public:
+  virtual ~ClangTidyModule() {}
+
+  /// \brief Implement this function in order to register all \c CheckFactories
+  /// belonging to this module.
+  virtual void addCheckFactories(ClangTidyCheckFactories &CheckFactories) = 0;
+
+  /// \brief Gets default options for checks defined in this module.
+  virtual ClangTidyOptions getModuleOptions();
+};
+
+} // end namespace tidy
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyModuleRegistry.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyModuleRegistry.h
new file mode 100644
index 0000000..dc44d14
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyModuleRegistry.h
@@ -0,0 +1,24 @@
+//===--- ClangTidyModuleRegistry.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_CLANGTIDYMODULEREGISTRY_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULEREGISTRY_H
+
+#include "ClangTidyModule.h"
+#include "llvm/Support/Registry.h"
+
+namespace clang {
+namespace tidy {
+
+typedef llvm::Registry<ClangTidyModule> ClangTidyModuleRegistry;
+
+} // end namespace tidy
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULEREGISTRY_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
new file mode 100644
index 0000000..430f8b3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -0,0 +1,349 @@
+//===--- ClangTidyOptions.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 "ClangTidyOptions.h"
+#include "ClangTidyModuleRegistry.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+#include <utility>
+
+#define DEBUG_TYPE "clang-tidy-options"
+
+using clang::tidy::ClangTidyOptions;
+using clang::tidy::FileFilter;
+using OptionsSource = clang::tidy::ClangTidyOptionsProvider::OptionsSource;
+
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter::LineRange)
+
+namespace llvm {
+namespace yaml {
+
+// Map std::pair<int, int> to a JSON array of size 2.
+template <> struct SequenceTraits<FileFilter::LineRange> {
+  static size_t size(IO &IO, FileFilter::LineRange &Range) {
+    return Range.first == 0 ? 0 : Range.second == 0 ? 1 : 2;
+  }
+  static unsigned &element(IO &IO, FileFilter::LineRange &Range, size_t Index) {
+    if (Index > 1)
+      IO.setError("Too many elements in line range.");
+    return Index == 0 ? Range.first : Range.second;
+  }
+};
+
+template <> struct MappingTraits<FileFilter> {
+  static void mapping(IO &IO, FileFilter &File) {
+    IO.mapRequired("name", File.Name);
+    IO.mapOptional("lines", File.LineRanges);
+  }
+  static StringRef validate(IO &io, FileFilter &File) {
+    if (File.Name.empty())
+      return "No file name specified";
+    for (const FileFilter::LineRange &Range : File.LineRanges) {
+      if (Range.first <= 0 || Range.second <= 0)
+        return "Invalid line range";
+    }
+    return StringRef();
+  }
+};
+
+template <> struct MappingTraits<ClangTidyOptions::StringPair> {
+  static void mapping(IO &IO, ClangTidyOptions::StringPair &KeyValue) {
+    IO.mapRequired("key", KeyValue.first);
+    IO.mapRequired("value", KeyValue.second);
+  }
+};
+
+struct NOptionMap {
+  NOptionMap(IO &) {}
+  NOptionMap(IO &, const ClangTidyOptions::OptionMap &OptionMap)
+      : Options(OptionMap.begin(), OptionMap.end()) {}
+  ClangTidyOptions::OptionMap denormalize(IO &) {
+    ClangTidyOptions::OptionMap Map;
+    for (const auto &KeyValue : Options)
+      Map[KeyValue.first] = KeyValue.second;
+    return Map;
+  }
+  std::vector<ClangTidyOptions::StringPair> Options;
+};
+
+template <> struct MappingTraits<ClangTidyOptions> {
+  static void mapping(IO &IO, ClangTidyOptions &Options) {
+    MappingNormalization<NOptionMap, ClangTidyOptions::OptionMap> NOpts(
+        IO, Options.CheckOptions);
+    bool Ignored = false;
+    IO.mapOptional("Checks", Options.Checks);
+    IO.mapOptional("WarningsAsErrors", Options.WarningsAsErrors);
+    IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex);
+    IO.mapOptional("AnalyzeTemporaryDtors", Ignored); // legacy compatibility
+    IO.mapOptional("FormatStyle", Options.FormatStyle);
+    IO.mapOptional("User", Options.User);
+    IO.mapOptional("CheckOptions", NOpts->Options);
+    IO.mapOptional("ExtraArgs", Options.ExtraArgs);
+    IO.mapOptional("ExtraArgsBefore", Options.ExtraArgsBefore);
+  }
+};
+
+} // namespace yaml
+} // namespace llvm
+
+namespace clang {
+namespace tidy {
+
+ClangTidyOptions ClangTidyOptions::getDefaults() {
+  ClangTidyOptions Options;
+  Options.Checks = "";
+  Options.WarningsAsErrors = "";
+  Options.HeaderFilterRegex = "";
+  Options.SystemHeaders = false;
+  Options.FormatStyle = "none";
+  Options.User = llvm::None;
+  for (ClangTidyModuleRegistry::iterator I = ClangTidyModuleRegistry::begin(),
+                                         E = ClangTidyModuleRegistry::end();
+       I != E; ++I)
+    Options = Options.mergeWith(I->instantiate()->getModuleOptions());
+  return Options;
+}
+
+template <typename T>
+static void mergeVectors(Optional<T> &Dest, const Optional<T> &Src) {
+  if (Src) {
+    if (Dest)
+      Dest->insert(Dest->end(), Src->begin(), Src->end());
+    else
+      Dest = Src;
+  }
+}
+
+static void mergeCommaSeparatedLists(Optional<std::string> &Dest,
+                                     const Optional<std::string> &Src) {
+  if (Src)
+    Dest = (Dest && !Dest->empty() ? *Dest + "," : "") + *Src;
+}
+
+template <typename T>
+static void overrideValue(Optional<T> &Dest, const Optional<T> &Src) {
+  if (Src)
+    Dest = Src;
+}
+
+ClangTidyOptions
+ClangTidyOptions::mergeWith(const ClangTidyOptions &Other) const {
+  ClangTidyOptions Result = *this;
+
+  mergeCommaSeparatedLists(Result.Checks, Other.Checks);
+  mergeCommaSeparatedLists(Result.WarningsAsErrors, Other.WarningsAsErrors);
+  overrideValue(Result.HeaderFilterRegex, Other.HeaderFilterRegex);
+  overrideValue(Result.SystemHeaders, Other.SystemHeaders);
+  overrideValue(Result.FormatStyle, Other.FormatStyle);
+  overrideValue(Result.User, Other.User);
+  mergeVectors(Result.ExtraArgs, Other.ExtraArgs);
+  mergeVectors(Result.ExtraArgsBefore, Other.ExtraArgsBefore);
+
+  for (const auto &KeyValue : Other.CheckOptions)
+    Result.CheckOptions[KeyValue.first] = KeyValue.second;
+
+  return Result;
+}
+
+const char ClangTidyOptionsProvider::OptionsSourceTypeDefaultBinary[] =
+    "clang-tidy binary";
+const char ClangTidyOptionsProvider::OptionsSourceTypeCheckCommandLineOption[] =
+    "command-line option '-checks'";
+const char
+    ClangTidyOptionsProvider::OptionsSourceTypeConfigCommandLineOption[] =
+        "command-line option '-config'";
+
+ClangTidyOptions
+ClangTidyOptionsProvider::getOptions(llvm::StringRef FileName) {
+  ClangTidyOptions Result;
+  for (const auto &Source : getRawOptions(FileName))
+    Result = Result.mergeWith(Source.first);
+  return Result;
+}
+
+std::vector<OptionsSource>
+DefaultOptionsProvider::getRawOptions(llvm::StringRef FileName) {
+  std::vector<OptionsSource> Result;
+  Result.emplace_back(DefaultOptions, OptionsSourceTypeDefaultBinary);
+  return Result;
+}
+
+ConfigOptionsProvider::ConfigOptionsProvider(
+    const ClangTidyGlobalOptions &GlobalOptions,
+    const ClangTidyOptions &DefaultOptions,
+    const ClangTidyOptions &ConfigOptions,
+    const ClangTidyOptions &OverrideOptions)
+    : DefaultOptionsProvider(GlobalOptions, DefaultOptions),
+      ConfigOptions(ConfigOptions), OverrideOptions(OverrideOptions) {}
+
+std::vector<OptionsSource>
+ConfigOptionsProvider::getRawOptions(llvm::StringRef FileName) {
+  std::vector<OptionsSource> RawOptions =
+      DefaultOptionsProvider::getRawOptions(FileName);
+  RawOptions.emplace_back(ConfigOptions,
+                          OptionsSourceTypeConfigCommandLineOption);
+  RawOptions.emplace_back(OverrideOptions,
+                          OptionsSourceTypeCheckCommandLineOption);
+  return RawOptions;
+}
+
+FileOptionsProvider::FileOptionsProvider(
+    const ClangTidyGlobalOptions &GlobalOptions,
+    const ClangTidyOptions &DefaultOptions,
+    const ClangTidyOptions &OverrideOptions,
+    llvm::IntrusiveRefCntPtr<vfs::FileSystem> VFS)
+    : DefaultOptionsProvider(GlobalOptions, DefaultOptions),
+      OverrideOptions(OverrideOptions), FS(std::move(VFS)) {
+  if (!FS)
+    FS = vfs::getRealFileSystem();
+  ConfigHandlers.emplace_back(".clang-tidy", parseConfiguration);
+}
+
+FileOptionsProvider::FileOptionsProvider(
+    const ClangTidyGlobalOptions &GlobalOptions,
+    const ClangTidyOptions &DefaultOptions,
+    const ClangTidyOptions &OverrideOptions,
+    const FileOptionsProvider::ConfigFileHandlers &ConfigHandlers)
+    : DefaultOptionsProvider(GlobalOptions, DefaultOptions),
+      OverrideOptions(OverrideOptions), ConfigHandlers(ConfigHandlers) {}
+
+// FIXME: This method has some common logic with clang::format::getStyle().
+// Consider pulling out common bits to a findParentFileWithName function or
+// similar.
+std::vector<OptionsSource>
+FileOptionsProvider::getRawOptions(StringRef FileName) {
+  LLVM_DEBUG(llvm::dbgs() << "Getting options for file " << FileName
+                          << "...\n");
+  assert(FS && "FS must be set.");
+
+  llvm::SmallString<128> AbsoluteFilePath(FileName);
+
+  if (FS->makeAbsolute(AbsoluteFilePath))
+    return {};
+
+  std::vector<OptionsSource> RawOptions =
+      DefaultOptionsProvider::getRawOptions(AbsoluteFilePath.str());
+  OptionsSource CommandLineOptions(OverrideOptions,
+                                   OptionsSourceTypeCheckCommandLineOption);
+  // Look for a suitable configuration file in all parent directories of the
+  // file. Start with the immediate parent directory and move up.
+  StringRef Path = llvm::sys::path::parent_path(AbsoluteFilePath.str());
+  for (StringRef CurrentPath = Path; !CurrentPath.empty();
+       CurrentPath = llvm::sys::path::parent_path(CurrentPath)) {
+    llvm::Optional<OptionsSource> Result;
+
+    auto Iter = CachedOptions.find(CurrentPath);
+    if (Iter != CachedOptions.end())
+      Result = Iter->second;
+
+    if (!Result)
+      Result = tryReadConfigFile(CurrentPath);
+
+    if (Result) {
+      // Store cached value for all intermediate directories.
+      while (Path != CurrentPath) {
+        LLVM_DEBUG(llvm::dbgs()
+                   << "Caching configuration for path " << Path << ".\n");
+        CachedOptions[Path] = *Result;
+        Path = llvm::sys::path::parent_path(Path);
+      }
+      CachedOptions[Path] = *Result;
+
+      RawOptions.push_back(*Result);
+      break;
+    }
+  }
+  RawOptions.push_back(CommandLineOptions);
+  return RawOptions;
+}
+
+llvm::Optional<OptionsSource>
+FileOptionsProvider::tryReadConfigFile(StringRef Directory) {
+  assert(!Directory.empty());
+
+  if (!llvm::sys::fs::is_directory(Directory)) {
+    llvm::errs() << "Error reading configuration from " << Directory
+                 << ": directory doesn't exist.\n";
+    return llvm::None;
+  }
+
+  for (const ConfigFileHandler &ConfigHandler : ConfigHandlers) {
+    SmallString<128> ConfigFile(Directory);
+    llvm::sys::path::append(ConfigFile, ConfigHandler.first);
+    LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
+
+    bool IsFile = false;
+    // Ignore errors from is_regular_file: we only need to know if we can read
+    // the file or not.
+    llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile);
+    if (!IsFile)
+      continue;
+
+    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
+        llvm::MemoryBuffer::getFile(ConfigFile.c_str());
+    if (std::error_code EC = Text.getError()) {
+      llvm::errs() << "Can't read " << ConfigFile << ": " << EC.message()
+                   << "\n";
+      continue;
+    }
+
+    // Skip empty files, e.g. files opened for writing via shell output
+    // redirection.
+    if ((*Text)->getBuffer().empty())
+      continue;
+    llvm::ErrorOr<ClangTidyOptions> ParsedOptions =
+        ConfigHandler.second((*Text)->getBuffer());
+    if (!ParsedOptions) {
+      if (ParsedOptions.getError())
+        llvm::errs() << "Error parsing " << ConfigFile << ": "
+                     << ParsedOptions.getError().message() << "\n";
+      continue;
+    }
+    return OptionsSource(*ParsedOptions, ConfigFile.c_str());
+  }
+  return llvm::None;
+}
+
+/// \brief Parses -line-filter option and stores it to the \c Options.
+std::error_code parseLineFilter(StringRef LineFilter,
+                                clang::tidy::ClangTidyGlobalOptions &Options) {
+  llvm::yaml::Input Input(LineFilter);
+  Input >> Options.LineFilter;
+  return Input.error();
+}
+
+llvm::ErrorOr<ClangTidyOptions> parseConfiguration(StringRef Config) {
+  llvm::yaml::Input Input(Config);
+  ClangTidyOptions Options;
+  Input >> Options;
+  if (Input.error())
+    return Input.error();
+  return Options;
+}
+
+std::string configurationAsText(const ClangTidyOptions &Options) {
+  std::string Text;
+  llvm::raw_string_ostream Stream(Text);
+  llvm::yaml::Output Output(Stream);
+  // We use the same mapping method for input and output, so we need a non-const
+  // reference here.
+  ClangTidyOptions NonConstValue = Options;
+  Output << NonConstValue;
+  return Stream.str();
+}
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyOptions.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyOptions.h
new file mode 100644
index 0000000..b2a4ce4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyOptions.h
@@ -0,0 +1,275 @@
+//===--- ClangTidyOptions.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_CLANGTIDYOPTIONS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYOPTIONS_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/ErrorOr.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include <functional>
+#include <map>
+#include <string>
+#include <system_error>
+#include <utility>
+#include <vector>
+
+namespace clang {
+namespace tidy {
+
+/// \brief Contains a list of line ranges in a single file.
+struct FileFilter {
+  /// \brief File name.
+  std::string Name;
+
+  /// \brief LineRange is a pair<start, end> (inclusive).
+  typedef std::pair<unsigned, unsigned> LineRange;
+
+  /// \brief A list of line ranges in this file, for which we show warnings.
+  std::vector<LineRange> LineRanges;
+};
+
+/// \brief Global options. These options are neither stored nor read from
+/// configuration files.
+struct ClangTidyGlobalOptions {
+  /// \brief Output warnings from certain line ranges of certain files only.
+  /// If empty, no warnings will be filtered.
+  std::vector<FileFilter> LineFilter;
+};
+
+/// \brief Contains options for clang-tidy. These options may be read from
+/// configuration files, and may be different for different translation units.
+struct ClangTidyOptions {
+  /// \brief These options are used for all settings that haven't been
+  /// overridden by the \c OptionsProvider.
+  ///
+  /// Allow no checks and no headers by default. This method initializes
+  /// check-specific options by calling \c ClangTidyModule::getModuleOptions()
+  /// of each registered \c ClangTidyModule.
+  static ClangTidyOptions getDefaults();
+
+  /// \brief Creates a new \c ClangTidyOptions instance combined from all fields
+  /// of this instance overridden by the fields of \p Other that have a value.
+  ClangTidyOptions mergeWith(const ClangTidyOptions &Other) const;
+
+  /// \brief Checks filter.
+  llvm::Optional<std::string> Checks;
+
+  /// \brief WarningsAsErrors filter.
+  llvm::Optional<std::string> WarningsAsErrors;
+
+  /// \brief Output warnings from headers matching this filter. Warnings from
+  /// main files will always be displayed.
+  llvm::Optional<std::string> HeaderFilterRegex;
+
+  /// \brief Output warnings from system headers matching \c HeaderFilterRegex.
+  llvm::Optional<bool> SystemHeaders;
+
+  /// \brief Format code around applied fixes with clang-format using this
+  /// style.
+  ///
+  /// Can be one of:
+  ///   * 'none' - don't format code around applied fixes;
+  ///   * 'llvm', 'google', 'mozilla' or other predefined clang-format style
+  ///     names;
+  ///   * 'file' - use the .clang-format file in the closest parent directory of
+  ///     each source file;
+  ///   * '{inline-formatting-style-in-yaml-format}'.
+  ///
+  /// See clang-format documentation for more about configuring format style.
+  llvm::Optional<std::string> FormatStyle;
+
+  /// \brief Specifies the name or e-mail of the user running clang-tidy.
+  ///
+  /// This option is used, for example, to place the correct user name in TODO()
+  /// comments in the relevant check.
+  llvm::Optional<std::string> User;
+
+  typedef std::pair<std::string, std::string> StringPair;
+  typedef std::map<std::string, std::string> OptionMap;
+
+  /// \brief Key-value mapping used to store check-specific options.
+  OptionMap CheckOptions;
+
+  typedef std::vector<std::string> ArgList;
+
+  /// \brief Add extra compilation arguments to the end of the list.
+  llvm::Optional<ArgList> ExtraArgs;
+
+  /// \brief Add extra compilation arguments to the start of the list.
+  llvm::Optional<ArgList> ExtraArgsBefore;
+};
+
+/// \brief Abstract interface for retrieving various ClangTidy options.
+class ClangTidyOptionsProvider {
+public:
+  static const char OptionsSourceTypeDefaultBinary[];
+  static const char OptionsSourceTypeCheckCommandLineOption[];
+  static const char OptionsSourceTypeConfigCommandLineOption[];
+
+  virtual ~ClangTidyOptionsProvider() {}
+
+  /// \brief Returns global options, which are independent of the file.
+  virtual const ClangTidyGlobalOptions &getGlobalOptions() = 0;
+
+  /// \brief ClangTidyOptions and its source.
+  //
+  /// clang-tidy has 3 types of the sources in order of increasing priority:
+  ///    * clang-tidy binary.
+  ///    * '-config' commandline option or a specific configuration file. If the
+  ///       commandline option is specified, clang-tidy will ignore the
+  ///       configuration file.
+  ///    * '-checks' commandline option.
+  typedef std::pair<ClangTidyOptions, std::string> OptionsSource;
+
+  /// \brief Returns an ordered vector of OptionsSources, in order of increasing
+  /// priority.
+  virtual std::vector<OptionsSource>
+  getRawOptions(llvm::StringRef FileName) = 0;
+
+  /// \brief Returns options applying to a specific translation unit with the
+  /// specified \p FileName.
+  ClangTidyOptions getOptions(llvm::StringRef FileName);
+};
+
+/// \brief Implementation of the \c ClangTidyOptionsProvider interface, which
+/// returns the same options for all files.
+class DefaultOptionsProvider : public ClangTidyOptionsProvider {
+public:
+  DefaultOptionsProvider(const ClangTidyGlobalOptions &GlobalOptions,
+                         const ClangTidyOptions &Options)
+      : GlobalOptions(GlobalOptions), DefaultOptions(Options) {}
+  const ClangTidyGlobalOptions &getGlobalOptions() override {
+    return GlobalOptions;
+  }
+  std::vector<OptionsSource> getRawOptions(llvm::StringRef FileName) override;
+
+private:
+  ClangTidyGlobalOptions GlobalOptions;
+  ClangTidyOptions DefaultOptions;
+};
+
+/// \brief Implementation of ClangTidyOptions interface, which is used for
+/// '-config' command-line option.
+class ConfigOptionsProvider : public DefaultOptionsProvider {
+public:
+  ConfigOptionsProvider(const ClangTidyGlobalOptions &GlobalOptions,
+                        const ClangTidyOptions &DefaultOptions,
+                        const ClangTidyOptions &ConfigOptions,
+                        const ClangTidyOptions &OverrideOptions);
+  std::vector<OptionsSource> getRawOptions(llvm::StringRef FileName) override;
+
+private:
+  ClangTidyOptions ConfigOptions;
+  ClangTidyOptions OverrideOptions;
+};
+
+/// \brief Implementation of the \c ClangTidyOptionsProvider interface, which
+/// tries to find a configuration file in the closest parent directory of each
+/// source file.
+///
+/// By default, files named ".clang-tidy" will be considered, and the
+/// \c clang::tidy::parseConfiguration function will be used for parsing, but a
+/// custom set of configuration file names and parsing functions can be
+/// specified using the appropriate constructor.
+class FileOptionsProvider : public DefaultOptionsProvider {
+public:
+  // \brief A pair of configuration file base name and a function parsing
+  // configuration from text in the corresponding format.
+  typedef std::pair<std::string, std::function<llvm::ErrorOr<ClangTidyOptions>(
+                                     llvm::StringRef)>>
+      ConfigFileHandler;
+
+  /// \brief Configuration file handlers listed in the order of priority.
+  ///
+  /// Custom configuration file formats can be supported by constructing the
+  /// list of handlers and passing it to the appropriate \c FileOptionsProvider
+  /// constructor. E.g. initialization of a \c FileOptionsProvider with support
+  /// of a custom configuration file format for files named ".my-tidy-config"
+  /// could look similar to this:
+  /// \code
+  /// FileOptionsProvider::ConfigFileHandlers ConfigHandlers;
+  /// ConfigHandlers.emplace_back(".my-tidy-config", parseMyConfigFormat);
+  /// ConfigHandlers.emplace_back(".clang-tidy", parseConfiguration);
+  /// return llvm::make_unique<FileOptionsProvider>(
+  ///     GlobalOptions, DefaultOptions, OverrideOptions, ConfigHandlers);
+  /// \endcode
+  ///
+  /// With the order of handlers shown above, the ".my-tidy-config" file would
+  /// take precedence over ".clang-tidy" if both reside in the same directory.
+  typedef std::vector<ConfigFileHandler> ConfigFileHandlers;
+
+  /// \brief Initializes the \c FileOptionsProvider instance.
+  ///
+  /// \param GlobalOptions are just stored and returned to the caller of
+  /// \c getGlobalOptions.
+  ///
+  /// \param DefaultOptions are used for all settings not specified in a
+  /// configuration file.
+  ///
+  /// If any of the \param OverrideOptions fields are set, they will override
+  /// whatever options are read from the configuration file.
+  FileOptionsProvider(const ClangTidyGlobalOptions &GlobalOptions,
+                      const ClangTidyOptions &DefaultOptions,
+                      const ClangTidyOptions &OverrideOptions,
+                      llvm::IntrusiveRefCntPtr<vfs::FileSystem> FS = nullptr);
+
+  /// \brief Initializes the \c FileOptionsProvider instance with a custom set
+  /// of configuration file handlers.
+  ///
+  /// \param GlobalOptions are just stored and returned to the caller of
+  /// \c getGlobalOptions.
+  ///
+  /// \param DefaultOptions are used for all settings not specified in a
+  /// configuration file.
+  ///
+  /// If any of the \param OverrideOptions fields are set, they will override
+  /// whatever options are read from the configuration file.
+  ///
+  /// \param ConfigHandlers specifies a custom set of configuration file
+  /// handlers. Each handler is a pair of configuration file name and a function
+  /// that can parse configuration from this file type. The configuration files
+  /// in each directory are searched for in the order of appearance in
+  /// \p ConfigHandlers.
+  FileOptionsProvider(const ClangTidyGlobalOptions &GlobalOptions,
+                      const ClangTidyOptions &DefaultOptions,
+                      const ClangTidyOptions &OverrideOptions,
+                      const ConfigFileHandlers &ConfigHandlers);
+
+  std::vector<OptionsSource> getRawOptions(llvm::StringRef FileName) override;
+
+protected:
+  /// \brief Try to read configuration files from \p Directory using registered
+  /// \c ConfigHandlers.
+  llvm::Optional<OptionsSource> tryReadConfigFile(llvm::StringRef Directory);
+
+  llvm::StringMap<OptionsSource> CachedOptions;
+  ClangTidyOptions OverrideOptions;
+  ConfigFileHandlers ConfigHandlers;
+  llvm::IntrusiveRefCntPtr<vfs::FileSystem> FS;
+};
+
+/// \brief Parses LineFilter from JSON and stores it to the \p Options.
+std::error_code parseLineFilter(llvm::StringRef LineFilter,
+                                ClangTidyGlobalOptions &Options);
+
+/// \brief Parses configuration from JSON and returns \c ClangTidyOptions or an
+/// error.
+llvm::ErrorOr<ClangTidyOptions> parseConfiguration(llvm::StringRef Config);
+
+/// \brief Serializes configuration to a YAML-encoded string.
+std::string configurationAsText(const ClangTidyOptions &Options);
+
+} // end namespace tidy
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYOPTIONS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyProfiling.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyProfiling.cpp
new file mode 100644
index 0000000..fc0a969
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyProfiling.cpp
@@ -0,0 +1,93 @@
+//===--- ClangTidyProfiling.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 "ClangTidyProfiling.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+#include <system_error>
+#include <utility>
+
+#define DEBUG_TYPE "clang-tidy-profiling"
+
+namespace clang {
+namespace tidy {
+
+ClangTidyProfiling::StorageParams::StorageParams(llvm::StringRef ProfilePrefix,
+                                                 llvm::StringRef SourceFile)
+    : Timestamp(std::chrono::system_clock::now()), SourceFilename(SourceFile) {
+  llvm::SmallString<32> TimestampStr;
+  llvm::raw_svector_ostream OS(TimestampStr);
+  llvm::format_provider<decltype(Timestamp)>::format(Timestamp, OS,
+                                                     "%Y%m%d%H%M%S%N");
+
+  llvm::SmallString<256> FinalPrefix(ProfilePrefix);
+  llvm::sys::path::append(FinalPrefix, TimestampStr);
+
+  // So the full output name is: /ProfilePrefix/timestamp-inputfilename.json
+  StoreFilename = llvm::Twine(FinalPrefix + "-" +
+                              llvm::sys::path::filename(SourceFile) + ".json")
+                      .str();
+}
+
+void ClangTidyProfiling::printUserFriendlyTable(llvm::raw_ostream &OS) {
+  TG->print(OS);
+  OS.flush();
+}
+
+void ClangTidyProfiling::printAsJSON(llvm::raw_ostream &OS) {
+  OS << "{\n";
+  OS << "\"file\": \"" << Storage->SourceFilename << "\",\n";
+  OS << "\"timestamp\": \"" << Storage->Timestamp << "\",\n";
+  OS << "\"profile\": {\n";
+  TG->printJSONValues(OS, "");
+  OS << "\n}\n";
+  OS << "}\n";
+  OS.flush();
+}
+
+void ClangTidyProfiling::storeProfileData() {
+  assert(Storage.hasValue() && "We should have a filename.");
+
+  llvm::SmallString<256> OutputDirectory(Storage->StoreFilename);
+  llvm::sys::path::remove_filename(OutputDirectory);
+  if (std::error_code EC = llvm::sys::fs::create_directories(OutputDirectory)) {
+    llvm::errs() << "Unable to create output directory '" << OutputDirectory
+                 << "': " << EC.message() << "\n";
+    return;
+  }
+
+  std::error_code EC;
+  llvm::raw_fd_ostream OS(Storage->StoreFilename, EC, llvm::sys::fs::F_None);
+  if (EC) {
+    llvm::errs() << "Error opening output file '" << Storage->StoreFilename
+                 << "': " << EC.message() << "\n";
+    return;
+  }
+
+  printAsJSON(OS);
+}
+
+ClangTidyProfiling::ClangTidyProfiling(llvm::Optional<StorageParams> Storage)
+    : Storage(std::move(Storage)) {}
+
+ClangTidyProfiling::~ClangTidyProfiling() {
+  TG.emplace("clang-tidy", "clang-tidy checks profiling", Records);
+
+  if (!Storage.hasValue())
+    printUserFriendlyTable(llvm::errs());
+  else
+    storeProfileData();
+}
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyProfiling.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyProfiling.h
new file mode 100644
index 0000000..9d86b8e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/ClangTidyProfiling.h
@@ -0,0 +1,60 @@
+//===--- ClangTidyProfiling.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_CLANGTIDYPROFILING_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYPROFILING_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace clang {
+namespace tidy {
+
+class ClangTidyProfiling {
+public:
+  struct StorageParams {
+    llvm::sys::TimePoint<> Timestamp;
+    std::string SourceFilename;
+    std::string StoreFilename;
+
+    StorageParams() = default;
+
+    StorageParams(llvm::StringRef ProfilePrefix, llvm::StringRef SourceFile);
+  };
+
+private:
+  llvm::Optional<llvm::TimerGroup> TG;
+
+  llvm::Optional<StorageParams> Storage;
+
+  void printUserFriendlyTable(llvm::raw_ostream &OS);
+  void printAsJSON(llvm::raw_ostream &OS);
+
+  void storeProfileData();
+
+public:
+  llvm::StringMap<llvm::TimeRecord> Records;
+
+  ClangTidyProfiling() = default;
+
+  ClangTidyProfiling(llvm::Optional<StorageParams> Storage);
+
+  ~ClangTidyProfiling();
+};
+
+} // end namespace tidy
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYPROFILING_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/abseil/AbseilTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/abseil/AbseilTidyModule.cpp
new file mode 100644
index 0000000..8e427f0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/abseil/AbseilTidyModule.cpp
@@ -0,0 +1,38 @@
+//===------- AbseilTidyModule.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 "StringFindStartswithCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+class AbseilModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<StringFindStartswithCheck>(
+        "abseil-string-find-startswith");
+  }
+};
+
+// Register the AbseilModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<AbseilModule> X("abseil-module",
+                                                    "Add Abseil checks.");
+
+} // namespace abseil
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the AbseilModule.
+volatile int AbseilModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/abseil/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/abseil/CMakeLists.txt
new file mode 100644
index 0000000..dd59dcf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/abseil/CMakeLists.txt
@@ -0,0 +1,14 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyAbseilModule
+  AbseilTidyModule.cpp
+  StringFindStartswithCheck.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyUtils
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
new file mode 100644
index 0000000..7a94c10
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
@@ -0,0 +1,136 @@
+//===--- StringFindStartswithCheck.cc - 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 "StringFindStartswithCheck.h"
+
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Frontend/CompilerInstance.h"
+
+#include <cassert>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+StringFindStartswithCheck::StringFindStartswithCheck(StringRef Name,
+                                                     ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      StringLikeClasses(utils::options::parseStringList(
+          Options.get("StringLikeClasses", "::std::basic_string"))),
+      IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
+          Options.getLocalOrGlobal("IncludeStyle", "llvm"))),
+      AbseilStringsMatchHeader(
+          Options.get("AbseilStringsMatchHeader", "absl/strings/match.h")) {}
+
+void StringFindStartswithCheck::registerMatchers(MatchFinder *Finder) {
+  auto ZeroLiteral = integerLiteral(equals(0));
+  auto StringClassMatcher = cxxRecordDecl(hasAnyName(SmallVector<StringRef, 4>(
+      StringLikeClasses.begin(), StringLikeClasses.end())));
+  auto StringType = hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(StringClassMatcher)));
+
+  auto StringFind = cxxMemberCallExpr(
+      // .find()-call on a string...
+      callee(cxxMethodDecl(hasName("find"))),
+      on(hasType(StringType)),
+      // ... with some search expression ...
+      hasArgument(0, expr().bind("needle")),
+      // ... and either "0" as second argument or the default argument (also 0).
+      anyOf(hasArgument(1, ZeroLiteral), hasArgument(1, cxxDefaultArgExpr())));
+
+  Finder->addMatcher(
+      // Match [=!]= with a zero on one side and a string.find on the other.
+      binaryOperator(
+          anyOf(hasOperatorName("=="), hasOperatorName("!=")),
+          hasEitherOperand(ignoringParenImpCasts(ZeroLiteral)),
+          hasEitherOperand(ignoringParenImpCasts(StringFind.bind("findexpr"))))
+          .bind("expr"),
+      this);
+}
+
+void StringFindStartswithCheck::check(const MatchFinder::MatchResult &Result) {
+  const ASTContext &Context = *Result.Context;
+  const SourceManager &Source = Context.getSourceManager();
+
+  // Extract matching (sub)expressions
+  const auto *ComparisonExpr = Result.Nodes.getNodeAs<BinaryOperator>("expr");
+  assert(ComparisonExpr != nullptr);
+  const auto *Needle = Result.Nodes.getNodeAs<Expr>("needle");
+  assert(Needle != nullptr);
+  const Expr *Haystack = Result.Nodes.getNodeAs<CXXMemberCallExpr>("findexpr")
+                             ->getImplicitObjectArgument();
+  assert(Haystack != nullptr);
+
+  if (ComparisonExpr->getLocStart().isMacroID())
+    return;
+
+  // Get the source code blocks (as characters) for both the string object
+  // and the search expression
+  const StringRef NeedleExprCode = Lexer::getSourceText(
+      CharSourceRange::getTokenRange(Needle->getSourceRange()), Source,
+      Context.getLangOpts());
+  const StringRef HaystackExprCode = Lexer::getSourceText(
+      CharSourceRange::getTokenRange(Haystack->getSourceRange()), Source,
+      Context.getLangOpts());
+
+  // Create the StartsWith string, negating if comparison was "!=".
+  bool Neg = ComparisonExpr->getOpcodeStr() == "!=";
+  StringRef StartswithStr;
+  if (Neg) {
+    StartswithStr = "!absl::StartsWith";
+  } else {
+    StartswithStr = "absl::StartsWith";
+  }
+
+  // Create the warning message and a FixIt hint replacing the original expr.
+  auto Diagnostic =
+      diag(ComparisonExpr->getLocStart(),
+           (StringRef("use ") + StartswithStr + " instead of find() " +
+            ComparisonExpr->getOpcodeStr() + " 0")
+               .str());
+
+  Diagnostic << FixItHint::CreateReplacement(
+      ComparisonExpr->getSourceRange(),
+      (StartswithStr + "(" + HaystackExprCode + ", " + NeedleExprCode + ")")
+          .str());
+
+  // Create a preprocessor #include FixIt hint (CreateIncludeInsertion checks
+  // whether this already exists).
+  auto IncludeHint = IncludeInserter->CreateIncludeInsertion(
+      Source.getFileID(ComparisonExpr->getLocStart()), AbseilStringsMatchHeader,
+      false);
+  if (IncludeHint) {
+    Diagnostic << *IncludeHint;
+  }
+}
+
+void StringFindStartswithCheck::registerPPCallbacks(
+    CompilerInstance &Compiler) {
+  IncludeInserter = llvm::make_unique<clang::tidy::utils::IncludeInserter>(
+      Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle);
+  Compiler.getPreprocessor().addPPCallbacks(
+      IncludeInserter->CreatePPCallbacks());
+}
+
+void StringFindStartswithCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "StringLikeClasses",
+                utils::options::serializeStringList(StringLikeClasses));
+  Options.store(Opts, "IncludeStyle",
+                utils::IncludeSorter::toString(IncludeStyle));
+  Options.store(Opts, "AbseilStringsMatchHeader", AbseilStringsMatchHeader);
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.h
new file mode 100644
index 0000000..1c04e80
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.h
@@ -0,0 +1,48 @@
+//===--- StringFindStartswithCheck.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_ABSEIL_STRINGFINDSTARTSWITHCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_STRINGFINDSTARTSWITHCHECK_H
+
+#include "../ClangTidy.h"
+#include "../utils/IncludeInserter.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+// Find string.find(...) == 0 comparisons and suggest replacing with StartsWith.
+// FIXME(niko): Add similar check for EndsWith
+// FIXME(niko): Add equivalent modernize checks for C++20's std::starts_With
+class StringFindStartswithCheck : public ClangTidyCheck {
+public:
+  using ClangTidyCheck::ClangTidyCheck;
+  StringFindStartswithCheck(StringRef Name, ClangTidyContext *Context);
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  std::unique_ptr<clang::tidy::utils::IncludeInserter> IncludeInserter;
+  const std::vector<std::string> StringLikeClasses;
+  const utils::IncludeSorter::IncludeStyle IncludeStyle;
+  const std::string AbseilStringsMatchHeader;
+};
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_STRINGFINDSTARTSWITHCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/add_new_check.py b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/add_new_check.py
new file mode 100755
index 0000000..4d811aa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/add_new_check.py
@@ -0,0 +1,368 @@
+#!/usr/bin/env python
+#
+#===- add_new_check.py - clang-tidy check generator ----------*- python -*--===#
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+from __future__ import print_function
+
+import argparse
+import os
+import re
+import sys
+
+# Adapts the module's CMakelist file. Returns 'True' if it could add a new entry
+# and 'False' if the entry already existed.
+def adapt_cmake(module_path, check_name_camel):
+  filename = os.path.join(module_path, 'CMakeLists.txt')
+  with open(filename, 'r') as f:
+    lines = f.readlines()
+
+  cpp_file = check_name_camel + '.cpp'
+
+  # Figure out whether this check already exists.
+  for line in lines:
+    if line.strip() == cpp_file:
+      return False
+
+  print('Updating %s...' % filename)
+  with open(filename, 'w') as f:
+    cpp_found = False
+    file_added = False
+    for line in lines:
+      cpp_line = line.strip().endswith('.cpp')
+      if (not file_added) and (cpp_line or cpp_found):
+        cpp_found = True
+        if (line.strip() > cpp_file) or (not cpp_line):
+          f.write('  ' + cpp_file + '\n')
+          file_added = True
+      f.write(line)
+
+  return True
+
+
+# Adds a header for the new check.
+def write_header(module_path, module, check_name, check_name_camel):
+  check_name_dashes = module + '-' + check_name
+  filename = os.path.join(module_path, check_name_camel) + '.h'
+  print('Creating %s...' % filename)
+  with open(filename, 'w') as f:
+    header_guard = ('LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_' + module.upper() + '_'
+                    + check_name_camel.upper() + '_H')
+    f.write('//===--- ')
+    f.write(os.path.basename(filename))
+    f.write(' - clang-tidy')
+    f.write('-' * max(0, 43 - len(os.path.basename(filename))))
+    f.write('*- C++ -*-===//')
+    f.write("""
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef %(header_guard)s
+#define %(header_guard)s
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace %(module)s {
+
+/// FIXME: Write a short description.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/%(check_name_dashes)s.html
+class %(check_name)s : public ClangTidyCheck {
+public:
+  %(check_name)s(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace %(module)s
+} // namespace tidy
+} // namespace clang
+
+#endif // %(header_guard)s
+""" % {'header_guard': header_guard,
+       'check_name': check_name_camel,
+       'check_name_dashes': check_name_dashes,
+       'module': module})
+
+
+# Adds the implementation of the new check.
+def write_implementation(module_path, module, check_name_camel):
+  filename = os.path.join(module_path, check_name_camel) + '.cpp'
+  print('Creating %s...' % filename)
+  with open(filename, 'w') as f:
+    f.write('//===--- ')
+    f.write(os.path.basename(filename))
+    f.write(' - clang-tidy')
+    f.write('-' * max(0, 52 - len(os.path.basename(filename))))
+    f.write('-===//')
+    f.write("""
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "%(check_name)s.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace %(module)s {
+
+void %(check_name)s::registerMatchers(MatchFinder *Finder) {
+  // FIXME: Add matchers.
+  Finder->addMatcher(functionDecl().bind("x"), this);
+}
+
+void %(check_name)s::check(const MatchFinder::MatchResult &Result) {
+  // FIXME: Add callback implementation.
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>("x");
+  if (MatchedDecl->getName().startswith("awesome_"))
+    return;
+  diag(MatchedDecl->getLocation(), "function %%0 is insufficiently awesome")
+      << MatchedDecl
+      << FixItHint::CreateInsertion(MatchedDecl->getLocation(), "awesome_");
+}
+
+} // namespace %(module)s
+} // namespace tidy
+} // namespace clang
+""" % {'check_name': check_name_camel,
+       'module': module})
+
+
+# Modifies the module to include the new check.
+def adapt_module(module_path, module, check_name, check_name_camel):
+  modulecpp = list(filter(
+      lambda p: p.lower() == module.lower() + 'tidymodule.cpp',
+      os.listdir(module_path)))[0]
+  filename = os.path.join(module_path, modulecpp)
+  with open(filename, 'r') as f:
+    lines = f.readlines()
+
+  print('Updating %s...' % filename)
+  with open(filename, 'w') as f:
+    header_added = False
+    header_found = False
+    check_added = False
+    check_decl = ('    CheckFactories.registerCheck<' + check_name_camel +
+                  '>(\n        "' + module + '-' + check_name + '");\n')
+
+    for line in lines:
+      if not header_added:
+        match = re.search('#include "(.*)"', line)
+        if match:
+          header_found = True
+          if match.group(1) > check_name_camel:
+            header_added = True
+            f.write('#include "' + check_name_camel + '.h"\n')
+        elif header_found:
+          header_added = True
+          f.write('#include "' + check_name_camel + '.h"\n')
+
+      if not check_added:
+        if line.strip() == '}':
+          check_added = True
+          f.write(check_decl)
+        else:
+          match = re.search('registerCheck<(.*)>', line)
+          if match and match.group(1) > check_name_camel:
+            check_added = True
+            f.write(check_decl)
+      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, 'w') 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 :doc:`%s
+  <clang-tidy/checks/%s>` 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, test_extension):
+  check_name_dashes = module + '-' + check_name
+  filename = os.path.normpath(os.path.join(module_path, '../../test/clang-tidy',
+                                           check_name_dashes + '.' + test_extension))
+  print('Creating %s...' % filename)
+  with open(filename, 'w') as f:
+    f.write("""// RUN: %%check_clang_tidy %%s %(check_name_dashes)s %%t
+
+// FIXME: Add something that triggers the check here.
+void f();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'f' is insufficiently awesome [%(check_name_dashes)s]
+
+// FIXME: Verify the applied fix.
+//   * Make the CHECK patterns specific enough and try to make verified lines
+//     unique to avoid incorrect matches.
+//   * Use {{}} for regular expressions.
+// CHECK-FIXES: {{^}}void awesome_f();{{$}}
+
+// FIXME: Add something that doesn't trigger the check here.
+void awesome_f2();
+""" % {'check_name_dashes': check_name_dashes})
+
+
+# Recreates the list of checks in the docs/clang-tidy/checks directory.
+def update_checks_list(clang_tidy_path):
+  docs_dir = os.path.join(clang_tidy_path, '../docs/clang-tidy/checks')
+  filename = os.path.normpath(os.path.join(docs_dir, 'list.rst'))
+  with open(filename, 'r') as f:
+    lines = f.readlines()
+  doc_files = list(filter(lambda s: s.endswith('.rst') and s != 'list.rst',
+                     os.listdir(docs_dir)))
+  doc_files.sort()
+
+  def format_link(doc_file):
+    check_name = doc_file.replace('.rst', '')
+    with open(os.path.join(docs_dir, doc_file), 'r') as doc:
+      content = doc.read()
+      match = re.search('.*:orphan:.*', content)
+      if match:
+        return ''
+
+      match = re.search('.*:http-equiv=refresh: \d+;URL=(.*).html.*',
+                        content)
+      if match:
+        return '   %(check)s (redirects to %(target)s) <%(check)s>\n' % {
+            'check': check_name,
+            'target': match.group(1)
+        }
+      return '   %s\n' % check_name
+
+  checks = map(format_link, doc_files)
+
+  print('Updating %s...' % filename)
+  with open(filename, 'w') as f:
+    for line in lines:
+      f.write(line)
+      if line.startswith('.. toctree::'):
+        f.writelines(checks)
+        break
+
+
+# Adds a documentation for the check.
+def write_docs(module_path, module, check_name):
+  check_name_dashes = module + '-' + check_name
+  filename = os.path.normpath(os.path.join(
+      module_path, '../../docs/clang-tidy/checks/', check_name_dashes + '.rst'))
+  print('Creating %s...' % filename)
+  with open(filename, 'w') as f:
+    f.write(""".. title:: clang-tidy - %(check_name_dashes)s
+
+%(check_name_dashes)s
+%(underline)s
+
+FIXME: Describe what patterns does the check detect and why. Give examples.
+""" % {'check_name_dashes': check_name_dashes,
+       'underline': '=' * len(check_name_dashes)})
+
+
+def main():
+  language_to_extension = {
+      'c': 'c',
+      'c++': 'cpp',
+      'objc': 'm',
+      'objc++': 'mm',
+  }
+  parser = argparse.ArgumentParser()
+  parser.add_argument(
+      '--update-docs',
+      action='store_true',
+      help='just update the list of documentation files, then exit')
+  parser.add_argument(
+      '--language',
+      help='language to use for new check (defaults to c++)',
+      choices=language_to_extension.keys(),
+      default='c++',
+      metavar='LANG')
+  parser.add_argument(
+      'module',
+      nargs='?',
+      help='module directory under which to place the new tidy check (e.g., misc)')
+  parser.add_argument(
+      'check',
+      nargs='?',
+      help='name of new tidy check to add (e.g. foo-do-the-stuff)')
+  args = parser.parse_args()
+
+  if args.update_docs:
+    update_checks_list(os.path.dirname(sys.argv[0]))
+    return
+
+  if not args.module or not args.check:
+    print('Module and check must be specified.')
+    parser.print_usage()
+    return
+
+  module = args.module
+  check_name = args.check
+
+  if check_name.startswith(module):
+    print('Check name "%s" must not start with the module "%s". Exiting.' % (
+        check_name, module))
+    return
+  check_name_camel = ''.join(map(lambda elem: elem.capitalize(),
+                                 check_name.split('-'))) + 'Check'
+  clang_tidy_path = os.path.dirname(sys.argv[0])
+  module_path = os.path.join(clang_tidy_path, module)
+
+  if not adapt_cmake(module_path, check_name_camel):
+    return
+  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)
+  test_extension = language_to_extension.get(args.language)
+  write_test(module_path, module, check_name, test_extension)
+  write_docs(module_path, module, check_name)
+  update_checks_list(clang_tidy_path)
+  print('Done. Now it\'s your turn!')
+
+
+if __name__ == '__main__':
+  main()
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/AndroidTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/AndroidTidyModule.cpp
new file mode 100644
index 0000000..64d35c7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/AndroidTidyModule.cpp
@@ -0,0 +1,70 @@
+//===--- 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 "CloexecDupCheck.h"
+#include "CloexecEpollCreate1Check.h"
+#include "CloexecEpollCreateCheck.h"
+#include "CloexecFopenCheck.h"
+#include "CloexecInotifyInit1Check.h"
+#include "CloexecInotifyInitCheck.h"
+#include "CloexecMemfdCreateCheck.h"
+#include "CloexecOpenCheck.h"
+#include "CloexecSocketCheck.h"
+#include "ComparisonInTempFailureRetryCheck.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");
+    CheckFactories.registerCheck<ComparisonInTempFailureRetryCheck>(
+        "android-comparison-in-temp-failure-retry");
+  }
+};
+
+// 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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CMakeLists.txt
new file mode 100644
index 0000000..37aebac
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CMakeLists.txt
@@ -0,0 +1,27 @@
+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
+  ComparisonInTempFailureRetryCheck.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyUtils
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecAccept4Check.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecAccept4Check.cpp
new file mode 100644
index 0000000..3d172ef
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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, /*MacroFlag=*/"SOCK_CLOEXEC", /*ArgPos=*/3);
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecAccept4Check.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecAccept4Check.h
new file mode 100644
index 0000000..0cf3215
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecAcceptCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecAcceptCheck.cpp
new file mode 100644
index 0000000..f583bd0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecAcceptCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecAcceptCheck.h
new file mode 100644
index 0000000..cba1c09
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecCheck.cpp
new file mode 100644
index 0000000..8473f1a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecCheck.h
new file mode 100644
index 0000000..1c58a31
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecCreatCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecCreatCheck.cpp
new file mode 100644
index 0000000..83ca49a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecCreatCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecCreatCheck.h
new file mode 100644
index 0000000..335990c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecDupCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecDupCheck.cpp
new file mode 100644
index 0000000..ec4ff0a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecDupCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecDupCheck.h
new file mode 100644
index 0000000..c040b38
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecEpollCreate1Check.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecEpollCreate1Check.cpp
new file mode 100644
index 0000000..d94b4a0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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, /*MacroFlag=*/"EPOLL_CLOEXEC", /*ArgPos=*/0);
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecEpollCreate1Check.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecEpollCreate1Check.h
new file mode 100644
index 0000000..9890d5f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecEpollCreateCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecEpollCreateCheck.cpp
new file mode 100644
index 0000000..7165d24
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecEpollCreateCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecEpollCreateCheck.h
new file mode 100644
index 0000000..21d2b2a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecFopenCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecFopenCheck.cpp
new file mode 100644
index 0000000..33058d6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecFopenCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecFopenCheck.h
new file mode 100644
index 0000000..1c82b8b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecInotifyInit1Check.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecInotifyInit1Check.cpp
new file mode 100644
index 0000000..ca0aeb8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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, /*MacroFlag=*/"IN_CLOEXEC", /*ArgPos=*/0);
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecInotifyInit1Check.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecInotifyInit1Check.h
new file mode 100644
index 0000000..deb04f2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecInotifyInitCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecInotifyInitCheck.cpp
new file mode 100644
index 0000000..0d5a56d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecInotifyInitCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecInotifyInitCheck.h
new file mode 100644
index 0000000..ceeecbe
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecMemfdCreateCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecMemfdCreateCheck.cpp
new file mode 100644
index 0000000..4820e2b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecMemfdCreateCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecMemfdCreateCheck.h
new file mode 100644
index 0000000..0fe96f4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecOpenCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecOpenCheck.cpp
new file mode 100644
index 0000000..a4d3bc6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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, /*MacroFlag=*/"O_CLOEXEC", ArgPos);
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecOpenCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecOpenCheck.h
new file mode 100644
index 0000000..c221087
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecSocketCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecSocketCheck.cpp
new file mode 100644
index 0000000..b223918
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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, /*MacroFlag=*/"SOCK_CLOEXEC", /*ArgPos=*/1);
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecSocketCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/CloexecSocketCheck.h
new file mode 100644
index 0000000..c1fd01f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/ComparisonInTempFailureRetryCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/ComparisonInTempFailureRetryCheck.cpp
new file mode 100644
index 0000000..49db53a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/ComparisonInTempFailureRetryCheck.cpp
@@ -0,0 +1,84 @@
+//===--- ComparisonInTempFailureRetryCheck.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 "../utils/Matchers.h"
+#include "ComparisonInTempFailureRetryCheck.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 {
+AST_MATCHER(BinaryOperator, isRHSATempFailureRetryArg) {
+  if (!Node.getLocStart().isMacroID())
+    return false;
+
+  const SourceManager &SM = Finder->getASTContext().getSourceManager();
+  if (!SM.isMacroArgExpansion(Node.getRHS()->IgnoreParenCasts()->getLocStart()))
+    return false;
+
+  const LangOptions &Opts = Finder->getASTContext().getLangOpts();
+  SourceLocation LocStart = Node.getLocStart();
+  while (LocStart.isMacroID()) {
+    SourceLocation Invocation = SM.getImmediateMacroCallerLoc(LocStart);
+    Token Tok;
+    if (!Lexer::getRawToken(SM.getSpellingLoc(Invocation), Tok, SM, Opts,
+                            /*IgnoreWhiteSpace=*/true)) {
+      if (Tok.getKind() == tok::raw_identifier &&
+          Tok.getRawIdentifier() == "TEMP_FAILURE_RETRY")
+        return true;
+    }
+
+    LocStart = Invocation;
+  }
+  return false;
+}
+} // namespace
+
+void ComparisonInTempFailureRetryCheck::registerMatchers(MatchFinder *Finder) {
+  // Both glibc's and Bionic's TEMP_FAILURE_RETRY macros structurally look like:
+  //
+  // #define TEMP_FAILURE_RETRY(x) ({ \
+  //    typeof(x) y; \
+  //    do y = (x); \
+  //    while (y == -1 && errno == EINTR); \
+  //    y; \
+  // })
+  //
+  // (glibc uses `long int` instead of `typeof(x)` for the type of y).
+  //
+  // It's unclear how to walk up the AST from inside the expansion of `x`, and
+  // we need to not complain about things like TEMP_FAILURE_RETRY(foo(x == 1)),
+  // so we just match the assignment of `y = (x)` and inspect `x` from there.
+  Finder->addMatcher(
+      binaryOperator(
+          hasOperatorName("="),
+          hasRHS(ignoringParenCasts(
+              binaryOperator(matchers::isComparisonOperator()).bind("binop"))),
+          isRHSATempFailureRetryArg()),
+      this);
+}
+
+void ComparisonInTempFailureRetryCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto &BinOp = *Result.Nodes.getNodeAs<BinaryOperator>("binop");
+  diag(BinOp.getOperatorLoc(), "top-level comparison in TEMP_FAILURE_RETRY");
+
+  // FIXME: FixIts would be nice, but potentially nontrivial when nested macros
+  // happen, e.g. `TEMP_FAILURE_RETRY(IS_ZERO(foo()))`
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/ComparisonInTempFailureRetryCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/ComparisonInTempFailureRetryCheck.h
new file mode 100644
index 0000000..de81232
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/android/ComparisonInTempFailureRetryCheck.h
@@ -0,0 +1,36 @@
+//===--- ComparisonInTempFailureRetryCheck.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_COMPARISONINTEMPFAILURERETRYCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_COMPARISONINTEMPFAILURERETRYCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+/// Attempts to catch calls to TEMP_FAILURE_RETRY with a top-level comparison
+/// operation, like `TEMP_FAILURE_RETRY(read(...) != N)`. In these cases, the
+/// comparison should go outside of the TEMP_FAILURE_RETRY.
+///
+/// TEMP_FAILURE_RETRY is a macro provided by both glibc and Bionic.
+class ComparisonInTempFailureRetryCheck : public ClangTidyCheck {
+public:
+  ComparisonInTempFailureRetryCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(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_COMPARISONINTEMPFAILURERETRYCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/boost/BoostTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/boost/BoostTidyModule.cpp
new file mode 100644
index 0000000..28eb1d6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/boost/BoostTidyModule.cpp
@@ -0,0 +1,38 @@
+//===------- BoostTidyModule.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 "UseToStringCheck.h"
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace boost {
+
+class BoostModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<UseToStringCheck>("boost-use-to-string");
+  }
+};
+
+// Register the BoostModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<BoostModule> X("boost-module",
+                                                   "Add boost checks.");
+
+} // namespace boost
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the BoostModule.
+volatile int BoostModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/boost/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/boost/CMakeLists.txt
new file mode 100644
index 0000000..059f6e9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/boost/CMakeLists.txt
@@ -0,0 +1,14 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyBoostModule
+  BoostTidyModule.cpp
+  UseToStringCheck.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyUtils
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/boost/UseToStringCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/boost/UseToStringCheck.cpp
new file mode 100644
index 0000000..1775440
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/boost/UseToStringCheck.cpp
@@ -0,0 +1,75 @@
+//===--- UseToStringCheck.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 "UseToStringCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace boost {
+
+namespace {
+AST_MATCHER(Type, isStrictlyInteger) {
+  return Node.isIntegerType() && !Node.isAnyCharacterType() &&
+         !Node.isBooleanType();
+}
+} // namespace
+
+void UseToStringCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(
+      callExpr(
+          hasDeclaration(functionDecl(
+              returns(hasDeclaration(classTemplateSpecializationDecl(
+                  hasName("std::basic_string"),
+                  hasTemplateArgument(0,
+                                      templateArgument().bind("char_type"))))),
+              hasName("boost::lexical_cast"),
+              hasParameter(0, hasType(qualType(has(substTemplateTypeParmType(
+                                  isStrictlyInteger()))))))),
+          argumentCountIs(1), unless(isInTemplateInstantiation()))
+          .bind("to_string"),
+      this);
+}
+
+void UseToStringCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Call = Result.Nodes.getNodeAs<CallExpr>("to_string");
+  auto CharType =
+      Result.Nodes.getNodeAs<TemplateArgument>("char_type")->getAsType();
+
+  StringRef StringType;
+  if (CharType->isSpecificBuiltinType(BuiltinType::Char_S) ||
+      CharType->isSpecificBuiltinType(BuiltinType::Char_U))
+    StringType = "string";
+  else if (CharType->isSpecificBuiltinType(BuiltinType::WChar_S) ||
+           CharType->isSpecificBuiltinType(BuiltinType::WChar_U))
+    StringType = "wstring";
+  else
+    return;
+
+  auto Loc = Call->getLocStart();
+  auto Diag =
+      diag(Loc, "use std::to_%0 instead of boost::lexical_cast<std::%0>")
+      << StringType;
+
+  if (Loc.isMacroID())
+    return;
+
+  Diag << FixItHint::CreateReplacement(
+      CharSourceRange::getCharRange(Call->getLocStart(),
+                                    Call->getArg(0)->getLocStart()),
+      (llvm::Twine("std::to_") + StringType + "(").str());
+}
+
+} // namespace boost
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/boost/UseToStringCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/boost/UseToStringCheck.h
new file mode 100644
index 0000000..76e7823
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/boost/UseToStringCheck.h
@@ -0,0 +1,37 @@
+//===--- UseToStringCheck.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_BOOST_USE_TO_STRING_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BOOST_USE_TO_STRING_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace boost {
+
+/// Finds calls to ``boost::lexical_cast<std::string>`` and
+/// ``boost::lexical_cast<std::wstring>`` and replaces them with
+/// ``std::to_string`` and ``std::to_wstring`` calls.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/boost-use-to-string.html
+class UseToStringCheck : public ClangTidyCheck {
+public:
+  UseToStringCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace boost
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BOOST_USE_TO_STRING_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp
new file mode 100644
index 0000000..a8da703
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp
@@ -0,0 +1,308 @@
+//===--- ArgumentCommentCheck.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 "ArgumentCommentCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Token.h"
+#include "../utils/LexerUtils.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+ArgumentCommentCheck::ArgumentCommentCheck(StringRef Name,
+                                           ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      StrictMode(Options.getLocalOrGlobal("StrictMode", 0) != 0),
+      IdentRE("^(/\\* *)([_A-Za-z][_A-Za-z0-9]*)( *= *\\*/)$") {}
+
+void ArgumentCommentCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "StrictMode", StrictMode);
+}
+
+void ArgumentCommentCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      callExpr(unless(cxxOperatorCallExpr()),
+               // NewCallback's arguments relate to the pointed function, don't
+               // check them against NewCallback's parameter names.
+               // FIXME: Make this configurable.
+               unless(hasDeclaration(functionDecl(
+                   hasAnyName("NewCallback", "NewPermanentCallback")))))
+          .bind("expr"),
+      this);
+  Finder->addMatcher(cxxConstructExpr().bind("expr"), this);
+}
+
+static std::vector<std::pair<SourceLocation, StringRef>>
+getCommentsInRange(ASTContext *Ctx, CharSourceRange Range) {
+  std::vector<std::pair<SourceLocation, StringRef>> Comments;
+  auto &SM = Ctx->getSourceManager();
+  std::pair<FileID, unsigned> BeginLoc = SM.getDecomposedLoc(Range.getBegin()),
+                              EndLoc = SM.getDecomposedLoc(Range.getEnd());
+
+  if (BeginLoc.first != EndLoc.first)
+    return Comments;
+
+  bool Invalid = false;
+  StringRef Buffer = SM.getBufferData(BeginLoc.first, &Invalid);
+  if (Invalid)
+    return Comments;
+
+  const char *StrData = Buffer.data() + BeginLoc.second;
+
+  Lexer TheLexer(SM.getLocForStartOfFile(BeginLoc.first), Ctx->getLangOpts(),
+                 Buffer.begin(), StrData, Buffer.end());
+  TheLexer.SetCommentRetentionState(true);
+
+  while (true) {
+    Token Tok;
+    if (TheLexer.LexFromRawLexer(Tok))
+      break;
+    if (Tok.getLocation() == Range.getEnd() || Tok.is(tok::eof))
+      break;
+
+    if (Tok.is(tok::comment)) {
+      std::pair<FileID, unsigned> CommentLoc =
+          SM.getDecomposedLoc(Tok.getLocation());
+      assert(CommentLoc.first == BeginLoc.first);
+      Comments.emplace_back(
+          Tok.getLocation(),
+          StringRef(Buffer.begin() + CommentLoc.second, Tok.getLength()));
+    } else {
+      // Clear comments found before the different token, e.g. comma.
+      Comments.clear();
+    }
+  }
+
+  return Comments;
+}
+
+static std::vector<std::pair<SourceLocation, StringRef>>
+getCommentsBeforeLoc(ASTContext *Ctx, SourceLocation Loc) {
+  std::vector<std::pair<SourceLocation, StringRef>> Comments;
+  while (Loc.isValid()) {
+    clang::Token Tok =
+        utils::lexer::getPreviousToken(*Ctx, Loc, /*SkipComments=*/false);
+    if (Tok.isNot(tok::comment))
+      break;
+    Loc = Tok.getLocation();
+    Comments.emplace_back(
+        Loc,
+        Lexer::getSourceText(CharSourceRange::getCharRange(
+                                 Loc, Loc.getLocWithOffset(Tok.getLength())),
+                             Ctx->getSourceManager(), Ctx->getLangOpts()));
+  }
+  return Comments;
+}
+
+static bool isLikelyTypo(llvm::ArrayRef<ParmVarDecl *> Params,
+                         StringRef ArgName, unsigned ArgIndex) {
+  std::string ArgNameLowerStr = ArgName.lower();
+  StringRef ArgNameLower = ArgNameLowerStr;
+  // The threshold is arbitrary.
+  unsigned UpperBound = (ArgName.size() + 2) / 3 + 1;
+  unsigned ThisED = ArgNameLower.edit_distance(
+      Params[ArgIndex]->getIdentifier()->getName().lower(),
+      /*AllowReplacements=*/true, UpperBound);
+  if (ThisED >= UpperBound)
+    return false;
+
+  for (unsigned I = 0, E = Params.size(); I != E; ++I) {
+    if (I == ArgIndex)
+      continue;
+    IdentifierInfo *II = Params[I]->getIdentifier();
+    if (!II)
+      continue;
+
+    const unsigned Threshold = 2;
+    // Other parameters must be an edit distance at least Threshold more away
+    // from this parameter. This gives us greater confidence that this is a typo
+    // of this parameter and not one with a similar name.
+    unsigned OtherED = ArgNameLower.edit_distance(II->getName().lower(),
+                                                  /*AllowReplacements=*/true,
+                                                  ThisED + Threshold);
+    if (OtherED < ThisED + Threshold)
+      return false;
+  }
+
+  return true;
+}
+
+static bool sameName(StringRef InComment, StringRef InDecl, bool StrictMode) {
+  if (StrictMode)
+    return InComment == InDecl;
+  InComment = InComment.trim('_');
+  InDecl = InDecl.trim('_');
+  // FIXME: compare_lower only works for ASCII.
+  return InComment.compare_lower(InDecl) == 0;
+}
+
+static bool looksLikeExpectMethod(const CXXMethodDecl *Expect) {
+  return Expect != nullptr && Expect->getLocation().isMacroID() &&
+         Expect->getNameInfo().getName().isIdentifier() &&
+         Expect->getName().startswith("gmock_");
+}
+static bool areMockAndExpectMethods(const CXXMethodDecl *Mock,
+                                    const CXXMethodDecl *Expect) {
+  assert(looksLikeExpectMethod(Expect));
+  return Mock != nullptr && Mock->getNextDeclInContext() == Expect &&
+         Mock->getNumParams() == Expect->getNumParams() &&
+         Mock->getLocation().isMacroID() &&
+         Mock->getNameInfo().getName().isIdentifier() &&
+         Mock->getName() == Expect->getName().substr(strlen("gmock_"));
+}
+
+// This uses implementation details of MOCK_METHODx_ macros: for each mocked
+// method M it defines M() with appropriate signature and a method used to set
+// up expectations - gmock_M() - with each argument's type changed the
+// corresponding matcher. This function returns M when given either M or
+// gmock_M.
+static const CXXMethodDecl *findMockedMethod(const CXXMethodDecl *Method) {
+  if (looksLikeExpectMethod(Method)) {
+    const DeclContext *Ctx = Method->getDeclContext();
+    if (Ctx == nullptr || !Ctx->isRecord())
+      return nullptr;
+    for (const auto *D : Ctx->decls()) {
+      if (D->getNextDeclInContext() == Method) {
+        const auto *Previous = dyn_cast<CXXMethodDecl>(D);
+        return areMockAndExpectMethods(Previous, Method) ? Previous : nullptr;
+      }
+    }
+    return nullptr;
+  }
+  if (const auto *Next = dyn_cast_or_null<CXXMethodDecl>(
+                 Method->getNextDeclInContext())) {
+    if (looksLikeExpectMethod(Next) && areMockAndExpectMethods(Method, Next))
+      return Method;
+  }
+  return nullptr;
+}
+
+// For gmock expectation builder method (the target of the call generated by
+// `EXPECT_CALL(obj, Method(...))`) tries to find the real method being mocked
+// (returns nullptr, if the mock method doesn't override anything). For other
+// functions returns the function itself.
+static const FunctionDecl *resolveMocks(const FunctionDecl *Func) {
+  if (const auto *Method = dyn_cast<CXXMethodDecl>(Func)) {
+    if (const auto *MockedMethod = findMockedMethod(Method)) {
+      // If mocked method overrides the real one, we can use its parameter
+      // names, otherwise we're out of luck.
+      if (MockedMethod->size_overridden_methods() > 0) {
+        return *MockedMethod->begin_overridden_methods();
+      }
+      return nullptr;
+    }
+  }
+  return Func;
+}
+
+void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx,
+                                         const FunctionDecl *OriginalCallee,
+                                         SourceLocation ArgBeginLoc,
+                                         llvm::ArrayRef<const Expr *> Args) {
+  const FunctionDecl *Callee = resolveMocks(OriginalCallee);
+  if (!Callee)
+    return;
+
+  Callee = Callee->getFirstDecl();
+  unsigned NumArgs = std::min<unsigned>(Args.size(), Callee->getNumParams());
+  if (NumArgs == 0)
+    return;
+
+  auto makeFileCharRange = [Ctx](SourceLocation Begin, SourceLocation End) {
+    return Lexer::makeFileCharRange(CharSourceRange::getCharRange(Begin, End),
+                                    Ctx->getSourceManager(),
+                                    Ctx->getLangOpts());
+  };
+
+  for (unsigned I = 0; I < NumArgs; ++I) {
+    const ParmVarDecl *PVD = Callee->getParamDecl(I);
+    IdentifierInfo *II = PVD->getIdentifier();
+    if (!II)
+      continue;
+    if (auto Template = Callee->getTemplateInstantiationPattern()) {
+      // Don't warn on arguments for parameters instantiated from template
+      // parameter packs. If we find more arguments than the template
+      // definition has, it also means that they correspond to a parameter
+      // pack.
+      if (Template->getNumParams() <= I ||
+          Template->getParamDecl(I)->isParameterPack()) {
+        continue;
+      }
+    }
+
+    CharSourceRange BeforeArgument =
+        makeFileCharRange(ArgBeginLoc, Args[I]->getLocStart());
+    ArgBeginLoc = Args[I]->getLocEnd();
+
+    std::vector<std::pair<SourceLocation, StringRef>> Comments;
+    if (BeforeArgument.isValid()) {
+      Comments = getCommentsInRange(Ctx, BeforeArgument);
+    } else {
+      // Fall back to parsing back from the start of the argument.
+      CharSourceRange ArgsRange = makeFileCharRange(
+          Args[I]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
+      Comments = getCommentsBeforeLoc(Ctx, ArgsRange.getBegin());
+    }
+
+    for (auto Comment : Comments) {
+      llvm::SmallVector<StringRef, 2> Matches;
+      if (IdentRE.match(Comment.second, &Matches) &&
+          !sameName(Matches[2], II->getName(), StrictMode)) {
+        {
+          DiagnosticBuilder Diag =
+              diag(Comment.first, "argument name '%0' in comment does not "
+                                  "match parameter name %1")
+              << Matches[2] << II;
+          if (isLikelyTypo(Callee->parameters(), Matches[2], I)) {
+            Diag << FixItHint::CreateReplacement(
+                Comment.first, (Matches[1] + II->getName() + Matches[3]).str());
+          }
+        }
+        diag(PVD->getLocation(), "%0 declared here", DiagnosticIDs::Note) << II;
+        if (OriginalCallee != Callee) {
+          diag(OriginalCallee->getLocation(),
+               "actual callee (%0) is declared here", DiagnosticIDs::Note)
+              << OriginalCallee;
+        }
+      }
+    }
+  }
+}
+
+void ArgumentCommentCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *E = Result.Nodes.getNodeAs<Expr>("expr");
+  if (const auto *Call = dyn_cast<CallExpr>(E)) {
+    const FunctionDecl *Callee = Call->getDirectCallee();
+    if (!Callee)
+      return;
+
+    checkCallArgs(Result.Context, Callee, Call->getCallee()->getLocEnd(),
+                  llvm::makeArrayRef(Call->getArgs(), Call->getNumArgs()));
+  } else {
+    const auto *Construct = cast<CXXConstructExpr>(E);
+    if (Construct->getNumArgs() == 1 &&
+        Construct->getArg(0)->getSourceRange() == Construct->getSourceRange()) {
+      // Ignore implicit construction.
+      return;
+    }
+    checkCallArgs(
+        Result.Context, Construct->getConstructor(),
+        Construct->getParenOrBraceRange().getBegin(),
+        llvm::makeArrayRef(Construct->getArgs(), Construct->getNumArgs()));
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.h
new file mode 100644
index 0000000..2f5a751
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.h
@@ -0,0 +1,55 @@
+//===--- ArgumentCommentCheck.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_ARGUMENTCOMMENTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ARGUMENTCOMMENTCHECK_H
+
+#include "../ClangTidy.h"
+#include "llvm/Support/Regex.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Checks that argument comments match parameter names.
+///
+/// The check understands argument comments in the form `/*parameter_name=*/`
+/// that are placed right before the argument.
+///
+/// \code
+///   void f(bool foo);
+///
+///   ...
+///   f(/*bar=*/true);
+///   // warning: argument name 'bar' in comment does not match parameter name 'foo'
+/// \endcode
+///
+/// The check tries to detect typos and suggest automated fixes for them.
+class ArgumentCommentCheck : public ClangTidyCheck {
+public:
+  ArgumentCommentCheck(StringRef Name, ClangTidyContext *Context);
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  const bool StrictMode;
+  llvm::Regex IdentRE;
+
+  void checkCallArgs(ASTContext *Ctx, const FunctionDecl *Callee,
+                     SourceLocation ArgBeginLoc,
+                     llvm::ArrayRef<const Expr *> Args);
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ARGUMENTCOMMENTCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp
new file mode 100644
index 0000000..244e755
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp
@@ -0,0 +1,127 @@
+//===--- AssertSideEffectCheck.cpp - clang-tidy ---------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AssertSideEffectCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include <algorithm>
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+
+AST_MATCHER_P(Expr, hasSideEffect, bool, CheckFunctionCalls) {
+  const Expr *E = &Node;
+
+  if (const auto *Op = dyn_cast<UnaryOperator>(E)) {
+    UnaryOperator::Opcode OC = Op->getOpcode();
+    return OC == UO_PostInc || OC == UO_PostDec || OC == UO_PreInc ||
+           OC == UO_PreDec;
+  }
+
+  if (const auto *Op = dyn_cast<BinaryOperator>(E)) {
+    return Op->isAssignmentOp();
+  }
+
+  if (const auto *OpCallExpr = dyn_cast<CXXOperatorCallExpr>(E)) {
+    OverloadedOperatorKind OpKind = OpCallExpr->getOperator();
+    return OpKind == OO_Equal || OpKind == OO_PlusEqual ||
+           OpKind == OO_MinusEqual || OpKind == OO_StarEqual ||
+           OpKind == OO_SlashEqual || OpKind == OO_AmpEqual ||
+           OpKind == OO_PipeEqual || OpKind == OO_CaretEqual ||
+           OpKind == OO_LessLessEqual || OpKind == OO_GreaterGreaterEqual ||
+           OpKind == OO_PlusPlus || OpKind == OO_MinusMinus ||
+           OpKind == OO_PercentEqual || OpKind == OO_New ||
+           OpKind == OO_Delete || OpKind == OO_Array_New ||
+           OpKind == OO_Array_Delete;
+  }
+
+  if (const auto *CExpr = dyn_cast<CallExpr>(E)) {
+    bool Result = CheckFunctionCalls;
+    if (const auto *FuncDecl = CExpr->getDirectCallee()) {
+      if (FuncDecl->getDeclName().isIdentifier() &&
+          FuncDecl->getName() == "__builtin_expect") // exceptions come here
+        Result = false;
+      else if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FuncDecl))
+        Result &= !MethodDecl->isConst();
+    }
+    return Result;
+  }
+
+  return isa<CXXNewExpr>(E) || isa<CXXDeleteExpr>(E) || isa<CXXThrowExpr>(E);
+}
+
+} // namespace
+
+AssertSideEffectCheck::AssertSideEffectCheck(StringRef Name,
+                                             ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      CheckFunctionCalls(Options.get("CheckFunctionCalls", false)),
+      RawAssertList(Options.get("AssertMacros", "assert")) {
+  StringRef(RawAssertList).split(AssertMacros, ",", -1, false);
+}
+
+// The options are explained in AssertSideEffectCheck.h.
+void AssertSideEffectCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "CheckFunctionCalls", CheckFunctionCalls);
+  Options.store(Opts, "AssertMacros", RawAssertList);
+}
+
+void AssertSideEffectCheck::registerMatchers(MatchFinder *Finder) {
+  auto DescendantWithSideEffect =
+      hasDescendant(expr(hasSideEffect(CheckFunctionCalls)));
+  auto ConditionWithSideEffect = hasCondition(DescendantWithSideEffect);
+  Finder->addMatcher(
+      stmt(
+          anyOf(conditionalOperator(ConditionWithSideEffect),
+                ifStmt(ConditionWithSideEffect),
+                unaryOperator(hasOperatorName("!"),
+                              hasUnaryOperand(unaryOperator(
+                                  hasOperatorName("!"),
+                                  hasUnaryOperand(DescendantWithSideEffect))))))
+          .bind("condStmt"),
+      this);
+}
+
+void AssertSideEffectCheck::check(const MatchFinder::MatchResult &Result) {
+  const SourceManager &SM = *Result.SourceManager;
+  const LangOptions LangOpts = getLangOpts();
+  SourceLocation Loc = Result.Nodes.getNodeAs<Stmt>("condStmt")->getLocStart();
+
+  StringRef AssertMacroName;
+  while (Loc.isValid() && Loc.isMacroID()) {
+    StringRef MacroName = Lexer::getImmediateMacroName(Loc, SM, LangOpts);
+
+    // Check if this macro is an assert.
+    if (std::find(AssertMacros.begin(), AssertMacros.end(), MacroName) !=
+        AssertMacros.end()) {
+      AssertMacroName = MacroName;
+      break;
+    }
+    Loc = SM.getImmediateMacroCallerLoc(Loc);
+  }
+  if (AssertMacroName.empty())
+    return;
+
+  diag(Loc, "found %0() with side effect") << AssertMacroName;
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.h
new file mode 100644
index 0000000..0f386c9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.h
@@ -0,0 +1,52 @@
+//===--- AssertSideEffectCheck.h - clang-tidy -------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ASSERTSIDEEFFECTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ASSERTSIDEEFFECTCHECK_H
+
+#include "../ClangTidy.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds `assert()` with side effect.
+///
+/// The condition of `assert()` is evaluated only in debug builds so a
+/// condition with side effect can cause different behavior in debug / release
+/// builds.
+///
+/// There are two options:
+///
+///   - `AssertMacros`: A comma-separated list of the names of assert macros to
+///     be checked.
+///   - `CheckFunctionCalls`: Whether to treat non-const member and non-member
+///     functions as they produce side effects. Disabled by default because it
+///     can increase the number of false positive warnings.
+class AssertSideEffectCheck : public ClangTidyCheck {
+public:
+  AssertSideEffectCheck(StringRef Name, ClangTidyContext *Context);
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  const bool CheckFunctionCalls;
+  const std::string RawAssertList;
+  SmallVector<StringRef, 5> AssertMacros;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ASSERTSIDEEFFECTCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp
new file mode 100644
index 0000000..ed2c2db
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp
@@ -0,0 +1,73 @@
+//===--- BoolPointerImplicitConversionCheck.cpp - clang-tidy --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "BoolPointerImplicitConversionCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void BoolPointerImplicitConversionCheck::registerMatchers(MatchFinder *Finder) {
+  // Look for ifs that have an implicit bool* to bool conversion in the
+  // condition. Filter negations.
+  Finder->addMatcher(
+      ifStmt(hasCondition(findAll(implicitCastExpr(
+                 allOf(unless(hasParent(unaryOperator(hasOperatorName("!")))),
+                       hasSourceExpression(expr(
+                           hasType(pointerType(pointee(booleanType()))),
+                           ignoringParenImpCasts(declRefExpr().bind("expr")))),
+                       hasCastKind(CK_PointerToBoolean))))),
+             unless(isInTemplateInstantiation()))
+          .bind("if"),
+      this);
+}
+
+void BoolPointerImplicitConversionCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
+  auto *Var = Result.Nodes.getNodeAs<DeclRefExpr>("expr");
+
+  // Ignore macros.
+  if (Var->getLocStart().isMacroID())
+    return;
+
+  // Only allow variable accesses for now, no function calls or member exprs.
+  // Check that we don't dereference the variable anywhere within the if. This
+  // avoids false positives for checks of the pointer for nullptr before it is
+  // dereferenced. If there is a dereferencing operator on this variable don't
+  // emit a diagnostic. Also ignore array subscripts.
+  const Decl *D = Var->getDecl();
+  auto DeclRef = ignoringParenImpCasts(declRefExpr(to(equalsNode(D))));
+  if (!match(findAll(
+                 unaryOperator(hasOperatorName("*"), hasUnaryOperand(DeclRef))),
+             *If, *Result.Context)
+           .empty() ||
+      !match(findAll(arraySubscriptExpr(hasBase(DeclRef))), *If,
+             *Result.Context)
+           .empty() ||
+      // FIXME: We should still warn if the paremater is implicitly converted to
+      // bool.
+      !match(findAll(callExpr(hasAnyArgument(ignoringParenImpCasts(DeclRef)))),
+             *If, *Result.Context)
+           .empty() ||
+      !match(findAll(cxxDeleteExpr(has(ignoringParenImpCasts(expr(DeclRef))))),
+             *If, *Result.Context)
+           .empty())
+    return;
+
+  diag(Var->getLocStart(), "dubious check of 'bool *' against 'nullptr', did "
+                           "you mean to dereference it?")
+      << FixItHint::CreateInsertion(Var->getLocStart(), "*");
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.h
new file mode 100644
index 0000000..b3416a9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.h
@@ -0,0 +1,42 @@
+//===--- BoolPointerImplicitConversionCheck.h - clang-tidy ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BOOLPOINTERIMPLICITCONVERSIONCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BOOLPOINTERIMPLICITCONVERSIONCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Checks for conditions based on implicit conversion from a bool pointer to
+/// bool.
+///
+/// Example:
+///
+/// \code
+///   bool *p;
+///   if (p) {
+///     // Never used in a pointer-specific way.
+///   }
+/// \endcode
+class BoolPointerImplicitConversionCheck : public ClangTidyCheck {
+public:
+  BoolPointerImplicitConversionCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BOOLPOINTERIMPLICITCONVERSIONCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
new file mode 100644
index 0000000..09a252b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -0,0 +1,155 @@
+//===--- 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 "../cppcoreguidelines/NarrowingConversionsCheck.h"
+#include "ArgumentCommentCheck.h"
+#include "AssertSideEffectCheck.h"
+#include "BoolPointerImplicitConversionCheck.h"
+#include "CopyConstructorInitCheck.h"
+#include "DanglingHandleCheck.h"
+#include "ExceptionEscapeCheck.h"
+#include "FoldInitTypeCheck.h"
+#include "ForwardDeclarationNamespaceCheck.h"
+#include "ForwardingReferenceOverloadCheck.h"
+#include "InaccurateEraseCheck.h"
+#include "IncorrectRoundingsCheck.h"
+#include "IntegerDivisionCheck.h"
+#include "LambdaFunctionNameCheck.h"
+#include "MacroParenthesesCheck.h"
+#include "MacroRepeatedSideEffectsCheck.h"
+#include "MisplacedOperatorInStrlenInAllocCheck.h"
+#include "MisplacedWideningCastCheck.h"
+#include "MoveForwardingReferenceCheck.h"
+#include "MultipleStatementMacroCheck.h"
+#include "ParentVirtualCallCheck.h"
+#include "SizeofContainerCheck.h"
+#include "SizeofExpressionCheck.h"
+#include "StringConstructorCheck.h"
+#include "StringIntegerAssignmentCheck.h"
+#include "StringLiteralWithEmbeddedNulCheck.h"
+#include "SuspiciousEnumUsageCheck.h"
+#include "SuspiciousMemsetUsageCheck.h"
+#include "SuspiciousMissingCommaCheck.h"
+#include "SuspiciousSemicolonCheck.h"
+#include "SuspiciousStringCompareCheck.h"
+#include "SwappedArgumentsCheck.h"
+#include "TerminatingContinueCheck.h"
+#include "ThrowKeywordMissingCheck.h"
+#include "UndefinedMemoryManipulationCheck.h"
+#include "UndelegatedConstructorCheck.h"
+#include "UnusedRaiiCheck.h"
+#include "UnusedReturnValueCheck.h"
+#include "UseAfterMoveCheck.h"
+#include "VirtualNearMissCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+class BugproneModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<ArgumentCommentCheck>(
+        "bugprone-argument-comment");
+    CheckFactories.registerCheck<AssertSideEffectCheck>(
+        "bugprone-assert-side-effect");
+    CheckFactories.registerCheck<BoolPointerImplicitConversionCheck>(
+        "bugprone-bool-pointer-implicit-conversion");
+    CheckFactories.registerCheck<CopyConstructorInitCheck>(
+        "bugprone-copy-constructor-init");
+    CheckFactories.registerCheck<DanglingHandleCheck>(
+        "bugprone-dangling-handle");
+    CheckFactories.registerCheck<ExceptionEscapeCheck>(
+        "bugprone-exception-escape");
+    CheckFactories.registerCheck<FoldInitTypeCheck>(
+        "bugprone-fold-init-type");
+    CheckFactories.registerCheck<ForwardDeclarationNamespaceCheck>(
+        "bugprone-forward-declaration-namespace");
+    CheckFactories.registerCheck<ForwardingReferenceOverloadCheck>(
+        "bugprone-forwarding-reference-overload");
+    CheckFactories.registerCheck<InaccurateEraseCheck>(
+        "bugprone-inaccurate-erase");
+    CheckFactories.registerCheck<IncorrectRoundingsCheck>(
+        "bugprone-incorrect-roundings");
+    CheckFactories.registerCheck<IntegerDivisionCheck>(
+        "bugprone-integer-division");
+    CheckFactories.registerCheck<LambdaFunctionNameCheck>(
+        "bugprone-lambda-function-name");
+    CheckFactories.registerCheck<MacroParenthesesCheck>(
+        "bugprone-macro-parentheses");
+    CheckFactories.registerCheck<MacroRepeatedSideEffectsCheck>(
+        "bugprone-macro-repeated-side-effects");
+    CheckFactories.registerCheck<MisplacedOperatorInStrlenInAllocCheck>(
+        "bugprone-misplaced-operator-in-strlen-in-alloc");
+    CheckFactories.registerCheck<MisplacedWideningCastCheck>(
+        "bugprone-misplaced-widening-cast");
+    CheckFactories.registerCheck<MoveForwardingReferenceCheck>(
+        "bugprone-move-forwarding-reference");
+    CheckFactories.registerCheck<MultipleStatementMacroCheck>(
+        "bugprone-multiple-statement-macro");
+    CheckFactories.registerCheck<cppcoreguidelines::NarrowingConversionsCheck>(
+        "bugprone-narrowing-conversions");
+    CheckFactories.registerCheck<ParentVirtualCallCheck>(
+        "bugprone-parent-virtual-call");
+    CheckFactories.registerCheck<SizeofContainerCheck>(
+        "bugprone-sizeof-container");
+    CheckFactories.registerCheck<SizeofExpressionCheck>(
+        "bugprone-sizeof-expression");
+    CheckFactories.registerCheck<StringConstructorCheck>(
+        "bugprone-string-constructor");
+    CheckFactories.registerCheck<StringIntegerAssignmentCheck>(
+        "bugprone-string-integer-assignment");
+    CheckFactories.registerCheck<StringLiteralWithEmbeddedNulCheck>(
+        "bugprone-string-literal-with-embedded-nul");
+    CheckFactories.registerCheck<SuspiciousEnumUsageCheck>(
+        "bugprone-suspicious-enum-usage");
+    CheckFactories.registerCheck<SuspiciousMemsetUsageCheck>(
+        "bugprone-suspicious-memset-usage");
+    CheckFactories.registerCheck<SuspiciousMissingCommaCheck>(
+        "bugprone-suspicious-missing-comma");
+    CheckFactories.registerCheck<SuspiciousSemicolonCheck>(
+        "bugprone-suspicious-semicolon");
+    CheckFactories.registerCheck<SuspiciousStringCompareCheck>(
+        "bugprone-suspicious-string-compare");
+    CheckFactories.registerCheck<SwappedArgumentsCheck>(
+        "bugprone-swapped-arguments");
+    CheckFactories.registerCheck<TerminatingContinueCheck>(
+        "bugprone-terminating-continue");
+    CheckFactories.registerCheck<ThrowKeywordMissingCheck>(
+        "bugprone-throw-keyword-missing");
+    CheckFactories.registerCheck<UndefinedMemoryManipulationCheck>(
+        "bugprone-undefined-memory-manipulation");
+    CheckFactories.registerCheck<UndelegatedConstructorCheck>(
+        "bugprone-undelegated-constructor");
+    CheckFactories.registerCheck<UnusedRaiiCheck>(
+        "bugprone-unused-raii");
+    CheckFactories.registerCheck<UnusedReturnValueCheck>(
+        "bugprone-unused-return-value");
+    CheckFactories.registerCheck<UseAfterMoveCheck>(
+        "bugprone-use-after-move");
+    CheckFactories.registerCheck<VirtualNearMissCheck>(
+        "bugprone-virtual-near-miss");
+  }
+};
+
+} // 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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
new file mode 100644
index 0000000..b20997c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -0,0 +1,55 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyBugproneModule
+  ArgumentCommentCheck.cpp
+  AssertSideEffectCheck.cpp
+  BoolPointerImplicitConversionCheck.cpp
+  BugproneTidyModule.cpp
+  CopyConstructorInitCheck.cpp
+  DanglingHandleCheck.cpp
+  ExceptionEscapeCheck.cpp
+  FoldInitTypeCheck.cpp
+  ForwardDeclarationNamespaceCheck.cpp
+  ForwardingReferenceOverloadCheck.cpp
+  InaccurateEraseCheck.cpp
+  IncorrectRoundingsCheck.cpp
+  IntegerDivisionCheck.cpp
+  LambdaFunctionNameCheck.cpp
+  MacroParenthesesCheck.cpp
+  MacroRepeatedSideEffectsCheck.cpp
+  MisplacedOperatorInStrlenInAllocCheck.cpp
+  MisplacedWideningCastCheck.cpp
+  MoveForwardingReferenceCheck.cpp
+  MultipleStatementMacroCheck.cpp
+  ParentVirtualCallCheck.cpp
+  SizeofContainerCheck.cpp
+  SizeofExpressionCheck.cpp
+  StringConstructorCheck.cpp
+  StringIntegerAssignmentCheck.cpp
+  StringLiteralWithEmbeddedNulCheck.cpp
+  SuspiciousEnumUsageCheck.cpp
+  SuspiciousMemsetUsageCheck.cpp
+  SuspiciousMissingCommaCheck.cpp
+  SuspiciousSemicolonCheck.cpp
+  SuspiciousStringCompareCheck.cpp
+  SwappedArgumentsCheck.cpp
+  TerminatingContinueCheck.cpp
+  ThrowKeywordMissingCheck.cpp
+  UndefinedMemoryManipulationCheck.cpp
+  UndelegatedConstructorCheck.cpp
+  UnusedRaiiCheck.cpp
+  UnusedReturnValueCheck.cpp
+  UseAfterMoveCheck.cpp
+  VirtualNearMissCheck.cpp
+
+  LINK_LIBS
+  clangAnalysis
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyCppCoreGuidelinesModule
+  clangTidyUtils
+  clangTooling
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.cpp
new file mode 100644
index 0000000..151e56c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.cpp
@@ -0,0 +1,121 @@
+//===--- CopyConstructorInitCheck.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 "CopyConstructorInitCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void CopyConstructorInitCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // In the future this might be extended to move constructors?
+  Finder->addMatcher(
+      cxxConstructorDecl(
+          isCopyConstructor(),
+          hasAnyConstructorInitializer(cxxCtorInitializer(
+              isBaseInitializer(),
+              withInitializer(cxxConstructExpr(hasDeclaration(
+                  cxxConstructorDecl(isDefaultConstructor())))))),
+          unless(isInstantiated()))
+          .bind("ctor"),
+      this);
+}
+
+void CopyConstructorInitCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
+  std::string ParamName = Ctor->getParamDecl(0)->getNameAsString();
+
+  // We want only one warning (and FixIt) for each ctor.
+  std::string FixItInitList;
+  bool HasRelevantBaseInit = false;
+  bool ShouldNotDoFixit = false;
+  bool HasWrittenInitializer = false;
+  SmallVector<FixItHint, 2> SafeFixIts;
+  for (const auto *Init : Ctor->inits()) {
+    bool CtorInitIsWritten = Init->isWritten();
+    HasWrittenInitializer = HasWrittenInitializer || CtorInitIsWritten;
+    if (!Init->isBaseInitializer())
+      continue;
+    const Type *BaseType = Init->getBaseClass();
+    // Do not do fixits if there is a type alias involved or one of the bases
+    // are explicitly initialized. In the latter case we not do fixits to avoid
+    // -Wreorder warnings.
+    if (const auto *TempSpecTy = dyn_cast<TemplateSpecializationType>(BaseType))
+      ShouldNotDoFixit = ShouldNotDoFixit || TempSpecTy->isTypeAlias();
+    ShouldNotDoFixit = ShouldNotDoFixit || isa<TypedefType>(BaseType);
+    ShouldNotDoFixit = ShouldNotDoFixit || CtorInitIsWritten;
+    const CXXRecordDecl *BaseClass =
+        BaseType->getAsCXXRecordDecl()->getDefinition();
+    if (BaseClass->field_empty() &&
+        BaseClass->forallBases(
+            [](const CXXRecordDecl *Class) { return Class->field_empty(); }))
+      continue;
+    bool NonCopyableBase = false;
+    for (const auto *Ctor : BaseClass->ctors()) {
+      if (Ctor->isCopyConstructor() &&
+          (Ctor->getAccess() == AS_private || Ctor->isDeleted())) {
+        NonCopyableBase = true;
+        break;
+      }
+    }
+    if (NonCopyableBase)
+      continue;
+    const auto *CExpr = dyn_cast<CXXConstructExpr>(Init->getInit());
+    if (!CExpr || !CExpr->getConstructor()->isDefaultConstructor())
+      continue;
+    HasRelevantBaseInit = true;
+    if (CtorInitIsWritten) {
+      if (!ParamName.empty())
+        SafeFixIts.push_back(
+            FixItHint::CreateInsertion(CExpr->getLocEnd(), ParamName));
+    } else {
+      if (Init->getSourceLocation().isMacroID() ||
+          Ctor->getLocation().isMacroID() || ShouldNotDoFixit)
+        break;
+      FixItInitList += BaseClass->getNameAsString();
+      FixItInitList += "(" + ParamName + "), ";
+    }
+  }
+  if (!HasRelevantBaseInit)
+    return;
+
+  auto Diag = diag(Ctor->getLocation(),
+                   "calling a base constructor other than the copy constructor")
+              << SafeFixIts;
+
+  if (FixItInitList.empty() || ParamName.empty() || ShouldNotDoFixit)
+    return;
+
+  std::string FixItMsg{FixItInitList.substr(0, FixItInitList.size() - 2)};
+  SourceLocation FixItLoc;
+  // There is no initialization list in this constructor.
+  if (!HasWrittenInitializer) {
+    FixItLoc = Ctor->getBody()->getLocStart();
+    FixItMsg = " : " + FixItMsg;
+  } else {
+    // We apply the missing ctors at the beginning of the initialization list.
+    FixItLoc = (*Ctor->init_begin())->getSourceLocation();
+    FixItMsg += ',';
+  }
+  FixItMsg += ' ';
+
+  Diag << FixItHint::CreateInsertion(FixItLoc, FixItMsg);
+} // namespace misc
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.h
new file mode 100644
index 0000000..4d13da4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.h
@@ -0,0 +1,36 @@
+//===--- CopyConstructorInitCheck.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_COPY_CONSTRUCTOR_INIT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_COPY_CONSTRUCTOR_INIT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds copy constructors where the ctor don't call the copy constructor of
+/// the base class.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-copy-constructor-init.html
+class CopyConstructorInitCheck : public ClangTidyCheck {
+public:
+  CopyConstructorInitCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_COPY_CONSTRUCTOR_INIT_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp
new file mode 100644
index 0000000..a22dcad
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp
@@ -0,0 +1,188 @@
+//===--- DanglingHandleCheck.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 "DanglingHandleCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+using namespace clang::tidy::matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+
+ast_matchers::internal::BindableMatcher<Stmt>
+handleFrom(const ast_matchers::internal::Matcher<RecordDecl> &IsAHandle,
+           const ast_matchers::internal::Matcher<Expr> &Arg) {
+  return expr(
+      anyOf(cxxConstructExpr(hasDeclaration(cxxMethodDecl(ofClass(IsAHandle))),
+                             hasArgument(0, Arg)),
+            cxxMemberCallExpr(hasType(cxxRecordDecl(IsAHandle)),
+                              callee(memberExpr(member(cxxConversionDecl()))),
+                              on(Arg))));
+}
+
+ast_matchers::internal::Matcher<Stmt> handleFromTemporaryValue(
+    const ast_matchers::internal::Matcher<RecordDecl> &IsAHandle) {
+  // If a ternary operator returns a temporary value, then both branches hold a
+  // temporary value. If one of them is not a temporary then it must be copied
+  // into one to satisfy the type of the operator.
+  const auto TemporaryTernary =
+      conditionalOperator(hasTrueExpression(cxxBindTemporaryExpr()),
+                          hasFalseExpression(cxxBindTemporaryExpr()));
+
+  return handleFrom(IsAHandle, anyOf(cxxBindTemporaryExpr(), TemporaryTernary));
+}
+
+ast_matchers::internal::Matcher<RecordDecl> isASequence() {
+  return hasAnyName("::std::deque", "::std::forward_list", "::std::list",
+                    "::std::vector");
+}
+
+ast_matchers::internal::Matcher<RecordDecl> isASet() {
+  return hasAnyName("::std::set", "::std::multiset", "::std::unordered_set",
+                    "::std::unordered_multiset");
+}
+
+ast_matchers::internal::Matcher<RecordDecl> isAMap() {
+  return hasAnyName("::std::map", "::std::multimap", "::std::unordered_map",
+                    "::std::unordered_multimap");
+}
+
+ast_matchers::internal::BindableMatcher<Stmt> makeContainerMatcher(
+    const ast_matchers::internal::Matcher<RecordDecl> &IsAHandle) {
+  // This matcher could be expanded to detect:
+  //  - Constructors: eg. vector<string_view>(3, string("A"));
+  //  - emplace*(): This requires a different logic to determine that
+  //                the conversion will happen inside the container.
+  //  - map's insert: This requires detecting that the pair conversion triggers
+  //                  the bug. A little more complicated than what we have now.
+  return callExpr(
+      hasAnyArgument(
+          ignoringParenImpCasts(handleFromTemporaryValue(IsAHandle))),
+      anyOf(
+          // For sequences: assign, push_back, resize.
+          cxxMemberCallExpr(
+              callee(functionDecl(hasAnyName("assign", "push_back", "resize"))),
+              on(expr(hasType(hasUnqualifiedDesugaredType(
+                  recordType(hasDeclaration(recordDecl(isASequence())))))))),
+          // For sequences and sets: insert.
+          cxxMemberCallExpr(callee(functionDecl(hasName("insert"))),
+                            on(expr(hasType(hasUnqualifiedDesugaredType(
+                                recordType(hasDeclaration(recordDecl(
+                                    anyOf(isASequence(), isASet()))))))))),
+          // For maps: operator[].
+          cxxOperatorCallExpr(callee(cxxMethodDecl(ofClass(isAMap()))),
+                              hasOverloadedOperatorName("[]"))));
+}
+
+} // anonymous namespace
+
+DanglingHandleCheck::DanglingHandleCheck(StringRef Name,
+                                         ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      HandleClasses(utils::options::parseStringList(Options.get(
+          "HandleClasses",
+          "std::basic_string_view;std::experimental::basic_string_view"))),
+      IsAHandle(cxxRecordDecl(hasAnyName(std::vector<StringRef>(
+                                  HandleClasses.begin(), HandleClasses.end())))
+                    .bind("handle")) {}
+
+void DanglingHandleCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "HandleClasses",
+                utils::options::serializeStringList(HandleClasses));
+}
+
+void DanglingHandleCheck::registerMatchersForVariables(MatchFinder *Finder) {
+  const auto ConvertedHandle = handleFromTemporaryValue(IsAHandle);
+
+  // Find 'Handle foo(ReturnsAValue());'
+  Finder->addMatcher(
+      varDecl(hasType(hasUnqualifiedDesugaredType(
+                  recordType(hasDeclaration(cxxRecordDecl(IsAHandle))))),
+              hasInitializer(
+                  exprWithCleanups(has(ignoringParenImpCasts(ConvertedHandle)))
+                      .bind("bad_stmt"))),
+      this);
+
+  // Find 'Handle foo = ReturnsAValue();'
+  Finder->addMatcher(
+      varDecl(
+          hasType(hasUnqualifiedDesugaredType(
+              recordType(hasDeclaration(cxxRecordDecl(IsAHandle))))),
+          unless(parmVarDecl()),
+          hasInitializer(exprWithCleanups(has(ignoringParenImpCasts(handleFrom(
+                                              IsAHandle, ConvertedHandle))))
+                             .bind("bad_stmt"))),
+      this);
+  // Find 'foo = ReturnsAValue();  // foo is Handle'
+  Finder->addMatcher(
+      cxxOperatorCallExpr(callee(cxxMethodDecl(ofClass(IsAHandle))),
+                          hasOverloadedOperatorName("="),
+                          hasArgument(1, ConvertedHandle))
+          .bind("bad_stmt"),
+      this);
+
+  // Container insertions that will dangle.
+  Finder->addMatcher(makeContainerMatcher(IsAHandle).bind("bad_stmt"), this);
+}
+
+void DanglingHandleCheck::registerMatchersForReturn(MatchFinder *Finder) {
+  // Return a local.
+  Finder->addMatcher(
+      returnStmt(
+          // The AST contains two constructor calls:
+          //   1. Value to Handle conversion.
+          //   2. Handle copy construction.
+          // 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(hasUnqualifiedDesugaredType(
+                                       recordType(hasDeclaration(recordDecl(
+                                           unless(IsAHandle)))))))))))))),
+          // Temporary fix for false positives inside lambdas.
+          unless(hasAncestor(lambdaExpr())))
+          .bind("bad_stmt"),
+      this);
+
+  // Return a temporary.
+  Finder->addMatcher(
+      returnStmt(
+          has(ignoringParenImpCasts(exprWithCleanups(has(ignoringParenImpCasts(
+              handleFrom(IsAHandle, handleFromTemporaryValue(IsAHandle))))))))
+          .bind("bad_stmt"),
+      this);
+}
+
+void DanglingHandleCheck::registerMatchers(MatchFinder *Finder) {
+  registerMatchersForVariables(Finder);
+  registerMatchersForReturn(Finder);
+}
+
+void DanglingHandleCheck::check(const MatchFinder::MatchResult &Result) {
+  auto *Handle = Result.Nodes.getNodeAs<CXXRecordDecl>("handle");
+  diag(Result.Nodes.getNodeAs<Stmt>("bad_stmt")->getLocStart(),
+       "%0 outlives its value")
+      << Handle->getQualifiedNameAsString();
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.h
new file mode 100644
index 0000000..add8d42
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.h
@@ -0,0 +1,43 @@
+//===--- DanglingHandleCheck.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_DANGLING_HANDLE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DANGLING_HANDLE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Detect dangling references in value handlers like
+/// std::experimental::string_view.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-dangling-handle.html
+class DanglingHandleCheck : public ClangTidyCheck {
+public:
+  DanglingHandleCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  void registerMatchersForVariables(ast_matchers::MatchFinder *Finder);
+  void registerMatchersForReturn(ast_matchers::MatchFinder *Finder);
+
+  const std::vector<std::string> HandleClasses;
+  const ast_matchers::internal::Matcher<RecordDecl> IsAHandle;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DANGLING_HANDLE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp
new file mode 100644
index 0000000..416cf3f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp
@@ -0,0 +1,214 @@
+//===--- ExceptionEscapeCheck.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 "ExceptionEscapeCheck.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringSet.h"
+
+using namespace clang::ast_matchers;
+
+namespace {
+typedef llvm::SmallVector<const clang::Type *, 8> TypeVec;
+} // namespace
+
+namespace clang {
+
+static bool isBaseOf(const Type *DerivedType, const Type *BaseType) {
+  const auto *DerivedClass = DerivedType->getAsCXXRecordDecl();
+  const auto *BaseClass = BaseType->getAsCXXRecordDecl();
+  if (!DerivedClass || !BaseClass)
+    return false;
+
+  return !DerivedClass->forallBases(
+      [BaseClass](const CXXRecordDecl *Cur) { return Cur != BaseClass; });
+}
+
+static const TypeVec
+throwsException(const Stmt *St, const TypeVec &Caught,
+                llvm::SmallSet<const FunctionDecl *, 32> &CallStack);
+
+static const TypeVec
+throwsException(const FunctionDecl *Func,
+                llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
+  if (CallStack.count(Func))
+    return TypeVec();
+
+  if (const Stmt *Body = Func->getBody()) {
+    CallStack.insert(Func);
+    const TypeVec Result = throwsException(Body, TypeVec(), CallStack);
+    CallStack.erase(Func);
+    return Result;
+  }
+
+  TypeVec Result;
+  if (const auto *FPT = Func->getType()->getAs<FunctionProtoType>()) {
+    for (const QualType Ex : FPT->exceptions()) {
+      Result.push_back(Ex.getTypePtr());
+    }
+  }
+  return Result;
+}
+
+static const TypeVec
+throwsException(const Stmt *St, const TypeVec &Caught,
+                llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
+  TypeVec Results;
+
+  if (!St)
+    return Results;
+
+  if (const auto *Throw = dyn_cast<CXXThrowExpr>(St)) {
+    if (const auto *ThrownExpr = Throw->getSubExpr()) {
+      const auto *ThrownType =
+          ThrownExpr->getType()->getUnqualifiedDesugaredType();
+      if (ThrownType->isReferenceType()) {
+        ThrownType = ThrownType->castAs<ReferenceType>()
+                         ->getPointeeType()
+                         ->getUnqualifiedDesugaredType();
+      }
+      if (const auto *TD = ThrownType->getAsTagDecl()) {
+        if (TD->getDeclName().isIdentifier() && TD->getName() == "bad_alloc"
+            && TD->isInStdNamespace())
+          return Results;
+      }
+      Results.push_back(ThrownExpr->getType()->getUnqualifiedDesugaredType());
+    } else {
+      Results.append(Caught.begin(), Caught.end());
+    }
+  } else if (const auto *Try = dyn_cast<CXXTryStmt>(St)) {
+    TypeVec Uncaught = throwsException(Try->getTryBlock(), Caught, CallStack);
+    for (unsigned i = 0; i < Try->getNumHandlers(); ++i) {
+      const CXXCatchStmt *Catch = Try->getHandler(i);
+      if (!Catch->getExceptionDecl()) {
+        const TypeVec Rethrown =
+            throwsException(Catch->getHandlerBlock(), Uncaught, CallStack);
+        Results.append(Rethrown.begin(), Rethrown.end());
+        Uncaught.clear();
+      } else {
+        const auto *CaughtType =
+            Catch->getCaughtType()->getUnqualifiedDesugaredType();
+        if (CaughtType->isReferenceType()) {
+          CaughtType = CaughtType->castAs<ReferenceType>()
+                           ->getPointeeType()
+                           ->getUnqualifiedDesugaredType();
+        }
+        auto NewEnd =
+            llvm::remove_if(Uncaught, [&CaughtType](const Type *ThrownType) {
+              return ThrownType == CaughtType ||
+                     isBaseOf(ThrownType, CaughtType);
+            });
+        if (NewEnd != Uncaught.end()) {
+          Uncaught.erase(NewEnd, Uncaught.end());
+          const TypeVec Rethrown = throwsException(
+              Catch->getHandlerBlock(), TypeVec(1, CaughtType), CallStack);
+          Results.append(Rethrown.begin(), Rethrown.end());
+        }
+      }
+    }
+    Results.append(Uncaught.begin(), Uncaught.end());
+  } else if (const auto *Call = dyn_cast<CallExpr>(St)) {
+    if (const FunctionDecl *Func = Call->getDirectCallee()) {
+      TypeVec Excs = throwsException(Func, CallStack);
+      Results.append(Excs.begin(), Excs.end());
+    }
+  } else {
+    for (const Stmt *Child : St->children()) {
+      TypeVec Excs = throwsException(Child, Caught, CallStack);
+      Results.append(Excs.begin(), Excs.end());
+    }
+  }
+  return Results;
+}
+
+static const TypeVec throwsException(const FunctionDecl *Func) {
+  llvm::SmallSet<const FunctionDecl *, 32> CallStack;
+  return throwsException(Func, CallStack);
+}
+
+namespace ast_matchers {
+AST_MATCHER_P(FunctionDecl, throws, internal::Matcher<Type>, InnerMatcher) {
+  TypeVec ExceptionList = throwsException(&Node);
+  auto NewEnd = llvm::remove_if(
+      ExceptionList, [this, Finder, Builder](const Type *Exception) {
+        return !InnerMatcher.matches(*Exception, Finder, Builder);
+      });
+  ExceptionList.erase(NewEnd, ExceptionList.end());
+  return ExceptionList.size();
+}
+
+AST_MATCHER_P(Type, isIgnored, llvm::StringSet<>, IgnoredExceptions) {
+  if (const auto *TD = Node.getAsTagDecl()) {
+    if (TD->getDeclName().isIdentifier())
+      return IgnoredExceptions.count(TD->getName()) > 0;
+  }
+  return false;
+}
+
+AST_MATCHER_P(FunctionDecl, isEnabled, llvm::StringSet<>,
+              FunctionsThatShouldNotThrow) {
+  return FunctionsThatShouldNotThrow.count(Node.getNameAsString()) > 0;
+}
+} // namespace ast_matchers
+
+namespace tidy {
+namespace bugprone {
+
+ExceptionEscapeCheck::ExceptionEscapeCheck(StringRef Name,
+                                           ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context), RawFunctionsThatShouldNotThrow(Options.get(
+                                         "FunctionsThatShouldNotThrow", "")),
+      RawIgnoredExceptions(Options.get("IgnoredExceptions", "")) {
+  llvm::SmallVector<StringRef, 8> FunctionsThatShouldNotThrowVec,
+      IgnoredExceptionsVec;
+  StringRef(RawFunctionsThatShouldNotThrow)
+      .split(FunctionsThatShouldNotThrowVec, ",", -1, false);
+  FunctionsThatShouldNotThrow.insert(FunctionsThatShouldNotThrowVec.begin(),
+                                     FunctionsThatShouldNotThrowVec.end());
+  StringRef(RawIgnoredExceptions).split(IgnoredExceptionsVec, ",", -1, false);
+  IgnoredExceptions.insert(IgnoredExceptionsVec.begin(),
+                           IgnoredExceptionsVec.end());
+}
+
+void ExceptionEscapeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "FunctionsThatShouldNotThrow",
+                RawFunctionsThatShouldNotThrow);
+  Options.store(Opts, "IgnoredExceptions", RawIgnoredExceptions);
+}
+
+void ExceptionEscapeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      functionDecl(allOf(anyOf(isNoThrow(), cxxDestructorDecl(),
+                               cxxConstructorDecl(isMoveConstructor()),
+                               cxxMethodDecl(isMoveAssignmentOperator()),
+                               hasName("main"), hasName("swap"),
+                               isEnabled(FunctionsThatShouldNotThrow)),
+                         throws(unless(isIgnored(IgnoredExceptions)))))
+          .bind("thrower"),
+      this);
+}
+
+void ExceptionEscapeCheck::check(const MatchFinder::MatchResult &Result) {
+  const FunctionDecl *MatchedDecl =
+      Result.Nodes.getNodeAs<FunctionDecl>("thrower");
+  if (!MatchedDecl)
+    return;
+
+  // FIXME: We should provide more information about the exact location where
+  // the exception is thrown, maybe the full path the exception escapes
+  diag(MatchedDecl->getLocation(), "an exception may be thrown in function %0 "
+       "which should not throw exceptions") << MatchedDecl;
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h
new file mode 100644
index 0000000..d690022
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h
@@ -0,0 +1,47 @@
+//===--- ExceptionEscapeCheck.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_EXCEPTION_ESCAPE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTION_ESCAPE_H
+
+#include "../ClangTidy.h"
+
+#include "llvm/ADT/StringSet.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds functions which should not throw exceptions: Destructors, move
+/// constructors, move assignment operators, the main() function,
+/// swap() functions, functions marked with throw() or noexcept and functions
+/// given as option to the checker.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-exception-escape.html
+class ExceptionEscapeCheck : public ClangTidyCheck {
+public:
+  ExceptionEscapeCheck(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:
+  std::string RawFunctionsThatShouldNotThrow;
+  std::string RawIgnoredExceptions;
+
+  llvm::StringSet<> FunctionsThatShouldNotThrow;
+  llvm::StringSet<> IgnoredExceptions;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTION_ESCAPE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.cpp
new file mode 100644
index 0000000..6d7fd28
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.cpp
@@ -0,0 +1,140 @@
+//===--- FoldInitTypeCheck.cpp - clang-tidy--------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FoldInitTypeCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void FoldInitTypeCheck::registerMatchers(MatchFinder *Finder) {
+  // We match functions of interest and bind the iterator and init value types.
+  // Note: Right now we check only builtin types.
+  const auto BuiltinTypeWithId = [](const char *ID) {
+    return hasCanonicalType(builtinType().bind(ID));
+  };
+  const auto IteratorWithValueType = [&BuiltinTypeWithId](const char *ID) {
+    return anyOf(
+        // Pointer types.
+        pointsTo(BuiltinTypeWithId(ID)),
+        // Iterator types.
+        recordType(hasDeclaration(has(typedefNameDecl(
+            hasName("value_type"), hasType(BuiltinTypeWithId(ID)))))));
+  };
+
+  const auto IteratorParam = parmVarDecl(
+      hasType(hasCanonicalType(IteratorWithValueType("IterValueType"))));
+  const auto Iterator2Param = parmVarDecl(
+      hasType(hasCanonicalType(IteratorWithValueType("Iter2ValueType"))));
+  const auto InitParam = parmVarDecl(hasType(BuiltinTypeWithId("InitType")));
+
+  // std::accumulate, std::reduce.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(
+                   hasAnyName("::std::accumulate", "::std::reduce"),
+                   hasParameter(0, IteratorParam), hasParameter(2, InitParam))),
+               argumentCountIs(3))
+          .bind("Call"),
+      this);
+  // std::inner_product.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasName("::std::inner_product"),
+                                   hasParameter(0, IteratorParam),
+                                   hasParameter(2, Iterator2Param),
+                                   hasParameter(3, InitParam))),
+               argumentCountIs(4))
+          .bind("Call"),
+      this);
+  // std::reduce with a policy.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasName("::std::reduce"),
+                                   hasParameter(1, IteratorParam),
+                                   hasParameter(3, InitParam))),
+               argumentCountIs(4))
+          .bind("Call"),
+      this);
+  // std::inner_product with a policy.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasName("::std::inner_product"),
+                                   hasParameter(1, IteratorParam),
+                                   hasParameter(3, Iterator2Param),
+                                   hasParameter(4, InitParam))),
+               argumentCountIs(5))
+          .bind("Call"),
+      this);
+}
+
+/// Returns true if ValueType is allowed to fold into InitType, i.e. if:
+///   static_cast<InitType>(ValueType{some_value})
+/// does not result in trucation.
+static bool isValidBuiltinFold(const BuiltinType &ValueType,
+                               const BuiltinType &InitType,
+                               const ASTContext &Context) {
+  const auto ValueTypeSize = Context.getTypeSize(&ValueType);
+  const auto InitTypeSize = Context.getTypeSize(&InitType);
+  // It's OK to fold a float into a float of bigger or equal size, but not OK to
+  // fold into an int.
+  if (ValueType.isFloatingPoint())
+    return InitType.isFloatingPoint() && InitTypeSize >= ValueTypeSize;
+  // It's OK to fold an int into:
+  //  - an int of the same size and signedness.
+  //  - a bigger int, regardless of signedness.
+  //  - FIXME: should it be a warning to fold into floating point?
+  if (ValueType.isInteger()) {
+    if (InitType.isInteger()) {
+      if (InitType.isSignedInteger() == ValueType.isSignedInteger())
+        return InitTypeSize >= ValueTypeSize;
+      return InitTypeSize > ValueTypeSize;
+    }
+    if (InitType.isFloatingPoint())
+      return InitTypeSize >= ValueTypeSize;
+  }
+  return false;
+}
+
+/// Prints a diagnostic if IterValueType doe snot fold into IterValueType (see
+// isValidBuiltinFold for details).
+void FoldInitTypeCheck::doCheck(const BuiltinType &IterValueType,
+                                const BuiltinType &InitType,
+                                const ASTContext &Context,
+                                const CallExpr &CallNode) {
+  if (!isValidBuiltinFold(IterValueType, InitType, Context)) {
+    diag(CallNode.getExprLoc(), "folding type %0 into type %1 might result in "
+                                "loss of precision")
+        << IterValueType.desugar() << InitType.desugar();
+  }
+}
+
+void FoldInitTypeCheck::check(const MatchFinder::MatchResult &Result) {
+  // Given the iterator and init value type retreived by the matchers,
+  // we check that the ::value_type of the iterator is compatible with
+  // the init value type.
+  const auto *InitType = Result.Nodes.getNodeAs<BuiltinType>("InitType");
+  const auto *IterValueType =
+      Result.Nodes.getNodeAs<BuiltinType>("IterValueType");
+  assert(InitType != nullptr);
+  assert(IterValueType != nullptr);
+
+  const auto *CallNode = Result.Nodes.getNodeAs<CallExpr>("Call");
+  assert(CallNode != nullptr);
+
+  doCheck(*IterValueType, *InitType, *Result.Context, *CallNode);
+
+  if (const auto *Iter2ValueType =
+          Result.Nodes.getNodeAs<BuiltinType>("Iter2ValueType"))
+    doCheck(*Iter2ValueType, *InitType, *Result.Context, *CallNode);
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.h
new file mode 100644
index 0000000..e6170de
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.h
@@ -0,0 +1,44 @@
+//===--- FoldInitTypeCheck.h - clang-tidy------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FOLD_INIT_TYPE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FOLD_INIT_TYPE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Find and flag invalid initializer values in folds, e.g. std::accumulate.
+/// Example:
+/// \code
+///   auto v = {65536L * 65536 * 65536};
+///   std::accumulate(begin(v), end(v), 0 /* int type is too small */);
+/// \endcode
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-fold-init-type.html
+class FoldInitTypeCheck : public ClangTidyCheck {
+public:
+  FoldInitTypeCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void doCheck(const BuiltinType &IterValueType, const BuiltinType &InitType,
+               const ASTContext &Context, const CallExpr &CallNode);
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FOLD_INIT_TYPE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp
new file mode 100644
index 0000000..9ea5b55
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp
@@ -0,0 +1,174 @@
+//===--- ForwardDeclarationNamespaceCheck.cpp - clang-tidy ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ForwardDeclarationNamespaceCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include <stack>
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void ForwardDeclarationNamespaceCheck::registerMatchers(MatchFinder *Finder) {
+  // Match all class declarations/definitions *EXCEPT*
+  // 1. implicit classes, e.g. `class A {};` has implicit `class A` inside `A`.
+  // 2. nested classes declared/defined inside another class.
+  // 3. template class declaration, template instantiation or
+  //    specialization (NOTE: extern specialization is filtered out by
+  //    `unless(hasAncestor(cxxRecordDecl()))`).
+  auto IsInSpecialization = hasAncestor(
+      decl(anyOf(cxxRecordDecl(isExplicitTemplateSpecialization()),
+                 functionDecl(isExplicitTemplateSpecialization()))));
+  Finder->addMatcher(
+      cxxRecordDecl(
+          hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl()))),
+          unless(isImplicit()), unless(hasAncestor(cxxRecordDecl())),
+          unless(isInstantiated()), unless(IsInSpecialization),
+          unless(classTemplateSpecializationDecl()))
+          .bind("record_decl"),
+      this);
+
+  // Match all friend declarations. Classes used in friend declarations are not
+  // marked as referenced in AST. We need to record all record classes used in
+  // friend declarations.
+  Finder->addMatcher(friendDecl().bind("friend_decl"), this);
+}
+
+void ForwardDeclarationNamespaceCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  if (const auto *RecordDecl =
+          Result.Nodes.getNodeAs<CXXRecordDecl>("record_decl")) {
+    StringRef DeclName = RecordDecl->getName();
+    if (RecordDecl->isThisDeclarationADefinition()) {
+      DeclNameToDefinitions[DeclName].push_back(RecordDecl);
+    } else {
+      // If a declaration has no definition, the definition could be in another
+      // namespace (a wrong namespace).
+      // NOTE: even a declaration does have definition, we still need it to
+      // compare with other declarations.
+      DeclNameToDeclarations[DeclName].push_back(RecordDecl);
+    }
+  } else {
+    const auto *Decl = Result.Nodes.getNodeAs<FriendDecl>("friend_decl");
+    assert(Decl && "Decl is neither record_decl nor friend decl!");
+
+    // Classes used in friend delarations are not marked referenced in AST,
+    // so we need to check classes used in friend declarations manually to
+    // reduce the rate of false positive.
+    // For example, in
+    //    \code
+    //      struct A;
+    //      struct B { friend A; };
+    //    \endcode
+    // `A` will not be marked as "referenced" in the AST.
+    if (const TypeSourceInfo *Tsi = Decl->getFriendType()) {
+      QualType Desugared = Tsi->getType().getDesugaredType(*Result.Context);
+      FriendTypes.insert(Desugared.getTypePtr());
+    }
+  }
+}
+
+static bool haveSameNamespaceOrTranslationUnit(const CXXRecordDecl *Decl1,
+                                               const CXXRecordDecl *Decl2) {
+  const DeclContext *ParentDecl1 = Decl1->getLexicalParent();
+  const DeclContext *ParentDecl2 = Decl2->getLexicalParent();
+
+  // Since we only matched declarations whose parent is Namespace or
+  // TranslationUnit declaration, the parent should be either a translation unit
+  // or namespace.
+  if (ParentDecl1->getDeclKind() == Decl::TranslationUnit ||
+      ParentDecl2->getDeclKind() == Decl::TranslationUnit) {
+    return ParentDecl1 == ParentDecl2;
+  }
+  assert(ParentDecl1->getDeclKind() == Decl::Namespace &&
+         "ParentDecl1 declaration must be a namespace");
+  assert(ParentDecl2->getDeclKind() == Decl::Namespace &&
+         "ParentDecl2 declaration must be a namespace");
+  auto *Ns1 = NamespaceDecl::castFromDeclContext(ParentDecl1);
+  auto *Ns2 = NamespaceDecl::castFromDeclContext(ParentDecl2);
+  return Ns1->getOriginalNamespace() == Ns2->getOriginalNamespace();
+}
+
+static std::string getNameOfNamespace(const CXXRecordDecl *Decl) {
+  const auto *ParentDecl = Decl->getLexicalParent();
+  if (ParentDecl->getDeclKind() == Decl::TranslationUnit) {
+    return "(global)";
+  }
+  const auto *NsDecl = cast<NamespaceDecl>(ParentDecl);
+  std::string Ns;
+  llvm::raw_string_ostream OStream(Ns);
+  NsDecl->printQualifiedName(OStream);
+  OStream.flush();
+  return Ns.empty() ? "(global)" : Ns;
+}
+
+void ForwardDeclarationNamespaceCheck::onEndOfTranslationUnit() {
+  // Iterate each group of declarations by name.
+  for (const auto &KeyValuePair : DeclNameToDeclarations) {
+    const auto &Declarations = KeyValuePair.second;
+    // If more than 1 declaration exists, we check if all are in the same
+    // namespace.
+    for (const auto *CurDecl : Declarations) {
+      if (CurDecl->hasDefinition() || CurDecl->isReferenced()) {
+        continue; // Skip forward declarations that are used/referenced.
+      }
+      if (FriendTypes.count(CurDecl->getTypeForDecl()) != 0) {
+        continue; // Skip forward declarations referenced as friend.
+      }
+      if (CurDecl->getLocation().isMacroID() ||
+          CurDecl->getLocation().isInvalid()) {
+        continue;
+      }
+      // Compare with all other declarations with the same name.
+      for (const auto *Decl : Declarations) {
+        if (Decl == CurDecl) {
+          continue; // Don't compare with self.
+        }
+        if (!CurDecl->hasDefinition() &&
+            !haveSameNamespaceOrTranslationUnit(CurDecl, Decl)) {
+          diag(CurDecl->getLocation(),
+               "declaration %0 is never referenced, but a declaration with "
+               "the same name found in another namespace '%1'")
+              << CurDecl << getNameOfNamespace(Decl);
+          diag(Decl->getLocation(), "a declaration of %0 is found here",
+               DiagnosticIDs::Note)
+              << Decl;
+          break; // FIXME: We only generate one warning for each declaration.
+        }
+      }
+      // Check if a definition in another namespace exists.
+      const auto DeclName = CurDecl->getName();
+      if (DeclNameToDefinitions.find(DeclName) == DeclNameToDefinitions.end()) {
+        continue; // No definition in this translation unit, we can skip it.
+      }
+      // Make a warning for each definition with the same name (in other
+      // namespaces).
+      const auto &Definitions = DeclNameToDefinitions[DeclName];
+      for (const auto *Def : Definitions) {
+        diag(CurDecl->getLocation(),
+             "no definition found for %0, but a definition with "
+             "the same name %1 found in another namespace '%2'")
+            << CurDecl << Def << getNameOfNamespace(Def);
+        diag(Def->getLocation(), "a definition of %0 is found here",
+             DiagnosticIDs::Note)
+            << Def;
+      }
+    }
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.h
new file mode 100644
index 0000000..c3d3018
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.h
@@ -0,0 +1,59 @@
+//===--- ForwardDeclarationNamespaceCheck.h - clang-tidy --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FORWARDDECLARATIONNAMESPACECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FORWARDDECLARATIONNAMESPACECHECK_H
+
+#include "../ClangTidy.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include <set>
+#include <vector>
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Checks if an unused forward declaration is in a wrong namespace.
+///
+/// The check inspects all unused forward declarations and checks if there is
+/// any declaration/definition with the same name, which could indicate
+/// that the forward declaration is potentially in a wrong namespace.
+///
+/// \code
+///   namespace na { struct A; }
+///   namespace nb { struct A {} };
+///   nb::A a;
+///   // warning : no definition found for 'A', but a definition with the same
+///   name 'A' found in another namespace 'nb::'
+/// \endcode
+///
+/// This check can only generate warnings, but it can't suggest fixes at this
+/// point.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-forward-declaration-namespace.html
+class ForwardDeclarationNamespaceCheck : public ClangTidyCheck {
+public:
+  ForwardDeclarationNamespaceCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void onEndOfTranslationUnit() override;
+
+private:
+  llvm::StringMap<std::vector<const CXXRecordDecl *>> DeclNameToDefinitions;
+  llvm::StringMap<std::vector<const CXXRecordDecl *>> DeclNameToDeclarations;
+  llvm::SmallPtrSet<const Type *, 16> FriendTypes;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FORWARDDECLARATIONNAMESPACECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
new file mode 100644
index 0000000..17bdc76
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
@@ -0,0 +1,148 @@
+//===--- ForwardingReferenceOverloadCheck.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 "ForwardingReferenceOverloadCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include <algorithm>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+// Check if the given type is related to std::enable_if.
+AST_MATCHER(QualType, isEnableIf) {
+  auto CheckTemplate = [](const TemplateSpecializationType *Spec) {
+    if (!Spec || !Spec->getTemplateName().getAsTemplateDecl()) {
+      return false;
+    }
+    const NamedDecl *TypeDecl =
+        Spec->getTemplateName().getAsTemplateDecl()->getTemplatedDecl();
+    return TypeDecl->isInStdNamespace() &&
+           (TypeDecl->getName().equals("enable_if") ||
+            TypeDecl->getName().equals("enable_if_t"));
+  };
+  const Type *BaseType = Node.getTypePtr();
+  // Case: pointer or reference to enable_if.
+  while (BaseType->isPointerType() || BaseType->isReferenceType()) {
+    BaseType = BaseType->getPointeeType().getTypePtr();
+  }
+  // Case: type parameter dependent (enable_if<is_integral<T>>).
+  if (const auto *Dependent = BaseType->getAs<DependentNameType>()) {
+    BaseType = Dependent->getQualifier()->getAsType();
+  }
+  if (!BaseType)
+    return false;
+  if (CheckTemplate(BaseType->getAs<TemplateSpecializationType>())) {
+    return true; // Case: enable_if_t< >.
+  } else if (const auto *Elaborated = BaseType->getAs<ElaboratedType>()) {
+    if (const auto *Qualifier = Elaborated->getQualifier()->getAsType()) {
+      if (CheckTemplate(Qualifier->getAs<TemplateSpecializationType>())) {
+        return true; // Case: enable_if< >::type.
+      }
+    }
+  }
+  return false;
+}
+AST_MATCHER_P(TemplateTypeParmDecl, hasDefaultArgument,
+              clang::ast_matchers::internal::Matcher<QualType>, TypeMatcher) {
+  return Node.hasDefaultArgument() &&
+         TypeMatcher.matches(Node.getDefaultArgument(), Finder, Builder);
+}
+} // namespace
+
+void ForwardingReferenceOverloadCheck::registerMatchers(MatchFinder *Finder) {
+  // Forwarding references require C++11 or later.
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  auto ForwardingRefParm =
+      parmVarDecl(
+          hasType(qualType(rValueReferenceType(),
+                           references(templateTypeParmType(hasDeclaration(
+                               templateTypeParmDecl().bind("type-parm-decl")))),
+                           unless(references(isConstQualified())))))
+          .bind("parm-var");
+
+  DeclarationMatcher findOverload =
+      cxxConstructorDecl(
+          hasParameter(0, ForwardingRefParm),
+          unless(hasAnyParameter(
+              // No warning: enable_if as constructor parameter.
+              parmVarDecl(hasType(isEnableIf())))),
+          unless(hasParent(functionTemplateDecl(has(templateTypeParmDecl(
+              // No warning: enable_if as type parameter.
+              hasDefaultArgument(isEnableIf())))))))
+          .bind("ctor");
+  Finder->addMatcher(findOverload, this);
+}
+
+void ForwardingReferenceOverloadCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *ParmVar = Result.Nodes.getNodeAs<ParmVarDecl>("parm-var");
+  const auto *TypeParmDecl =
+      Result.Nodes.getNodeAs<TemplateTypeParmDecl>("type-parm-decl");
+
+  // Get the FunctionDecl and FunctionTemplateDecl containing the function
+  // parameter.
+  const auto *FuncForParam = dyn_cast<FunctionDecl>(ParmVar->getDeclContext());
+  if (!FuncForParam)
+    return;
+  const FunctionTemplateDecl *FuncTemplate =
+      FuncForParam->getDescribedFunctionTemplate();
+  if (!FuncTemplate)
+    return;
+
+  // Check that the template type parameter belongs to the same function
+  // template as the function parameter of that type. (This implies that type
+  // deduction will happen on the type.)
+  const TemplateParameterList *Params = FuncTemplate->getTemplateParameters();
+  if (std::find(Params->begin(), Params->end(), TypeParmDecl) == Params->end())
+    return;
+
+  // Every parameter after the first must have a default value.
+  const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
+  for (auto Iter = Ctor->param_begin() + 1; Iter != Ctor->param_end(); ++Iter) {
+    if (!(*Iter)->hasDefaultArg())
+      return;
+  }
+  bool EnabledCopy = false, DisabledCopy = false, EnabledMove = false,
+       DisabledMove = false;
+  for (const auto *OtherCtor : Ctor->getParent()->ctors()) {
+    if (OtherCtor->isCopyOrMoveConstructor()) {
+      if (OtherCtor->isDeleted() || OtherCtor->getAccess() == AS_private)
+        (OtherCtor->isCopyConstructor() ? DisabledCopy : DisabledMove) = true;
+      else
+        (OtherCtor->isCopyConstructor() ? EnabledCopy : EnabledMove) = true;
+    }
+  }
+  bool Copy = (!EnabledMove && !DisabledMove && !DisabledCopy) || EnabledCopy;
+  bool Move = !DisabledMove || EnabledMove;
+  if (!Copy && !Move)
+    return;
+  diag(Ctor->getLocation(),
+       "constructor accepting a forwarding reference can "
+       "hide the %select{copy|move|copy and move}0 constructor%s1")
+      << (Copy && Move ? 2 : (Copy ? 0 : 1)) << Copy + Move;
+  for (const auto *OtherCtor : Ctor->getParent()->ctors()) {
+    if (OtherCtor->isCopyOrMoveConstructor() && !OtherCtor->isDeleted() &&
+        OtherCtor->getAccess() != AS_private) {
+      diag(OtherCtor->getLocation(),
+           "%select{copy|move}0 constructor declared here", DiagnosticIDs::Note)
+          << OtherCtor->isMoveConstructor();
+    }
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.h
new file mode 100644
index 0000000..4b00ab2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.h
@@ -0,0 +1,42 @@
+//===--- ForwardingReferenceOverloadCheck.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_FORWARDINGREFERENCEOVERLOADCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FORWARDINGREFERENCEOVERLOADCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// The checker looks for constructors that can act as copy or move constructors
+/// through their forwarding reference parameters. If a non const lvalue
+/// reference is passed to the constructor, the forwarding reference parameter
+/// can be a perfect match while the const reference parameter of the copy
+/// constructor can't. The forwarding reference constructor will be called,
+/// which can lead to confusion.
+/// For detailed description of this problem see: Scott Meyers, Effective Modern
+/// C++ Design, item 26.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-forwarding-reference-overload.html
+class ForwardingReferenceOverloadCheck : public ClangTidyCheck {
+public:
+  ForwardingReferenceOverloadCheck(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_FORWARDINGREFERENCEOVERLOADCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp
new file mode 100644
index 0000000..cf1be0e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp
@@ -0,0 +1,81 @@
+//===--- InaccurateEraseCheck.cpp - clang-tidy-----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InaccurateEraseCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+AST_MATCHER(Decl, isInStdNamespace) { return Node.isInStdNamespace(); }
+}
+
+void InaccurateEraseCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  const auto EndCall =
+      callExpr(
+          callee(functionDecl(hasAnyName("remove", "remove_if", "unique"))),
+          hasArgument(
+              1,
+              anyOf(cxxConstructExpr(has(ignoringImplicit(
+                        cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end"))))
+                            .bind("end")))),
+                    anything())))
+          .bind("alg");
+
+  const auto DeclInStd = type(hasUnqualifiedDesugaredType(
+      tagType(hasDeclaration(decl(isInStdNamespace())))));
+  Finder->addMatcher(
+      cxxMemberCallExpr(
+          on(anyOf(hasType(DeclInStd), hasType(pointsTo(DeclInStd)))),
+          callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1),
+          hasArgument(0, has(ignoringImplicit(
+                             anyOf(EndCall, has(ignoringImplicit(EndCall)))))),
+          unless(isInTemplateInstantiation()))
+          .bind("erase"),
+      this);
+}
+
+void InaccurateEraseCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MemberCall =
+      Result.Nodes.getNodeAs<CXXMemberCallExpr>("erase");
+  const auto *EndExpr =
+      Result.Nodes.getNodeAs<CXXMemberCallExpr>("end");
+  const SourceLocation Loc = MemberCall->getLocStart();
+
+  FixItHint Hint;
+
+  if (!Loc.isMacroID() && EndExpr) {
+    const auto *AlgCall = Result.Nodes.getNodeAs<CallExpr>("alg");
+    std::string ReplacementText = Lexer::getSourceText(
+        CharSourceRange::getTokenRange(EndExpr->getSourceRange()),
+        *Result.SourceManager, getLangOpts());
+    const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+        AlgCall->getLocEnd(), 0, *Result.SourceManager, getLangOpts());
+    Hint = FixItHint::CreateInsertion(EndLoc, ", " + ReplacementText);
+  }
+
+  diag(Loc, "this call will remove at most one item even when multiple items "
+            "should be removed")
+      << Hint;
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.h
new file mode 100644
index 0000000..d6b3729
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.h
@@ -0,0 +1,38 @@
+//===--- InaccurateEraseCheck.h - clang-tidy---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INACCURATEERASECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INACCURATEERASECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Checks for inaccurate use of the `erase()` method.
+///
+/// Algorithms like `remove()` do not actually remove any element from the
+/// container but return an iterator to the first redundant element at the end
+/// of the container. These redundant elements must be removed using the
+/// `erase()` method. This check warns when not all of the elements will be
+/// removed due to using an inappropriate overload.
+class InaccurateEraseCheck : public ClangTidyCheck {
+public:
+  InaccurateEraseCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INACCURATEERASECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp
new file mode 100644
index 0000000..ab7b28d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp
@@ -0,0 +1,71 @@
+//===--- IncorrectRoundingsCheck.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 "IncorrectRoundingsCheck.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/Type.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 bugprone {
+
+namespace {
+AST_MATCHER(FloatingLiteral, floatHalf) {
+  const auto &literal = Node.getValue();
+  if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
+    return literal.convertToFloat() == 0.5f;
+  if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
+    return literal.convertToDouble() == 0.5;
+  return false;
+}
+} // namespace
+
+void IncorrectRoundingsCheck::registerMatchers(MatchFinder *MatchFinder) {
+  // Match a floating literal with value 0.5.
+  auto FloatHalf = floatLiteral(floatHalf());
+
+  // Match a floating point expression.
+  auto FloatType = expr(hasType(realFloatingPointType()));
+
+  // Match a floating literal of 0.5 or a floating literal of 0.5 implicitly.
+  // cast to floating type.
+  auto FloatOrCastHalf =
+      anyOf(FloatHalf,
+            implicitCastExpr(FloatType, has(ignoringParenImpCasts(FloatHalf))));
+
+  // Match if either the LHS or RHS is a floating literal of 0.5 or a floating
+  // literal of 0.5 and the other is of type double or vice versa.
+  auto OneSideHalf = anyOf(allOf(hasLHS(FloatOrCastHalf), hasRHS(FloatType)),
+                           allOf(hasRHS(FloatOrCastHalf), hasLHS(FloatType)));
+
+  // Find expressions of cast to int of the sum of a floating point expression
+  // and 0.5.
+  MatchFinder->addMatcher(
+      implicitCastExpr(
+          hasImplicitDestinationType(isInteger()),
+          ignoringParenCasts(binaryOperator(hasOperatorName("+"), OneSideHalf)))
+          .bind("CastExpr"),
+      this);
+}
+
+void IncorrectRoundingsCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *CastExpr = Result.Nodes.getNodeAs<ImplicitCastExpr>("CastExpr");
+  diag(CastExpr->getLocStart(),
+       "casting (double + 0.5) to integer leads to incorrect rounding; "
+       "consider using lround (#include <cmath>) instead");
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.h
new file mode 100644
index 0000000..b1886fd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.h
@@ -0,0 +1,39 @@
+//===--- IncorrectRoundingsCheck.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_INCORRECTROUNDINGSCHECK_H_
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INCORRECTROUNDINGSCHECK_H_
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// \brief Checks the usage of patterns known to produce incorrect rounding.
+/// Programmers often use
+///   (int)(double_expression + 0.5)
+/// to round the double expression to an integer. The problem with this
+///  1. It is unnecessarily slow.
+///  2. It is incorrect. The number 0.499999975 (smallest representable float
+///     number below 0.5) rounds to 1.0. Even worse behavior for negative
+///     numbers where both -0.5f and -1.4f both round to 0.0.
+class IncorrectRoundingsCheck : public ClangTidyCheck {
+public:
+  IncorrectRoundingsCheck(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_INCORRECTROUNDINGSCHECK_H_
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.cpp
new file mode 100644
index 0000000..1b4eaea
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.h
new file mode 100644
index 0000000..307e493
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp
new file mode 100644
index 0000000..55dbe8b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp
@@ -0,0 +1,99 @@
+//===--- LambdaFunctionNameCheck.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 "LambdaFunctionNameCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+
+// Keep track of macro expansions that contain both __FILE__ and __LINE__. If
+// such a macro also uses __func__ or __FUNCTION__, we don't want to issue a
+// warning because __FILE__ and __LINE__ may be useful even if __func__ or
+// __FUNCTION__ is not, especially if the macro could be used in the context of
+// either a function body or a lambda body.
+class MacroExpansionsWithFileAndLine : public PPCallbacks {
+public:
+  explicit MacroExpansionsWithFileAndLine(
+      LambdaFunctionNameCheck::SourceRangeSet *SME)
+      : SuppressMacroExpansions(SME) {}
+
+  void MacroExpands(const Token &MacroNameTok,
+                    const MacroDefinition &MD, SourceRange Range,
+                    const MacroArgs *Args) override {
+    bool has_file = false;
+    bool has_line = false;
+    for (const auto& T : MD.getMacroInfo()->tokens()) {
+      if (T.is(tok::identifier)) {
+        StringRef IdentName = T.getIdentifierInfo()->getName();
+        if (IdentName == "__FILE__") {
+          has_file = true;
+        } else if (IdentName == "__LINE__") {
+          has_line = true;
+        }
+      }
+    }
+    if (has_file && has_line) {
+      SuppressMacroExpansions->insert(Range);
+    }
+  }
+
+private:
+  LambdaFunctionNameCheck::SourceRangeSet* SuppressMacroExpansions;
+};
+
+} // namespace
+
+void LambdaFunctionNameCheck::registerMatchers(MatchFinder *Finder) {
+  // Match on PredefinedExprs inside a lambda.
+  Finder->addMatcher(predefinedExpr(hasAncestor(lambdaExpr())).bind("E"),
+                     this);
+}
+
+void LambdaFunctionNameCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  Compiler.getPreprocessor().addPPCallbacks(
+      llvm::make_unique<MacroExpansionsWithFileAndLine>(
+          &SuppressMacroExpansions));
+}
+
+void LambdaFunctionNameCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *E = Result.Nodes.getNodeAs<PredefinedExpr>("E");
+  if (E->getIdentType() != PredefinedExpr::Func &&
+      E->getIdentType() != PredefinedExpr::Function) {
+    // We don't care about other PredefinedExprs.
+    return;
+  }
+  if (E->getLocation().isMacroID()) {
+    auto ER =
+        Result.SourceManager->getImmediateExpansionRange(E->getLocation());
+    if (SuppressMacroExpansions.find(ER.getAsRange()) !=
+        SuppressMacroExpansions.end()) {
+      // This is a macro expansion for which we should not warn.
+      return;
+    }
+  }
+  diag(E->getLocation(),
+       "inside a lambda, '%0' expands to the name of the function call "
+       "operator; consider capturing the name of the enclosing function "
+       "explicitly")
+      << PredefinedExpr::getIdentTypeName(E->getIdentType());
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.h
new file mode 100644
index 0000000..b7b1b44
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.h
@@ -0,0 +1,51 @@
+//===--- LambdaFunctionNameCheck.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_LAMBDAFUNCTIONNAMECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_LAMBDAFUNCTIONNAMECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Detect when __func__ or __FUNCTION__ is being used from within a lambda. In
+/// that context, those expressions expand to the name of the call operator
+/// (i.e., `operator()`).
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-lambda-function-name.html
+class LambdaFunctionNameCheck : public ClangTidyCheck {
+public:
+  struct SourceRangeLessThan {
+    bool operator()(const SourceRange &L, const SourceRange &R) const {
+      if (L.getBegin() == R.getBegin()) {
+        return L.getEnd() < R.getEnd();
+      }
+      return L.getBegin() < R.getBegin();
+    }
+  };
+  using SourceRangeSet = std::set<SourceRange, SourceRangeLessThan>;
+
+  LambdaFunctionNameCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  SourceRangeSet SuppressMacroExpansions;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_LAMBDAFUNCTIONNAMECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp
new file mode 100644
index 0000000..6846bc2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp
@@ -0,0 +1,260 @@
+//===--- MacroParenthesesCheck.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 "MacroParenthesesCheck.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+class MacroParenthesesPPCallbacks : public PPCallbacks {
+public:
+  MacroParenthesesPPCallbacks(Preprocessor *PP, MacroParenthesesCheck *Check)
+      : PP(PP), Check(Check) {}
+
+  void MacroDefined(const Token &MacroNameTok,
+                    const MacroDirective *MD) override {
+    replacementList(MacroNameTok, MD->getMacroInfo());
+    argument(MacroNameTok, MD->getMacroInfo());
+  }
+
+private:
+  /// Replacement list with calculations should be enclosed in parentheses.
+  void replacementList(const Token &MacroNameTok, const MacroInfo *MI);
+
+  /// Arguments should be enclosed in parentheses.
+  void argument(const Token &MacroNameTok, const MacroInfo *MI);
+
+  Preprocessor *PP;
+  MacroParenthesesCheck *Check;
+};
+} // namespace
+
+/// Is argument surrounded properly with parentheses/braces/squares/commas?
+static bool isSurroundedLeft(const Token &T) {
+  return T.isOneOf(tok::l_paren, tok::l_brace, tok::l_square, tok::comma,
+                   tok::semi);
+}
+
+/// Is argument surrounded properly with parentheses/braces/squares/commas?
+static bool isSurroundedRight(const Token &T) {
+  return T.isOneOf(tok::r_paren, tok::r_brace, tok::r_square, tok::comma,
+                   tok::semi);
+}
+
+/// Is given TokenKind a keyword?
+static bool isKeyword(const Token &T) {
+  // FIXME: better matching of keywords to avoid false positives.
+  return T.isOneOf(tok::kw_case, tok::kw_const, tok::kw_struct);
+}
+
+/// Warning is written when one of these operators are not within parentheses.
+static bool isWarnOp(const Token &T) {
+  // FIXME: This is an initial list of operators. It can be tweaked later to
+  // get more positives or perhaps avoid some false positive.
+  return T.isOneOf(tok::plus, tok::minus, tok::star, tok::slash, tok::percent,
+                   tok::amp, tok::pipe, tok::caret);
+}
+
+/// Is given Token a keyword that is used in variable declarations?
+static bool isVarDeclKeyword(const Token &T) {
+  return T.isOneOf(tok::kw_bool, tok::kw_char, tok::kw_short, tok::kw_int,
+                   tok::kw_long, tok::kw_float, tok::kw_double, tok::kw_const,
+                   tok::kw_enum, tok::kw_inline, tok::kw_static, tok::kw_struct,
+                   tok::kw_signed, tok::kw_unsigned);
+}
+
+/// Is there a possible variable declaration at Tok?
+static bool possibleVarDecl(const MacroInfo *MI, const Token *Tok) {
+  if (Tok == MI->tokens_end())
+    return false;
+
+  // If we see int/short/struct/etc., just assume this is a variable
+  // declaration.
+  if (isVarDeclKeyword(*Tok))
+    return true;
+
+  // Variable declarations start with identifier or coloncolon.
+  if (!Tok->isOneOf(tok::identifier, tok::raw_identifier, tok::coloncolon))
+    return false;
+
+  // Skip possible types, etc
+  while (Tok != MI->tokens_end() &&
+         Tok->isOneOf(tok::identifier, tok::raw_identifier, tok::coloncolon,
+                      tok::star, tok::amp, tok::ampamp, tok::less,
+                      tok::greater))
+    Tok++;
+
+  // Return true for possible variable declarations.
+  return Tok == MI->tokens_end() ||
+         Tok->isOneOf(tok::equal, tok::semi, tok::l_square, tok::l_paren) ||
+         isVarDeclKeyword(*Tok);
+}
+
+void MacroParenthesesPPCallbacks::replacementList(const Token &MacroNameTok,
+                                                  const MacroInfo *MI) {
+  // Make sure macro replacement isn't a variable declaration.
+  if (possibleVarDecl(MI, MI->tokens_begin()))
+    return;
+
+  // Count how deep we are in parentheses/braces/squares.
+  int Count = 0;
+
+  // SourceLocation for error
+  SourceLocation Loc;
+
+  for (auto TI = MI->tokens_begin(), TE = MI->tokens_end(); TI != TE; ++TI) {
+    const Token &Tok = *TI;
+    // Replacement list contains keywords, don't warn about it.
+    if (isKeyword(Tok))
+      return;
+    // When replacement list contains comma/semi don't warn about it.
+    if (Count == 0 && Tok.isOneOf(tok::comma, tok::semi))
+      return;
+    if (Tok.isOneOf(tok::l_paren, tok::l_brace, tok::l_square)) {
+      ++Count;
+    } else if (Tok.isOneOf(tok::r_paren, tok::r_brace, tok::r_square)) {
+      --Count;
+      // If there are unbalanced parentheses don't write any warning
+      if (Count < 0)
+        return;
+    } else if (Count == 0 && isWarnOp(Tok)) {
+      // Heuristic for macros that are clearly not intended to be enclosed in
+      // parentheses, macro starts with operator. For example:
+      // #define X     *10
+      if (TI == MI->tokens_begin() && (TI + 1) != TE &&
+          !Tok.isOneOf(tok::plus, tok::minus))
+        return;
+      // Don't warn about this macro if the last token is a star. For example:
+      // #define X    void *
+      if ((TE - 1)->is(tok::star))
+        return;
+
+      Loc = Tok.getLocation();
+    }
+  }
+  if (Loc.isValid()) {
+    const Token &Last = *(MI->tokens_end() - 1);
+    Check->diag(Loc, "macro replacement list should be enclosed in parentheses")
+        << FixItHint::CreateInsertion(MI->tokens_begin()->getLocation(), "(")
+        << FixItHint::CreateInsertion(Last.getLocation().getLocWithOffset(
+                                          PP->getSpelling(Last).length()),
+                                      ")");
+  }
+}
+
+void MacroParenthesesPPCallbacks::argument(const Token &MacroNameTok,
+                                           const MacroInfo *MI) {
+
+  // Skip variable declaration.
+  bool VarDecl = possibleVarDecl(MI, MI->tokens_begin());
+
+  for (auto TI = MI->tokens_begin(), TE = MI->tokens_end(); TI != TE; ++TI) {
+    // First token.
+    if (TI == MI->tokens_begin())
+      continue;
+
+    // Last token.
+    if ((TI + 1) == MI->tokens_end())
+      continue;
+
+    const Token &Prev = *(TI - 1);
+    const Token &Next = *(TI + 1);
+
+    const Token &Tok = *TI;
+
+    // There should not be extra parentheses in possible variable declaration.
+    if (VarDecl) {
+      if (Tok.isOneOf(tok::equal, tok::semi, tok::l_square, tok::l_paren))
+        VarDecl = false;
+      continue;
+    }
+
+    // Only interested in identifiers.
+    if (!Tok.isOneOf(tok::identifier, tok::raw_identifier))
+      continue;
+
+    // Only interested in macro arguments.
+    if (MI->getParameterNum(Tok.getIdentifierInfo()) < 0)
+      continue;
+
+    // Argument is surrounded with parentheses/squares/braces/commas.
+    if (isSurroundedLeft(Prev) && isSurroundedRight(Next))
+      continue;
+
+    // Don't warn after hash/hashhash or before hashhash.
+    if (Prev.isOneOf(tok::hash, tok::hashhash) || Next.is(tok::hashhash))
+      continue;
+
+    // Argument is a struct member.
+    if (Prev.isOneOf(tok::period, tok::arrow, tok::coloncolon, tok::arrowstar,
+                     tok::periodstar))
+      continue;
+
+    // Argument is a namespace or class.
+    if (Next.is(tok::coloncolon))
+      continue;
+
+    // String concatenation.
+    if (isStringLiteral(Prev.getKind()) || isStringLiteral(Next.getKind()))
+      continue;
+
+    // Type/Var.
+    if (isAnyIdentifier(Prev.getKind()) || isKeyword(Prev) ||
+        isAnyIdentifier(Next.getKind()) || isKeyword(Next))
+      continue;
+
+    // Initialization.
+    if (Next.is(tok::l_paren))
+      continue;
+
+    // Cast.
+    if (Prev.is(tok::l_paren) && Next.is(tok::star) &&
+        TI + 2 != MI->tokens_end() && (TI + 2)->is(tok::r_paren))
+      continue;
+
+    // Assignment/return, i.e. '=x;' or 'return x;'.
+    if (Prev.isOneOf(tok::equal, tok::kw_return) && Next.is(tok::semi))
+      continue;
+
+    // C++ template parameters.
+    if (PP->getLangOpts().CPlusPlus && Prev.isOneOf(tok::comma, tok::less) &&
+        Next.isOneOf(tok::comma, tok::greater))
+      continue;
+
+    // Namespaces.
+    if (Prev.is(tok::kw_namespace))
+      continue;
+
+    // Variadic templates
+    if (MI->isVariadic())
+      continue;
+
+    Check->diag(Tok.getLocation(), "macro argument should be enclosed in "
+                                   "parentheses")
+        << FixItHint::CreateInsertion(Tok.getLocation(), "(")
+        << FixItHint::CreateInsertion(Tok.getLocation().getLocWithOffset(
+                                          PP->getSpelling(Tok).length()),
+                                      ")");
+  }
+}
+
+void MacroParenthesesCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  Compiler.getPreprocessor().addPPCallbacks(
+      llvm::make_unique<MacroParenthesesPPCallbacks>(
+          &Compiler.getPreprocessor(), this));
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.h
new file mode 100644
index 0000000..383a6cc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.h
@@ -0,0 +1,43 @@
+//===--- MacroParenthesesCheck.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_MACROPARENTHESESCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MACROPARENTHESESCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds macros that can have unexpected behaviour due to missing parentheses.
+///
+/// Macros are expanded by the preprocessor as-is. As a result, there can be
+/// unexpected behaviour; operators may be evaluated in unexpected order and
+/// unary operators may become binary operators, etc.
+///
+/// When the replacement list has an expression, it is recommended to surround
+/// it with parentheses. This ensures that the macro result is evaluated
+/// completely before it is used.
+///
+/// It is also recommended to surround macro arguments in the replacement list
+/// with parentheses. This ensures that the argument value is calculated
+/// properly.
+class MacroParenthesesCheck : public ClangTidyCheck {
+public:
+  MacroParenthesesCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MACROPARENTHESESCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.cpp
new file mode 100644
index 0000000..30c770e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.cpp
@@ -0,0 +1,184 @@
+//===--- MacroRepeatedSideEffectsCheck.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 "MacroRepeatedSideEffectsCheck.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/MacroArgs.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+class MacroRepeatedPPCallbacks : public PPCallbacks {
+public:
+  MacroRepeatedPPCallbacks(ClangTidyCheck &Check, Preprocessor &PP)
+      : Check(Check), PP(PP) {}
+
+  void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
+                    SourceRange Range, const MacroArgs *Args) override;
+
+private:
+  ClangTidyCheck &Check;
+  Preprocessor &PP;
+
+  unsigned countArgumentExpansions(const MacroInfo *MI,
+                                   const IdentifierInfo *Arg) const;
+
+  bool hasSideEffects(const Token *ResultArgToks) const;
+};
+} // End of anonymous namespace.
+
+void MacroRepeatedPPCallbacks::MacroExpands(const Token &MacroNameTok,
+                                            const MacroDefinition &MD,
+                                            SourceRange Range,
+                                            const MacroArgs *Args) {
+  // Ignore macro argument expansions.
+  if (!Range.getBegin().isFileID())
+    return;
+
+  const MacroInfo *MI = MD.getMacroInfo();
+
+  // Bail out if the contents of the macro are containing keywords that are
+  // making the macro too complex.
+  if (std::find_if(
+          MI->tokens().begin(), MI->tokens().end(), [](const Token &T) {
+            return T.isOneOf(tok::kw_if, tok::kw_else, tok::kw_switch,
+                             tok::kw_case, tok::kw_break, tok::kw_while,
+                             tok::kw_do, tok::kw_for, tok::kw_continue,
+                             tok::kw_goto, tok::kw_return);
+          }) != MI->tokens().end())
+    return;
+
+  for (unsigned ArgNo = 0U; ArgNo < MI->getNumParams(); ++ArgNo) {
+    const IdentifierInfo *Arg = *(MI->param_begin() + ArgNo);
+    const Token *ResultArgToks = Args->getUnexpArgument(ArgNo);
+
+    if (hasSideEffects(ResultArgToks) &&
+        countArgumentExpansions(MI, Arg) >= 2) {
+      Check.diag(ResultArgToks->getLocation(),
+                 "side effects in the %ordinal0 macro argument %1 are "
+                 "repeated in macro expansion")
+          << (ArgNo + 1) << Arg;
+      Check.diag(MI->getDefinitionLoc(), "macro %0 defined here",
+                 DiagnosticIDs::Note)
+          << MacroNameTok.getIdentifierInfo();
+    }
+  }
+}
+
+unsigned MacroRepeatedPPCallbacks::countArgumentExpansions(
+    const MacroInfo *MI, const IdentifierInfo *Arg) const {
+  // Current argument count. When moving forward to a different control-flow
+  // path this can decrease.
+  unsigned Current = 0;
+  // Max argument count.
+  unsigned Max = 0;
+  bool SkipParen = false;
+  int SkipParenCount = 0;
+  // Has a __builtin_constant_p been found?
+  bool FoundBuiltin = false;
+  bool PrevTokenIsHash = false;
+  // Count when "?" is reached. The "Current" will get this value when the ":"
+  // is reached.
+  std::stack<unsigned, SmallVector<unsigned, 8>> CountAtQuestion;
+  for (const auto &T : MI->tokens()) {
+    // The result of __builtin_constant_p(x) is 0 if x is a macro argument
+    // with side effects. If we see a __builtin_constant_p(x) followed by a
+    // "?" "&&" or "||", then we need to reason about control flow to report
+    // warnings correctly. Until such reasoning is added, bail out when this
+    // happens.
+    if (FoundBuiltin && T.isOneOf(tok::question, tok::ampamp, tok::pipepipe))
+      return Max;
+
+    // Skip stringified tokens.
+    if (T.is(tok::hash)) {
+      PrevTokenIsHash = true;
+      continue;
+    }
+    if (PrevTokenIsHash) {
+      PrevTokenIsHash = false;
+      continue;
+    }
+
+    // Handling of ? and :.
+    if (T.is(tok::question)) {
+      CountAtQuestion.push(Current);
+    } else if (T.is(tok::colon)) {
+      if (CountAtQuestion.empty())
+        return 0;
+      Current = CountAtQuestion.top();
+      CountAtQuestion.pop();
+    }
+
+    // If current token is a parenthesis, skip it.
+    if (SkipParen) {
+      if (T.is(tok::l_paren))
+        SkipParenCount++;
+      else if (T.is(tok::r_paren))
+        SkipParenCount--;
+      SkipParen = (SkipParenCount != 0);
+      if (SkipParen)
+        continue;
+    }
+
+    IdentifierInfo *TII = T.getIdentifierInfo();
+    // If not existent, skip it.
+    if (TII == nullptr)
+      continue;
+
+    // If a __builtin_constant_p is found within the macro definition, don't
+    // count arguments inside the parentheses and remember that it has been
+    // seen in case there are "?", "&&" or "||" operators later.
+    if (TII->getBuiltinID() == Builtin::BI__builtin_constant_p) {
+      FoundBuiltin = true;
+      SkipParen = true;
+      continue;
+    }
+
+    // If another macro is found within the macro definition, skip the macro
+    // and the eventual arguments.
+    if (TII->hasMacroDefinition()) {
+      const MacroInfo *M = PP.getMacroDefinition(TII).getMacroInfo();
+      if (M != nullptr && M->isFunctionLike())
+        SkipParen = true;
+      continue;
+    }
+
+    // Count argument.
+    if (TII == Arg) {
+      Current++;
+      if (Current > Max)
+        Max = Current;
+    }
+  }
+  return Max;
+}
+
+bool MacroRepeatedPPCallbacks::hasSideEffects(
+    const Token *ResultArgToks) const {
+  for (; ResultArgToks->isNot(tok::eof); ++ResultArgToks) {
+    if (ResultArgToks->isOneOf(tok::plusplus, tok::minusminus))
+      return true;
+  }
+  return false;
+}
+
+void MacroRepeatedSideEffectsCheck::registerPPCallbacks(
+    CompilerInstance &Compiler) {
+  Compiler.getPreprocessor().addPPCallbacks(
+      ::llvm::make_unique<MacroRepeatedPPCallbacks>(
+          *this, Compiler.getPreprocessor()));
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.h
new file mode 100644
index 0000000..a2a3134
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.h
@@ -0,0 +1,31 @@
+//===--- MacroRepeatedSideEffectsCheck.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_MACROREPEATEDSIDEEFFECTSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MACROREPEATEDSIDEEFFECTSCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Checks for repeated argument with side effects in macros.
+class MacroRepeatedSideEffectsCheck : public ClangTidyCheck {
+public:
+  MacroRepeatedSideEffectsCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MACROREPEATEDSIDEEFFECTSCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp
new file mode 100644
index 0000000..f8db0b3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp
@@ -0,0 +1,112 @@
+//===--- MisplacedOperatorInStrlenInAllocCheck.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 "MisplacedOperatorInStrlenInAllocCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void MisplacedOperatorInStrlenInAllocCheck::registerMatchers(
+    MatchFinder *Finder) {
+  const auto StrLenFunc = functionDecl(anyOf(
+      hasName("::strlen"), hasName("::std::strlen"), hasName("::strnlen"),
+      hasName("::std::strnlen"), hasName("::strnlen_s"),
+      hasName("::std::strnlen_s"), hasName("::wcslen"),
+      hasName("::std::wcslen"), hasName("::wcsnlen"), hasName("::std::wcsnlen"),
+      hasName("::wcsnlen_s"), hasName("std::wcsnlen_s")));
+
+  const auto BadUse =
+      callExpr(callee(StrLenFunc),
+               hasAnyArgument(ignoringImpCasts(
+                   binaryOperator(allOf(hasOperatorName("+"),
+                                        hasRHS(ignoringParenImpCasts(
+                                            integerLiteral(equals(1))))))
+                       .bind("BinOp"))))
+          .bind("StrLen");
+
+  const auto BadArg = anyOf(
+      allOf(hasDescendant(BadUse),
+            unless(binaryOperator(allOf(
+                hasOperatorName("+"), hasLHS(BadUse),
+                hasRHS(ignoringParenImpCasts(integerLiteral(equals(1)))))))),
+      BadUse);
+
+  const auto Alloc0Func =
+      functionDecl(anyOf(hasName("::malloc"), hasName("std::malloc"),
+                         hasName("::alloca"), hasName("std::alloca")));
+  const auto Alloc1Func =
+      functionDecl(anyOf(hasName("::calloc"), hasName("std::calloc"),
+                         hasName("::realloc"), hasName("std::realloc")));
+
+  const auto Alloc0FuncPtr =
+      varDecl(hasType(isConstQualified()),
+              hasInitializer(ignoringParenImpCasts(
+                  declRefExpr(hasDeclaration(Alloc0Func)))));
+  const auto Alloc1FuncPtr =
+      varDecl(hasType(isConstQualified()),
+              hasInitializer(ignoringParenImpCasts(
+                  declRefExpr(hasDeclaration(Alloc1Func)))));
+
+  Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc0Func, Alloc0FuncPtr))),
+                              hasArgument(0, BadArg))
+                         .bind("Alloc"),
+                     this);
+  Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc1Func, Alloc1FuncPtr))),
+                              hasArgument(1, BadArg))
+                         .bind("Alloc"),
+                     this);
+  Finder->addMatcher(
+      cxxNewExpr(isArray(), hasArraySize(BadArg)).bind("Alloc"), this);
+}
+
+void MisplacedOperatorInStrlenInAllocCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const Expr *Alloc = Result.Nodes.getNodeAs<CallExpr>("Alloc");
+  if (!Alloc)
+    Alloc = Result.Nodes.getNodeAs<CXXNewExpr>("Alloc");
+  assert(Alloc && "Matched node bound by 'Alloc' shoud be either 'CallExpr'"
+         " or 'CXXNewExpr'");
+
+  const auto *StrLen = Result.Nodes.getNodeAs<CallExpr>("StrLen");
+  const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("BinOp");
+
+  const StringRef StrLenText = Lexer::getSourceText(
+      CharSourceRange::getTokenRange(StrLen->getSourceRange()),
+      *Result.SourceManager, getLangOpts());
+  const StringRef Arg0Text = Lexer::getSourceText(
+      CharSourceRange::getTokenRange(StrLen->getArg(0)->getSourceRange()),
+      *Result.SourceManager, getLangOpts());
+  const StringRef StrLenBegin = StrLenText.substr(0, StrLenText.find(Arg0Text));
+  const StringRef StrLenEnd = StrLenText.substr(
+      StrLenText.find(Arg0Text) + Arg0Text.size(), StrLenText.size());
+
+  const StringRef LHSText = Lexer::getSourceText(
+      CharSourceRange::getTokenRange(BinOp->getLHS()->getSourceRange()),
+      *Result.SourceManager, getLangOpts());
+  const StringRef RHSText = Lexer::getSourceText(
+      CharSourceRange::getTokenRange(BinOp->getRHS()->getSourceRange()),
+      *Result.SourceManager, getLangOpts());
+
+  auto Hint = FixItHint::CreateReplacement(
+      StrLen->getSourceRange(),
+      (StrLenBegin + LHSText + StrLenEnd + " + " + RHSText).str());
+
+  diag(Alloc->getLocStart(),
+       "addition operator is applied to the argument of %0 instead of its "
+       "result") << StrLen->getDirectCallee()->getName() << Hint;
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h
new file mode 100644
index 0000000..99cfcfb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h
@@ -0,0 +1,37 @@
+//===--- MisplacedOperatorInStrlenInAllocCheck.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_MISPLACED_OPERATOR_IN_STRLEN_IN_ALLOC_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACED_OPERATOR_IN_STRLEN_IN_ALLOC_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds cases where ``1`` is added to the string in the argument to a function
+/// in the ``strlen()`` family instead of the result and value is used as an
+/// argument to a memory allocation function.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.html
+class MisplacedOperatorInStrlenInAllocCheck : public ClangTidyCheck {
+public:
+  MisplacedOperatorInStrlenInAllocCheck(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_MISPLACED_OPERATOR_IN_STRLEN_IN_ALLOC_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp
new file mode 100644
index 0000000..e263366
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp
@@ -0,0 +1,233 @@
+//===--- MisplacedWideningCastCheck.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 "MisplacedWideningCastCheck.h"
+#include "../utils/Matchers.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+MisplacedWideningCastCheck::MisplacedWideningCastCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      CheckImplicitCasts(Options.get("CheckImplicitCasts", false)) {}
+
+void MisplacedWideningCastCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "CheckImplicitCasts", CheckImplicitCasts);
+}
+
+void MisplacedWideningCastCheck::registerMatchers(MatchFinder *Finder) {
+  const auto Calc =
+      expr(anyOf(binaryOperator(
+                     anyOf(hasOperatorName("+"), hasOperatorName("-"),
+                           hasOperatorName("*"), hasOperatorName("<<"))),
+                 unaryOperator(hasOperatorName("~"))),
+           hasType(isInteger()))
+          .bind("Calc");
+
+  const auto ExplicitCast = explicitCastExpr(hasDestinationType(isInteger()),
+                                             has(ignoringParenImpCasts(Calc)));
+  const auto ImplicitCast =
+      implicitCastExpr(hasImplicitDestinationType(isInteger()),
+                       has(ignoringParenImpCasts(Calc)));
+  const auto Cast = expr(anyOf(ExplicitCast, ImplicitCast)).bind("Cast");
+
+  Finder->addMatcher(varDecl(hasInitializer(Cast)), this);
+  Finder->addMatcher(returnStmt(hasReturnValue(Cast)), this);
+  Finder->addMatcher(callExpr(hasAnyArgument(Cast)), this);
+  Finder->addMatcher(binaryOperator(hasOperatorName("="), hasRHS(Cast)), this);
+  Finder->addMatcher(
+      binaryOperator(matchers::isComparisonOperator(), hasEitherOperand(Cast)),
+      this);
+}
+
+static unsigned getMaxCalculationWidth(const ASTContext &Context,
+                                       const Expr *E) {
+  E = E->IgnoreParenImpCasts();
+
+  if (const auto *Bop = dyn_cast<BinaryOperator>(E)) {
+    unsigned LHSWidth = getMaxCalculationWidth(Context, Bop->getLHS());
+    unsigned RHSWidth = getMaxCalculationWidth(Context, Bop->getRHS());
+    if (Bop->getOpcode() == BO_Mul)
+      return LHSWidth + RHSWidth;
+    if (Bop->getOpcode() == BO_Add)
+      return std::max(LHSWidth, RHSWidth) + 1;
+    if (Bop->getOpcode() == BO_Rem) {
+      llvm::APSInt Val;
+      if (Bop->getRHS()->EvaluateAsInt(Val, Context))
+        return Val.getActiveBits();
+    } else if (Bop->getOpcode() == BO_Shl) {
+      llvm::APSInt Bits;
+      if (Bop->getRHS()->EvaluateAsInt(Bits, Context)) {
+        // We don't handle negative values and large values well. It is assumed
+        // that compiler warnings are written for such values so the user will
+        // fix that.
+        return LHSWidth + Bits.getExtValue();
+      }
+
+      // Unknown bitcount, assume there is truncation.
+      return 1024U;
+    }
+  } else if (const auto *Uop = dyn_cast<UnaryOperator>(E)) {
+    // There is truncation when ~ is used.
+    if (Uop->getOpcode() == UO_Not)
+      return 1024U;
+
+    QualType T = Uop->getType();
+    return T->isIntegerType() ? Context.getIntWidth(T) : 1024U;
+  } else if (const auto *I = dyn_cast<IntegerLiteral>(E)) {
+    return I->getValue().getActiveBits();
+  }
+
+  return Context.getIntWidth(E->getType());
+}
+
+static int relativeIntSizes(BuiltinType::Kind Kind) {
+  switch (Kind) {
+  case BuiltinType::UChar:
+    return 1;
+  case BuiltinType::SChar:
+    return 1;
+  case BuiltinType::Char_U:
+    return 1;
+  case BuiltinType::Char_S:
+    return 1;
+  case BuiltinType::UShort:
+    return 2;
+  case BuiltinType::Short:
+    return 2;
+  case BuiltinType::UInt:
+    return 3;
+  case BuiltinType::Int:
+    return 3;
+  case BuiltinType::ULong:
+    return 4;
+  case BuiltinType::Long:
+    return 4;
+  case BuiltinType::ULongLong:
+    return 5;
+  case BuiltinType::LongLong:
+    return 5;
+  case BuiltinType::UInt128:
+    return 6;
+  case BuiltinType::Int128:
+    return 6;
+  default:
+    return 0;
+  }
+}
+
+static int relativeCharSizes(BuiltinType::Kind Kind) {
+  switch (Kind) {
+  case BuiltinType::UChar:
+    return 1;
+  case BuiltinType::SChar:
+    return 1;
+  case BuiltinType::Char_U:
+    return 1;
+  case BuiltinType::Char_S:
+    return 1;
+  case BuiltinType::Char16:
+    return 2;
+  case BuiltinType::Char32:
+    return 3;
+  default:
+    return 0;
+  }
+}
+
+static int relativeCharSizesW(BuiltinType::Kind Kind) {
+  switch (Kind) {
+  case BuiltinType::UChar:
+    return 1;
+  case BuiltinType::SChar:
+    return 1;
+  case BuiltinType::Char_U:
+    return 1;
+  case BuiltinType::Char_S:
+    return 1;
+  case BuiltinType::WChar_U:
+    return 2;
+  case BuiltinType::WChar_S:
+    return 2;
+  default:
+    return 0;
+  }
+}
+
+static bool isFirstWider(BuiltinType::Kind First, BuiltinType::Kind Second) {
+  int FirstSize, SecondSize;
+  if ((FirstSize = relativeIntSizes(First)) != 0 &&
+      (SecondSize = relativeIntSizes(Second)) != 0)
+    return FirstSize > SecondSize;
+  if ((FirstSize = relativeCharSizes(First)) != 0 &&
+      (SecondSize = relativeCharSizes(Second)) != 0)
+    return FirstSize > SecondSize;
+  if ((FirstSize = relativeCharSizesW(First)) != 0 &&
+      (SecondSize = relativeCharSizesW(Second)) != 0)
+    return FirstSize > SecondSize;
+  return false;
+}
+
+void MisplacedWideningCastCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Cast = Result.Nodes.getNodeAs<CastExpr>("Cast");
+  if (!CheckImplicitCasts && isa<ImplicitCastExpr>(Cast))
+    return;
+  if (Cast->getLocStart().isMacroID())
+    return;
+
+  const auto *Calc = Result.Nodes.getNodeAs<Expr>("Calc");
+  if (Calc->getLocStart().isMacroID())
+    return;
+
+  if (Cast->isTypeDependent() || Cast->isValueDependent() ||
+      Calc->isTypeDependent() || Calc->isValueDependent())
+    return;
+
+  ASTContext &Context = *Result.Context;
+
+  QualType CastType = Cast->getType();
+  QualType CalcType = Calc->getType();
+
+  // Explicit truncation using cast.
+  if (Context.getIntWidth(CastType) < Context.getIntWidth(CalcType))
+    return;
+
+  // If CalcType and CastType have same size then there is no real danger, but
+  // there can be a portability problem.
+
+  if (Context.getIntWidth(CastType) == Context.getIntWidth(CalcType)) {
+    const auto *CastBuiltinType =
+        dyn_cast<BuiltinType>(CastType->getUnqualifiedDesugaredType());
+    const auto *CalcBuiltinType =
+        dyn_cast<BuiltinType>(CalcType->getUnqualifiedDesugaredType());
+    if (CastBuiltinType && CalcBuiltinType &&
+        !isFirstWider(CastBuiltinType->getKind(), CalcBuiltinType->getKind()))
+      return;
+  }
+
+  // Don't write a warning if we can easily see that the result is not
+  // truncated.
+  if (Context.getIntWidth(CalcType) >= getMaxCalculationWidth(Context, Calc))
+    return;
+
+  diag(Cast->getLocStart(), "either cast from %0 to %1 is ineffective, or "
+                            "there is loss of precision before the conversion")
+      << CalcType << CastType;
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.h
new file mode 100644
index 0000000..b61556f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.h
@@ -0,0 +1,46 @@
+//===--- MisplacedWideningCastCheck.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_MISPLACEDWIDENINGCASTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACEDWIDENINGCASTCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Find casts of calculation results to bigger type. Typically from int to
+/// long. If the intention of the cast is to avoid loss of precision then
+/// the cast is misplaced, and there can be loss of precision. Otherwise
+/// such cast is ineffective.
+///
+/// There is one option:
+///
+///   - `CheckImplicitCasts`: Whether to check implicit casts as well which may
+//      be the most common case. Enabled by default.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-misplaced-widening-cast.html
+class MisplacedWideningCastCheck : public ClangTidyCheck {
+public:
+  MisplacedWideningCastCheck(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 CheckImplicitCasts;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp
new file mode 100644
index 0000000..516ee19
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp
@@ -0,0 +1,133 @@
+//===--- MoveForwardingReferenceCheck.cpp - clang-tidy --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MoveForwardingReferenceCheck.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <algorithm>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+static void replaceMoveWithForward(const UnresolvedLookupExpr *Callee,
+                                   const ParmVarDecl *ParmVar,
+                                   const TemplateTypeParmDecl *TypeParmDecl,
+                                   DiagnosticBuilder &Diag,
+                                   const ASTContext &Context) {
+  const SourceManager &SM = Context.getSourceManager();
+  const LangOptions &LangOpts = Context.getLangOpts();
+
+  CharSourceRange CallRange =
+      Lexer::makeFileCharRange(CharSourceRange::getTokenRange(
+                                   Callee->getLocStart(), Callee->getLocEnd()),
+                               SM, LangOpts);
+
+  if (CallRange.isValid()) {
+    const std::string TypeName =
+        TypeParmDecl->getIdentifier()
+            ? TypeParmDecl->getName().str()
+            : (llvm::Twine("decltype(") + ParmVar->getName() + ")").str();
+
+    const std::string ForwardName =
+        (llvm::Twine("forward<") + TypeName + ">").str();
+
+    // Create a replacement only if we see a "standard" way of calling
+    // std::move(). This will hopefully prevent erroneous replacements if the
+    // code does unusual things (e.g. create an alias for std::move() in
+    // another namespace).
+    NestedNameSpecifier *NNS = Callee->getQualifier();
+    if (!NNS) {
+      // Called as "move" (i.e. presumably the code had a "using std::move;").
+      // We still conservatively put a "std::" in front of the forward because
+      // we don't know whether the code also had a "using std::forward;".
+      Diag << FixItHint::CreateReplacement(CallRange, "std::" + ForwardName);
+    } else if (const NamespaceDecl *Namespace = NNS->getAsNamespace()) {
+      if (Namespace->getName() == "std") {
+        if (!NNS->getPrefix()) {
+          // Called as "std::move".
+          Diag << FixItHint::CreateReplacement(CallRange,
+                                               "std::" + ForwardName);
+        } else if (NNS->getPrefix()->getKind() == NestedNameSpecifier::Global) {
+          // Called as "::std::move".
+          Diag << FixItHint::CreateReplacement(CallRange,
+                                               "::std::" + ForwardName);
+        }
+      }
+    }
+  }
+}
+
+void MoveForwardingReferenceCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  // Matches a ParmVarDecl for a forwarding reference, i.e. a non-const rvalue
+  // reference of a function template parameter type.
+  auto ForwardingReferenceParmMatcher =
+      parmVarDecl(
+          hasType(qualType(rValueReferenceType(),
+                           references(templateTypeParmType(hasDeclaration(
+                               templateTypeParmDecl().bind("type-parm-decl")))),
+                           unless(references(qualType(isConstQualified()))))))
+          .bind("parm-var");
+
+  Finder->addMatcher(
+      callExpr(callee(unresolvedLookupExpr(
+                          hasAnyDeclaration(namedDecl(
+                              hasUnderlyingDecl(hasName("::std::move")))))
+                          .bind("lookup")),
+               argumentCountIs(1),
+               hasArgument(0, ignoringParenImpCasts(declRefExpr(
+                                  to(ForwardingReferenceParmMatcher)))))
+          .bind("call-move"),
+      this);
+}
+
+void MoveForwardingReferenceCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *CallMove = Result.Nodes.getNodeAs<CallExpr>("call-move");
+  const auto *UnresolvedLookup =
+      Result.Nodes.getNodeAs<UnresolvedLookupExpr>("lookup");
+  const auto *ParmVar = Result.Nodes.getNodeAs<ParmVarDecl>("parm-var");
+  const auto *TypeParmDecl =
+      Result.Nodes.getNodeAs<TemplateTypeParmDecl>("type-parm-decl");
+
+  // Get the FunctionDecl and FunctionTemplateDecl containing the function
+  // parameter.
+  const auto *FuncForParam = dyn_cast<FunctionDecl>(ParmVar->getDeclContext());
+  if (!FuncForParam)
+    return;
+  const FunctionTemplateDecl *FuncTemplate =
+      FuncForParam->getDescribedFunctionTemplate();
+  if (!FuncTemplate)
+    return;
+
+  // Check that the template type parameter belongs to the same function
+  // template as the function parameter of that type. (This implies that type
+  // deduction will happen on the type.)
+  const TemplateParameterList *Params = FuncTemplate->getTemplateParameters();
+  if (!std::count(Params->begin(), Params->end(), TypeParmDecl))
+    return;
+
+  auto Diag = diag(CallMove->getExprLoc(),
+                   "forwarding reference passed to std::move(), which may "
+                   "unexpectedly cause lvalues to be moved; use "
+                   "std::forward() instead");
+
+  replaceMoveWithForward(UnresolvedLookup, ParmVar, TypeParmDecl, Diag,
+                         *Result.Context);
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.h
new file mode 100644
index 0000000..c61de75
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.h
@@ -0,0 +1,49 @@
+//===--- MoveForwardingReferenceCheck.h - clang-tidy ----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MOVEFORWARDINGREFERENCECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MOVEFORWARDINGREFERENCECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// The check warns if std::move is applied to a forwarding reference (i.e. an
+/// rvalue reference of a function template argument type).
+///
+/// If a developer is unaware of the special rules for template argument
+/// deduction on forwarding references, it will seem reasonable to apply
+/// std::move to the forwarding reference, in the same way that this would be
+/// done for a "normal" rvalue reference.
+///
+/// This has a consequence that is usually unwanted and possibly surprising: if
+/// the function that takes the forwarding reference as its parameter is called
+/// with an lvalue, that lvalue will be moved from (and hence placed into an
+/// indeterminate state) even though no std::move was applied to the lvalue at
+/// the call site.
+//
+/// The check suggests replacing the std::move with a std::forward.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-move-forwarding-reference.html
+class MoveForwardingReferenceCheck : public ClangTidyCheck {
+public:
+  MoveForwardingReferenceCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MOVEFORWARDINGREFERENCECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.cpp
new file mode 100644
index 0000000..942c875
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.cpp
@@ -0,0 +1,107 @@
+//===--- MultipleStatementMacroCheck.cpp - clang-tidy----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MultipleStatementMacroCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+
+AST_MATCHER(Expr, isInMacro) { return Node.getLocStart().isMacroID(); }
+
+/// \brief Find the next statement after `S`.
+const Stmt *nextStmt(const MatchFinder::MatchResult &Result, const Stmt *S) {
+  auto Parents = Result.Context->getParents(*S);
+  if (Parents.empty())
+    return nullptr;
+  const auto *Parent = Parents[0].get<Stmt>();
+  if (!Parent)
+    return nullptr;
+  const Stmt *Prev = nullptr;
+  for (const Stmt *Child : Parent->children()) {
+    if (Prev == S)
+      return Child;
+    Prev = Child;
+  }
+  return nextStmt(Result, Parent);
+}
+
+using ExpansionRanges = std::vector<SourceRange>;
+
+/// \bried Get all the macro expansion ranges related to `Loc`.
+///
+/// The result is ordered from most inner to most outer.
+ExpansionRanges getExpansionRanges(SourceLocation Loc,
+                                   const MatchFinder::MatchResult &Result) {
+  ExpansionRanges Locs;
+  while (Loc.isMacroID()) {
+    Locs.push_back(
+        Result.SourceManager->getImmediateExpansionRange(Loc).getAsRange());
+    Loc = Locs.back().getBegin();
+  }
+  return Locs;
+}
+
+} // namespace
+
+void MultipleStatementMacroCheck::registerMatchers(MatchFinder *Finder) {
+  const auto Inner = expr(isInMacro(), unless(compoundStmt())).bind("inner");
+  Finder->addMatcher(
+      stmt(anyOf(ifStmt(hasThen(Inner)), ifStmt(hasElse(Inner)).bind("else"),
+                 whileStmt(hasBody(Inner)), forStmt(hasBody(Inner))))
+          .bind("outer"),
+      this);
+}
+
+void MultipleStatementMacroCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *Inner = Result.Nodes.getNodeAs<Expr>("inner");
+  const auto *Outer = Result.Nodes.getNodeAs<Stmt>("outer");
+  const auto *Next = nextStmt(Result, Outer);
+  if (!Next)
+    return;
+
+  SourceLocation OuterLoc = Outer->getLocStart();
+  if (Result.Nodes.getNodeAs<Stmt>("else"))
+    OuterLoc = cast<IfStmt>(Outer)->getElseLoc();
+
+  auto InnerRanges = getExpansionRanges(Inner->getLocStart(), Result);
+  auto OuterRanges = getExpansionRanges(OuterLoc, Result);
+  auto NextRanges = getExpansionRanges(Next->getLocStart(), Result);
+
+  // Remove all the common ranges, starting from the top (the last ones in the
+  // list).
+  while (!InnerRanges.empty() && !OuterRanges.empty() && !NextRanges.empty() &&
+         InnerRanges.back() == OuterRanges.back() &&
+         InnerRanges.back() == NextRanges.back()) {
+    InnerRanges.pop_back();
+    OuterRanges.pop_back();
+    NextRanges.pop_back();
+  }
+
+  // Inner and Next must have at least one more macro that Outer doesn't have,
+  // and that range must be common to both.
+  if (InnerRanges.empty() || NextRanges.empty() ||
+      InnerRanges.back() != NextRanges.back())
+    return;
+
+  diag(InnerRanges.back().getBegin(), "multiple statement macro used without "
+                                      "braces; some statements will be "
+                                      "unconditionally executed");
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.h
new file mode 100644
index 0000000..efc6599
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.h
@@ -0,0 +1,37 @@
+//===--- MultipleStatementMacroCheck.h - clang-tidy--------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLE_STATEMENT_MACRO_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLE_STATEMENT_MACRO_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Detect multiple statement macros that are used in unbraced conditionals.
+/// Only the first statement of the macro will be inside the conditional and the
+/// other ones will be executed unconditionally.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-multiple-statement-macro.html
+class MultipleStatementMacroCheck : public ClangTidyCheck {
+public:
+  MultipleStatementMacroCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLE_STATEMENT_MACRO_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ParentVirtualCallCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ParentVirtualCallCheck.cpp
new file mode 100755
index 0000000..919a691
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ParentVirtualCallCheck.cpp
@@ -0,0 +1,156 @@
+//===--- ParentVirtualCallCheck.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 "ParentVirtualCallCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include <algorithm>
+#include <cctype>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+using BasesVector = llvm::SmallVector<const CXXRecordDecl *, 5>;
+
+static bool isParentOf(const CXXRecordDecl &Parent,
+                       const CXXRecordDecl &ThisClass) {
+  if (Parent.getCanonicalDecl() == ThisClass.getCanonicalDecl())
+    return true;
+  const CXXRecordDecl *ParentCanonicalDecl = Parent.getCanonicalDecl();
+  return ThisClass.bases_end() !=
+         llvm::find_if(ThisClass.bases(), [=](const CXXBaseSpecifier &Base) {
+           auto *BaseDecl = Base.getType()->getAsCXXRecordDecl();
+           assert(BaseDecl);
+           return ParentCanonicalDecl == BaseDecl->getCanonicalDecl();
+         });
+}
+
+static BasesVector getParentsByGrandParent(const CXXRecordDecl &GrandParent,
+                                           const CXXRecordDecl &ThisClass,
+                                           const CXXMethodDecl &MemberDecl) {
+  BasesVector Result;
+  for (const auto &Base : ThisClass.bases()) {
+    const auto *BaseDecl = Base.getType()->getAsCXXRecordDecl();
+    const CXXMethodDecl *ActualMemberDecl =
+        MemberDecl.getCorrespondingMethodInClass(BaseDecl);
+    if (!ActualMemberDecl)
+      continue;
+    // TypePtr is the nearest base class to ThisClass between ThisClass and
+    // GrandParent, where MemberDecl is overridden. TypePtr is the class the
+    // check proposes to fix to.
+    const Type *TypePtr =
+        ActualMemberDecl->getThisType(ActualMemberDecl->getASTContext())
+            .getTypePtr();
+    const CXXRecordDecl *RecordDeclType = TypePtr->getPointeeCXXRecordDecl();
+    assert(RecordDeclType && "TypePtr is not a pointer to CXXRecordDecl!");
+    if (RecordDeclType->getCanonicalDecl()->isDerivedFrom(&GrandParent))
+      Result.emplace_back(RecordDeclType);
+  }
+
+  return Result;
+}
+
+static std::string getNameAsString(const NamedDecl *Decl) {
+  std::string QualName;
+  llvm::raw_string_ostream OS(QualName);
+  PrintingPolicy PP(Decl->getASTContext().getPrintingPolicy());
+  PP.SuppressUnwrittenScope = true;
+  Decl->printQualifiedName(OS, PP);
+  return OS.str();
+}
+
+// Returns E as written in the source code. Used to handle 'using' and
+// 'typedef'ed names of grand-parent classes.
+static std::string getExprAsString(const clang::Expr &E,
+                                   clang::ASTContext &AC) {
+  std::string Text = tooling::fixit::getText(E, AC).str();
+  Text.erase(
+      llvm::remove_if(
+          Text,
+          [](char C) { return std::isspace(static_cast<unsigned char>(C)); }),
+      Text.end());
+  return Text;
+}
+
+void ParentVirtualCallCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      cxxMemberCallExpr(
+          callee(memberExpr(hasDescendant(implicitCastExpr(
+                                hasImplicitDestinationType(pointsTo(
+                                    type(anything()).bind("castToType"))),
+                                hasSourceExpression(cxxThisExpr(hasType(
+                                    type(anything()).bind("thisType")))))))
+                     .bind("member")),
+          callee(cxxMethodDecl(isVirtual()))),
+      this);
+}
+
+void ParentVirtualCallCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Member = Result.Nodes.getNodeAs<MemberExpr>("member");
+  assert(Member);
+
+  if (!Member->getQualifier())
+    return;
+
+  const auto *MemberDecl = cast<CXXMethodDecl>(Member->getMemberDecl());
+
+  const auto *ThisTypePtr = Result.Nodes.getNodeAs<PointerType>("thisType");
+  assert(ThisTypePtr);
+
+  const auto *ThisType = ThisTypePtr->getPointeeCXXRecordDecl();
+  assert(ThisType);
+
+  const auto *CastToTypePtr = Result.Nodes.getNodeAs<Type>("castToType");
+  assert(CastToTypePtr);
+
+  const auto *CastToType = CastToTypePtr->getAsCXXRecordDecl();
+  assert(CastToType);
+
+  if (isParentOf(*CastToType, *ThisType))
+    return;
+
+  const BasesVector Parents =
+      getParentsByGrandParent(*CastToType, *ThisType, *MemberDecl);
+
+  if (Parents.empty())
+    return;
+
+  std::string ParentsStr;
+  ParentsStr.reserve(30 * Parents.size());
+  for (const CXXRecordDecl *Parent : Parents) {
+    if (!ParentsStr.empty())
+      ParentsStr.append(" or ");
+    ParentsStr.append("'").append(getNameAsString(Parent)).append("'");
+  }
+
+  assert(Member->getQualifierLoc().getSourceRange().getBegin().isValid());
+  auto Diag = diag(Member->getQualifierLoc().getSourceRange().getBegin(),
+                   "qualified name '%0' refers to a member overridden "
+                   "in subclass%1; did you mean %2?")
+              << getExprAsString(*Member, *Result.Context)
+              << (Parents.size() > 1 ? "es" : "") << ParentsStr;
+
+  // Propose a fix if there's only one parent class...
+  if (Parents.size() == 1 &&
+      // ...unless parent class is templated
+      !isa<ClassTemplateSpecializationDecl>(Parents.front()))
+    Diag << FixItHint::CreateReplacement(
+        Member->getQualifierLoc().getSourceRange(),
+        getNameAsString(Parents.front()) + "::");
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ParentVirtualCallCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ParentVirtualCallCheck.h
new file mode 100755
index 0000000..08c3aef
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ParentVirtualCallCheck.h
@@ -0,0 +1,35 @@
+//===--- ParentVirtualCallCheck.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_PARENTVIRTUALCALLCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_PARENTVIRTUALCALLCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds calls to grand..-parent virtual methods instead of parent's.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-parent-virtual-call.html
+class ParentVirtualCallCheck : public ClangTidyCheck {
+public:
+  ParentVirtualCallCheck(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_PARENTVIRTUALCALLCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SizeofContainerCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SizeofContainerCheck.cpp
new file mode 100644
index 0000000..b4a019e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SizeofContainerCheck.cpp
@@ -0,0 +1,49 @@
+//===--- SizeofContainerCheck.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 "SizeofContainerCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void SizeofContainerCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      expr(unless(isInTemplateInstantiation()),
+           expr(sizeOfExpr(has(ignoringParenImpCasts(
+                    expr(hasType(hasCanonicalType(hasDeclaration(cxxRecordDecl(
+                        matchesName("^(::std::|::string)"),
+                        unless(matchesName("^::std::(bitset|array)$")),
+                        hasMethod(cxxMethodDecl(hasName("size"), isPublic(),
+                                                isConst())))))))))))
+               .bind("sizeof"),
+           // Ignore ARRAYSIZE(<array of containers>) pattern.
+           unless(hasAncestor(binaryOperator(
+               anyOf(hasOperatorName("/"), hasOperatorName("%")),
+               hasLHS(ignoringParenCasts(sizeOfExpr(expr()))),
+               hasRHS(ignoringParenCasts(equalsBoundNode("sizeof"))))))),
+      this);
+}
+
+void SizeofContainerCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *SizeOf =
+      Result.Nodes.getNodeAs<UnaryExprOrTypeTraitExpr>("sizeof");
+
+  auto Diag =
+      diag(SizeOf->getLocStart(), "sizeof() doesn't return the size of the "
+                                  "container; did you mean .size()?");
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SizeofContainerCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SizeofContainerCheck.h
new file mode 100644
index 0000000..76b82b0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SizeofContainerCheck.h
@@ -0,0 +1,36 @@
+//===--- SizeofContainerCheck.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_SIZEOFCONTAINERCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SIZEOFCONTAINERCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Find usages of sizeof on expressions of STL container types. Most likely the
+/// user wanted to use `.size()` instead.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-sizeof-container.html
+class SizeofContainerCheck : public ClangTidyCheck {
+public:
+  SizeofContainerCheck(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_SIZEOFCONTAINERCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
new file mode 100644
index 0000000..f05a900
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
@@ -0,0 +1,284 @@
+//===--- SizeofExpressionCheck.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 "SizeofExpressionCheck.h"
+#include "../utils/Matchers.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_P(IntegerLiteral, isBiggerThan, unsigned, N) {
+  return Node.getValue().getZExtValue() > N;
+}
+
+AST_MATCHER_P2(Expr, hasSizeOfDescendant, int, Depth,
+               ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
+  if (Depth < 0)
+    return false;
+
+  const Expr *E = Node.IgnoreParenImpCasts();
+  if (InnerMatcher.matches(*E, Finder, Builder))
+    return true;
+
+  if (const auto *CE = dyn_cast<CastExpr>(E)) {
+    const auto M = hasSizeOfDescendant(Depth - 1, InnerMatcher);
+    return M.matches(*CE->getSubExpr(), Finder, Builder);
+  } else if (const auto *UE = dyn_cast<UnaryOperator>(E)) {
+    const auto M = hasSizeOfDescendant(Depth - 1, InnerMatcher);
+    return M.matches(*UE->getSubExpr(), Finder, Builder);
+  } else if (const auto *BE = dyn_cast<BinaryOperator>(E)) {
+    const auto LHS = hasSizeOfDescendant(Depth - 1, InnerMatcher);
+    const auto RHS = hasSizeOfDescendant(Depth - 1, InnerMatcher);
+    return LHS.matches(*BE->getLHS(), Finder, Builder) ||
+           RHS.matches(*BE->getRHS(), Finder, Builder);
+  }
+
+  return false;
+}
+
+CharUnits getSizeOfType(const ASTContext &Ctx, const Type *Ty) {
+  if (!Ty || Ty->isIncompleteType() || Ty->isDependentType() ||
+      isa<DependentSizedArrayType>(Ty) || !Ty->isConstantSizeType())
+    return CharUnits::Zero();
+  return Ctx.getTypeSizeInChars(Ty);
+}
+
+} // namespace
+
+SizeofExpressionCheck::SizeofExpressionCheck(StringRef Name,
+                                             ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      WarnOnSizeOfConstant(Options.get("WarnOnSizeOfConstant", 1) != 0),
+      WarnOnSizeOfIntegerExpression(
+          Options.get("WarnOnSizeOfIntegerExpression", 0) != 0),
+      WarnOnSizeOfThis(Options.get("WarnOnSizeOfThis", 1) != 0),
+      WarnOnSizeOfCompareToConstant(
+          Options.get("WarnOnSizeOfCompareToConstant", 1) != 0) {}
+
+void SizeofExpressionCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "WarnOnSizeOfConstant", WarnOnSizeOfConstant);
+  Options.store(Opts, "WarnOnSizeOfIntegerExpression",
+                WarnOnSizeOfIntegerExpression);
+  Options.store(Opts, "WarnOnSizeOfThis", WarnOnSizeOfThis);
+  Options.store(Opts, "WarnOnSizeOfCompareToConstant",
+                WarnOnSizeOfCompareToConstant);
+}
+
+void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IntegerExpr = ignoringParenImpCasts(integerLiteral());
+  const auto ConstantExpr = expr(ignoringParenImpCasts(
+      anyOf(integerLiteral(), unaryOperator(hasUnaryOperand(IntegerExpr)),
+            binaryOperator(hasLHS(IntegerExpr), hasRHS(IntegerExpr)))));
+  const auto IntegerCallExpr = expr(ignoringParenImpCasts(
+      callExpr(anyOf(hasType(isInteger()), hasType(enumType())),
+               unless(isInTemplateInstantiation()))));
+  const auto SizeOfExpr =
+      expr(anyOf(sizeOfExpr(has(type())), sizeOfExpr(has(expr()))));
+  const auto SizeOfZero = expr(
+      sizeOfExpr(has(ignoringParenImpCasts(expr(integerLiteral(equals(0)))))));
+
+  // Detect expression like: sizeof(ARRAYLEN);
+  // Note: The expression 'sizeof(sizeof(0))' is a portable trick used to know
+  //       the sizeof size_t.
+  if (WarnOnSizeOfConstant) {
+    Finder->addMatcher(
+        expr(sizeOfExpr(has(ignoringParenImpCasts(ConstantExpr))),
+             unless(SizeOfZero))
+            .bind("sizeof-constant"),
+        this);
+  }
+
+  // Detect sizeof(f())
+  if (WarnOnSizeOfIntegerExpression) {
+    Finder->addMatcher(
+        expr(sizeOfExpr(ignoringParenImpCasts(has(IntegerCallExpr))))
+            .bind("sizeof-integer-call"),
+        this);
+  }
+
+  // Detect expression like: sizeof(this);
+  if (WarnOnSizeOfThis) {
+    Finder->addMatcher(
+        expr(sizeOfExpr(has(ignoringParenImpCasts(expr(cxxThisExpr())))))
+            .bind("sizeof-this"),
+        this);
+  }
+
+  // Detect sizeof(kPtr) where kPtr is 'const char* kPtr = "abc"';
+  const auto CharPtrType = pointerType(pointee(isAnyCharacter()));
+  const auto ConstStrLiteralDecl =
+      varDecl(isDefinition(), hasType(qualType(hasCanonicalType(CharPtrType))),
+              hasInitializer(ignoringParenImpCasts(stringLiteral())));
+  Finder->addMatcher(expr(sizeOfExpr(has(ignoringParenImpCasts(expr(
+                              hasType(qualType(hasCanonicalType(CharPtrType))),
+                              ignoringParenImpCasts(declRefExpr(
+                                  hasDeclaration(ConstStrLiteralDecl))))))))
+                         .bind("sizeof-charp"),
+                     this);
+
+  // Detect sizeof(ptr) where ptr points to an aggregate (i.e. sizeof(&S)).
+  const auto ArrayExpr = expr(ignoringParenImpCasts(
+      expr(hasType(qualType(hasCanonicalType(arrayType()))))));
+  const auto ArrayCastExpr = expr(anyOf(
+      unaryOperator(hasUnaryOperand(ArrayExpr), unless(hasOperatorName("*"))),
+      binaryOperator(hasEitherOperand(ArrayExpr)),
+      castExpr(hasSourceExpression(ArrayExpr))));
+  const auto PointerToArrayExpr = expr(ignoringParenImpCasts(expr(
+      hasType(qualType(hasCanonicalType(pointerType(pointee(arrayType()))))))));
+
+  const auto StructAddrOfExpr =
+      unaryOperator(hasOperatorName("&"),
+                    hasUnaryOperand(ignoringParenImpCasts(expr(
+                        hasType(qualType(hasCanonicalType(recordType())))))));
+
+  Finder->addMatcher(
+      expr(sizeOfExpr(has(expr(ignoringParenImpCasts(
+               anyOf(ArrayCastExpr, PointerToArrayExpr, StructAddrOfExpr))))))
+          .bind("sizeof-pointer-to-aggregate"),
+      this);
+
+  // Detect expression like: sizeof(epxr) <= k for a suspicious constant 'k'.
+  if (WarnOnSizeOfCompareToConstant) {
+    Finder->addMatcher(
+        binaryOperator(matchers::isRelationalOperator(),
+                       hasEitherOperand(ignoringParenImpCasts(SizeOfExpr)),
+                       hasEitherOperand(ignoringParenImpCasts(
+                           anyOf(integerLiteral(equals(0)),
+                                 integerLiteral(isBiggerThan(0x80000))))))
+            .bind("sizeof-compare-constant"),
+        this);
+  }
+
+  // Detect expression like: sizeof(expr, expr); most likely an error.
+  Finder->addMatcher(expr(sizeOfExpr(has(expr(ignoringParenImpCasts(
+                              binaryOperator(hasOperatorName(",")))))))
+                         .bind("sizeof-comma-expr"),
+                     this);
+
+  // Detect sizeof(...) /sizeof(...));
+  const auto ElemType =
+      arrayType(hasElementType(recordType().bind("elem-type")));
+  const auto ElemPtrType = pointerType(pointee(type().bind("elem-ptr-type")));
+  const auto NumType = qualType(hasCanonicalType(
+      type(anyOf(ElemType, ElemPtrType, type())).bind("num-type")));
+  const auto DenomType = qualType(hasCanonicalType(type().bind("denom-type")));
+
+  Finder->addMatcher(
+      binaryOperator(hasOperatorName("/"),
+                     hasLHS(expr(ignoringParenImpCasts(
+                         anyOf(sizeOfExpr(has(NumType)),
+                               sizeOfExpr(has(expr(hasType(NumType)))))))),
+                     hasRHS(expr(ignoringParenImpCasts(
+                         anyOf(sizeOfExpr(has(DenomType)),
+                               sizeOfExpr(has(expr(hasType(DenomType)))))))))
+          .bind("sizeof-divide-expr"),
+      this);
+
+  // Detect expression like: sizeof(...) * sizeof(...)); most likely an error.
+  Finder->addMatcher(binaryOperator(hasOperatorName("*"),
+                                    hasLHS(ignoringParenImpCasts(SizeOfExpr)),
+                                    hasRHS(ignoringParenImpCasts(SizeOfExpr)))
+                         .bind("sizeof-multiply-sizeof"),
+                     this);
+
+  Finder->addMatcher(
+      binaryOperator(hasOperatorName("*"),
+                     hasEitherOperand(ignoringParenImpCasts(SizeOfExpr)),
+                     hasEitherOperand(ignoringParenImpCasts(binaryOperator(
+                         hasOperatorName("*"),
+                         hasEitherOperand(ignoringParenImpCasts(SizeOfExpr))))))
+          .bind("sizeof-multiply-sizeof"),
+      this);
+
+  // Detect strange double-sizeof expression like: sizeof(sizeof(...));
+  // Note: The expression 'sizeof(sizeof(0))' is accepted.
+  Finder->addMatcher(
+      expr(sizeOfExpr(has(ignoringParenImpCasts(expr(
+               hasSizeOfDescendant(8, expr(SizeOfExpr, unless(SizeOfZero))))))))
+          .bind("sizeof-sizeof-expr"),
+      this);
+}
+
+void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) {
+  const ASTContext &Ctx = *Result.Context;
+
+  if (const auto *E = Result.Nodes.getNodeAs<Expr>("sizeof-constant")) {
+    diag(E->getLocStart(),
+         "suspicious usage of 'sizeof(K)'; did you mean 'K'?");
+  } else if (const auto *E =
+                 Result.Nodes.getNodeAs<Expr>("sizeof-integer-call")) {
+    diag(E->getLocStart(), "suspicious usage of 'sizeof()' on an expression "
+                           "that results in an integer");
+  } else if (const auto *E = Result.Nodes.getNodeAs<Expr>("sizeof-this")) {
+    diag(E->getLocStart(),
+         "suspicious usage of 'sizeof(this)'; did you mean 'sizeof(*this)'");
+  } else if (const auto *E = Result.Nodes.getNodeAs<Expr>("sizeof-charp")) {
+    diag(E->getLocStart(),
+         "suspicious usage of 'sizeof(char*)'; do you mean 'strlen'?");
+  } else if (const auto *E =
+                 Result.Nodes.getNodeAs<Expr>("sizeof-pointer-to-aggregate")) {
+    diag(E->getLocStart(),
+         "suspicious usage of 'sizeof(A*)'; pointer to aggregate");
+  } else if (const auto *E =
+                 Result.Nodes.getNodeAs<Expr>("sizeof-compare-constant")) {
+    diag(E->getLocStart(),
+         "suspicious comparison of 'sizeof(expr)' to a constant");
+  } else if (const auto *E =
+                 Result.Nodes.getNodeAs<Expr>("sizeof-comma-expr")) {
+    diag(E->getLocStart(), "suspicious usage of 'sizeof(..., ...)'");
+  } else if (const auto *E =
+                 Result.Nodes.getNodeAs<Expr>("sizeof-divide-expr")) {
+    const auto *NumTy = Result.Nodes.getNodeAs<Type>("num-type");
+    const auto *DenomTy = Result.Nodes.getNodeAs<Type>("denom-type");
+    const auto *ElementTy = Result.Nodes.getNodeAs<Type>("elem-type");
+    const auto *PointedTy = Result.Nodes.getNodeAs<Type>("elem-ptr-type");
+
+    CharUnits NumeratorSize = getSizeOfType(Ctx, NumTy);
+    CharUnits DenominatorSize = getSizeOfType(Ctx, DenomTy);
+    CharUnits ElementSize = getSizeOfType(Ctx, ElementTy);
+
+    if (DenominatorSize > CharUnits::Zero() &&
+        !NumeratorSize.isMultipleOf(DenominatorSize)) {
+      diag(E->getLocStart(), "suspicious usage of 'sizeof(...)/sizeof(...)';"
+                             " numerator is not a multiple of denominator");
+    } else if (ElementSize > CharUnits::Zero() &&
+               DenominatorSize > CharUnits::Zero() &&
+               ElementSize != DenominatorSize) {
+      diag(E->getLocStart(), "suspicious usage of 'sizeof(...)/sizeof(...)';"
+                             " numerator is not a multiple of denominator");
+    } else if (NumTy && DenomTy && NumTy == DenomTy) {
+      diag(E->getLocStart(),
+           "suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'");
+    } else if (PointedTy && DenomTy && PointedTy == DenomTy) {
+      diag(E->getLocStart(),
+           "suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'");
+    } else if (NumTy && DenomTy && NumTy->isPointerType() &&
+               DenomTy->isPointerType()) {
+      diag(E->getLocStart(),
+           "suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'");
+    }
+  } else if (const auto *E =
+                 Result.Nodes.getNodeAs<Expr>("sizeof-sizeof-expr")) {
+    diag(E->getLocStart(), "suspicious usage of 'sizeof(sizeof(...))'");
+  } else if (const auto *E =
+                 Result.Nodes.getNodeAs<Expr>("sizeof-multiply-sizeof")) {
+    diag(E->getLocStart(), "suspicious 'sizeof' by 'sizeof' multiplication");
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.h
new file mode 100644
index 0000000..8e14c31
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.h
@@ -0,0 +1,41 @@
+//===--- SizeofExpressionCheck.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_SIZEOFEXPRESSIONCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SIZEOFEXPRESSIONCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Find suspicious usages of sizeof expression.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-sizeof-expression.html
+class SizeofExpressionCheck : public ClangTidyCheck {
+public:
+  SizeofExpressionCheck(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 WarnOnSizeOfConstant;
+  const bool WarnOnSizeOfIntegerExpression;
+  const bool WarnOnSizeOfThis;
+  const bool WarnOnSizeOfCompareToConstant;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SIZEOFEXPRESSIONCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp
new file mode 100644
index 0000000..420428f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp
@@ -0,0 +1,136 @@
+//===--- StringConstructorCheck.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 "StringConstructorCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+AST_MATCHER_P(IntegerLiteral, isBiggerThan, unsigned, N) {
+  return Node.getValue().getZExtValue() > N;
+}
+} // namespace
+
+StringConstructorCheck::StringConstructorCheck(StringRef Name,
+                                               ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      WarnOnLargeLength(Options.get("WarnOnLargeLength", 1) != 0),
+      LargeLengthThreshold(Options.get("LargeLengthThreshold", 0x800000)) {}
+
+void StringConstructorCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "WarnOnLargeLength", WarnOnLargeLength);
+  Options.store(Opts, "LargeLengthThreshold", LargeLengthThreshold);
+}
+
+void StringConstructorCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  const auto ZeroExpr = expr(ignoringParenImpCasts(integerLiteral(equals(0))));
+  const auto CharExpr = expr(ignoringParenImpCasts(characterLiteral()));
+  const auto NegativeExpr = expr(ignoringParenImpCasts(
+      unaryOperator(hasOperatorName("-"),
+                    hasUnaryOperand(integerLiteral(unless(equals(0)))))));
+  const auto LargeLengthExpr = expr(ignoringParenImpCasts(
+      integerLiteral(isBiggerThan(LargeLengthThreshold))));
+  const auto CharPtrType = type(anyOf(pointerType(), arrayType()));
+
+  // Match a string-literal; even through a declaration with initializer.
+  const auto BoundStringLiteral = stringLiteral().bind("str");
+  const auto ConstStrLiteralDecl = varDecl(
+      isDefinition(), hasType(constantArrayType()), hasType(isConstQualified()),
+      hasInitializer(ignoringParenImpCasts(BoundStringLiteral)));
+  const auto ConstPtrStrLiteralDecl = varDecl(
+      isDefinition(),
+      hasType(pointerType(pointee(isAnyCharacter(), isConstQualified()))),
+      hasInitializer(ignoringParenImpCasts(BoundStringLiteral)));
+  const auto ConstStrLiteral = expr(ignoringParenImpCasts(anyOf(
+      BoundStringLiteral, declRefExpr(hasDeclaration(anyOf(
+                              ConstPtrStrLiteralDecl, ConstStrLiteralDecl))))));
+
+  // Check the fill constructor. Fills the string with n consecutive copies of
+  // character c. [i.e string(size_t n, char c);].
+  Finder->addMatcher(
+      cxxConstructExpr(
+          hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
+          hasArgument(0, hasType(qualType(isInteger()))),
+          hasArgument(1, hasType(qualType(isInteger()))),
+          anyOf(
+              // Detect the expression: string('x', 40);
+              hasArgument(0, CharExpr.bind("swapped-parameter")),
+              // Detect the expression: string(0, ...);
+              hasArgument(0, ZeroExpr.bind("empty-string")),
+              // Detect the expression: string(-4, ...);
+              hasArgument(0, NegativeExpr.bind("negative-length")),
+              // Detect the expression: string(0x1234567, ...);
+              hasArgument(0, LargeLengthExpr.bind("large-length"))))
+          .bind("constructor"),
+      this);
+
+  // Check the literal string constructor with char pointer and length
+  // parameters. [i.e. string (const char* s, size_t n);]
+  Finder->addMatcher(
+      cxxConstructExpr(
+          hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
+          hasArgument(0, hasType(CharPtrType)),
+          hasArgument(1, hasType(isInteger())),
+          anyOf(
+              // Detect the expression: string("...", 0);
+              hasArgument(1, ZeroExpr.bind("empty-string")),
+              // Detect the expression: string("...", -4);
+              hasArgument(1, NegativeExpr.bind("negative-length")),
+              // Detect the expression: string("lit", 0x1234567);
+              hasArgument(1, LargeLengthExpr.bind("large-length")),
+              // Detect the expression: string("lit", 5)
+              allOf(hasArgument(0, ConstStrLiteral.bind("literal-with-length")),
+                    hasArgument(1, ignoringParenImpCasts(
+                                       integerLiteral().bind("int"))))))
+          .bind("constructor"),
+      this);
+}
+
+void StringConstructorCheck::check(const MatchFinder::MatchResult &Result) {
+  const ASTContext &Ctx = *Result.Context;
+  const auto *E = Result.Nodes.getNodeAs<CXXConstructExpr>("constructor");
+  assert(E && "missing constructor expression");
+  SourceLocation Loc = E->getLocStart();
+
+  if (Result.Nodes.getNodeAs<Expr>("swapped-parameter")) {
+    const Expr *P0 = E->getArg(0);
+    const Expr *P1 = E->getArg(1);
+    diag(Loc, "string constructor parameters are probably swapped;"
+              " expecting string(count, character)")
+        << tooling::fixit::createReplacement(*P0, *P1, Ctx)
+        << tooling::fixit::createReplacement(*P1, *P0, Ctx);
+  } else if (Result.Nodes.getNodeAs<Expr>("empty-string")) {
+    diag(Loc, "constructor creating an empty string");
+  } else if (Result.Nodes.getNodeAs<Expr>("negative-length")) {
+    diag(Loc, "negative value used as length parameter");
+  } else if (Result.Nodes.getNodeAs<Expr>("large-length")) {
+    if (WarnOnLargeLength)
+      diag(Loc, "suspicious large length parameter");
+  } else if (Result.Nodes.getNodeAs<Expr>("literal-with-length")) {
+    const auto *Str = Result.Nodes.getNodeAs<StringLiteral>("str");
+    const auto *Lit = Result.Nodes.getNodeAs<IntegerLiteral>("int");
+    if (Lit->getValue().ugt(Str->getLength())) {
+      diag(Loc, "length is bigger then string literal size");
+    }
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.h
new file mode 100644
index 0000000..52e9791
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.h
@@ -0,0 +1,39 @@
+//===--- StringConstructorCheck.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_STRING_CONSTRUCTOR_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRING_CONSTRUCTOR_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds suspicious string constructor and check their parameters.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-string-constructor.html
+class StringConstructorCheck : public ClangTidyCheck {
+public:
+  StringConstructorCheck(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 WarnOnLargeLength;
+  const unsigned int LargeLengthThreshold;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRING_CONSTRUCTOR_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp
new file mode 100644
index 0000000..f373648
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp
@@ -0,0 +1,86 @@
+//===--- StringIntegerAssignmentCheck.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 "StringIntegerAssignmentCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void StringIntegerAssignmentCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+  Finder->addMatcher(
+      cxxOperatorCallExpr(
+          anyOf(hasOverloadedOperatorName("="),
+                hasOverloadedOperatorName("+=")),
+          callee(cxxMethodDecl(ofClass(classTemplateSpecializationDecl(
+              hasName("::std::basic_string"),
+              hasTemplateArgument(0, refersToType(qualType().bind("type"))))))),
+          hasArgument(1,
+                      ignoringImpCasts(expr(hasType(isInteger()),
+                                            unless(hasType(isAnyCharacter())))
+                                           .bind("expr"))),
+          unless(isInTemplateInstantiation())),
+      this);
+}
+
+void StringIntegerAssignmentCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *Argument = Result.Nodes.getNodeAs<Expr>("expr");
+  SourceLocation Loc = Argument->getLocStart();
+
+  auto Diag =
+      diag(Loc, "an integer is interpreted as a character code when assigning "
+                "it to a string; if this is intended, cast the integer to the "
+                "appropriate character type; if you want a string "
+                "representation, use the appropriate conversion facility");
+
+  if (Loc.isMacroID())
+    return;
+
+  auto CharType = *Result.Nodes.getNodeAs<QualType>("type");
+  bool IsWideCharType = CharType->isWideCharType();
+  if (!CharType->isCharType() && !IsWideCharType)
+    return;
+  bool IsOneDigit = false;
+  bool IsLiteral = false;
+  if (const auto *Literal = dyn_cast<IntegerLiteral>(Argument)) {
+    IsOneDigit = Literal->getValue().getLimitedValue() < 10;
+    IsLiteral = true;
+  }
+
+  SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+      Argument->getLocEnd(), 0, *Result.SourceManager, getLangOpts());
+  if (IsOneDigit) {
+    Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "L'" : "'")
+         << FixItHint::CreateInsertion(EndLoc, "'");
+    return;
+  }
+  if (IsLiteral) {
+    Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "L\"" : "\"")
+         << FixItHint::CreateInsertion(EndLoc, "\"");
+    return;
+  }
+
+  if (getLangOpts().CPlusPlus11) {
+    Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "std::to_wstring("
+                                                           : "std::to_string(")
+         << FixItHint::CreateInsertion(EndLoc, ")");
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringIntegerAssignmentCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringIntegerAssignmentCheck.h
new file mode 100644
index 0000000..42fa53e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringIntegerAssignmentCheck.h
@@ -0,0 +1,35 @@
+//===--- StringIntegerAssignmentCheck.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_STRINGINTEGERASSIGNMENTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRINGINTEGERASSIGNMENTCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds instances where an integer is assigned to a string.
+///
+/// For more details see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-string-assignment.html
+class StringIntegerAssignmentCheck : public ClangTidyCheck {
+public:
+  StringIntegerAssignmentCheck(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_STRINGINTEGERASSIGNMENTCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.cpp
new file mode 100644
index 0000000..eaa610f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.cpp
@@ -0,0 +1,85 @@
+//===--- StringLiteralWithEmbeddedNulCheck.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 "StringLiteralWithEmbeddedNulCheck.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(StringLiteral, containsNul) {
+  for (size_t i = 0; i < Node.getLength(); ++i)
+    if (Node.getCodeUnit(i) == '\0')
+      return true;
+  return false;
+}
+} // namespace
+
+void StringLiteralWithEmbeddedNulCheck::registerMatchers(MatchFinder *Finder) {
+  // Match a string that contains embedded NUL character. Extra-checks are
+  // applied in |check| to find incorectly escaped characters.
+  Finder->addMatcher(stringLiteral(containsNul()).bind("strlit"), this);
+
+  // The remaining checks only apply to C++.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  const auto StrLitWithNul =
+      ignoringParenImpCasts(stringLiteral(containsNul()).bind("truncated"));
+
+  // Match string constructor.
+  const auto StringConstructorExpr = expr(anyOf(
+      cxxConstructExpr(argumentCountIs(1),
+                       hasDeclaration(cxxMethodDecl(hasName("basic_string")))),
+      // If present, the second argument is the alloc object which must not
+      // be present explicitly.
+      cxxConstructExpr(argumentCountIs(2),
+                       hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
+                       hasArgument(1, cxxDefaultArgExpr()))));
+
+  // Detect passing a suspicious string literal to a string constructor.
+  // example: std::string str = "abc\0def";
+  Finder->addMatcher(
+      cxxConstructExpr(StringConstructorExpr, hasArgument(0, StrLitWithNul)),
+      this);
+
+  // Detect passing a suspicious string literal through an overloaded operator.
+  Finder->addMatcher(cxxOperatorCallExpr(hasAnyArgument(StrLitWithNul)), this);
+}
+
+void StringLiteralWithEmbeddedNulCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  if (const auto *SL = Result.Nodes.getNodeAs<StringLiteral>("strlit")) {
+    for (size_t Offset = 0, Length = SL->getLength(); Offset < Length;
+         ++Offset) {
+      // Find a sequence of character like "\0x12".
+      if (Offset + 3 < Length && SL->getCodeUnit(Offset) == '\0' &&
+          SL->getCodeUnit(Offset + 1) == 'x' &&
+          isDigit(SL->getCodeUnit(Offset + 2)) &&
+          isDigit(SL->getCodeUnit(Offset + 3))) {
+        diag(SL->getLocStart(), "suspicious embedded NUL character");
+        return;
+      }
+    }
+  }
+
+  if (const auto *SL = Result.Nodes.getNodeAs<StringLiteral>("truncated")) {
+    diag(SL->getLocStart(),
+         "truncated string literal with embedded NUL character");
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.h
new file mode 100644
index 0000000..f5341c3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.h
@@ -0,0 +1,35 @@
+//===--- StringLiteralWithEmbeddedNulCheck.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_STRINGLITERALWITHEMBEDDEDNULCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRINGLITERALWITHEMBEDDEDNULCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Find suspicious string literals with embedded NUL characters.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-string-literal-with-embedded-nul.html
+class StringLiteralWithEmbeddedNulCheck : public ClangTidyCheck {
+public:
+  StringLiteralWithEmbeddedNulCheck(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_STRINGLITERALWITHEMBEDDEDNULCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp
new file mode 100644
index 0000000..1abad4e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp
@@ -0,0 +1,219 @@
+//===--- SuspiciousEnumUsageCheck.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 "SuspiciousEnumUsageCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include <algorithm>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+static const char DifferentEnumErrorMessage[] =
+    "enum values are from different enum types";
+
+static const char BitmaskErrorMessage[] =
+    "enum type seems like a bitmask (contains mostly "
+    "power-of-2 literals), but this literal is not a "
+    "power-of-2";
+
+static const char BitmaskVarErrorMessage[] =
+    "enum type seems like a bitmask (contains mostly "
+    "power-of-2 literals) but %plural{1:a literal is|:some literals are}0 not "
+    "power-of-2";
+
+static const char BitmaskNoteMessage[] = "used here as a bitmask";
+
+/// Stores a min and a max value which describe an interval.
+struct ValueRange {
+  llvm::APSInt MinVal;
+  llvm::APSInt MaxVal;
+
+  ValueRange(const EnumDecl *EnumDec) {
+    const auto MinMaxVal = std::minmax_element(
+        EnumDec->enumerator_begin(), EnumDec->enumerator_end(),
+        [](const EnumConstantDecl *E1, const EnumConstantDecl *E2) {
+          return llvm::APSInt::compareValues(E1->getInitVal(),
+                                             E2->getInitVal()) < 0;
+        });
+    MinVal = MinMaxVal.first->getInitVal();
+    MaxVal = MinMaxVal.second->getInitVal();
+  }
+};
+
+/// Return the number of EnumConstantDecls in an EnumDecl.
+static int enumLength(const EnumDecl *EnumDec) {
+  return std::distance(EnumDec->enumerator_begin(), EnumDec->enumerator_end());
+}
+
+static bool hasDisjointValueRange(const EnumDecl *Enum1,
+                                  const EnumDecl *Enum2) {
+  ValueRange Range1(Enum1), Range2(Enum2);
+  return llvm::APSInt::compareValues(Range1.MaxVal, Range2.MinVal) < 0 ||
+         llvm::APSInt::compareValues(Range2.MaxVal, Range1.MinVal) < 0;
+}
+
+static bool isNonPowerOf2NorNullLiteral(const EnumConstantDecl *EnumConst) {
+  llvm::APSInt Val = EnumConst->getInitVal();
+  if (Val.isPowerOf2() || !Val.getBoolValue())
+    return false;
+  const Expr *InitExpr = EnumConst->getInitExpr();
+  if (!InitExpr)
+    return true;
+  return isa<IntegerLiteral>(InitExpr->IgnoreImpCasts());
+}
+
+static bool isMaxValAllBitSetLiteral(const EnumDecl *EnumDec) {
+  auto EnumConst = std::max_element(
+      EnumDec->enumerator_begin(), EnumDec->enumerator_end(),
+      [](const EnumConstantDecl *E1, const EnumConstantDecl *E2) {
+        return E1->getInitVal() < E2->getInitVal();
+      });
+
+  if (const Expr *InitExpr = EnumConst->getInitExpr()) {
+    return EnumConst->getInitVal().countTrailingOnes() ==
+               EnumConst->getInitVal().getActiveBits() &&
+           isa<IntegerLiteral>(InitExpr->IgnoreImpCasts());
+  }
+  return false;
+}
+
+static int countNonPowOfTwoLiteralNum(const EnumDecl *EnumDec) {
+  return std::count_if(
+      EnumDec->enumerator_begin(), EnumDec->enumerator_end(),
+      [](const EnumConstantDecl *E) { return isNonPowerOf2NorNullLiteral(E); });
+}
+
+/// Check if there is one or two enumerators that are not a power of 2 and are
+/// initialized by a literal in the enum type, and that the enumeration contains
+/// enough elements to reasonably act as a bitmask. Exclude the case where the
+/// last enumerator is the sum of the lesser values (and initialized by a
+/// literal) or when it could contain consecutive values.
+static bool isPossiblyBitMask(const EnumDecl *EnumDec) {
+  ValueRange VR(EnumDec);
+  int EnumLen = enumLength(EnumDec);
+  int NonPowOfTwoCounter = countNonPowOfTwoLiteralNum(EnumDec);
+  return NonPowOfTwoCounter >= 1 && NonPowOfTwoCounter <= 2 &&
+         NonPowOfTwoCounter < EnumLen / 2 &&
+         (VR.MaxVal - VR.MinVal != EnumLen - 1) &&
+         !(NonPowOfTwoCounter == 1 && isMaxValAllBitSetLiteral(EnumDec));
+}
+
+SuspiciousEnumUsageCheck::SuspiciousEnumUsageCheck(StringRef Name,
+                                                   ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      StrictMode(Options.getLocalOrGlobal("StrictMode", 0)) {}
+
+void SuspiciousEnumUsageCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "StrictMode", StrictMode);
+}
+
+void SuspiciousEnumUsageCheck::registerMatchers(MatchFinder *Finder) {
+  const auto enumExpr = [](StringRef RefName, StringRef DeclName) {
+    return allOf(ignoringImpCasts(expr().bind(RefName)),
+                 ignoringImpCasts(hasType(enumDecl().bind(DeclName))));
+  };
+
+  Finder->addMatcher(
+      binaryOperator(hasOperatorName("|"), hasLHS(enumExpr("", "enumDecl")),
+                     hasRHS(allOf(enumExpr("", "otherEnumDecl"),
+                                  ignoringImpCasts(hasType(enumDecl(
+                                      unless(equalsBoundNode("enumDecl"))))))))
+          .bind("diffEnumOp"),
+      this);
+
+  Finder->addMatcher(
+      binaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("|")),
+                     hasLHS(enumExpr("lhsExpr", "enumDecl")),
+                     hasRHS(allOf(enumExpr("rhsExpr", ""),
+                                  ignoringImpCasts(hasType(enumDecl(
+                                      equalsBoundNode("enumDecl"))))))),
+      this);
+
+  Finder->addMatcher(
+      binaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("|")),
+                     hasEitherOperand(
+                         allOf(hasType(isInteger()), unless(enumExpr("", "")))),
+                     hasEitherOperand(enumExpr("enumExpr", "enumDecl"))),
+      this);
+
+  Finder->addMatcher(
+      binaryOperator(anyOf(hasOperatorName("|="), hasOperatorName("+=")),
+                     hasRHS(enumExpr("enumExpr", "enumDecl"))),
+      this);
+}
+
+void SuspiciousEnumUsageCheck::checkSuspiciousBitmaskUsage(
+    const Expr *NodeExpr, const EnumDecl *EnumDec) {
+  const auto *EnumExpr = dyn_cast<DeclRefExpr>(NodeExpr);
+  const auto *EnumConst =
+      EnumExpr ? dyn_cast<EnumConstantDecl>(EnumExpr->getDecl()) : nullptr;
+
+  // Report the parameter if neccessary.
+  if (!EnumConst) {
+    diag(EnumDec->getInnerLocStart(), BitmaskVarErrorMessage)
+        << countNonPowOfTwoLiteralNum(EnumDec);
+    diag(EnumExpr->getExprLoc(), BitmaskNoteMessage, DiagnosticIDs::Note);
+  } else if (isNonPowerOf2NorNullLiteral(EnumConst)) {
+    diag(EnumConst->getSourceRange().getBegin(), BitmaskErrorMessage);
+    diag(EnumExpr->getExprLoc(), BitmaskNoteMessage, DiagnosticIDs::Note);
+  }
+}
+
+void SuspiciousEnumUsageCheck::check(const MatchFinder::MatchResult &Result) {
+  // Case 1: The two enum values come from different types.
+  if (const auto *DiffEnumOp =
+          Result.Nodes.getNodeAs<BinaryOperator>("diffEnumOp")) {
+    const auto *EnumDec = Result.Nodes.getNodeAs<EnumDecl>("enumDecl");
+    const auto *OtherEnumDec =
+        Result.Nodes.getNodeAs<EnumDecl>("otherEnumDecl");
+    // Skip when one of the parameters is an empty enum. The
+    // hasDisjointValueRange function could not decide the values properly in
+    // case of an empty enum.
+    if (EnumDec->enumerator_begin() == EnumDec->enumerator_end() ||
+        OtherEnumDec->enumerator_begin() == OtherEnumDec->enumerator_end())
+      return;
+
+    if (!hasDisjointValueRange(EnumDec, OtherEnumDec))
+      diag(DiffEnumOp->getOperatorLoc(), DifferentEnumErrorMessage);
+    return;
+  }
+
+  // Case 2 and 3 only checked in strict mode. The checker tries to detect
+  // suspicious bitmasks which contains values initialized by non power-of-2
+  // literals.
+  if (!StrictMode)
+    return;
+  const auto *EnumDec = Result.Nodes.getNodeAs<EnumDecl>("enumDecl");
+  if (!isPossiblyBitMask(EnumDec))
+    return;
+
+  // Case 2:
+  //   a. Investigating the right hand side of `+=` or `|=` operator.
+  //   b. When the operator is `|` or `+` but only one of them is an EnumExpr
+  if (const auto *EnumExpr = Result.Nodes.getNodeAs<Expr>("enumExpr")) {
+    checkSuspiciousBitmaskUsage(EnumExpr, EnumDec);
+    return;
+  }
+
+  // Case 3:
+  // '|' or '+' operator where both argument comes from the same enum type
+  const auto *LhsExpr = Result.Nodes.getNodeAs<Expr>("lhsExpr");
+  checkSuspiciousBitmaskUsage(LhsExpr, EnumDec);
+
+  const auto *RhsExpr = Result.Nodes.getNodeAs<Expr>("rhsExpr");
+  checkSuspiciousBitmaskUsage(RhsExpr, EnumDec);
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.h
new file mode 100644
index 0000000..9c1b53d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.h
@@ -0,0 +1,39 @@
+//===--- SuspiciousEnumUsageCheck.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_SUSPICIOUSENUMUSAGECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSENUMUSAGECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// The checker detects various cases when an enum is probably misused (as a
+/// bitmask).
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-suspicious-enum-usage.html
+class SuspiciousEnumUsageCheck : public ClangTidyCheck {
+public:
+  SuspiciousEnumUsageCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  void checkSuspiciousBitmaskUsage(const Expr*, const EnumDecl*);
+  const bool StrictMode;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSENUMUSAGECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp
new file mode 100644
index 0000000..8e11a43
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h
new file mode 100644
index 0000000..1c0d1bc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp
new file mode 100644
index 0000000..3831dc3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp
@@ -0,0 +1,129 @@
+//===--- SuspiciousMissingCommaCheck.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 "SuspiciousMissingCommaCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+
+bool isConcatenatedLiteralsOnPurpose(ASTContext *Ctx,
+                                     const StringLiteral *Lit) {
+  // String literals surrounded by parentheses are assumed to be on purpose.
+  //    i.e.:  const char* Array[] = { ("a" "b" "c"), "d", [...] };
+  auto Parents = Ctx->getParents(*Lit);
+  if (Parents.size() == 1 && Parents[0].get<ParenExpr>() != nullptr)
+    return true;
+
+  // Appropriately indented string literals are assumed to be on purpose.
+  // The following frequent indentation is accepted:
+  //     const char* Array[] = {
+  //       "first literal"
+  //           "indented literal"
+  //           "indented literal",
+  //       "second literal",
+  //       [...]
+  //     };
+  const SourceManager &SM = Ctx->getSourceManager();
+  bool IndentedCorrectly = true;
+  SourceLocation FirstToken = Lit->getStrTokenLoc(0);
+  FileID BaseFID = SM.getFileID(FirstToken);
+  unsigned int BaseIndent = SM.getSpellingColumnNumber(FirstToken);
+  unsigned int BaseLine = SM.getSpellingLineNumber(FirstToken);
+  for (unsigned int TokNum = 1; TokNum < Lit->getNumConcatenated(); ++TokNum) {
+    SourceLocation Token = Lit->getStrTokenLoc(TokNum);
+    FileID FID = SM.getFileID(Token);
+    unsigned int Indent = SM.getSpellingColumnNumber(Token);
+    unsigned int Line = SM.getSpellingLineNumber(Token);
+    if (FID != BaseFID || Line != BaseLine + TokNum || Indent <= BaseIndent) {
+      IndentedCorrectly = false;
+      break;
+    }
+  }
+  if (IndentedCorrectly)
+    return true;
+
+  // There is no pattern recognized by the checker, assume it's not on purpose.
+  return false;
+}
+
+AST_MATCHER_P(StringLiteral, isConcatenatedLiteral, unsigned,
+              MaxConcatenatedTokens) {
+  return Node.getNumConcatenated() > 1 &&
+         Node.getNumConcatenated() < MaxConcatenatedTokens &&
+         !isConcatenatedLiteralsOnPurpose(&Finder->getASTContext(), &Node);
+}
+
+} // namespace
+
+SuspiciousMissingCommaCheck::SuspiciousMissingCommaCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      SizeThreshold(Options.get("SizeThreshold", 5U)),
+      RatioThreshold(std::stod(Options.get("RatioThreshold", ".2"))),
+      MaxConcatenatedTokens(Options.get("MaxConcatenatedTokens", 5U)) {}
+
+void SuspiciousMissingCommaCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "SizeThreshold", SizeThreshold);
+  Options.store(Opts, "RatioThreshold", std::to_string(RatioThreshold));
+  Options.store(Opts, "MaxConcatenatedTokens", MaxConcatenatedTokens);
+}
+
+void SuspiciousMissingCommaCheck::registerMatchers(MatchFinder *Finder) {
+  const auto ConcatenatedStringLiteral =
+      stringLiteral(isConcatenatedLiteral(MaxConcatenatedTokens)).bind("str");
+
+  const auto StringsInitializerList =
+      initListExpr(hasType(constantArrayType()),
+                   has(ignoringParenImpCasts(expr(ConcatenatedStringLiteral))));
+
+  Finder->addMatcher(StringsInitializerList.bind("list"), this);
+}
+
+void SuspiciousMissingCommaCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *InitializerList = Result.Nodes.getNodeAs<InitListExpr>("list");
+  const auto *ConcatenatedLiteral =
+      Result.Nodes.getNodeAs<StringLiteral>("str");
+  assert(InitializerList && ConcatenatedLiteral);
+
+  // Skip small arrays as they often generate false-positive.
+  unsigned int Size = InitializerList->getNumInits();
+  if (Size < SizeThreshold)
+    return;
+
+  // Count the number of occurence of concatenated string literal.
+  unsigned int Count = 0;
+  for (unsigned int i = 0; i < Size; ++i) {
+    const Expr *Child = InitializerList->getInit(i)->IgnoreImpCasts();
+    if (const auto *Literal = dyn_cast<StringLiteral>(Child)) {
+      if (Literal->getNumConcatenated() > 1)
+        ++Count;
+    }
+  }
+
+  // Warn only when concatenation is not common in this initializer list.
+  // The current threshold is set to less than 1/5 of the string literals.
+  if (double(Count) / Size > RatioThreshold)
+    return;
+
+  diag(ConcatenatedLiteral->getLocStart(),
+       "suspicious string literal, probably missing a comma");
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.h
new file mode 100644
index 0000000..4ae3ecf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.h
@@ -0,0 +1,44 @@
+//===--- SuspiciousMissingCommaCheck.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_SUSPICIOUSMISSINGCOMMACHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSMISSINGCOMMACHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// This check finds string literals which are probably concatenated
+/// accidentally.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-suspicious-missing-comma.html
+class SuspiciousMissingCommaCheck : public ClangTidyCheck {
+public:
+  SuspiciousMissingCommaCheck(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:
+  // Minimal size of a string literals array to be considered by the checker.
+  const unsigned SizeThreshold;
+  // Maximal threshold ratio of suspicious string literals to be considered.
+  const double RatioThreshold;
+  // Maximal number of concatenated tokens.
+  const unsigned MaxConcatenatedTokens;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSMISSINGCOMMACHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp
new file mode 100644
index 0000000..d7f51d0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp
@@ -0,0 +1,77 @@
+//===--- SuspiciousSemicolonCheck.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 "SuspiciousSemicolonCheck.h"
+#include "../utils/LexerUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void SuspiciousSemicolonCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      stmt(anyOf(ifStmt(hasThen(nullStmt().bind("semi")),
+                        unless(hasElse(stmt()))),
+                 forStmt(hasBody(nullStmt().bind("semi"))),
+                 cxxForRangeStmt(hasBody(nullStmt().bind("semi"))),
+                 whileStmt(hasBody(nullStmt().bind("semi")))))
+          .bind("stmt"),
+      this);
+}
+
+void SuspiciousSemicolonCheck::check(const MatchFinder::MatchResult &Result) {
+  if (Result.Context->getDiagnostics().hasUncompilableErrorOccurred())
+    return;
+
+  const auto *Semicolon = Result.Nodes.getNodeAs<NullStmt>("semi");
+  SourceLocation LocStart = Semicolon->getLocStart();
+
+  if (LocStart.isMacroID())
+    return;
+
+  ASTContext &Ctxt = *Result.Context;
+  auto Token = utils::lexer::getPreviousToken(Ctxt, LocStart);
+  auto &SM = *Result.SourceManager;
+  unsigned SemicolonLine = SM.getSpellingLineNumber(LocStart);
+
+  const auto *Statement = Result.Nodes.getNodeAs<Stmt>("stmt");
+  const bool IsIfStmt = isa<IfStmt>(Statement);
+
+  if (!IsIfStmt &&
+      SM.getSpellingLineNumber(Token.getLocation()) != SemicolonLine)
+    return;
+
+  SourceLocation LocEnd = Semicolon->getLocEnd();
+  FileID FID = SM.getFileID(LocEnd);
+  llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, LocEnd);
+  Lexer Lexer(SM.getLocForStartOfFile(FID), Ctxt.getLangOpts(),
+              Buffer->getBufferStart(), SM.getCharacterData(LocEnd) + 1,
+              Buffer->getBufferEnd());
+  if (Lexer.LexFromRawLexer(Token))
+    return;
+
+  unsigned BaseIndent = SM.getSpellingColumnNumber(Statement->getLocStart());
+  unsigned NewTokenIndent = SM.getSpellingColumnNumber(Token.getLocation());
+  unsigned NewTokenLine = SM.getSpellingLineNumber(Token.getLocation());
+
+  if (!IsIfStmt && NewTokenIndent <= BaseIndent &&
+      Token.getKind() != tok::l_brace && NewTokenLine != SemicolonLine)
+    return;
+
+  diag(LocStart, "potentially unintended semicolon")
+      << FixItHint::CreateRemoval(SourceRange(LocStart, LocEnd));
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.h
new file mode 100644
index 0000000..adfced1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.h
@@ -0,0 +1,36 @@
+//===--- SuspiciousSemicolonCheck.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_SUSPICIOUSSEMICOLONCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSSEMICOLONCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// This check finds semicolon that modifies the meaning of the program
+/// unintendedly.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-suspicious-semicolon.html
+class SuspiciousSemicolonCheck : public ClangTidyCheck {
+public:
+  SuspiciousSemicolonCheck(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_SUSPICIOUSSEMICOLONCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp
new file mode 100644
index 0000000..0cc6215
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp
@@ -0,0 +1,218 @@
+//===--- SuspiciousStringCompareCheck.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 "SuspiciousStringCompareCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+// Semicolon separated list of known string compare-like functions. The list
+// must ends with a semicolon.
+static const char KnownStringCompareFunctions[] = "__builtin_memcmp;"
+                                                  "__builtin_strcasecmp;"
+                                                  "__builtin_strcmp;"
+                                                  "__builtin_strncasecmp;"
+                                                  "__builtin_strncmp;"
+                                                  "_mbscmp;"
+                                                  "_mbscmp_l;"
+                                                  "_mbsicmp;"
+                                                  "_mbsicmp_l;"
+                                                  "_mbsnbcmp;"
+                                                  "_mbsnbcmp_l;"
+                                                  "_mbsnbicmp;"
+                                                  "_mbsnbicmp_l;"
+                                                  "_mbsncmp;"
+                                                  "_mbsncmp_l;"
+                                                  "_mbsnicmp;"
+                                                  "_mbsnicmp_l;"
+                                                  "_memicmp;"
+                                                  "_memicmp_l;"
+                                                  "_stricmp;"
+                                                  "_stricmp_l;"
+                                                  "_strnicmp;"
+                                                  "_strnicmp_l;"
+                                                  "_wcsicmp;"
+                                                  "_wcsicmp_l;"
+                                                  "_wcsnicmp;"
+                                                  "_wcsnicmp_l;"
+                                                  "lstrcmp;"
+                                                  "lstrcmpi;"
+                                                  "memcmp;"
+                                                  "memicmp;"
+                                                  "strcasecmp;"
+                                                  "strcmp;"
+                                                  "strcmpi;"
+                                                  "stricmp;"
+                                                  "strncasecmp;"
+                                                  "strncmp;"
+                                                  "strnicmp;"
+                                                  "wcscasecmp;"
+                                                  "wcscmp;"
+                                                  "wcsicmp;"
+                                                  "wcsncmp;"
+                                                  "wcsnicmp;"
+                                                  "wmemcmp;";
+
+SuspiciousStringCompareCheck::SuspiciousStringCompareCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      WarnOnImplicitComparison(Options.get("WarnOnImplicitComparison", 1)),
+      WarnOnLogicalNotComparison(Options.get("WarnOnLogicalNotComparison", 0)),
+      StringCompareLikeFunctions(
+          Options.get("StringCompareLikeFunctions", "")) {}
+
+void SuspiciousStringCompareCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "WarnOnImplicitComparison", WarnOnImplicitComparison);
+  Options.store(Opts, "WarnOnLogicalNotComparison", WarnOnLogicalNotComparison);
+  Options.store(Opts, "StringCompareLikeFunctions", StringCompareLikeFunctions);
+}
+
+void SuspiciousStringCompareCheck::registerMatchers(MatchFinder *Finder) {
+  // Match relational operators.
+  const auto ComparisonUnaryOperator = unaryOperator(hasOperatorName("!"));
+  const auto ComparisonBinaryOperator =
+      binaryOperator(matchers::isComparisonOperator());
+  const auto ComparisonOperator =
+      expr(anyOf(ComparisonUnaryOperator, ComparisonBinaryOperator));
+
+  // Add the list of known string compare-like functions and add user-defined
+  // functions.
+  std::vector<std::string> FunctionNames = utils::options::parseStringList(
+      (llvm::Twine(KnownStringCompareFunctions) + StringCompareLikeFunctions)
+          .str());
+
+  // Match a call to a string compare functions.
+  const auto FunctionCompareDecl =
+      functionDecl(hasAnyName(std::vector<StringRef>(FunctionNames.begin(),
+                                                     FunctionNames.end())))
+          .bind("decl");
+  const auto DirectStringCompareCallExpr =
+      callExpr(hasDeclaration(FunctionCompareDecl)).bind("call");
+  const auto MacroStringCompareCallExpr = conditionalOperator(anyOf(
+      hasTrueExpression(ignoringParenImpCasts(DirectStringCompareCallExpr)),
+      hasFalseExpression(ignoringParenImpCasts(DirectStringCompareCallExpr))));
+  // The implicit cast is not present in C.
+  const auto StringCompareCallExpr = ignoringParenImpCasts(
+      anyOf(DirectStringCompareCallExpr, MacroStringCompareCallExpr));
+
+  if (WarnOnImplicitComparison) {
+    // Detect suspicious calls to string compare:
+    //     'if (strcmp())'  ->  'if (strcmp() != 0)'
+    Finder->addMatcher(
+        stmt(anyOf(ifStmt(hasCondition(StringCompareCallExpr)),
+                   whileStmt(hasCondition(StringCompareCallExpr)),
+                   doStmt(hasCondition(StringCompareCallExpr)),
+                   forStmt(hasCondition(StringCompareCallExpr)),
+                   binaryOperator(
+                       anyOf(hasOperatorName("&&"), hasOperatorName("||")),
+                       hasEitherOperand(StringCompareCallExpr))))
+            .bind("missing-comparison"),
+        this);
+  }
+
+  if (WarnOnLogicalNotComparison) {
+    // Detect suspicious calls to string compared with '!' operator:
+    //     'if (!strcmp())'  ->  'if (strcmp() == 0)'
+    Finder->addMatcher(unaryOperator(hasOperatorName("!"),
+                                     hasUnaryOperand(ignoringParenImpCasts(
+                                         StringCompareCallExpr)))
+                           .bind("logical-not-comparison"),
+                       this);
+  }
+
+  // Detect suspicious cast to an inconsistant type (i.e. not integer type).
+  Finder->addMatcher(
+      implicitCastExpr(unless(hasType(isInteger())),
+                       hasSourceExpression(StringCompareCallExpr))
+          .bind("invalid-conversion"),
+      this);
+
+  // Detect suspicious operator with string compare function as operand.
+  Finder->addMatcher(
+      binaryOperator(
+          unless(anyOf(matchers::isComparisonOperator(), hasOperatorName("&&"),
+                       hasOperatorName("||"), hasOperatorName("="))),
+          hasEitherOperand(StringCompareCallExpr))
+          .bind("suspicious-operator"),
+      this);
+
+  // Detect comparison to invalid constant: 'strcmp() == -1'.
+  const auto InvalidLiteral = ignoringParenImpCasts(
+      anyOf(integerLiteral(unless(equals(0))),
+            unaryOperator(
+                hasOperatorName("-"),
+                has(ignoringParenImpCasts(integerLiteral(unless(equals(0)))))),
+            characterLiteral(), cxxBoolLiteral()));
+
+  Finder->addMatcher(binaryOperator(matchers::isComparisonOperator(),
+                                    hasEitherOperand(StringCompareCallExpr),
+                                    hasEitherOperand(InvalidLiteral))
+                         .bind("invalid-comparison"),
+                     this);
+}
+
+void SuspiciousStringCompareCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *Decl = Result.Nodes.getNodeAs<FunctionDecl>("decl");
+  const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
+  assert(Decl != nullptr && Call != nullptr);
+
+  if (Result.Nodes.getNodeAs<Stmt>("missing-comparison")) {
+    SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+        Call->getRParenLoc(), 0, Result.Context->getSourceManager(),
+        getLangOpts());
+
+    diag(Call->getLocStart(),
+         "function %0 is called without explicitly comparing result")
+        << Decl << FixItHint::CreateInsertion(EndLoc, " != 0");
+  }
+
+  if (const auto *E = Result.Nodes.getNodeAs<Expr>("logical-not-comparison")) {
+    SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+        Call->getRParenLoc(), 0, Result.Context->getSourceManager(),
+        getLangOpts());
+    SourceLocation NotLoc = E->getLocStart();
+
+    diag(Call->getLocStart(),
+         "function %0 is compared using logical not operator")
+        << Decl << FixItHint::CreateRemoval(
+                       CharSourceRange::getTokenRange(NotLoc, NotLoc))
+        << FixItHint::CreateInsertion(EndLoc, " == 0");
+  }
+
+  if (Result.Nodes.getNodeAs<Stmt>("invalid-comparison")) {
+    diag(Call->getLocStart(),
+         "function %0 is compared to a suspicious constant")
+        << Decl;
+  }
+
+  if (const auto *BinOp =
+          Result.Nodes.getNodeAs<BinaryOperator>("suspicious-operator")) {
+    diag(Call->getLocStart(), "results of function %0 used by operator '%1'")
+        << Decl << BinOp->getOpcodeStr();
+  }
+
+  if (Result.Nodes.getNodeAs<Stmt>("invalid-conversion")) {
+    diag(Call->getLocStart(), "function %0 has suspicious implicit cast")
+        << Decl;
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.h
new file mode 100644
index 0000000..38a9d9c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.h
@@ -0,0 +1,40 @@
+//===--- SuspiciousStringCompareCheck.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_SUSPICIOUSSTRINGCOMPARECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSSTRINGCOMPARECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Find suspicious calls to string compare functions.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-suspicious-string-compare.html
+class SuspiciousStringCompareCheck : public ClangTidyCheck {
+public:
+  SuspiciousStringCompareCheck(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 WarnOnImplicitComparison;
+  const bool WarnOnLogicalNotComparison;
+  const std::string StringCompareLikeFunctions;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSSTRINGCOMPARECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SwappedArgumentsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SwappedArgumentsCheck.cpp
new file mode 100644
index 0000000..64d3eaf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SwappedArgumentsCheck.cpp
@@ -0,0 +1,102 @@
+//===--- SwappedArgumentsCheck.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 "SwappedArgumentsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void SwappedArgumentsCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(callExpr().bind("call"), this);
+}
+
+/// \brief Look through lvalue to rvalue and nop casts. This filters out
+/// implicit conversions that have no effect on the input but block our view for
+/// other implicit casts.
+static const Expr *ignoreNoOpCasts(const Expr *E) {
+  if (auto *Cast = dyn_cast<CastExpr>(E))
+    if (Cast->getCastKind() == CK_LValueToRValue ||
+        Cast->getCastKind() == CK_NoOp)
+      return ignoreNoOpCasts(Cast->getSubExpr());
+  return E;
+}
+
+/// \brief Restrict the warning to implicit casts that are most likely
+/// accidental. User defined or integral conversions fit in this category,
+/// lvalue to rvalue or derived to base does not.
+static bool isImplicitCastCandidate(const CastExpr *Cast) {
+  return Cast->getCastKind() == CK_UserDefinedConversion ||
+         Cast->getCastKind() == CK_FloatingToBoolean ||
+         Cast->getCastKind() == CK_FloatingToIntegral ||
+         Cast->getCastKind() == CK_IntegralToBoolean ||
+         Cast->getCastKind() == CK_IntegralToFloating ||
+         Cast->getCastKind() == CK_MemberPointerToBoolean ||
+         Cast->getCastKind() == CK_PointerToBoolean;
+}
+
+void SwappedArgumentsCheck::check(const MatchFinder::MatchResult &Result) {
+  const ASTContext &Ctx = *Result.Context;
+  const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
+
+  llvm::SmallPtrSet<const Expr *, 4> UsedArgs;
+  for (unsigned I = 1, E = Call->getNumArgs(); I < E; ++I) {
+    const Expr *LHS = Call->getArg(I - 1);
+    const Expr *RHS = Call->getArg(I);
+
+    // Only need to check RHS, as LHS has already been covered. We don't want to
+    // emit two warnings for a single argument.
+    if (UsedArgs.count(RHS))
+      continue;
+
+    const auto *LHSCast = dyn_cast<ImplicitCastExpr>(ignoreNoOpCasts(LHS));
+    const auto *RHSCast = dyn_cast<ImplicitCastExpr>(ignoreNoOpCasts(RHS));
+
+    // Look if this is a potentially swapped argument pair. First look for
+    // implicit casts.
+    if (!LHSCast || !RHSCast || !isImplicitCastCandidate(LHSCast) ||
+        !isImplicitCastCandidate(RHSCast))
+      continue;
+
+    // If the types that go into the implicit casts match the types of the other
+    // argument in the declaration there is a high probability that the
+    // arguments were swapped.
+    // TODO: We could make use of the edit distance between the argument name
+    // and the name of the passed variable in addition to this type based
+    // heuristic.
+    const Expr *LHSFrom = ignoreNoOpCasts(LHSCast->getSubExpr());
+    const Expr *RHSFrom = ignoreNoOpCasts(RHSCast->getSubExpr());
+    if (LHS->getType() == RHS->getType() ||
+        LHS->getType() != RHSFrom->getType() ||
+        RHS->getType() != LHSFrom->getType())
+      continue;
+
+    // Emit a warning and fix-its that swap the arguments.
+    diag(Call->getLocStart(), "argument with implicit conversion from %0 "
+                              "to %1 followed by argument converted from "
+                              "%2 to %3, potentially swapped arguments.")
+        << LHS->getType() << LHSFrom->getType() << RHS->getType()
+        << RHSFrom->getType()
+        << tooling::fixit::createReplacement(*LHS, *RHS, Ctx)
+        << tooling::fixit::createReplacement(*RHS, *LHS, Ctx);
+
+    // Remember that we emitted a warning for this argument.
+    UsedArgs.insert(RHSCast);
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SwappedArgumentsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SwappedArgumentsCheck.h
new file mode 100644
index 0000000..59ec3ad
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/SwappedArgumentsCheck.h
@@ -0,0 +1,32 @@
+//===--- SwappedArgumentsCheck.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_SWAPPEDARGUMENTSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SWAPPEDARGUMENTSCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds potentially swapped arguments by looking at implicit conversions.
+class SwappedArgumentsCheck : public ClangTidyCheck {
+public:
+  SwappedArgumentsCheck(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_SWAPPEDARGUMENTSCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/TerminatingContinueCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/TerminatingContinueCheck.cpp
new file mode 100644
index 0000000..3e11e06
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/TerminatingContinueCheck.cpp
@@ -0,0 +1,49 @@
+//===--- TerminatingContinueCheck.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 "TerminatingContinueCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void TerminatingContinueCheck::registerMatchers(MatchFinder *Finder) {
+  const auto doWithFalse =
+      doStmt(hasCondition(ignoringImpCasts(
+                 anyOf(cxxBoolLiteral(equals(false)), integerLiteral(equals(0)),
+                       cxxNullPtrLiteralExpr(), gnuNullExpr()))),
+             equalsBoundNode("closestLoop"));
+
+  Finder->addMatcher(
+      continueStmt(hasAncestor(stmt(anyOf(forStmt(), whileStmt(),
+                                          cxxForRangeStmt(), doStmt()))
+                                   .bind("closestLoop")),
+                   hasAncestor(doWithFalse))
+          .bind("continue"),
+      this);
+}
+
+void TerminatingContinueCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *ContStmt = Result.Nodes.getNodeAs<ContinueStmt>("continue");
+
+  auto Diag =
+      diag(ContStmt->getLocStart(),
+           "'continue' in loop with false condition is equivalent to 'break'")
+      << tooling::fixit::createReplacement(*ContStmt, "break");
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/TerminatingContinueCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/TerminatingContinueCheck.h
new file mode 100644
index 0000000..5985693
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/TerminatingContinueCheck.h
@@ -0,0 +1,36 @@
+//===--- TerminatingContinueCheck.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_TERMINATINGCONTINUECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_TERMINATINGCONTINUECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Checks if a 'continue' statement terminates the loop (i.e. the loop has
+///	a condition which always evaluates to false).
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-terminating-continue.html
+class TerminatingContinueCheck : public ClangTidyCheck {
+public:
+  TerminatingContinueCheck(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_TERMINATINGCONTINUECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ThrowKeywordMissingCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ThrowKeywordMissingCheck.cpp
new file mode 100644
index 0000000..350cf3b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ThrowKeywordMissingCheck.cpp
@@ -0,0 +1,52 @@
+//===--- ThrowKeywordMissingCheck.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 "ThrowKeywordMissingCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void ThrowKeywordMissingCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  auto CtorInitializerList =
+      cxxConstructorDecl(hasAnyConstructorInitializer(anything()));
+
+  Finder->addMatcher(
+      expr(anyOf(cxxFunctionalCastExpr(), cxxBindTemporaryExpr(),
+                 cxxTemporaryObjectExpr()),
+           hasType(cxxRecordDecl(
+               isSameOrDerivedFrom(matchesName("[Ee]xception|EXCEPTION")))),
+           unless(anyOf(hasAncestor(stmt(
+                            anyOf(cxxThrowExpr(), callExpr(), returnStmt()))),
+                        hasAncestor(varDecl()),
+                        allOf(hasAncestor(CtorInitializerList),
+                              unless(hasAncestor(cxxCatchStmt()))))))
+          .bind("temporary-exception-not-thrown"),
+      this); 
+}
+
+void ThrowKeywordMissingCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *TemporaryExpr =
+      Result.Nodes.getNodeAs<Expr>("temporary-exception-not-thrown");
+
+  diag(TemporaryExpr->getLocStart(), "suspicious exception object created but "
+                                     "not thrown; did you mean 'throw %0'?")
+      << TemporaryExpr->getType().getBaseTypeIdentifier()->getName();
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ThrowKeywordMissingCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ThrowKeywordMissingCheck.h
new file mode 100644
index 0000000..cc57083
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/ThrowKeywordMissingCheck.h
@@ -0,0 +1,36 @@
+//===--- ThrowKeywordMissingCheck.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_THROWKEYWORDMISSINGCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_THROWKEYWORDMISSINGCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Emits a warning about temporary objects whose type is (or is derived from) a
+/// class that has 'EXCEPTION', 'Exception' or 'exception' in its name.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-throw-keyword-missing.html
+class ThrowKeywordMissingCheck : public ClangTidyCheck {
+public:
+  ThrowKeywordMissingCheck(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_THROWKEYWORDMISSINGCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
new file mode 100644
index 0000000..ebfe517
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h
new file mode 100644
index 0000000..64d6c56
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.cpp
new file mode 100644
index 0000000..f47ad7e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.cpp
@@ -0,0 +1,84 @@
+//===--- UndelegatedConstructorCheck.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 "UndelegatedConstructorCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+AST_MATCHER_P(Stmt, ignoringTemporaryExpr,
+              ast_matchers::internal::Matcher<Stmt>, InnerMatcher) {
+  const Stmt *E = &Node;
+  for (;;) {
+    // Temporaries with non-trivial dtors.
+    if (const auto *EWC = dyn_cast<ExprWithCleanups>(E))
+      E = EWC->getSubExpr();
+    // Temporaries with zero or more than two ctor arguments.
+    else if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))
+      E = BTE->getSubExpr();
+    // Temporaries with exactly one ctor argument.
+    else if (const auto *FCE = dyn_cast<CXXFunctionalCastExpr>(E))
+      E = FCE->getSubExpr();
+    else
+      break;
+  }
+
+  return InnerMatcher.matches(*E, Finder, Builder);
+}
+
+// Finds a node if it's a base of an already bound node.
+AST_MATCHER_P(CXXRecordDecl, baseOfBoundNode, std::string, ID) {
+  return Builder->removeBindings(
+      [&](const ast_matchers::internal::BoundNodesMap &Nodes) {
+        const auto *Derived = Nodes.getNodeAs<CXXRecordDecl>(ID);
+        return Derived != &Node && !Derived->isDerivedFrom(&Node);
+      });
+}
+} // namespace
+
+void UndelegatedConstructorCheck::registerMatchers(MatchFinder *Finder) {
+  // We look for calls to constructors of the same type in constructors. To do
+  // this we have to look through a variety of nodes that occur in the path,
+  // depending on the type's destructor and the number of arguments on the
+  // constructor call, this is handled by ignoringTemporaryExpr. Ignore template
+  // instantiations to reduce the number of duplicated warnings.
+  //
+  // Only register the matchers for C++11; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  Finder->addMatcher(
+      compoundStmt(
+          hasParent(
+              cxxConstructorDecl(ofClass(cxxRecordDecl().bind("parent")))),
+          forEach(ignoringTemporaryExpr(
+              cxxConstructExpr(hasDeclaration(cxxConstructorDecl(ofClass(
+                                   cxxRecordDecl(baseOfBoundNode("parent"))))))
+                  .bind("construct"))),
+          unless(isInTemplateInstantiation())),
+      this);
+}
+
+void UndelegatedConstructorCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *E = Result.Nodes.getNodeAs<CXXConstructExpr>("construct");
+  diag(E->getLocStart(), "did you intend to call a delegated constructor? "
+                         "A temporary object is created here instead");
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.h
new file mode 100644
index 0000000..ed881e1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.h
@@ -0,0 +1,36 @@
+//===--- UndelegatedConstructorCheck.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_MISC_UNDELEGATEDCONSTRUCTOR_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNDELEGATEDCONSTRUCTOR_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds creation of temporary objects in constructors that look like a
+/// function call to another constructor of the same class.
+///
+/// The user most likely meant to use a delegating constructor or base class
+/// initializer.
+class UndelegatedConstructorCheck : public ClangTidyCheck {
+public:
+  UndelegatedConstructorCheck(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_MISC_UNDELEGATEDCONSTRUCTOR_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp
new file mode 100644
index 0000000..e2882f3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp
@@ -0,0 +1,94 @@
+//===--- UnusedRaiiCheck.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 "UnusedRaiiCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+AST_MATCHER(CXXRecordDecl, hasNonTrivialDestructor) {
+  // TODO: If the dtor is there but empty we don't want to warn either.
+  return Node.hasDefinition() && Node.hasNonTrivialDestructor();
+}
+} // namespace
+
+void UnusedRaiiCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // Look for temporaries that are constructed in-place and immediately
+  // destroyed. Look for temporaries created by a functional cast but not for
+  // those returned from a call.
+  auto BindTemp =
+      cxxBindTemporaryExpr(unless(has(ignoringParenImpCasts(callExpr()))))
+          .bind("temp");
+  Finder->addMatcher(
+      exprWithCleanups(unless(isInTemplateInstantiation()),
+                       hasParent(compoundStmt().bind("compound")),
+                       hasType(cxxRecordDecl(hasNonTrivialDestructor())),
+                       anyOf(has(ignoringParenImpCasts(BindTemp)),
+                             has(ignoringParenImpCasts(cxxFunctionalCastExpr(
+                                 has(ignoringParenImpCasts(BindTemp)))))))
+          .bind("expr"),
+      this);
+}
+
+void UnusedRaiiCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *E = Result.Nodes.getNodeAs<Expr>("expr");
+
+  // We ignore code expanded from macros to reduce the number of false
+  // positives.
+  if (E->getLocStart().isMacroID())
+    return;
+
+  // Don't emit a warning for the last statement in the surrounding compund
+  // statement.
+  const auto *CS = Result.Nodes.getNodeAs<CompoundStmt>("compound");
+  if (E == CS->body_back())
+    return;
+
+  // Emit a warning.
+  auto D = diag(E->getLocStart(), "object destroyed immediately after "
+                                  "creation; did you mean to name the object?");
+  const char *Replacement = " give_me_a_name";
+
+  // If this is a default ctor we have to remove the parens or we'll introduce a
+  // most vexing parse.
+  const auto *BTE = Result.Nodes.getNodeAs<CXXBindTemporaryExpr>("temp");
+  if (const auto *TOE = dyn_cast<CXXTemporaryObjectExpr>(BTE->getSubExpr()))
+    if (TOE->getNumArgs() == 0) {
+      D << FixItHint::CreateReplacement(
+          CharSourceRange::getTokenRange(TOE->getParenOrBraceRange()),
+          Replacement);
+      return;
+    }
+
+  // Otherwise just suggest adding a name. To find the place to insert the name
+  // find the first TypeLoc in the children of E, which always points to the
+  // written type.
+  auto Matches =
+      match(expr(hasDescendant(typeLoc().bind("t"))), *E, *Result.Context);
+  const auto *TL = selectFirst<TypeLoc>("t", Matches);
+  D << FixItHint::CreateInsertion(
+      Lexer::getLocForEndOfToken(TL->getLocEnd(), 0, *Result.SourceManager,
+                                 getLangOpts()),
+      Replacement);
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.h
new file mode 100644
index 0000000..34190ec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.h
@@ -0,0 +1,35 @@
+//===--- UnusedRaiiCheck.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_UNUSEDRAIICHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNUSEDRAIICHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds temporaries that look like RAII objects.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-unused-raii.html
+class UnusedRaiiCheck : public ClangTidyCheck {
+public:
+  UnusedRaiiCheck(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_UNUSEDRAIICHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp
new file mode 100644
index 0000000..d0c5885
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp
@@ -0,0 +1,100 @@
+//===--- UnusedReturnValueCheck.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 "UnusedReturnValueCheck.h"
+#include "../utils/OptionsUtils.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 bugprone {
+
+namespace {
+
+// Matches functions that are instantiated from a class template member function
+// matching InnerMatcher. Functions not instantiated from a class template
+// member function are matched directly with InnerMatcher.
+AST_MATCHER_P(FunctionDecl, isInstantiatedFrom, Matcher<FunctionDecl>,
+              InnerMatcher) {
+  FunctionDecl *InstantiatedFrom = Node.getInstantiatedFromMemberFunction();
+  return InnerMatcher.matches(InstantiatedFrom ? *InstantiatedFrom : Node,
+                              Finder, Builder);
+}
+
+} // namespace
+
+UnusedReturnValueCheck::UnusedReturnValueCheck(llvm::StringRef Name,
+                                               ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      CheckedFunctions(Options.get("CheckedFunctions",
+                                   "::std::async;"
+                                   "::std::launder;"
+                                   "::std::remove;"
+                                   "::std::remove_if;"
+                                   "::std::unique;"
+                                   "::std::unique_ptr::release;"
+                                   "::std::basic_string::empty;"
+                                   "::std::vector::empty")) {}
+
+void UnusedReturnValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "CheckedFunctions", CheckedFunctions);
+}
+
+void UnusedReturnValueCheck::registerMatchers(MatchFinder *Finder) {
+  auto FunVec = utils::options::parseStringList(CheckedFunctions);
+  auto MatchedCallExpr = expr(ignoringImplicit(ignoringParenImpCasts(
+      callExpr(callee(functionDecl(
+                   // Don't match void overloads of checked functions.
+                   unless(returns(voidType())),
+                   isInstantiatedFrom(hasAnyName(
+                       std::vector<StringRef>(FunVec.begin(), FunVec.end()))))))
+          .bind("match"))));
+
+  auto UnusedInCompoundStmt =
+      compoundStmt(forEach(MatchedCallExpr),
+                   // The checker can't currently differentiate between the
+                   // return statement and other statements inside GNU statement
+                   // expressions, so disable the checker inside them to avoid
+                   // false positives.
+                   unless(hasParent(stmtExpr())));
+  auto UnusedInIfStmt =
+      ifStmt(eachOf(hasThen(MatchedCallExpr), hasElse(MatchedCallExpr)));
+  auto UnusedInWhileStmt = whileStmt(hasBody(MatchedCallExpr));
+  auto UnusedInDoStmt = doStmt(hasBody(MatchedCallExpr));
+  auto UnusedInForStmt =
+      forStmt(eachOf(hasLoopInit(MatchedCallExpr),
+                     hasIncrement(MatchedCallExpr), hasBody(MatchedCallExpr)));
+  auto UnusedInRangeForStmt = cxxForRangeStmt(hasBody(MatchedCallExpr));
+  auto UnusedInCaseStmt = switchCase(forEach(MatchedCallExpr));
+
+  Finder->addMatcher(
+      stmt(anyOf(UnusedInCompoundStmt, UnusedInIfStmt, UnusedInWhileStmt,
+                 UnusedInDoStmt, UnusedInForStmt, UnusedInRangeForStmt,
+                 UnusedInCaseStmt)),
+      this);
+}
+
+void UnusedReturnValueCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *Matched = Result.Nodes.getNodeAs<CallExpr>("match")) {
+    diag(Matched->getLocStart(),
+         "the value returned by this function should be used")
+        << Matched->getSourceRange();
+    diag(Matched->getLocStart(),
+         "cast the expression to void to silence this warning",
+         DiagnosticIDs::Note);
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h
new file mode 100644
index 0000000..9475f56
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h
@@ -0,0 +1,39 @@
+//===--- UnusedReturnValueCheck.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_UNUSEDRETURNVALUECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNUSEDRETURNVALUECHECK_H
+
+#include "../ClangTidy.h"
+#include <string>
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Detects function calls where the return value is unused.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-unused-return-value.html
+class UnusedReturnValueCheck : public ClangTidyCheck {
+public:
+  UnusedReturnValueCheck(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:
+  std::string CheckedFunctions;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNUSEDRETURNVALUECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
new file mode 100644
index 0000000..6fa4cab
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
@@ -0,0 +1,434 @@
+//===--- UseAfterMoveCheck.cpp - clang-tidy -------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "UseAfterMoveCheck.h"
+
+#include "clang/Analysis/CFG.h"
+#include "clang/Lex/Lexer.h"
+
+#include "../utils/ExprSequence.h"
+
+using namespace clang::ast_matchers;
+using namespace clang::tidy::utils;
+
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+
+/// Contains information about a use-after-move.
+struct UseAfterMove {
+  // The DeclRefExpr that constituted the use of the object.
+  const DeclRefExpr *DeclRef;
+
+  // Is the order in which the move and the use are evaluated undefined?
+  bool EvaluationOrderUndefined;
+};
+
+/// Finds uses of a variable after a move (and maintains state required by the
+/// various internal helper functions).
+class UseAfterMoveFinder {
+public:
+  UseAfterMoveFinder(ASTContext *TheContext);
+
+  // Within the given function body, finds the first use of 'MovedVariable' that
+  // occurs after 'MovingCall' (the expression that performs the move). If a
+  // use-after-move is found, writes information about it to 'TheUseAfterMove'.
+  // Returns whether a use-after-move was found.
+  bool find(Stmt *FunctionBody, const Expr *MovingCall,
+            const ValueDecl *MovedVariable, UseAfterMove *TheUseAfterMove);
+
+private:
+  bool findInternal(const CFGBlock *Block, const Expr *MovingCall,
+                    const ValueDecl *MovedVariable,
+                    UseAfterMove *TheUseAfterMove);
+  void getUsesAndReinits(const CFGBlock *Block, const ValueDecl *MovedVariable,
+                         llvm::SmallVectorImpl<const DeclRefExpr *> *Uses,
+                         llvm::SmallPtrSetImpl<const Stmt *> *Reinits);
+  void getDeclRefs(const CFGBlock *Block, const Decl *MovedVariable,
+                   llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs);
+  void getReinits(const CFGBlock *Block, const ValueDecl *MovedVariable,
+                  llvm::SmallPtrSetImpl<const Stmt *> *Stmts,
+                  llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs);
+
+  ASTContext *Context;
+  std::unique_ptr<ExprSequence> Sequence;
+  std::unique_ptr<StmtToBlockMap> BlockMap;
+  llvm::SmallPtrSet<const CFGBlock *, 8> Visited;
+};
+
+} // namespace
+
+
+// Matches nodes that are
+// - Part of a decltype argument or class template argument (we check this by
+//   seeing if they are children of a TypeLoc), or
+// - Part of a function template argument (we check this by seeing if they are
+//   children of a DeclRefExpr that references a function template).
+// DeclRefExprs that fulfill these conditions should not be counted as a use or
+// move.
+static StatementMatcher inDecltypeOrTemplateArg() {
+  return anyOf(hasAncestor(typeLoc()),
+               hasAncestor(declRefExpr(
+                   to(functionDecl(ast_matchers::isTemplateInstantiation())))));
+}
+
+UseAfterMoveFinder::UseAfterMoveFinder(ASTContext *TheContext)
+    : Context(TheContext) {}
+
+bool UseAfterMoveFinder::find(Stmt *FunctionBody, const Expr *MovingCall,
+                              const ValueDecl *MovedVariable,
+                              UseAfterMove *TheUseAfterMove) {
+  // Generate the CFG manually instead of through an AnalysisDeclContext because
+  // it seems the latter can't be used to generate a CFG for the body of a
+  // labmda.
+  //
+  // We include implicit and temporary destructors in the CFG so that
+  // destructors marked [[noreturn]] are handled correctly in the control flow
+  // analysis. (These are used in some styles of assertion macros.)
+  CFG::BuildOptions Options;
+  Options.AddImplicitDtors = true;
+  Options.AddTemporaryDtors = true;
+  std::unique_ptr<CFG> TheCFG =
+      CFG::buildCFG(nullptr, FunctionBody, Context, Options);
+  if (!TheCFG)
+    return false;
+
+  Sequence.reset(new ExprSequence(TheCFG.get(), Context));
+  BlockMap.reset(new StmtToBlockMap(TheCFG.get(), Context));
+  Visited.clear();
+
+  const CFGBlock *Block = BlockMap->blockContainingStmt(MovingCall);
+  if (!Block)
+    return false;
+
+  return findInternal(Block, MovingCall, MovedVariable, TheUseAfterMove);
+}
+
+bool UseAfterMoveFinder::findInternal(const CFGBlock *Block,
+                                      const Expr *MovingCall,
+                                      const ValueDecl *MovedVariable,
+                                      UseAfterMove *TheUseAfterMove) {
+  if (Visited.count(Block))
+    return false;
+
+  // Mark the block as visited (except if this is the block containing the
+  // std::move() and it's being visited the first time).
+  if (!MovingCall)
+    Visited.insert(Block);
+
+  // Get all uses and reinits in the block.
+  llvm::SmallVector<const DeclRefExpr *, 1> Uses;
+  llvm::SmallPtrSet<const Stmt *, 1> Reinits;
+  getUsesAndReinits(Block, MovedVariable, &Uses, &Reinits);
+
+  // Ignore all reinitializations where the move potentially comes after the
+  // reinit.
+  llvm::SmallVector<const Stmt *, 1> ReinitsToDelete;
+  for (const Stmt *Reinit : Reinits) {
+    if (MovingCall && Sequence->potentiallyAfter(MovingCall, Reinit))
+      ReinitsToDelete.push_back(Reinit);
+  }
+  for (const Stmt *Reinit : ReinitsToDelete) {
+    Reinits.erase(Reinit);
+  }
+
+  // Find all uses that potentially come after the move.
+  for (const DeclRefExpr *Use : Uses) {
+    if (!MovingCall || Sequence->potentiallyAfter(Use, MovingCall)) {
+      // Does the use have a saving reinit? A reinit is saving if it definitely
+      // comes before the use, i.e. if there's no potential that the reinit is
+      // after the use.
+      bool HaveSavingReinit = false;
+      for (const Stmt *Reinit : Reinits) {
+        if (!Sequence->potentiallyAfter(Reinit, Use))
+          HaveSavingReinit = true;
+      }
+
+      if (!HaveSavingReinit) {
+        TheUseAfterMove->DeclRef = Use;
+
+        // Is this a use-after-move that depends on order of evaluation?
+        // This is the case if the move potentially comes after the use (and we
+        // already know that use potentially comes after the move, which taken
+        // together tells us that the ordering is unclear).
+        TheUseAfterMove->EvaluationOrderUndefined =
+            MovingCall != nullptr &&
+            Sequence->potentiallyAfter(MovingCall, Use);
+
+        return true;
+      }
+    }
+  }
+
+  // If the object wasn't reinitialized, call ourselves recursively on all
+  // successors.
+  if (Reinits.empty()) {
+    for (const auto &Succ : Block->succs()) {
+      if (Succ && findInternal(Succ, nullptr, MovedVariable, TheUseAfterMove))
+        return true;
+    }
+  }
+
+  return false;
+}
+
+void UseAfterMoveFinder::getUsesAndReinits(
+    const CFGBlock *Block, const ValueDecl *MovedVariable,
+    llvm::SmallVectorImpl<const DeclRefExpr *> *Uses,
+    llvm::SmallPtrSetImpl<const Stmt *> *Reinits) {
+  llvm::SmallPtrSet<const DeclRefExpr *, 1> DeclRefs;
+  llvm::SmallPtrSet<const DeclRefExpr *, 1> ReinitDeclRefs;
+
+  getDeclRefs(Block, MovedVariable, &DeclRefs);
+  getReinits(Block, MovedVariable, Reinits, &ReinitDeclRefs);
+
+  // All references to the variable that aren't reinitializations are uses.
+  Uses->clear();
+  for (const DeclRefExpr *DeclRef : DeclRefs) {
+    if (!ReinitDeclRefs.count(DeclRef))
+      Uses->push_back(DeclRef);
+  }
+
+  // Sort the uses by their occurrence in the source code.
+  std::sort(Uses->begin(), Uses->end(),
+            [](const DeclRefExpr *D1, const DeclRefExpr *D2) {
+              return D1->getExprLoc() < D2->getExprLoc();
+            });
+}
+
+bool isStandardSmartPointer(const ValueDecl *VD) {
+  const Type *TheType = VD->getType().getTypePtrOrNull();
+  if (!TheType)
+    return false;
+
+  const CXXRecordDecl *RecordDecl = TheType->getAsCXXRecordDecl();
+  if (!RecordDecl)
+    return false;
+
+  const IdentifierInfo *ID = RecordDecl->getIdentifier();
+  if (!ID)
+    return false;
+
+  StringRef Name = ID->getName();
+  if (Name != "unique_ptr" && Name != "shared_ptr" && Name != "weak_ptr")
+    return false;
+
+  return RecordDecl->getDeclContext()->isStdNamespace();
+}
+
+void UseAfterMoveFinder::getDeclRefs(
+    const CFGBlock *Block, const Decl *MovedVariable,
+    llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs) {
+  DeclRefs->clear();
+  for (const auto &Elem : *Block) {
+    Optional<CFGStmt> S = Elem.getAs<CFGStmt>();
+    if (!S)
+      continue;
+
+    auto addDeclRefs = [this, Block,
+                        DeclRefs](const ArrayRef<BoundNodes> Matches) {
+      for (const auto &Match : Matches) {
+        const auto *DeclRef = Match.getNodeAs<DeclRefExpr>("declref");
+        const auto *Operator = Match.getNodeAs<CXXOperatorCallExpr>("operator");
+        if (DeclRef && BlockMap->blockContainingStmt(DeclRef) == Block) {
+          // Ignore uses of a standard smart pointer that don't dereference the
+          // pointer.
+          if (Operator || !isStandardSmartPointer(DeclRef->getDecl())) {
+            DeclRefs->insert(DeclRef);
+          }
+        }
+      }
+    };
+
+    auto DeclRefMatcher = declRefExpr(hasDeclaration(equalsNode(MovedVariable)),
+                                      unless(inDecltypeOrTemplateArg()))
+                              .bind("declref");
+
+    addDeclRefs(match(findAll(DeclRefMatcher), *S->getStmt(), *Context));
+    addDeclRefs(match(
+        findAll(cxxOperatorCallExpr(anyOf(hasOverloadedOperatorName("*"),
+                                          hasOverloadedOperatorName("->"),
+                                          hasOverloadedOperatorName("[]")),
+                                    hasArgument(0, DeclRefMatcher))
+                    .bind("operator")),
+        *S->getStmt(), *Context));
+  }
+}
+
+void UseAfterMoveFinder::getReinits(
+    const CFGBlock *Block, const ValueDecl *MovedVariable,
+    llvm::SmallPtrSetImpl<const Stmt *> *Stmts,
+    llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs) {
+  auto DeclRefMatcher =
+      declRefExpr(hasDeclaration(equalsNode(MovedVariable))).bind("declref");
+
+  auto StandardContainerTypeMatcher = hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(cxxRecordDecl(hasAnyName(
+          "::std::basic_string", "::std::vector", "::std::deque",
+          "::std::forward_list", "::std::list", "::std::set", "::std::map",
+          "::std::multiset", "::std::multimap", "::std::unordered_set",
+          "::std::unordered_map", "::std::unordered_multiset",
+          "::std::unordered_multimap"))))));
+
+  auto StandardSmartPointerTypeMatcher = hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(cxxRecordDecl(hasAnyName(
+          "::std::unique_ptr", "::std::shared_ptr", "::std::weak_ptr"))))));
+
+  // Matches different types of reinitialization.
+  auto ReinitMatcher =
+      stmt(anyOf(
+               // Assignment. In addition to the overloaded assignment operator,
+               // test for built-in assignment as well, since template functions
+               // may be instantiated to use std::move() on built-in types.
+               binaryOperator(hasOperatorName("="), hasLHS(DeclRefMatcher)),
+               cxxOperatorCallExpr(hasOverloadedOperatorName("="),
+                                   hasArgument(0, DeclRefMatcher)),
+               // Declaration. We treat this as a type of reinitialization too,
+               // so we don't need to treat it separately.
+               declStmt(hasDescendant(equalsNode(MovedVariable))),
+               // clear() and assign() on standard containers.
+               cxxMemberCallExpr(
+                   on(allOf(DeclRefMatcher, StandardContainerTypeMatcher)),
+                   // To keep the matcher simple, we check for assign() calls
+                   // on all standard containers, even though only vector,
+                   // deque, forward_list and list have assign(). If assign()
+                   // is called on any of the other containers, this will be
+                   // flagged by a compile error anyway.
+                   callee(cxxMethodDecl(hasAnyName("clear", "assign")))),
+               // reset() on standard smart pointers.
+               cxxMemberCallExpr(
+                   on(allOf(DeclRefMatcher, StandardSmartPointerTypeMatcher)),
+                   callee(cxxMethodDecl(hasName("reset")))),
+               // Passing variable to a function as a non-const pointer.
+               callExpr(forEachArgumentWithParam(
+                   unaryOperator(hasOperatorName("&"),
+                                 hasUnaryOperand(DeclRefMatcher)),
+                   unless(parmVarDecl(hasType(pointsTo(isConstQualified())))))),
+               // Passing variable to a function as a non-const lvalue reference
+               // (unless that function is std::move()).
+               callExpr(forEachArgumentWithParam(
+                            DeclRefMatcher,
+                            unless(parmVarDecl(hasType(
+                                references(qualType(isConstQualified())))))),
+                        unless(callee(functionDecl(hasName("::std::move")))))))
+          .bind("reinit");
+
+  Stmts->clear();
+  DeclRefs->clear();
+  for (const auto &Elem : *Block) {
+    Optional<CFGStmt> S = Elem.getAs<CFGStmt>();
+    if (!S)
+      continue;
+
+    SmallVector<BoundNodes, 1> Matches =
+        match(findAll(ReinitMatcher), *S->getStmt(), *Context);
+
+    for (const auto &Match : Matches) {
+      const auto *TheStmt = Match.getNodeAs<Stmt>("reinit");
+      const auto *TheDeclRef = Match.getNodeAs<DeclRefExpr>("declref");
+      if (TheStmt && BlockMap->blockContainingStmt(TheStmt) == Block) {
+        Stmts->insert(TheStmt);
+
+        // We count DeclStmts as reinitializations, but they don't have a
+        // DeclRefExpr associated with them -- so we need to check 'TheDeclRef'
+        // before adding it to the set.
+        if (TheDeclRef)
+          DeclRefs->insert(TheDeclRef);
+      }
+    }
+  }
+}
+
+static void emitDiagnostic(const Expr *MovingCall, const DeclRefExpr *MoveArg,
+                           const UseAfterMove &Use, ClangTidyCheck *Check,
+                           ASTContext *Context) {
+  SourceLocation UseLoc = Use.DeclRef->getExprLoc();
+  SourceLocation MoveLoc = MovingCall->getExprLoc();
+
+  Check->diag(UseLoc, "'%0' used after it was moved")
+      << MoveArg->getDecl()->getName();
+  Check->diag(MoveLoc, "move occurred here", DiagnosticIDs::Note);
+  if (Use.EvaluationOrderUndefined) {
+    Check->diag(UseLoc,
+                "the use and move are unsequenced, i.e. there is no guarantee "
+                "about the order in which they are evaluated",
+                DiagnosticIDs::Note);
+  } else if (UseLoc < MoveLoc || Use.DeclRef == MoveArg) {
+    Check->diag(UseLoc,
+                "the use happens in a later loop iteration than the move",
+                DiagnosticIDs::Note);
+  }
+}
+
+void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  auto CallMoveMatcher =
+      callExpr(callee(functionDecl(hasName("::std::move"))), argumentCountIs(1),
+               hasArgument(0, declRefExpr().bind("arg")),
+               anyOf(hasAncestor(lambdaExpr().bind("containing-lambda")),
+                     hasAncestor(functionDecl().bind("containing-func"))),
+               unless(inDecltypeOrTemplateArg()))
+          .bind("call-move");
+
+  Finder->addMatcher(
+      // To find the Stmt that we assume performs the actual move, we look for
+      // the direct ancestor of the std::move() that isn't one of the node
+      // types ignored by ignoringParenImpCasts().
+      stmt(forEach(expr(ignoringParenImpCasts(CallMoveMatcher))),
+           // Don't allow an InitListExpr to be the moving call. An InitListExpr
+           // has both a syntactic and a semantic form, and the parent-child
+           // relationships are different between the two. This could cause an
+           // InitListExpr to be analyzed as the moving call in addition to the
+           // Expr that we actually want, resulting in two diagnostics with
+           // different code locations for the same move.
+           unless(initListExpr()),
+           unless(expr(ignoringParenImpCasts(equalsBoundNode("call-move")))))
+          .bind("moving-call"),
+      this);
+}
+
+void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *ContainingLambda =
+      Result.Nodes.getNodeAs<LambdaExpr>("containing-lambda");
+  const auto *ContainingFunc =
+      Result.Nodes.getNodeAs<FunctionDecl>("containing-func");
+  const auto *CallMove = Result.Nodes.getNodeAs<CallExpr>("call-move");
+  const auto *MovingCall = Result.Nodes.getNodeAs<Expr>("moving-call");
+  const auto *Arg = Result.Nodes.getNodeAs<DeclRefExpr>("arg");
+
+  if (!MovingCall || !MovingCall->getExprLoc().isValid())
+    MovingCall = CallMove;
+
+  Stmt *FunctionBody = nullptr;
+  if (ContainingLambda)
+    FunctionBody = ContainingLambda->getBody();
+  else if (ContainingFunc)
+    FunctionBody = ContainingFunc->getBody();
+  else
+    return;
+
+  // Ignore the std::move if the variable that was passed to it isn't a local
+  // variable.
+  if (!Arg->getDecl()->getDeclContext()->isFunctionOrMethod())
+    return;
+
+  UseAfterMoveFinder finder(Result.Context);
+  UseAfterMove Use;
+  if (finder.find(FunctionBody, MovingCall, Arg->getDecl(), &Use))
+    emitDiagnostic(MovingCall, Arg, Use, this, Result.Context);
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.h
new file mode 100644
index 0000000..f6dea68
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.h
@@ -0,0 +1,36 @@
+//===--- UseAfterMoveCheck.h - clang-tidy ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_USEAFTERMOVECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_USEAFTERMOVECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// The check warns if an object is used after it has been moved, without an
+/// intervening reinitialization.
+///
+/// For details, see the user-facing documentation:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-use-after-move.html
+class UseAfterMoveCheck : public ClangTidyCheck {
+public:
+  UseAfterMoveCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_USEAFTERMOVECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp
new file mode 100644
index 0000000..bb9c9b6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp
@@ -0,0 +1,276 @@
+//===--- VirtualNearMissCheck.cpp - clang-tidy-----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "VirtualNearMissCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+AST_MATCHER(CXXMethodDecl, isStatic) { return Node.isStatic(); }
+
+AST_MATCHER(CXXMethodDecl, isOverloadedOperator) {
+  return Node.isOverloadedOperator();
+}
+} // namespace
+
+/// Finds out if the given method overrides some method.
+static bool isOverrideMethod(const CXXMethodDecl *MD) {
+  return MD->size_overridden_methods() > 0 || MD->hasAttr<OverrideAttr>();
+}
+
+/// Checks whether the return types are covariant, according to
+/// C++[class.virtual]p7.
+///
+/// Similar with clang::Sema::CheckOverridingFunctionReturnType.
+/// \returns true if the return types of BaseMD and DerivedMD are covariant.
+static bool checkOverridingFunctionReturnType(const ASTContext *Context,
+                                              const CXXMethodDecl *BaseMD,
+                                              const CXXMethodDecl *DerivedMD) {
+  QualType BaseReturnTy = BaseMD->getType()
+                              ->getAs<FunctionType>()
+                              ->getReturnType()
+                              .getCanonicalType();
+  QualType DerivedReturnTy = DerivedMD->getType()
+                                 ->getAs<FunctionType>()
+                                 ->getReturnType()
+                                 .getCanonicalType();
+
+  if (DerivedReturnTy->isDependentType() || BaseReturnTy->isDependentType())
+    return false;
+
+  // Check if return types are identical.
+  if (Context->hasSameType(DerivedReturnTy, BaseReturnTy))
+    return true;
+
+  /// Check if the return types are covariant.
+
+  // Both types must be pointers or references to classes.
+  if (!(BaseReturnTy->isPointerType() && DerivedReturnTy->isPointerType()) &&
+      !(BaseReturnTy->isReferenceType() && DerivedReturnTy->isReferenceType()))
+    return false;
+
+  /// BTy is the class type in return type of BaseMD. For example,
+  ///    B* Base::md()
+  /// While BRD is the declaration of B.
+  QualType DTy = DerivedReturnTy->getPointeeType().getCanonicalType();
+  QualType BTy = BaseReturnTy->getPointeeType().getCanonicalType();
+
+  const CXXRecordDecl *DRD = DTy->getAsCXXRecordDecl();
+  const CXXRecordDecl *BRD = BTy->getAsCXXRecordDecl();
+  if (DRD == nullptr || BRD == nullptr)
+    return false;
+
+  if (!DRD->hasDefinition() || !BRD->hasDefinition())
+    return false;
+
+  if (DRD == BRD)
+    return true;
+
+  if (!Context->hasSameUnqualifiedType(DTy, BTy)) {
+    // Begin checking whether the conversion from D to B is valid.
+    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                       /*DetectVirtual=*/false);
+
+    // Check whether D is derived from B, and fill in a CXXBasePaths object.
+    if (!DRD->isDerivedFrom(BRD, Paths))
+      return false;
+
+    // Check ambiguity.
+    if (Paths.isAmbiguous(Context->getCanonicalType(BTy).getUnqualifiedType()))
+      return false;
+
+    // Check accessibility.
+    // FIXME: We currently only support checking if B is accessible base class
+    // of D, or D is the same class which DerivedMD is in.
+    bool IsItself =
+        DRD->getCanonicalDecl() == DerivedMD->getParent()->getCanonicalDecl();
+    bool HasPublicAccess = false;
+    for (const auto &Path : Paths) {
+      if (Path.Access == AS_public)
+        HasPublicAccess = true;
+    }
+    if (!HasPublicAccess && !IsItself)
+      return false;
+    // End checking conversion from D to B.
+  }
+
+  // Both pointers or references should have the same cv-qualification.
+  if (DerivedReturnTy.getLocalCVRQualifiers() !=
+      BaseReturnTy.getLocalCVRQualifiers())
+    return false;
+
+  // The class type D should have the same cv-qualification as or less
+  // cv-qualification than the class type B.
+  if (DTy.isMoreQualifiedThan(BTy))
+    return false;
+
+  return true;
+}
+
+/// \returns decayed type for arrays and functions.
+static QualType getDecayedType(QualType Type) {
+  if (const auto *Decayed = Type->getAs<DecayedType>())
+    return Decayed->getDecayedType();
+  return Type;
+}
+
+/// \returns true if the param types are the same.
+static bool checkParamTypes(const CXXMethodDecl *BaseMD,
+                            const CXXMethodDecl *DerivedMD) {
+  unsigned NumParamA = BaseMD->getNumParams();
+  unsigned NumParamB = DerivedMD->getNumParams();
+  if (NumParamA != NumParamB)
+    return false;
+
+  for (unsigned I = 0; I < NumParamA; I++) {
+    if (getDecayedType(BaseMD->getParamDecl(I)->getType().getCanonicalType()) !=
+        getDecayedType(
+            DerivedMD->getParamDecl(I)->getType().getCanonicalType()))
+      return false;
+  }
+  return true;
+}
+
+/// \returns true if derived method can override base method except for the
+/// name.
+static bool checkOverrideWithoutName(const ASTContext *Context,
+                                     const CXXMethodDecl *BaseMD,
+                                     const CXXMethodDecl *DerivedMD) {
+  if (BaseMD->isStatic() != DerivedMD->isStatic())
+    return false;
+
+  if (BaseMD->getType() == DerivedMD->getType())
+    return true;
+
+  // Now the function types are not identical. Then check if the return types
+  // are covariant and if the param types are the same.
+  if (!checkOverridingFunctionReturnType(Context, BaseMD, DerivedMD))
+    return false;
+  return checkParamTypes(BaseMD, DerivedMD);
+}
+
+/// Check whether BaseMD overrides DerivedMD.
+///
+/// Prerequisite: the class which BaseMD is in should be a base class of that
+/// DerivedMD is in.
+static bool checkOverrideByDerivedMethod(const CXXMethodDecl *BaseMD,
+                                         const CXXMethodDecl *DerivedMD) {
+  for (CXXMethodDecl::method_iterator I = DerivedMD->begin_overridden_methods(),
+                                      E = DerivedMD->end_overridden_methods();
+       I != E; ++I) {
+    const CXXMethodDecl *OverriddenMD = *I;
+    if (BaseMD->getCanonicalDecl() == OverriddenMD->getCanonicalDecl())
+      return true;
+  }
+
+  return false;
+}
+
+bool VirtualNearMissCheck::isPossibleToBeOverridden(
+    const CXXMethodDecl *BaseMD) {
+  auto Iter = PossibleMap.find(BaseMD);
+  if (Iter != PossibleMap.end())
+    return Iter->second;
+
+  bool IsPossible = !BaseMD->isImplicit() && !isa<CXXConstructorDecl>(BaseMD) &&
+                    !isa<CXXDestructorDecl>(BaseMD) && BaseMD->isVirtual() &&
+                    !BaseMD->isOverloadedOperator() &&
+                    !isa<CXXConversionDecl>(BaseMD);
+  PossibleMap[BaseMD] = IsPossible;
+  return IsPossible;
+}
+
+bool VirtualNearMissCheck::isOverriddenByDerivedClass(
+    const CXXMethodDecl *BaseMD, const CXXRecordDecl *DerivedRD) {
+  auto Key = std::make_pair(BaseMD, DerivedRD);
+  auto Iter = OverriddenMap.find(Key);
+  if (Iter != OverriddenMap.end())
+    return Iter->second;
+
+  bool IsOverridden = false;
+  for (const CXXMethodDecl *DerivedMD : DerivedRD->methods()) {
+    if (!isOverrideMethod(DerivedMD))
+      continue;
+
+    if (checkOverrideByDerivedMethod(BaseMD, DerivedMD)) {
+      IsOverridden = true;
+      break;
+    }
+  }
+  OverriddenMap[Key] = IsOverridden;
+  return IsOverridden;
+}
+
+void VirtualNearMissCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(
+      cxxMethodDecl(
+          unless(anyOf(isOverride(), isImplicit(), cxxConstructorDecl(),
+                       cxxDestructorDecl(), cxxConversionDecl(), isStatic(),
+                       isOverloadedOperator())))
+          .bind("method"),
+      this);
+}
+
+void VirtualNearMissCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *DerivedMD = Result.Nodes.getNodeAs<CXXMethodDecl>("method");
+  assert(DerivedMD);
+
+  const ASTContext *Context = Result.Context;
+
+  const auto *DerivedRD = DerivedMD->getParent()->getDefinition();
+  assert(DerivedRD);
+
+  for (const auto &BaseSpec : DerivedRD->bases()) {
+    if (const auto *BaseRD = BaseSpec.getType()->getAsCXXRecordDecl()) {
+      for (const auto *BaseMD : BaseRD->methods()) {
+        if (!isPossibleToBeOverridden(BaseMD))
+          continue;
+
+        if (isOverriddenByDerivedClass(BaseMD, DerivedRD))
+          continue;
+
+        unsigned EditDistance = BaseMD->getName().edit_distance(
+            DerivedMD->getName(), EditDistanceThreshold);
+        if (EditDistance > 0 && EditDistance <= EditDistanceThreshold) {
+          if (checkOverrideWithoutName(Context, BaseMD, DerivedMD)) {
+            // A "virtual near miss" is found.
+            auto Range = CharSourceRange::getTokenRange(
+                SourceRange(DerivedMD->getLocation()));
+
+            bool ApplyFix = !BaseMD->isTemplateInstantiation() &&
+                            !DerivedMD->isTemplateInstantiation();
+            auto Diag =
+                diag(DerivedMD->getLocStart(),
+                     "method '%0' has a similar name and the same signature as "
+                     "virtual method '%1'; did you mean to override it?")
+                << DerivedMD->getQualifiedNameAsString()
+                << BaseMD->getQualifiedNameAsString();
+            if (ApplyFix)
+              Diag << FixItHint::CreateReplacement(Range, BaseMD->getName());
+          }
+        }
+      }
+    }
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.h
new file mode 100644
index 0000000..ea1e256
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.h
@@ -0,0 +1,65 @@
+//===--- VirtualNearMissCheck.h - clang-tidy---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_VIRTUAL_NEAR_MISS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_VIRTUAL_NEAR_MISS_H
+
+#include "../ClangTidy.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// \brief Checks for near miss of virtual methods.
+///
+/// For a method in a derived class, this check looks for virtual method with a
+/// very similar name and an identical signature defined in a base class.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-virtual-near-miss.html
+class VirtualNearMissCheck : public ClangTidyCheck {
+public:
+  VirtualNearMissCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  /// Check if the given method is possible to be overridden by some other
+  /// method. Operators and destructors are excluded.
+  ///
+  /// Results are memoized in PossibleMap.
+  bool isPossibleToBeOverridden(const CXXMethodDecl *BaseMD);
+
+  /// Check if the given base method is overridden by some methods in the given
+  /// derived class.
+  ///
+  /// Results are memoized in OverriddenMap.
+  bool isOverriddenByDerivedClass(const CXXMethodDecl *BaseMD,
+                                  const CXXRecordDecl *DerivedRD);
+
+  /// Key: the unique ID of a method.
+  /// Value: whether the method is possible to be overridden.
+  llvm::DenseMap<const CXXMethodDecl *, bool> PossibleMap;
+
+  /// Key: <unique ID of base method, name of derived class>
+  /// Value: whether the base method is overridden by some method in the derived
+  /// class.
+  llvm::DenseMap<std::pair<const CXXMethodDecl *, const CXXRecordDecl *>, bool>
+      OverriddenMap;
+
+  const unsigned EditDistanceThreshold = 1;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_VIRTUAL_NEAR_MISS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
new file mode 100644
index 0000000..da09932
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
@@ -0,0 +1,95 @@
+//===--- CERTTidyModule.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 "../google/UnnamedNamespaceInHeaderCheck.h"
+#include "../misc/NewDeleteOverloadsCheck.h"
+#include "../misc/NonCopyableObjects.h"
+#include "../misc/StaticAssertCheck.h"
+#include "../misc/ThrowByValueCatchByReferenceCheck.h"
+#include "../performance/MoveConstructorInitCheck.h"
+#include "CommandProcessorCheck.h"
+#include "DontModifyStdNamespaceCheck.h"
+#include "FloatLoopCounter.h"
+#include "LimitedRandomnessCheck.h"
+#include "PostfixOperatorCheck.h"
+#include "ProperlySeededRandomGeneratorCheck.h"
+#include "SetLongJmpCheck.h"
+#include "StaticObjectExceptionCheck.h"
+#include "StrToNumCheck.h"
+#include "ThrownExceptionTypeCheck.h"
+#include "VariadicFunctionDefCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+class CERTModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    // C++ checkers
+    // DCL
+    CheckFactories.registerCheck<PostfixOperatorCheck>(
+        "cert-dcl21-cpp");
+    CheckFactories.registerCheck<VariadicFunctionDefCheck>("cert-dcl50-cpp");
+    CheckFactories.registerCheck<misc::NewDeleteOverloadsCheck>(
+        "cert-dcl54-cpp");
+    CheckFactories.registerCheck<DontModifyStdNamespaceCheck>(
+        "cert-dcl58-cpp");
+    CheckFactories.registerCheck<google::build::UnnamedNamespaceInHeaderCheck>(
+        "cert-dcl59-cpp");
+    // OOP
+    CheckFactories.registerCheck<performance::MoveConstructorInitCheck>(
+        "cert-oop11-cpp");
+    // ERR
+    CheckFactories.registerCheck<misc::ThrowByValueCatchByReferenceCheck>(
+        "cert-err09-cpp");
+    CheckFactories.registerCheck<SetLongJmpCheck>("cert-err52-cpp");
+    CheckFactories.registerCheck<StaticObjectExceptionCheck>("cert-err58-cpp");
+    CheckFactories.registerCheck<ThrownExceptionTypeCheck>("cert-err60-cpp");
+    CheckFactories.registerCheck<misc::ThrowByValueCatchByReferenceCheck>(
+        "cert-err61-cpp");
+    // MSC
+    CheckFactories.registerCheck<LimitedRandomnessCheck>("cert-msc50-cpp");
+    CheckFactories.registerCheck<ProperlySeededRandomGeneratorCheck>(
+        "cert-msc51-cpp");
+
+    // C checkers
+    // DCL
+    CheckFactories.registerCheck<misc::StaticAssertCheck>("cert-dcl03-c");
+    // ENV
+    CheckFactories.registerCheck<CommandProcessorCheck>("cert-env33-c");
+    // FLP
+    CheckFactories.registerCheck<FloatLoopCounter>("cert-flp30-c");
+    // FIO
+    CheckFactories.registerCheck<misc::NonCopyableObjectsCheck>("cert-fio38-c");
+    // ERR
+    CheckFactories.registerCheck<StrToNumCheck>("cert-err34-c");
+    // MSC
+    CheckFactories.registerCheck<LimitedRandomnessCheck>("cert-msc30-c");
+    CheckFactories.registerCheck<ProperlySeededRandomGeneratorCheck>(
+        "cert-msc32-c");
+  }
+};
+
+} // namespace cert
+
+// Register the MiscTidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<cert::CERTModule>
+    X("cert-module",
+      "Adds lint checks corresponding to CERT secure coding guidelines.");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the CERTModule.
+volatile int CERTModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/CMakeLists.txt
new file mode 100644
index 0000000..edc93c8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/CMakeLists.txt
@@ -0,0 +1,28 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyCERTModule
+  CERTTidyModule.cpp
+  CommandProcessorCheck.cpp
+  DontModifyStdNamespaceCheck.cpp
+  FloatLoopCounter.cpp
+  LimitedRandomnessCheck.cpp
+  PostfixOperatorCheck.cpp
+  ProperlySeededRandomGeneratorCheck.cpp
+  SetLongJmpCheck.cpp
+  StaticObjectExceptionCheck.cpp
+  StrToNumCheck.cpp
+  ThrownExceptionTypeCheck.cpp
+  VariadicFunctionDefCheck.cpp
+
+  LINK_LIBS
+  clangAnalysis
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyGoogleModule
+  clangTidyMiscModule
+  clangTidyPerformanceModule
+  clangTidyUtils
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/CommandProcessorCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/CommandProcessorCheck.cpp
new file mode 100644
index 0000000..e2dbeca
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/CommandProcessorCheck.cpp
@@ -0,0 +1,45 @@
+//===--- Env33CCheck.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 "CommandProcessorCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+void CommandProcessorCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      callExpr(
+          callee(functionDecl(anyOf(hasName("::system"), hasName("::popen"),
+                                    hasName("::_popen")))
+                     .bind("func")),
+          // Do not diagnose when the call expression passes a null pointer
+          // constant to system(); that only checks for the presence of a
+          // command processor, which is not a security risk by itself.
+          unless(callExpr(callee(functionDecl(hasName("::system"))),
+                          argumentCountIs(1),
+                          hasArgument(0, nullPointerConstant()))))
+          .bind("expr"),
+      this);
+}
+
+void CommandProcessorCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Fn = Result.Nodes.getNodeAs<FunctionDecl>("func");
+  const auto *E = Result.Nodes.getNodeAs<CallExpr>("expr");
+
+  diag(E->getExprLoc(), "calling %0 uses a command processor") << Fn;
+}
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/CommandProcessorCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/CommandProcessorCheck.h
new file mode 100644
index 0000000..a85a7ed
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/CommandProcessorCheck.h
@@ -0,0 +1,38 @@
+//===--- CommandInterpreterCheck.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_CERT_COMMAND_PROCESSOR_CHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_COMMAND_PROCESSOR_CHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+/// Execution of a command processor can lead to security vulnerabilities,
+/// and is generally not required. Instead, prefer to launch executables
+/// directly via mechanisms that give you more control over what executable is
+/// actually launched.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cert-env33-c.html
+class CommandProcessorCheck : public ClangTidyCheck {
+public:
+  CommandProcessorCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_COMMAND_PROCESSOR_CHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/DontModifyStdNamespaceCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/DontModifyStdNamespaceCheck.cpp
new file mode 100644
index 0000000..e5759a5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/DontModifyStdNamespaceCheck.cpp
@@ -0,0 +1,49 @@
+//===--- DontModifyStdNamespaceCheck.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 "DontModifyStdNamespaceCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+void DontModifyStdNamespaceCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(
+      namespaceDecl(unless(isExpansionInSystemHeader()),
+                    anyOf(hasName("std"), hasName("posix")),
+                    has(decl(unless(anyOf(
+                        functionDecl(isExplicitTemplateSpecialization()),
+                        cxxRecordDecl(isExplicitTemplateSpecialization()))))))
+          .bind("nmspc"),
+      this);
+}
+
+void DontModifyStdNamespaceCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *N = Result.Nodes.getNodeAs<NamespaceDecl>("nmspc");
+
+  // Only consider top level namespaces.
+  if (N->getParent() != Result.Context->getTranslationUnitDecl())
+    return;
+
+  diag(N->getLocation(),
+       "modification of %0 namespace can result in undefined behavior")
+      << N;
+}
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/DontModifyStdNamespaceCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/DontModifyStdNamespaceCheck.h
new file mode 100644
index 0000000..0cc23f7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/DontModifyStdNamespaceCheck.h
@@ -0,0 +1,36 @@
+//===--- DontModifyStdNamespaceCheck.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_CERT_DONT_MODIFY_STD_NAMESPACE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_DONT_MODIFY_STD_NAMESPACE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+/// Modification of the std or posix namespace can result in undefined behavior.
+/// This check warns for such modifications.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cert-msc53-cpp.html
+class DontModifyStdNamespaceCheck : public ClangTidyCheck {
+public:
+  DontModifyStdNamespaceCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_DONT_MODIFY_STD_NAMESPACE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/FloatLoopCounter.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/FloatLoopCounter.cpp
new file mode 100644
index 0000000..e92552e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/FloatLoopCounter.cpp
@@ -0,0 +1,35 @@
+//===--- FloatLoopCounter.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 "FloatLoopCounter.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+void FloatLoopCounter::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      forStmt(hasIncrement(expr(hasType(realFloatingPointType())))).bind("for"),
+      this);
+}
+
+void FloatLoopCounter::check(const MatchFinder::MatchResult &Result) {
+  const auto *FS = Result.Nodes.getNodeAs<ForStmt>("for");
+
+  diag(FS->getInc()->getExprLoc(), "loop induction expression should not have "
+                                   "floating-point type");
+}
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/FloatLoopCounter.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/FloatLoopCounter.h
new file mode 100644
index 0000000..c66e44a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/FloatLoopCounter.h
@@ -0,0 +1,37 @@
+//===--- FloatLoopCounter.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_CERT_FLOAT_LOOP_COUNTER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_FLOAT_LOOP_COUNTER_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+/// This check diagnoses when the loop induction expression of a for loop has
+/// floating-point type. The check corresponds to:
+/// https://www.securecoding.cert.org/confluence/display/c/FLP30-C.+Do+not+use+floating-point+variables+as+loop+counters
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cert-flp30-c.html
+class FloatLoopCounter : public ClangTidyCheck {
+public:
+  FloatLoopCounter(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_FLOAT_LOOP_COUNTER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/LICENSE.TXT b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/LICENSE.TXT
new file mode 100644
index 0000000..d8395cc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/LICENSE.TXT
@@ -0,0 +1,22 @@
+------------------------------------------------------------------------------
+clang-tidy CERT Files
+------------------------------------------------------------------------------
+All clang-tidy files are licensed under the LLVM license with the following
+additions:
+
+Any file referencing a CERT Secure Coding guideline:
+Please allow this letter to serve as confirmation that open source projects on
+http://llvm.org are permitted to link via hypertext to the CERT(R) secure coding
+guidelines available at https://www.securecoding.cert.org.
+
+The foregoing is permitted by the Terms of Use as follows:
+"Linking to the Service
+Because we update many of our Web documents regularly, we would prefer that you
+link to our Web pages whenever possible rather than reproduce them. It is not
+necessary to request permission to make referential hypertext links to The
+Service."
+http://www.sei.cmu.edu/legal/ip/index.cfm.
+
+Please allow this letter to also confirm that no formal permission is required
+to reproduce the title of the content being linked to, nor to reproduce any
+de Minimis description of such content.
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/LimitedRandomnessCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/LimitedRandomnessCheck.cpp
new file mode 100644
index 0000000..f319f9f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/LimitedRandomnessCheck.cpp
@@ -0,0 +1,38 @@
+//===--- LimitedRandomnessCheck.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 "LimitedRandomnessCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+void LimitedRandomnessCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(callExpr(callee(functionDecl(namedDecl(hasName("::rand")),
+                                                  parameterCountIs(0))))
+                         .bind("randomGenerator"),
+                     this);
+}
+
+void LimitedRandomnessCheck::check(const MatchFinder::MatchResult &Result) {
+  std::string msg = "";
+  if (getLangOpts().CPlusPlus)
+    msg = "; use C++11 random library instead";
+
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<CallExpr>("randomGenerator");
+  diag(MatchedDecl->getLocStart(), "rand() has limited randomness" + msg);
+}
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/LimitedRandomnessCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/LimitedRandomnessCheck.h
new file mode 100644
index 0000000..59d511c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/LimitedRandomnessCheck.h
@@ -0,0 +1,38 @@
+//===--- LimitedRandomnessCheck.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_CERT_LIMITED_RANDOMNESS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_LIMITED_RANDOMNESS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+/// Pseudorandom number generators are not genuinely random. The result of the
+/// std::rand() function makes no guarantees as to the quality of the random
+/// sequence produced.
+/// This check warns for the usage of std::rand() function.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cert-msc50-cpp.html
+class LimitedRandomnessCheck : public ClangTidyCheck {
+public:
+  LimitedRandomnessCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_LIMITED_RANDOMNESS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/PostfixOperatorCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/PostfixOperatorCheck.cpp
new file mode 100644
index 0000000..2b8dbbe
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/PostfixOperatorCheck.cpp
@@ -0,0 +1,88 @@
+//===--- PostfixOperatorCheck.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 "PostfixOperatorCheck.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 cert {
+
+void PostfixOperatorCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(functionDecl(anyOf(hasOverloadedOperatorName("++"),
+                                        hasOverloadedOperatorName("--")))
+                         .bind("decl"),
+                     this);
+}
+
+void PostfixOperatorCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("decl");
+
+  bool HasThis = false;
+  if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FuncDecl))
+    HasThis = MethodDecl->isInstance();
+
+  // Check if the operator is a postfix one.
+  if (FuncDecl->getNumParams() != (HasThis ? 1 : 2))
+    return;
+
+  SourceRange ReturnRange = FuncDecl->getReturnTypeSourceRange();
+  SourceLocation Location = ReturnRange.getBegin();
+  if (!Location.isValid())
+    return;
+
+  QualType ReturnType = FuncDecl->getReturnType();
+
+  // Warn when the operators return a reference.
+  if (const auto *RefType = ReturnType->getAs<ReferenceType>()) {
+    auto Diag = diag(Location, "overloaded %0 returns a reference instead of a "
+                               "constant object type")
+                << FuncDecl;
+
+    if (Location.isMacroID() || ReturnType->getAs<TypedefType>() ||
+        RefType->getPointeeTypeAsWritten()->getAs<TypedefType>())
+      return;
+
+    QualType ReplaceType =
+        ReturnType.getNonReferenceType().getLocalUnqualifiedType();
+    // The getReturnTypeSourceRange omits the qualifiers. We do not want to
+    // duplicate the const.
+    if (!ReturnType->getPointeeType().isConstQualified())
+      ReplaceType.addConst();
+
+    Diag << FixItHint::CreateReplacement(
+        ReturnRange,
+        ReplaceType.getAsString(Result.Context->getPrintingPolicy()) + " ");
+
+    return;
+  }
+
+  if (ReturnType.isConstQualified() || ReturnType->isBuiltinType() ||
+      ReturnType->isPointerType())
+    return;
+
+  auto Diag =
+      diag(Location, "overloaded %0 returns a non-constant object instead of a "
+                     "constant object type")
+      << FuncDecl;
+
+  if (!Location.isMacroID() && !ReturnType->getAs<TypedefType>())
+    Diag << FixItHint::CreateInsertion(Location, "const ");
+}
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/PostfixOperatorCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/PostfixOperatorCheck.h
new file mode 100644
index 0000000..29c2306
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/PostfixOperatorCheck.h
@@ -0,0 +1,36 @@
+//===--- PostfixOperatorCheck.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_CERT_POSTFIX_OPERATOR_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_POSTFIX_OPERATOR_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+/// Checks if the overloaded postfix ++ and -- operator return a constant
+/// object.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cert-postfix-operator.html
+class PostfixOperatorCheck : public ClangTidyCheck {
+public:
+  PostfixOperatorCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_POSTFIX_OPERATOR_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp
new file mode 100644
index 0000000..256525e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp
@@ -0,0 +1,124 @@
+//===--- ProperlySeededRandomGeneratorCheck.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 "ProperlySeededRandomGeneratorCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+ProperlySeededRandomGeneratorCheck::ProperlySeededRandomGeneratorCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      RawDisallowedSeedTypes(
+          Options.get("DisallowedSeedTypes", "time_t,std::time_t")) {
+  StringRef(RawDisallowedSeedTypes).split(DisallowedSeedTypes, ',');
+}
+
+void ProperlySeededRandomGeneratorCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "DisallowedSeedTypes", RawDisallowedSeedTypes);
+}
+
+void ProperlySeededRandomGeneratorCheck::registerMatchers(MatchFinder *Finder) {
+  auto RandomGeneratorEngineDecl = cxxRecordDecl(hasAnyName(
+      "::std::linear_congruential_engine", "::std::mersenne_twister_engine",
+      "::std::subtract_with_carry_engine", "::std::discard_block_engine",
+      "::std::independent_bits_engine", "::std::shuffle_order_engine"));
+  auto RandomGeneratorEngineTypeMatcher = hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(RandomGeneratorEngineDecl))));
+
+  // std::mt19937 engine;
+  // engine.seed();
+  //        ^
+  // engine.seed(1);
+  //        ^
+  // const int x = 1;
+  // engine.seed(x);
+  //        ^
+  Finder->addMatcher(
+      cxxMemberCallExpr(
+          has(memberExpr(has(declRefExpr(RandomGeneratorEngineTypeMatcher)),
+                         member(hasName("seed")),
+                         unless(hasDescendant(cxxThisExpr())))))
+          .bind("seed"),
+      this);
+
+  // std::mt19937 engine;
+  //              ^
+  // std::mt19937 engine(1);
+  //              ^
+  // const int x = 1;
+  // std::mt19937 engine(x);
+  //              ^
+  Finder->addMatcher(
+      cxxConstructExpr(RandomGeneratorEngineTypeMatcher).bind("ctor"), this);
+
+  // srand();
+  // ^
+  // const int x = 1;
+  // srand(x);
+  // ^
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasAnyName("::srand", "::std::srand"))))
+          .bind("srand"),
+      this);
+}
+
+void ProperlySeededRandomGeneratorCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructExpr>("ctor");
+  if (Ctor)
+    checkSeed(Result, Ctor);
+
+  const auto *Func = Result.Nodes.getNodeAs<CXXMemberCallExpr>("seed");
+  if (Func)
+    checkSeed(Result, Func);
+
+  const auto *Srand = Result.Nodes.getNodeAs<CallExpr>("srand");
+  if (Srand)
+    checkSeed(Result, Srand);
+}
+
+template <class T>
+void ProperlySeededRandomGeneratorCheck::checkSeed(
+    const MatchFinder::MatchResult &Result, const T *Func) {
+  if (Func->getNumArgs() == 0 || Func->getArg(0)->isDefaultArgument()) {
+    diag(Func->getExprLoc(),
+         "random number generator seeded with a default argument will generate "
+         "a predictable sequence of values");
+    return;
+  }
+
+  llvm::APSInt Value;
+  if (Func->getArg(0)->EvaluateAsInt(Value, *Result.Context)) {
+    diag(Func->getExprLoc(),
+         "random number generator seeded with a constant value will generate a "
+         "predictable sequence of values");
+    return;
+  }
+
+  const std::string SeedType(
+      Func->getArg(0)->IgnoreCasts()->getType().getAsString());
+  if (llvm::find(DisallowedSeedTypes, SeedType) != DisallowedSeedTypes.end()) {
+    diag(Func->getExprLoc(),
+         "random number generator seeded with a disallowed source of seed "
+         "value will generate a predictable sequence of values");
+    return;
+  }
+}
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h
new file mode 100644
index 0000000..ac5507c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h
@@ -0,0 +1,47 @@
+//===--- ProperlySeededRandomGeneratorCheck.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_CERT_PROPERLY_SEEDED_RANDOM_GENERATOR_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_PROPERLY_SEEDED_RANDOM_GENERATOR_H
+
+#include "../ClangTidy.h"
+#include <string>
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+/// Random number generator must be seeded properly.
+///
+/// A random number generator initialized with default value or a
+/// constant expression is a security vulnerability.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cert-properly-seeded-random-generator.html
+class ProperlySeededRandomGeneratorCheck : public ClangTidyCheck {
+public:
+  ProperlySeededRandomGeneratorCheck(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:
+  template <class T>
+  void checkSeed(const ast_matchers::MatchFinder::MatchResult &Result,
+                 const T *Func);
+
+  std::string RawDisallowedSeedTypes;
+  SmallVector<StringRef, 5> DisallowedSeedTypes;
+};
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_PROPERLY_SEEDED_RANDOM_GENERATOR_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/SetLongJmpCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/SetLongJmpCheck.cpp
new file mode 100644
index 0000000..89ba5e7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/SetLongJmpCheck.cpp
@@ -0,0 +1,79 @@
+//===--- SetLongJmpCheck.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 "SetLongJmpCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+const char SetLongJmpCheck::DiagWording[] =
+    "do not call %0; consider using exception handling instead";
+
+namespace {
+class SetJmpMacroCallbacks : public PPCallbacks {
+  SetLongJmpCheck &Check;
+
+public:
+  explicit SetJmpMacroCallbacks(SetLongJmpCheck &Check) : Check(Check) {}
+
+  void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
+                    SourceRange Range, const MacroArgs *Args) override {
+    const auto *II = MacroNameTok.getIdentifierInfo();
+    if (!II)
+      return;
+
+    if (II->getName() == "setjmp")
+      Check.diag(Range.getBegin(), Check.DiagWording) << II;
+  }
+};
+} // namespace
+
+void SetLongJmpCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  // This checker only applies to C++, where exception handling is a superior
+  // solution to setjmp/longjmp calls.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // Per [headers]p5, setjmp must be exposed as a macro instead of a function,
+  // despite the allowance in C for setjmp to also be an extern function.
+  Compiler.getPreprocessor().addPPCallbacks(
+      llvm::make_unique<SetJmpMacroCallbacks>(*this));
+}
+
+void SetLongJmpCheck::registerMatchers(MatchFinder *Finder) {
+  // This checker only applies to C++, where exception handling is a superior
+  // solution to setjmp/longjmp calls.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // In case there is an implementation that happens to define setjmp as a
+  // function instead of a macro, this will also catch use of it. However, we
+  // are primarily searching for uses of longjmp.
+  Finder->addMatcher(callExpr(callee(functionDecl(anyOf(hasName("setjmp"),
+                                                        hasName("longjmp")))))
+                         .bind("expr"),
+                     this);
+}
+
+void SetLongJmpCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *E = Result.Nodes.getNodeAs<CallExpr>("expr");
+  diag(E->getExprLoc(), DiagWording) << cast<NamedDecl>(E->getCalleeDecl());
+}
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/SetLongJmpCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/SetLongJmpCheck.h
new file mode 100644
index 0000000..1d6c098
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/SetLongJmpCheck.h
@@ -0,0 +1,38 @@
+//===--- SetLongJmpCheck.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_SETLONGJMPCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SETLONGJMPCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+/// Guards against use of setjmp/longjmp in C++ code
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cert-err52-cpp.html
+class SetLongJmpCheck : public ClangTidyCheck {
+public:
+  SetLongJmpCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+
+  static const char DiagWording[];
+};
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SETLONGJMPCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/StaticObjectExceptionCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/StaticObjectExceptionCheck.cpp
new file mode 100644
index 0000000..45f9433
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/StaticObjectExceptionCheck.cpp
@@ -0,0 +1,60 @@
+//===--- StaticObjectExceptionCheck.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 "StaticObjectExceptionCheck.h"
+#include "../utils/Matchers.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+void StaticObjectExceptionCheck::registerMatchers(MatchFinder *Finder) {
+  if ((!getLangOpts().CPlusPlus) || (!getLangOpts().CXXExceptions))
+    return;
+
+  // Match any static or thread_local variable declaration that has an
+  // initializer that can throw.
+  Finder->addMatcher(
+      varDecl(anyOf(hasThreadStorageDuration(), hasStaticStorageDuration()),
+              unless(hasAncestor(functionDecl())),
+              anyOf(hasDescendant(cxxConstructExpr(hasDeclaration(
+                        cxxConstructorDecl(unless(isNoThrow())).bind("func")))),
+                    hasDescendant(cxxNewExpr(hasDeclaration(
+                        functionDecl(unless(isNoThrow())).bind("func")))),
+                    hasDescendant(callExpr(hasDeclaration(
+                        functionDecl(unless(isNoThrow())).bind("func"))))))
+          .bind("var"),
+      this);
+}
+
+void StaticObjectExceptionCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *VD = Result.Nodes.getNodeAs<VarDecl>("var");
+  const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func");
+
+  diag(VD->getLocation(),
+       "initialization of %0 with %select{static|thread_local}1 storage "
+       "duration may throw an exception that cannot be caught")
+      << VD << (VD->getStorageDuration() == SD_Static ? 0 : 1);
+
+  SourceLocation FuncLocation = Func->getLocation();
+  if (FuncLocation.isValid()) {
+    diag(FuncLocation,
+         "possibly throwing %select{constructor|function}0 declared here",
+         DiagnosticIDs::Note)
+        << (isa<CXXConstructorDecl>(Func) ? 0 : 1);
+  }
+}
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/StaticObjectExceptionCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/StaticObjectExceptionCheck.h
new file mode 100644
index 0000000..463f433
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/StaticObjectExceptionCheck.h
@@ -0,0 +1,36 @@
+//===--- StaticObjectExceptionCheck.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_CERT_ERR58_CPP_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_ERR58_CPP_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+/// Checks whether the constructor for a static or thread_local object will
+/// throw.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cert-err58-cpp.html
+class StaticObjectExceptionCheck : public ClangTidyCheck {
+public:
+  StaticObjectExceptionCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_ERR58_CPP_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/StrToNumCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/StrToNumCheck.cpp
new file mode 100644
index 0000000..bd84cf2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/StrToNumCheck.cpp
@@ -0,0 +1,235 @@
+//===--- Err34CCheck.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 "StrToNumCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Analysis/Analyses/FormatString.h"
+#include "llvm/ADT/StringSwitch.h"
+#include <cassert>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+void StrToNumCheck::registerMatchers(MatchFinder *Finder) {
+  // Match any function call to the C standard library string conversion
+  // functions that do no error checking.
+  Finder->addMatcher(
+      callExpr(
+          callee(functionDecl(anyOf(
+              functionDecl(hasAnyName("::atoi", "::atof", "::atol", "::atoll"))
+                  .bind("converter"),
+              functionDecl(hasAnyName("::scanf", "::sscanf", "::fscanf",
+                                      "::vfscanf", "::vscanf", "::vsscanf"))
+                  .bind("formatted")))))
+          .bind("expr"),
+      this);
+}
+
+namespace {
+enum class ConversionKind {
+  None,
+  ToInt,
+  ToUInt,
+  ToLongInt,
+  ToLongUInt,
+  ToIntMax,
+  ToUIntMax,
+  ToFloat,
+  ToDouble,
+  ToLongDouble
+};
+
+ConversionKind ClassifyConversionFunc(const FunctionDecl *FD) {
+  return llvm::StringSwitch<ConversionKind>(FD->getName())
+      .Cases("atoi", "atol", ConversionKind::ToInt)
+      .Case("atoll", ConversionKind::ToLongInt)
+      .Case("atof", ConversionKind::ToDouble)
+      .Default(ConversionKind::None);
+}
+
+ConversionKind ClassifyFormatString(StringRef Fmt, const LangOptions &LO,
+                                    const TargetInfo &TI) {
+  // Scan the format string for the first problematic format specifier, then
+  // report that as the conversion type. This will miss additional conversion
+  // specifiers, but that is acceptable behavior.
+
+  class Handler : public analyze_format_string::FormatStringHandler {
+    ConversionKind CK;
+
+    bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
+                              const char *startSpecifier,
+                              unsigned specifierLen) override {
+      // If we just consume the argument without assignment, we don't care
+      // about it having conversion errors.
+      if (!FS.consumesDataArgument())
+        return true;
+
+      // Get the conversion specifier and use it to determine the conversion
+      // kind.
+      analyze_scanf::ScanfConversionSpecifier SCS = FS.getConversionSpecifier();
+      if (SCS.isIntArg()) {
+        switch (FS.getLengthModifier().getKind()) {
+        case analyze_scanf::LengthModifier::AsLongLong:
+          CK = ConversionKind::ToLongInt;
+          break;
+        case analyze_scanf::LengthModifier::AsIntMax:
+          CK = ConversionKind::ToIntMax;
+          break;
+        default:
+          CK = ConversionKind::ToInt;
+          break;
+        }
+      } else if (SCS.isUIntArg()) {
+        switch (FS.getLengthModifier().getKind()) {
+        case analyze_scanf::LengthModifier::AsLongLong:
+          CK = ConversionKind::ToLongUInt;
+          break;
+        case analyze_scanf::LengthModifier::AsIntMax:
+          CK = ConversionKind::ToUIntMax;
+          break;
+        default:
+          CK = ConversionKind::ToUInt;
+          break;
+        }
+      } else if (SCS.isDoubleArg()) {
+        switch (FS.getLengthModifier().getKind()) {
+        case analyze_scanf::LengthModifier::AsLongDouble:
+          CK = ConversionKind::ToLongDouble;
+          break;
+        case analyze_scanf::LengthModifier::AsLong:
+          CK = ConversionKind::ToDouble;
+          break;
+        default:
+          CK = ConversionKind::ToFloat;
+          break;
+        }
+      }
+
+      // Continue if we have yet to find a conversion kind that we care about.
+      return CK == ConversionKind::None;
+    }
+
+  public:
+    Handler() : CK(ConversionKind::None) {}
+
+    ConversionKind get() const { return CK; }
+  };
+
+  Handler H;
+  analyze_format_string::ParseScanfString(H, Fmt.begin(), Fmt.end(), LO, TI);
+
+  return H.get();
+}
+
+StringRef ClassifyConversionType(ConversionKind K) {
+  switch (K) {
+  case ConversionKind::None:
+    assert(false && "Unexpected conversion kind");
+  case ConversionKind::ToInt:
+  case ConversionKind::ToLongInt:
+  case ConversionKind::ToIntMax:
+    return "an integer value";
+  case ConversionKind::ToUInt:
+  case ConversionKind::ToLongUInt:
+  case ConversionKind::ToUIntMax:
+    return "an unsigned integer value";
+  case ConversionKind::ToFloat:
+  case ConversionKind::ToDouble:
+  case ConversionKind::ToLongDouble:
+    return "a floating-point value";
+  }
+  llvm_unreachable("Unknown conversion kind");
+}
+
+StringRef ClassifyReplacement(ConversionKind K) {
+  switch (K) {
+  case ConversionKind::None:
+    assert(false && "Unexpected conversion kind");
+  case ConversionKind::ToInt:
+    return "strtol";
+  case ConversionKind::ToUInt:
+    return "strtoul";
+  case ConversionKind::ToIntMax:
+    return "strtoimax";
+  case ConversionKind::ToLongInt:
+    return "strtoll";
+  case ConversionKind::ToLongUInt:
+    return "strtoull";
+  case ConversionKind::ToUIntMax:
+    return "strtoumax";
+  case ConversionKind::ToFloat:
+    return "strtof";
+  case ConversionKind::ToDouble:
+    return "strtod";
+  case ConversionKind::ToLongDouble:
+    return "strtold";
+  }
+  llvm_unreachable("Unknown conversion kind");
+}
+} // unnamed namespace
+
+void StrToNumCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Call = Result.Nodes.getNodeAs<CallExpr>("expr");
+  const FunctionDecl *FuncDecl = nullptr;
+  ConversionKind Conversion;
+
+  if (const auto *ConverterFunc =
+          Result.Nodes.getNodeAs<FunctionDecl>("converter")) {
+    // Converter functions are always incorrect to use.
+    FuncDecl = ConverterFunc;
+    Conversion = ClassifyConversionFunc(ConverterFunc);
+  } else if (const auto *FFD =
+                 Result.Nodes.getNodeAs<FunctionDecl>("formatted")) {
+    StringRef FmtStr;
+    // The format string comes from the call expression and depends on which
+    // flavor of scanf is called.
+    // Index 0: scanf, vscanf, Index 1: fscanf, sscanf, vfscanf, vsscanf.
+    unsigned Idx =
+        (FFD->getName() == "scanf" || FFD->getName() == "vscanf") ? 0 : 1;
+
+    // Given the index, see if the call expression argument at that index is
+    // a string literal.
+    if (Call->getNumArgs() < Idx)
+      return;
+
+    if (const Expr *Arg = Call->getArg(Idx)->IgnoreParenImpCasts()) {
+      if (const auto *SL = dyn_cast<StringLiteral>(Arg)) {
+        FmtStr = SL->getString();
+      }
+    }
+
+    // If we could not get the format string, bail out.
+    if (FmtStr.empty())
+      return;
+
+    // Formatted input functions need further checking of the format string to
+    // determine whether a problematic conversion may be happening.
+    Conversion = ClassifyFormatString(FmtStr, getLangOpts(),
+                                      Result.Context->getTargetInfo());
+    if (Conversion != ConversionKind::None)
+      FuncDecl = FFD;
+  }
+
+  if (!FuncDecl)
+    return;
+
+  diag(Call->getExprLoc(),
+       "%0 used to convert a string to %1, but function will not report "
+       "conversion errors; consider using '%2' instead")
+      << FuncDecl << ClassifyConversionType(Conversion)
+      << ClassifyReplacement(Conversion);
+}
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/StrToNumCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/StrToNumCheck.h
new file mode 100644
index 0000000..55f13be
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/StrToNumCheck.h
@@ -0,0 +1,36 @@
+//===--- StrToNumCheck.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_CERT_STRTONUMCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_STRTONUMCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+/// Guards against use of string conversion functions that do not have
+/// reasonable error handling for conversion errors.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cert-err34-c.html
+class StrToNumCheck : public ClangTidyCheck {
+public:
+  StrToNumCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_STRTONUMCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp
new file mode 100644
index 0000000..37fb355
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp
@@ -0,0 +1,41 @@
+//===--- ThrownExceptionTypeCheck.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 "ThrownExceptionTypeCheck.h"
+#include "../utils/Matchers.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+void ThrownExceptionTypeCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(
+      cxxThrowExpr(has(ignoringParenImpCasts(
+          cxxConstructExpr(hasDeclaration(cxxConstructorDecl(
+                               isCopyConstructor(), unless(isNoThrow()))))
+              .bind("expr")))),
+      this);
+}
+
+void ThrownExceptionTypeCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *E = Result.Nodes.getNodeAs<Expr>("expr");
+  diag(E->getExprLoc(),
+       "thrown exception type is not nothrow copy constructible");
+}
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.h
new file mode 100644
index 0000000..2f9d887
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.h
@@ -0,0 +1,35 @@
+//===--- ThrownExceptionTypeCheck.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_CERT_THROWNEXCEPTIONTYPECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_THROWNEXCEPTIONTYPECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+/// Checks whether a thrown object is nothrow copy constructible.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cert-err60-cpp.html
+class ThrownExceptionTypeCheck : public ClangTidyCheck {
+public:
+  ThrownExceptionTypeCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_THROWNEXCEPTIONTYPECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/VariadicFunctionDefCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/VariadicFunctionDefCheck.cpp
new file mode 100644
index 0000000..ea6112a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/VariadicFunctionDefCheck.cpp
@@ -0,0 +1,42 @@
+//===--- VariadicfunctiondefCheck.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 "VariadicFunctionDefCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+void VariadicFunctionDefCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // We only care about function *definitions* that are variadic, and do not
+  // have extern "C" language linkage.
+  Finder->addMatcher(
+      functionDecl(isDefinition(), isVariadic(), unless(isExternC()))
+          .bind("func"),
+      this);
+}
+
+void VariadicFunctionDefCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("func");
+
+  diag(FD->getLocation(),
+       "do not define a C-style variadic function; consider using a function "
+       "parameter pack or currying instead");
+}
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/VariadicFunctionDefCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/VariadicFunctionDefCheck.h
new file mode 100644
index 0000000..e215e8d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cert/VariadicFunctionDefCheck.h
@@ -0,0 +1,35 @@
+//===--- VariadicFunctionDefCheck.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_CERT_VARIADICFUNCTIONDEF_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_VARIADICFUNCTIONDEF_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+/// Guards against any C-style variadic function definitions (not declarations).
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cert-dcl50-cpp.html
+class VariadicFunctionDefCheck : public ClangTidyCheck {
+public:
+  VariadicFunctionDefCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_VARIADICFUNCTIONDEF_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidGotoCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidGotoCheck.cpp
new file mode 100644
index 0000000..3e800cd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidGotoCheck.cpp
@@ -0,0 +1,57 @@
+//===--- AvoidGotoCheck.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 "AvoidGotoCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+namespace {
+AST_MATCHER(GotoStmt, isForwardJumping) {
+  return Node.getLocStart() < Node.getLabel()->getLocStart();
+}
+} // namespace
+
+void AvoidGotoCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // TODO: This check does not recognize `IndirectGotoStmt` which is a
+  // GNU extension. These must be matched separately and an AST matcher
+  // is currently missing for them.
+
+  // Check if the 'goto' is used for control flow other than jumping
+  // out of a nested loop.
+  auto Loop = stmt(anyOf(forStmt(), cxxForRangeStmt(), whileStmt(), doStmt()));
+  auto NestedLoop =
+      stmt(anyOf(forStmt(hasAncestor(Loop)), cxxForRangeStmt(hasAncestor(Loop)),
+                 whileStmt(hasAncestor(Loop)), doStmt(hasAncestor(Loop))));
+
+  Finder->addMatcher(gotoStmt(anyOf(unless(hasAncestor(NestedLoop)),
+                                    unless(isForwardJumping())))
+                         .bind("goto"),
+                     this);
+}
+
+void AvoidGotoCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Goto = Result.Nodes.getNodeAs<GotoStmt>("goto");
+
+  diag(Goto->getGotoLoc(), "avoid using 'goto' for flow control")
+      << Goto->getSourceRange();
+  diag(Goto->getLabel()->getLocStart(), "label defined here",
+       DiagnosticIDs::Note);
+}
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidGotoCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidGotoCheck.h
new file mode 100644
index 0000000..cf7dd76
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidGotoCheck.h
@@ -0,0 +1,36 @@
+//===--- AvoidGotoCheck.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_AVOIDGOTOCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDGOTOCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// The usage of ``goto`` for control flow is error prone and should be replaced
+/// with looping constructs. Only forward jumps in nested loops are accepted.
+//
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-avoid-goto.html
+class AvoidGotoCheck : public ClangTidyCheck {
+public:
+  AvoidGotoCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDGOTOCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
new file mode 100644
index 0000000..49fedd6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
@@ -0,0 +1,32 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyCppCoreGuidelinesModule
+  AvoidGotoCheck.cpp
+  CppCoreGuidelinesTidyModule.cpp
+  InterfacesGlobalInitCheck.cpp
+  NarrowingConversionsCheck.cpp
+  NoMallocCheck.cpp
+  OwningMemoryCheck.cpp
+  ProBoundsArrayToPointerDecayCheck.cpp
+  ProBoundsConstantArrayIndexCheck.cpp
+  ProBoundsPointerArithmeticCheck.cpp
+  ProTypeConstCastCheck.cpp
+  ProTypeCstyleCastCheck.cpp
+  ProTypeMemberInitCheck.cpp
+  ProTypeReinterpretCastCheck.cpp
+  ProTypeStaticCastDowncastCheck.cpp
+  ProTypeUnionAccessCheck.cpp
+  ProTypeVarargCheck.cpp
+  SpecialMemberFunctionsCheck.cpp
+  SlicingCheck.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyMiscModule
+  clangTidyUtils
+  clangTooling
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
new file mode 100644
index 0000000..a039259
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
@@ -0,0 +1,88 @@
+//===--- CppCoreGuidelinesModule.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 "../misc/UnconventionalAssignOperatorCheck.h"
+#include "AvoidGotoCheck.h"
+#include "InterfacesGlobalInitCheck.h"
+#include "NarrowingConversionsCheck.h"
+#include "NoMallocCheck.h"
+#include "OwningMemoryCheck.h"
+#include "ProBoundsArrayToPointerDecayCheck.h"
+#include "ProBoundsConstantArrayIndexCheck.h"
+#include "ProBoundsPointerArithmeticCheck.h"
+#include "ProTypeConstCastCheck.h"
+#include "ProTypeCstyleCastCheck.h"
+#include "ProTypeMemberInitCheck.h"
+#include "ProTypeReinterpretCastCheck.h"
+#include "ProTypeStaticCastDowncastCheck.h"
+#include "ProTypeUnionAccessCheck.h"
+#include "ProTypeVarargCheck.h"
+#include "SlicingCheck.h"
+#include "SpecialMemberFunctionsCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// A module containing checks of the C++ Core Guidelines
+class CppCoreGuidelinesModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<AvoidGotoCheck>(
+        "cppcoreguidelines-avoid-goto");
+    CheckFactories.registerCheck<InterfacesGlobalInitCheck>(
+        "cppcoreguidelines-interfaces-global-init");
+    CheckFactories.registerCheck<NarrowingConversionsCheck>(
+        "cppcoreguidelines-narrowing-conversions");
+    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>(
+        "cppcoreguidelines-pro-bounds-constant-array-index");
+    CheckFactories.registerCheck<ProBoundsPointerArithmeticCheck>(
+        "cppcoreguidelines-pro-bounds-pointer-arithmetic");
+    CheckFactories.registerCheck<ProTypeConstCastCheck>(
+        "cppcoreguidelines-pro-type-const-cast");
+    CheckFactories.registerCheck<ProTypeCstyleCastCheck>(
+        "cppcoreguidelines-pro-type-cstyle-cast");
+    CheckFactories.registerCheck<ProTypeMemberInitCheck>(
+        "cppcoreguidelines-pro-type-member-init");
+    CheckFactories.registerCheck<ProTypeReinterpretCastCheck>(
+        "cppcoreguidelines-pro-type-reinterpret-cast");
+    CheckFactories.registerCheck<ProTypeStaticCastDowncastCheck>(
+        "cppcoreguidelines-pro-type-static-cast-downcast");
+    CheckFactories.registerCheck<ProTypeUnionAccessCheck>(
+        "cppcoreguidelines-pro-type-union-access");
+    CheckFactories.registerCheck<ProTypeVarargCheck>(
+        "cppcoreguidelines-pro-type-vararg");
+    CheckFactories.registerCheck<SpecialMemberFunctionsCheck>(
+        "cppcoreguidelines-special-member-functions");
+    CheckFactories.registerCheck<SlicingCheck>("cppcoreguidelines-slicing");
+    CheckFactories.registerCheck<misc::UnconventionalAssignOperatorCheck>(
+        "cppcoreguidelines-c-copy-assignment-signature");
+  }
+};
+
+// Register the LLVMTidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<CppCoreGuidelinesModule>
+    X("cppcoreguidelines-module", "Adds checks for the C++ Core Guidelines.");
+
+} // namespace cppcoreguidelines
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the CppCoreGuidelinesModule.
+volatile int CppCoreGuidelinesModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp
new file mode 100644
index 0000000..f601b24
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp
@@ -0,0 +1,59 @@
+//===--- InterfacesGlobalInitCheck.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 "InterfacesGlobalInitCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+void InterfacesGlobalInitCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsGlobal =
+      allOf(hasGlobalStorage(),
+            hasDeclContext(anyOf(translationUnitDecl(), // Global scope.
+                                 namespaceDecl(),       // Namespace scope.
+                                 recordDecl())),        // Class scope.
+            unless(isConstexpr()));
+
+  const auto ReferencesUndefinedGlobalVar = declRefExpr(hasDeclaration(
+      varDecl(IsGlobal, unless(isDefinition())).bind("referencee")));
+
+  Finder->addMatcher(
+      varDecl(IsGlobal, isDefinition(),
+              hasInitializer(expr(hasDescendant(ReferencesUndefinedGlobalVar))))
+          .bind("var"),
+      this);
+}
+
+void InterfacesGlobalInitCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *const Var = Result.Nodes.getNodeAs<VarDecl>("var");
+  // For now assume that people who write macros know what they're doing.
+  if (Var->getLocation().isMacroID())
+    return;
+  const auto *const Referencee = Result.Nodes.getNodeAs<VarDecl>("referencee");
+  // If the variable has been defined, we're good.
+  const auto *const ReferenceeDef = Referencee->getDefinition();
+  if (ReferenceeDef != nullptr &&
+      Result.SourceManager->isBeforeInTranslationUnit(
+          ReferenceeDef->getLocation(), Var->getLocation())) {
+    return;
+  }
+  diag(Var->getLocation(),
+       "initializing non-local variable with non-const expression depending on "
+       "uninitialized non-local variable %0")
+      << Referencee;
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.h
new file mode 100644
index 0000000..13712d1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.h
@@ -0,0 +1,35 @@
+//===--- InterfacesGlobalInitCheck.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_INTERFACES_GLOBAL_INIT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_INTERFACES_GLOBAL_INIT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// Flags possible initialization order issues of static variables.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-interfaces-global-init.html
+class InterfacesGlobalInitCheck : public ClangTidyCheck {
+public:
+  InterfacesGlobalInitCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_INTERFACES_GLOBAL_INIT_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
new file mode 100644
index 0000000..2c5676e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
@@ -0,0 +1,70 @@
+//===--- NarrowingConversionsCheck.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 "NarrowingConversionsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+// FIXME: Check double -> float truncation. Pay attention to casts:
+void NarrowingConversionsCheck::registerMatchers(MatchFinder *Finder) {
+  // ceil() and floor() are guaranteed to return integers, even though the type
+  // is not integral.
+  const auto IsCeilFloorCall = callExpr(callee(functionDecl(
+      hasAnyName("::ceil", "::std::ceil", "::floor", "::std::floor"))));
+
+  const auto IsFloatExpr =
+      expr(hasType(realFloatingPointType()), unless(IsCeilFloorCall));
+
+  // casts:
+  //   i = 0.5;
+  //   void f(int); f(0.5);
+  Finder->addMatcher(implicitCastExpr(hasImplicitDestinationType(isInteger()),
+                                      hasSourceExpression(IsFloatExpr),
+                                      unless(hasParent(castExpr())),
+                                      unless(isInTemplateInstantiation()))
+                         .bind("cast"),
+                     this);
+
+  // Binary operators:
+  //   i += 0.5;
+  Finder->addMatcher(
+      binaryOperator(isAssignmentOperator(),
+                     // The `=` case generates an implicit cast which is covered
+                     // by the previous matcher.
+                     unless(hasOperatorName("=")),
+                     hasLHS(hasType(isInteger())), hasRHS(IsFloatExpr),
+                     unless(isInTemplateInstantiation()))
+          .bind("op"),
+      this);
+}
+
+void NarrowingConversionsCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *Op = Result.Nodes.getNodeAs<BinaryOperator>("op")) {
+    if (Op->getLocStart().isMacroID())
+      return;
+    diag(Op->getOperatorLoc(), "narrowing conversion from %0 to %1")
+        << Op->getRHS()->getType() << Op->getLHS()->getType();
+    return;
+  }
+  const auto *Cast = Result.Nodes.getNodeAs<ImplicitCastExpr>("cast");
+  if (Cast->getLocStart().isMacroID())
+    return;
+  diag(Cast->getExprLoc(), "narrowing conversion from %0 to %1")
+      << Cast->getSubExpr()->getType() << Cast->getType();
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h
new file mode 100644
index 0000000..35f58bc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h
@@ -0,0 +1,37 @@
+//===--- NarrowingConversionsCheck.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_NARROWING_CONVERSIONS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_NARROWING_CONVERSIONS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// Checks for narrowing conversions, e.g:
+///   int i = 0;
+///   i += 0.1;
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-narrowing-conversions.html
+class NarrowingConversionsCheck : public ClangTidyCheck {
+public:
+  NarrowingConversionsCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_NARROWING_CONVERSIONS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp
new file mode 100644
index 0000000..5a2b882
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp
@@ -0,0 +1,82 @@
+//===--- NoMallocCheck.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 "NoMallocCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include <algorithm>
+#include <string>
+#include <vector>
+
+using namespace clang::ast_matchers;
+using namespace clang::ast_matchers::internal;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+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 NoMallocCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "Allocations", AllocList);
+  Options.store(Opts, "Reallocations", ReallocList);
+  Options.store(Opts, "Deallocations", DeallocList);
+}
+
+void NoMallocCheck::registerMatchers(MatchFinder *Finder) {
+  // C-style memory management is only problematic in C++.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // Registering malloc, will suggest RAII.
+  Finder->addMatcher(callExpr(callee(functionDecl(hasAnyListedName(AllocList))))
+                         .bind("allocation"),
+                     this);
+
+  // Registering realloc calls, suggest std::vector or std::string.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasAnyListedName(ReallocList))))
+          .bind("realloc"),
+      this);
+
+  // Registering free calls, will suggest RAII instead.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasAnyListedName(DeallocList))))
+          .bind("free"),
+      this);
+}
+
+void NoMallocCheck::check(const MatchFinder::MatchResult &Result) {
+  const CallExpr *Call = nullptr;
+  StringRef Recommendation;
+
+  if ((Call = Result.Nodes.getNodeAs<CallExpr>("allocation")))
+    Recommendation = "consider a container or a smart pointer";
+  else if ((Call = Result.Nodes.getNodeAs<CallExpr>("realloc")))
+    Recommendation = "consider std::vector or std::string";
+  else if ((Call = Result.Nodes.getNodeAs<CallExpr>("free")))
+    Recommendation = "use RAII";
+
+  assert(Call && "Unhandled binding in the Matcher");
+
+  diag(Call->getLocStart(), "do not manage memory manually; %0")
+      << Recommendation << SourceRange(Call->getLocStart(), Call->getLocEnd());
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.h
new file mode 100644
index 0000000..4cec8a8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.h
@@ -0,0 +1,62 @@
+//===--- NoMallocCheck.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_NO_MALLOC_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_NO_MALLOC_H
+
+#include "../ClangTidy.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// This checker is concerned with C-style memory management and suggest modern
+/// alternatives to it.
+/// The check is only enabled in C++. For analyzing malloc calls see Clang
+/// Static Analyzer - unix.Malloc.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-no-malloc.html
+class NoMallocCheck : public ClangTidyCheck {
+public:
+  /// Construct Checker and read in configuration for function names.
+  NoMallocCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context),
+        AllocList(Options.get("Allocations", "::malloc;::calloc")),
+        ReallocList(Options.get("Reallocations", "::realloc")),
+        DeallocList(Options.get("Deallocations", "::free")) {}
+
+  /// Make configuration of checker discoverable.
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+  /// Registering for malloc, calloc, realloc and free calls.
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+
+  /// Checks matched function calls and gives suggestion to modernize the code.
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  /// Semicolon-separated list of fully qualified names of memory allocation
+  /// functions the check warns about. Defaults to `::malloc;::calloc`.
+  const std::string AllocList;
+  /// Semicolon-separated list of fully qualified names of memory reallocation
+  /// functions the check warns about. Defaults to `::realloc`.
+  const std::string ReallocList;
+  /// Semicolon-separated list of fully qualified names of memory deallocation
+  /// functions the check warns about. Defaults to `::free`.
+  const std::string DeallocList;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_NO_MALLOC_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp
new file mode 100644
index 0000000..6c86e05
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.h
new file mode 100644
index 0000000..e68e4c0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp
new file mode 100644
index 0000000..8b0f7ce
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp
@@ -0,0 +1,82 @@
+//===--- ProBoundsArrayToPointerDecayCheck.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 "ProBoundsArrayToPointerDecayCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+namespace {
+AST_MATCHER_P(CXXForRangeStmt, hasRangeBeginEndStmt,
+              ast_matchers::internal::Matcher<DeclStmt>, InnerMatcher) {
+  for (const DeclStmt *Stmt : {Node.getBeginStmt(), Node.getEndStmt()})
+    if (Stmt != nullptr && InnerMatcher.matches(*Stmt, Finder, Builder))
+      return true;
+  return false;
+}
+
+AST_MATCHER(Stmt, isInsideOfRangeBeginEndStmt) {
+  return stmt(hasAncestor(cxxForRangeStmt(
+                  hasRangeBeginEndStmt(hasDescendant(equalsNode(&Node))))))
+      .matches(Node, Finder, Builder);
+}
+
+AST_MATCHER_P(Expr, hasParentIgnoringImpCasts,
+              ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
+  const Expr *E = &Node;
+  do {
+    ASTContext::DynTypedNodeList Parents =
+        Finder->getASTContext().getParents(*E);
+    if (Parents.size() != 1)
+      return false;
+    E = Parents[0].get<Expr>();
+    if (!E)
+      return false;
+  } while (isa<ImplicitCastExpr>(E));
+
+  return InnerMatcher.matches(*E, Finder, Builder);
+}
+} // namespace
+
+void ProBoundsArrayToPointerDecayCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // The only allowed array to pointer decay
+  // 1) just before array subscription
+  // 2) inside a range-for over an array
+  // 3) if it converts a string literal to a pointer
+  Finder->addMatcher(
+      implicitCastExpr(unless(hasParent(arraySubscriptExpr())),
+                       unless(hasParentIgnoringImpCasts(explicitCastExpr())),
+                       unless(isInsideOfRangeBeginEndStmt()),
+                       unless(hasSourceExpression(stringLiteral())))
+          .bind("cast"),
+      this);
+}
+
+void ProBoundsArrayToPointerDecayCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *MatchedCast = Result.Nodes.getNodeAs<ImplicitCastExpr>("cast");
+  if (MatchedCast->getCastKind() != CK_ArrayToPointerDecay)
+    return;
+
+  diag(MatchedCast->getExprLoc(), "do not implicitly decay an array into a "
+                                  "pointer; consider using gsl::array_view or "
+                                  "an explicit cast instead");
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.h
new file mode 100644
index 0000000..0afffb6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.h
@@ -0,0 +1,35 @@
+//===--- ProBoundsArrayToPointerDecayCheck.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_PRO_BOUNDS_ARRAY_TO_POINTER_DECAY_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_ARRAY_TO_POINTER_DECAY_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// This check flags all array to pointer decays
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-pro-bounds-array-to-pointer-decay.html
+class ProBoundsArrayToPointerDecayCheck : public ClangTidyCheck {
+public:
+  ProBoundsArrayToPointerDecayCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_ARRAY_TO_POINTER_DECAY_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp
new file mode 100644
index 0000000..a81496e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp
@@ -0,0 +1,141 @@
+//===--- ProBoundsConstantArrayIndexCheck.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 "ProBoundsConstantArrayIndexCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+ProBoundsConstantArrayIndexCheck::ProBoundsConstantArrayIndexCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context), GslHeader(Options.get("GslHeader", "")),
+      IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
+          Options.getLocalOrGlobal("IncludeStyle", "llvm"))) {}
+
+void ProBoundsConstantArrayIndexCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "GslHeader", GslHeader);
+  Options.store(Opts, "IncludeStyle", IncludeStyle);
+}
+
+void ProBoundsConstantArrayIndexCheck::registerPPCallbacks(
+    CompilerInstance &Compiler) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Inserter.reset(new utils::IncludeInserter(
+      Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle));
+  Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+}
+
+void ProBoundsConstantArrayIndexCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // Note: if a struct contains an array member, the compiler-generated
+  // constructor has an arraySubscriptExpr.
+  Finder->addMatcher(
+      arraySubscriptExpr(
+          hasBase(ignoringImpCasts(hasType(constantArrayType().bind("type")))),
+          hasIndex(expr().bind("index")), unless(hasAncestor(isImplicit())))
+          .bind("expr"),
+      this);
+
+  Finder->addMatcher(
+      cxxOperatorCallExpr(
+          hasOverloadedOperatorName("[]"),
+          hasArgument(
+              0, hasType(cxxRecordDecl(hasName("::std::array")).bind("type"))),
+          hasArgument(1, expr().bind("index")))
+          .bind("expr"),
+      this);
+}
+
+void ProBoundsConstantArrayIndexCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *Matched = Result.Nodes.getNodeAs<Expr>("expr");
+  const auto *IndexExpr = Result.Nodes.getNodeAs<Expr>("index");
+
+  if (IndexExpr->isValueDependent())
+    return; // We check in the specialization.
+
+  llvm::APSInt Index;
+  if (!IndexExpr->isIntegerConstantExpr(Index, *Result.Context, nullptr,
+                                        /*isEvaluated=*/true)) {
+    SourceRange BaseRange;
+    if (const auto *ArraySubscriptE = dyn_cast<ArraySubscriptExpr>(Matched))
+      BaseRange = ArraySubscriptE->getBase()->getSourceRange();
+    else
+      BaseRange =
+          dyn_cast<CXXOperatorCallExpr>(Matched)->getArg(0)->getSourceRange();
+    SourceRange IndexRange = IndexExpr->getSourceRange();
+
+    auto Diag = diag(Matched->getExprLoc(),
+                     "do not use array subscript when the index is "
+                     "not an integer constant expression; use gsl::at() "
+                     "instead");
+    if (!GslHeader.empty()) {
+      Diag << FixItHint::CreateInsertion(BaseRange.getBegin(), "gsl::at(")
+           << FixItHint::CreateReplacement(
+                  SourceRange(BaseRange.getEnd().getLocWithOffset(1),
+                              IndexRange.getBegin().getLocWithOffset(-1)),
+                  ", ")
+           << FixItHint::CreateReplacement(Matched->getLocEnd(), ")");
+
+      Optional<FixItHint> Insertion = Inserter->CreateIncludeInsertion(
+          Result.SourceManager->getMainFileID(), GslHeader,
+          /*IsAngled=*/false);
+      if (Insertion)
+        Diag << Insertion.getValue();
+    }
+    return;
+  }
+
+  const auto *StdArrayDecl =
+      Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("type");
+
+  // For static arrays, this is handled in clang-diagnostic-array-bounds.
+  if (!StdArrayDecl)
+    return;
+
+  if (Index.isSigned() && Index.isNegative()) {
+    diag(Matched->getExprLoc(), "std::array<> index %0 is negative")
+        << Index.toString(10);
+    return;
+  }
+
+  const TemplateArgumentList &TemplateArgs = StdArrayDecl->getTemplateArgs();
+  if (TemplateArgs.size() < 2)
+    return;
+  // First template arg of std::array is the type, second arg is the size.
+  const auto &SizeArg = TemplateArgs[1];
+  if (SizeArg.getKind() != TemplateArgument::Integral)
+    return;
+  llvm::APInt ArraySize = SizeArg.getAsIntegral();
+
+  // Get uint64_t values, because different bitwidths would lead to an assertion
+  // in APInt::uge.
+  if (Index.getZExtValue() >= ArraySize.getZExtValue()) {
+    diag(Matched->getExprLoc(),
+         "std::array<> index %0 is past the end of the array "
+         "(which contains %1 elements)")
+        << Index.toString(10) << ArraySize.toString(10, false);
+  }
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h
new file mode 100644
index 0000000..28b24a6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h
@@ -0,0 +1,42 @@
+//===--- ProBoundsConstantArrayIndexCheck.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_PRO_BOUNDS_CONSTANT_ARRAY_INDEX_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_CONSTANT_ARRAY_INDEX_H
+
+#include "../ClangTidy.h"
+#include "../utils/IncludeInserter.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// This checks that all array subscriptions on static arrays and std::arrays
+/// have a constant index and are within bounds
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-pro-bounds-constant-array-index.html
+class ProBoundsConstantArrayIndexCheck : public ClangTidyCheck {
+  const std::string GslHeader;
+  const utils::IncludeSorter::IncludeStyle IncludeStyle;
+  std::unique_ptr<utils::IncludeInserter> Inserter;
+
+public:
+  ProBoundsConstantArrayIndexCheck(StringRef Name, ClangTidyContext *Context);
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_CONSTANT_ARRAY_INDEX_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp
new file mode 100644
index 0000000..dfbb51b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp
@@ -0,0 +1,63 @@
+//===--- ProBoundsPointerArithmeticCheck.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 "ProBoundsPointerArithmeticCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+void ProBoundsPointerArithmeticCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  const auto AllPointerTypes = anyOf(
+      hasType(pointerType()), hasType(autoType(hasDeducedType(pointerType()))),
+      hasType(decltypeType(hasUnderlyingType(pointerType()))));
+
+  // Flag all operators +, -, +=, -=, ++, -- that result in a pointer
+  Finder->addMatcher(
+      binaryOperator(
+          anyOf(hasOperatorName("+"), hasOperatorName("-"),
+                hasOperatorName("+="), hasOperatorName("-=")),
+          AllPointerTypes,
+          unless(hasLHS(ignoringImpCasts(declRefExpr(to(isImplicit()))))))
+          .bind("expr"),
+      this);
+
+  Finder->addMatcher(
+      unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--")),
+                    hasType(pointerType()))
+          .bind("expr"),
+      this);
+
+  // Array subscript on a pointer (not an array) is also pointer arithmetic
+  Finder->addMatcher(
+      arraySubscriptExpr(
+          hasBase(ignoringImpCasts(
+              anyOf(AllPointerTypes,
+                    hasType(decayedType(hasDecayedType(pointerType())))))))
+          .bind("expr"),
+      this);
+}
+
+void ProBoundsPointerArithmeticCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *MatchedExpr = Result.Nodes.getNodeAs<Expr>("expr");
+
+  diag(MatchedExpr->getExprLoc(), "do not use pointer arithmetic");
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h
new file mode 100644
index 0000000..5ecf93c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h
@@ -0,0 +1,37 @@
+//===--- ProBoundsPointerArithmeticCheck.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_PRO_BOUNDS_POINTER_ARITHMETIC_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_POINTER_ARITHMETIC_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// Flags all kinds of pointer arithmetic that have result of pointer type, i.e.
+/// +, -, +=, -=, ++, --. In addition, the [] operator on pointers (not on
+/// arrays) is flagged.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-pro-bounds-pointer-arithmetic.html
+class ProBoundsPointerArithmeticCheck : public ClangTidyCheck {
+public:
+  ProBoundsPointerArithmeticCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_POINTER_ARITHMETIC_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.cpp
new file mode 100644
index 0000000..4b6fb42
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.cpp
@@ -0,0 +1,34 @@
+//===--- ProTypeConstCastCheck.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 "ProTypeConstCastCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+void ProTypeConstCastCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(cxxConstCastExpr().bind("cast"), this);
+}
+
+void ProTypeConstCastCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedCast = Result.Nodes.getNodeAs<CXXConstCastExpr>("cast");
+  diag(MatchedCast->getOperatorLoc(), "do not use const_cast");
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.h
new file mode 100644
index 0000000..92a3a1b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.h
@@ -0,0 +1,35 @@
+//===--- ProTypeConstCastCheck.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_PRO_TYPE_CONST_CAST_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_CONST_CAST_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// This check flags all instances of const_cast
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-pro-type-const-cast.html
+class ProTypeConstCastCheck : public ClangTidyCheck {
+public:
+  ProTypeConstCastCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_CONST_CAST_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp
new file mode 100644
index 0000000..52156ad
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp
@@ -0,0 +1,108 @@
+//===--- ProTypeCstyleCastCheck.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 "ProTypeCstyleCastCheck.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 cppcoreguidelines {
+
+static bool needsConstCast(QualType SourceType, QualType DestType) {
+  SourceType = SourceType.getNonReferenceType();
+  DestType = DestType.getNonReferenceType();
+  while (SourceType->isPointerType() && DestType->isPointerType()) {
+    SourceType = SourceType->getPointeeType();
+    DestType = DestType->getPointeeType();
+    if (SourceType.isConstQualified() && !DestType.isConstQualified())
+      return true;
+  }
+  return false;
+}
+
+void ProTypeCstyleCastCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(
+      cStyleCastExpr(unless(isInTemplateInstantiation())).bind("cast"), this);
+}
+
+void ProTypeCstyleCastCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedCast = Result.Nodes.getNodeAs<CStyleCastExpr>("cast");
+
+  if (MatchedCast->getCastKind() == CK_BitCast ||
+      MatchedCast->getCastKind() == CK_LValueBitCast ||
+      MatchedCast->getCastKind() == CK_IntegralToPointer ||
+      MatchedCast->getCastKind() == CK_PointerToIntegral ||
+      MatchedCast->getCastKind() == CK_ReinterpretMemberPointer) {
+    diag(MatchedCast->getLocStart(),
+         "do not use C-style cast to convert between unrelated types");
+    return;
+  }
+
+  QualType SourceType = MatchedCast->getSubExpr()->getType();
+
+  if (MatchedCast->getCastKind() == CK_BaseToDerived) {
+    const auto *SourceDecl = SourceType->getPointeeCXXRecordDecl();
+    if (!SourceDecl) // The cast is from object to reference.
+      SourceDecl = SourceType->getAsCXXRecordDecl();
+    if (!SourceDecl)
+      return;
+
+    if (SourceDecl->isPolymorphic()) {
+      // Leave type spelling exactly as it was (unlike
+      // getTypeAsWritten().getAsString() which would spell enum types 'enum
+      // X').
+      StringRef DestTypeString = Lexer::getSourceText(
+          CharSourceRange::getTokenRange(
+              MatchedCast->getLParenLoc().getLocWithOffset(1),
+              MatchedCast->getRParenLoc().getLocWithOffset(-1)),
+          *Result.SourceManager, getLangOpts());
+
+      auto diag_builder = diag(
+          MatchedCast->getLocStart(),
+          "do not use C-style cast to downcast from a base to a derived class; "
+          "use dynamic_cast instead");
+
+      const Expr *SubExpr =
+          MatchedCast->getSubExprAsWritten()->IgnoreImpCasts();
+      std::string CastText = ("dynamic_cast<" + DestTypeString + ">").str();
+      if (!isa<ParenExpr>(SubExpr)) {
+        CastText.push_back('(');
+        diag_builder << FixItHint::CreateInsertion(
+            Lexer::getLocForEndOfToken(SubExpr->getLocEnd(), 0,
+                                       *Result.SourceManager, getLangOpts()),
+            ")");
+      }
+      auto ParenRange = CharSourceRange::getTokenRange(
+          MatchedCast->getLParenLoc(), MatchedCast->getRParenLoc());
+      diag_builder << FixItHint::CreateReplacement(ParenRange, CastText);
+    } else {
+      diag(
+          MatchedCast->getLocStart(),
+          "do not use C-style cast to downcast from a base to a derived class");
+    }
+    return;
+  }
+
+  if (MatchedCast->getCastKind() == CK_NoOp &&
+      needsConstCast(SourceType, MatchedCast->getType())) {
+    diag(MatchedCast->getLocStart(),
+         "do not use C-style cast to cast away constness");
+  }
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.h
new file mode 100644
index 0000000..c08b883
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.h
@@ -0,0 +1,36 @@
+//===--- ProTypeCstyleCastCheck.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_PRO_TYPE_CSTYLE_CAST_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_CSTYLE_CAST_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// This check flags all use of C-style casts that perform a static_cast
+/// downcast, const_cast, or reinterpret_cast.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-pro-type-cstyle-cast.html
+class ProTypeCstyleCastCheck : public ClangTidyCheck {
+public:
+  ProTypeCstyleCastCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_CSTYLE_CAST_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
new file mode 100644
index 0000000..4d9be81
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
@@ -0,0 +1,485 @@
+//===--- ProTypeMemberInitCheck.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 "ProTypeMemberInitCheck.h"
+#include "../utils/LexerUtils.h"
+#include "../utils/Matchers.h"
+#include "../utils/TypeTraits.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+using namespace clang::ast_matchers;
+using namespace clang::tidy::matchers;
+using llvm::SmallPtrSet;
+using llvm::SmallPtrSetImpl;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+namespace {
+
+AST_MATCHER(CXXRecordDecl, hasDefaultConstructor) {
+  return Node.hasDefaultConstructor();
+}
+
+// Iterate over all the fields in a record type, both direct and indirect (e.g.
+// if the record contains an anonmyous struct).
+template <typename T, typename Func>
+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(), Fn);
+    } else {
+      Fn(F);
+    }
+  }
+}
+
+void removeFieldsInitializedInBody(
+    const Stmt &Stmt, ASTContext &Context,
+    SmallPtrSetImpl<const FieldDecl *> &FieldDecls) {
+  auto Matches =
+      match(findAll(binaryOperator(
+                hasOperatorName("="),
+                hasLHS(memberExpr(member(fieldDecl().bind("fieldDecl")))))),
+            Stmt, Context);
+  for (const auto &Match : Matches)
+    FieldDecls.erase(Match.getNodeAs<FieldDecl>("fieldDecl"));
+}
+
+StringRef getName(const FieldDecl *Field) { return Field->getName(); }
+
+StringRef getName(const RecordDecl *Record) {
+  // Get the typedef name if this is a C-style anonymous struct and typedef.
+  if (const TypedefNameDecl *Typedef = Record->getTypedefNameForAnonDecl())
+    return Typedef->getName();
+  return Record->getName();
+}
+
+// Creates comma separated list of decls requiring initialization in order of
+// declaration.
+template <typename R, typename T>
+std::string
+toCommaSeparatedString(const R &OrderedDecls,
+                       const SmallPtrSetImpl<const T *> &DeclsToInit) {
+  SmallVector<StringRef, 16> Names;
+  for (const T *Decl : OrderedDecls) {
+    if (DeclsToInit.count(Decl))
+      Names.emplace_back(getName(Decl));
+  }
+  return llvm::join(Names.begin(), Names.end(), ", ");
+}
+
+SourceLocation getLocationForEndOfToken(const ASTContext &Context,
+                                        SourceLocation Location) {
+  return Lexer::getLocForEndOfToken(Location, 0, Context.getSourceManager(),
+                                    Context.getLangOpts());
+}
+
+// There are 3 kinds of insertion placements:
+enum class InitializerPlacement {
+  // 1. The fields are inserted after an existing CXXCtorInitializer stored in
+  // Where. This will be the case whenever there is a written initializer before
+  // the fields available.
+  After,
+
+  // 2. The fields are inserted before the first existing initializer stored in
+  // Where.
+  Before,
+
+  // 3. There are no written initializers and the fields will be inserted before
+  // the constructor's body creating a new initializer list including the ':'.
+  New
+};
+
+// An InitializerInsertion contains a list of fields and/or base classes to
+// insert into the initializer list of a constructor. We use this to ensure
+// proper absolute ordering according to the class declaration relative to the
+// (perhaps improper) ordering in the existing initializer list, if any.
+struct IntializerInsertion {
+  IntializerInsertion(InitializerPlacement Placement,
+                      const CXXCtorInitializer *Where)
+      : Placement(Placement), Where(Where) {}
+
+  SourceLocation getLocation(const ASTContext &Context,
+                             const CXXConstructorDecl &Constructor) const {
+    assert((Where != nullptr || Placement == InitializerPlacement::New) &&
+           "Location should be relative to an existing initializer or this "
+           "insertion represents a new initializer list.");
+    SourceLocation Location;
+    switch (Placement) {
+    case InitializerPlacement::New:
+      Location = utils::lexer::getPreviousToken(
+                     Context, Constructor.getBody()->getLocStart())
+                     .getLocation();
+      break;
+    case InitializerPlacement::Before:
+      Location = utils::lexer::getPreviousToken(
+                     Context, Where->getSourceRange().getBegin())
+                     .getLocation();
+      break;
+    case InitializerPlacement::After:
+      Location = Where->getRParenLoc();
+      break;
+    }
+    return getLocationForEndOfToken(Context, Location);
+  }
+
+  std::string codeToInsert() const {
+    assert(!Initializers.empty() && "No initializers to insert");
+    std::string Code;
+    llvm::raw_string_ostream Stream(Code);
+    std::string joined =
+        llvm::join(Initializers.begin(), Initializers.end(), "(), ");
+    switch (Placement) {
+    case InitializerPlacement::New:
+      Stream << " : " << joined << "()";
+      break;
+    case InitializerPlacement::Before:
+      Stream << " " << joined << "(),";
+      break;
+    case InitializerPlacement::After:
+      Stream << ", " << joined << "()";
+      break;
+    }
+    return Stream.str();
+  }
+
+  InitializerPlacement Placement;
+  const CXXCtorInitializer *Where;
+  SmallVector<std::string, 4> Initializers;
+};
+
+// Convenience utility to get a RecordDecl from a QualType.
+const RecordDecl *getCanonicalRecordDecl(const QualType &Type) {
+  if (const auto *RT = Type.getCanonicalType()->getAs<RecordType>())
+    return RT->getDecl();
+  return nullptr;
+}
+
+template <typename R, typename T>
+SmallVector<IntializerInsertion, 16>
+computeInsertions(const CXXConstructorDecl::init_const_range &Inits,
+                  const R &OrderedDecls,
+                  const SmallPtrSetImpl<const T *> &DeclsToInit) {
+  SmallVector<IntializerInsertion, 16> Insertions;
+  Insertions.emplace_back(InitializerPlacement::New, nullptr);
+
+  typename R::const_iterator Decl = std::begin(OrderedDecls);
+  for (const CXXCtorInitializer *Init : Inits) {
+    if (Init->isWritten()) {
+      if (Insertions.size() == 1)
+        Insertions.emplace_back(InitializerPlacement::Before, Init);
+
+      // Gets either the field or base class being initialized by the provided
+      // initializer.
+      const auto *InitDecl =
+          Init->isAnyMemberInitializer()
+              ? static_cast<const NamedDecl *>(Init->getAnyMember())
+              : Init->getBaseClass()->getAsCXXRecordDecl();
+
+      // Add all fields between current field up until the next intializer.
+      for (; Decl != std::end(OrderedDecls) && *Decl != InitDecl; ++Decl) {
+        if (const auto *D = dyn_cast<T>(*Decl)) {
+          if (DeclsToInit.count(D) > 0)
+            Insertions.back().Initializers.emplace_back(getName(D));
+        }
+      }
+
+      Insertions.emplace_back(InitializerPlacement::After, Init);
+    }
+  }
+
+  // Add remaining decls that require initialization.
+  for (; Decl != std::end(OrderedDecls); ++Decl) {
+    if (const auto *D = dyn_cast<T>(*Decl)) {
+      if (DeclsToInit.count(D) > 0)
+        Insertions.back().Initializers.emplace_back(getName(D));
+    }
+  }
+  return Insertions;
+}
+
+// Gets the list of bases and members that could possibly be initialized, in
+// order as they appear in the class declaration.
+void getInitializationsInOrder(const CXXRecordDecl &ClassDecl,
+                               SmallVectorImpl<const NamedDecl *> &Decls) {
+  Decls.clear();
+  for (const auto &Base : ClassDecl.bases()) {
+    // Decl may be null if the base class is a template parameter.
+    if (const NamedDecl *Decl = getCanonicalRecordDecl(Base.getType())) {
+      Decls.emplace_back(Decl);
+    }
+  }
+  forEachField(ClassDecl, ClassDecl.fields(),
+               [&](const FieldDecl *F) { Decls.push_back(F); });
+}
+
+template <typename T>
+void fixInitializerList(const ASTContext &Context, DiagnosticBuilder &Diag,
+                        const CXXConstructorDecl *Ctor,
+                        const SmallPtrSetImpl<const T *> &DeclsToInit) {
+  // Do not propose fixes in macros since we cannot place them correctly.
+  if (Ctor->getLocStart().isMacroID())
+    return;
+
+  SmallVector<const NamedDecl *, 16> OrderedDecls;
+  getInitializationsInOrder(*Ctor->getParent(), OrderedDecls);
+
+  for (const auto &Insertion :
+       computeInsertions(Ctor->inits(), OrderedDecls, DeclsToInit)) {
+    if (!Insertion.Initializers.empty())
+      Diag << FixItHint::CreateInsertion(Insertion.getLocation(Context, *Ctor),
+                                         Insertion.codeToInsert());
+  }
+}
+
+} // anonymous namespace
+
+ProTypeMemberInitCheck::ProTypeMemberInitCheck(StringRef Name,
+                                               ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      IgnoreArrays(Options.get("IgnoreArrays", false)) {}
+
+void ProTypeMemberInitCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  auto IsUserProvidedNonDelegatingConstructor =
+      allOf(isUserProvided(),
+            unless(anyOf(isInstantiated(), isDelegatingConstructor())));
+  auto IsNonTrivialDefaultConstructor = allOf(
+      isDefaultConstructor(), unless(isUserProvided()),
+      hasParent(cxxRecordDecl(unless(isTriviallyDefaultConstructible()))));
+  Finder->addMatcher(
+      cxxConstructorDecl(isDefinition(),
+                         anyOf(IsUserProvidedNonDelegatingConstructor,
+                               IsNonTrivialDefaultConstructor))
+          .bind("ctor"),
+      this);
+
+  // Match classes with a default constructor that is defaulted or is not in the
+  // AST.
+  Finder->addMatcher(
+      cxxRecordDecl(
+          isDefinition(), unless(isInstantiated()), hasDefaultConstructor(),
+          anyOf(has(cxxConstructorDecl(isDefaultConstructor(), isDefaulted(),
+                                       unless(isImplicit()))),
+                unless(has(cxxConstructorDecl()))),
+          unless(isTriviallyDefaultConstructible()))
+          .bind("record"),
+      this);
+
+  auto HasDefaultConstructor = hasInitializer(
+      cxxConstructExpr(unless(requiresZeroInitialization()),
+                       hasDeclaration(cxxConstructorDecl(
+                           isDefaultConstructor(), unless(isUserProvided())))));
+  Finder->addMatcher(
+      varDecl(isDefinition(), HasDefaultConstructor,
+              hasAutomaticStorageDuration(),
+              hasType(recordDecl(has(fieldDecl()),
+                                 isTriviallyDefaultConstructible())))
+          .bind("var"),
+      this);
+}
+
+void ProTypeMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor")) {
+    // Skip declarations delayed by late template parsing without a body.
+    if (!Ctor->getBody())
+      return;
+    checkMissingMemberInitializer(*Result.Context, *Ctor->getParent(), Ctor);
+    checkMissingBaseClassInitializer(*Result.Context, *Ctor->getParent(), Ctor);
+  } else if (const auto *Record =
+                 Result.Nodes.getNodeAs<CXXRecordDecl>("record")) {
+    assert(Record->hasDefaultConstructor() &&
+           "Matched record should have a default constructor");
+    checkMissingMemberInitializer(*Result.Context, *Record, nullptr);
+    checkMissingBaseClassInitializer(*Result.Context, *Record, nullptr);
+  } else if (const auto *Var = Result.Nodes.getNodeAs<VarDecl>("var")) {
+    checkUninitializedTrivialType(*Result.Context, Var);
+  }
+}
+
+void ProTypeMemberInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IgnoreArrays", IgnoreArrays);
+}
+
+// FIXME: Copied from clang/lib/Sema/SemaDeclCXX.cpp.
+static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) {
+  if (T->isIncompleteArrayType())
+    return true;
+
+  while (const ConstantArrayType *ArrayT = Context.getAsConstantArrayType(T)) {
+    if (!ArrayT->getSize())
+      return true;
+
+    T = ArrayT->getElementType();
+  }
+
+  return false;
+}
+
+static bool isEmpty(ASTContext &Context, const QualType &Type) {
+  if (const CXXRecordDecl *ClassDecl = Type->getAsCXXRecordDecl()) {
+    return ClassDecl->isEmpty();
+  }
+  return isIncompleteOrZeroLengthArrayType(Context, Type);
+}
+
+void ProTypeMemberInitCheck::checkMissingMemberInitializer(
+    ASTContext &Context, const CXXRecordDecl &ClassDecl,
+    const CXXConstructorDecl *Ctor) {
+  bool IsUnion = ClassDecl.isUnion();
+
+  if (IsUnion && ClassDecl.hasInClassInitializer())
+    return;
+
+  // Gather all fields (direct and indirect) that need to be initialized.
+  SmallPtrSet<const FieldDecl *, 16> FieldsToInit;
+  forEachField(ClassDecl, ClassDecl.fields(), [&](const FieldDecl *F) {
+    if (!F->hasInClassInitializer() &&
+        utils::type_traits::isTriviallyDefaultConstructible(F->getType(),
+                                                            Context) &&
+        !isEmpty(Context, F->getType()) && !F->isUnnamedBitfield())
+      FieldsToInit.insert(F);
+  });
+  if (FieldsToInit.empty())
+    return;
+
+  if (Ctor) {
+    for (const CXXCtorInitializer *Init : Ctor->inits()) {
+      // Remove any fields that were explicitly written in the initializer list
+      // or in-class.
+      if (Init->isAnyMemberInitializer() && Init->isWritten()) {
+        if (IsUnion)
+          return; // We can only initialize one member of a union.
+        FieldsToInit.erase(Init->getAnyMember());
+      }
+    }
+    removeFieldsInitializedInBody(*Ctor->getBody(), Context, FieldsToInit);
+  }
+
+  // Collect all fields in order, both direct fields and indirect fields from
+  // anonmyous record types.
+  SmallVector<const FieldDecl *, 16> OrderedFields;
+  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,
+               [&](const FieldDecl *F) { AllFieldsToInit.insert(F); });
+  if (AllFieldsToInit.empty())
+    return;
+
+  DiagnosticBuilder Diag =
+      diag(Ctor ? Ctor->getLocStart() : ClassDecl.getLocation(),
+           IsUnion
+               ? "union constructor should initialize one of these fields: %0"
+               : "constructor does not initialize these fields: %0")
+      << toCommaSeparatedString(OrderedFields, AllFieldsToInit);
+
+  // Do not propose fixes for constructors in macros since we cannot place them
+  // correctly.
+  if (Ctor && Ctor->getLocStart().isMacroID())
+    return;
+
+  // 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;
+  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 until C++2a.
+    if (F->getType()->isEnumeralType() ||
+        (!getLangOpts().CPlusPlus2a && F->isBitField()))
+      return;
+    if (!F->getParent()->isUnion() || UnionsSeen.insert(F->getParent()).second)
+      FieldsToFix.insert(F);
+  });
+  if (FieldsToFix.empty())
+    return;
+
+  // Use in-class initialization if possible.
+  if (Context.getLangOpts().CPlusPlus11) {
+    for (const FieldDecl *Field : FieldsToFix) {
+      Diag << FixItHint::CreateInsertion(
+          getLocationForEndOfToken(Context, Field->getSourceRange().getEnd()),
+          "{}");
+    }
+  } else if (Ctor) {
+    // Otherwise, rewrite the constructor's initializer list.
+    fixInitializerList(Context, Diag, Ctor, FieldsToFix);
+  }
+}
+
+void ProTypeMemberInitCheck::checkMissingBaseClassInitializer(
+    const ASTContext &Context, const CXXRecordDecl &ClassDecl,
+    const CXXConstructorDecl *Ctor) {
+
+  // Gather any base classes that need to be initialized.
+  SmallVector<const RecordDecl *, 4> AllBases;
+  SmallPtrSet<const RecordDecl *, 4> BasesToInit;
+  for (const CXXBaseSpecifier &Base : ClassDecl.bases()) {
+    if (const auto *BaseClassDecl = getCanonicalRecordDecl(Base.getType())) {
+      AllBases.emplace_back(BaseClassDecl);
+      if (!BaseClassDecl->field_empty() &&
+          utils::type_traits::isTriviallyDefaultConstructible(Base.getType(),
+                                                              Context))
+        BasesToInit.insert(BaseClassDecl);
+    }
+  }
+
+  if (BasesToInit.empty())
+    return;
+
+  // 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());
+    }
+  }
+
+  if (BasesToInit.empty())
+    return;
+
+  DiagnosticBuilder Diag =
+      diag(Ctor ? Ctor->getLocStart() : ClassDecl.getLocation(),
+           "constructor does not initialize these bases: %0")
+      << toCommaSeparatedString(AllBases, BasesToInit);
+
+  if (Ctor)
+    fixInitializerList(Context, Diag, Ctor, BasesToInit);
+}
+
+void ProTypeMemberInitCheck::checkUninitializedTrivialType(
+    const ASTContext &Context, const VarDecl *Var) {
+  DiagnosticBuilder Diag =
+      diag(Var->getLocStart(), "uninitialized record type: %0") << Var;
+
+  Diag << FixItHint::CreateInsertion(
+      getLocationForEndOfToken(Context, Var->getSourceRange().getEnd()),
+      Context.getLangOpts().CPlusPlus11 ? "{}" : " = {}");
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h
new file mode 100644
index 0000000..20d3f60
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h
@@ -0,0 +1,74 @@
+//===--- ProTypeMemberInitCheck.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_PRO_TYPE_MEMBER_INIT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_MEMBER_INIT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// \brief Implements C++ Core Guidelines Type.6.
+///
+/// Checks that every user-provided constructor value-initializes all class
+/// members and base classes that would have undefined behavior otherwise. Also
+/// check that any record types without user-provided default constructors are
+/// value-initialized where used.
+///
+/// Members initialized through function calls in the body of the constructor
+/// will result in false positives.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.html
+/// TODO: See if 'fixes' for false positives are optimized away by the compiler.
+/// TODO: For classes with multiple constructors, make sure that we don't offer
+///     multiple in-class initializer fixits for the same  member.
+class ProTypeMemberInitCheck : public ClangTidyCheck {
+public:
+  ProTypeMemberInitCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  // Checks Type.6 part 1:
+  // Issue a diagnostic for any constructor of a non-trivially-constructible
+  // type that does not initialize all member variables.
+  //
+  // To fix: Write a data member initializer, or mention it in the member
+  // initializer list.
+  void checkMissingMemberInitializer(ASTContext &Context,
+                                     const CXXRecordDecl &ClassDecl,
+                                     const CXXConstructorDecl *Ctor);
+
+  // A subtle side effect of Type.6 part 2:
+  // Make sure to initialize trivially constructible base classes.
+  void checkMissingBaseClassInitializer(const ASTContext &Context,
+                                        const CXXRecordDecl &ClassDecl,
+                                        const CXXConstructorDecl *Ctor);
+
+  // Checks Type.6 part 2:
+  // Issue a diagnostic when constructing an object of a trivially constructible
+  // type without () or {} to initialize its members.
+  //
+  // To fix: Add () or {}.
+  void checkUninitializedTrivialType(const ASTContext &Context,
+                                     const VarDecl *Var);
+
+  // Whether arrays need to be initialized or not. Default is false.
+  bool IgnoreArrays;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_MEMBER_INIT_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.cpp
new file mode 100644
index 0000000..e56e638
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.cpp
@@ -0,0 +1,36 @@
+//===--- ProTypeReinterpretCastCheck.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 "ProTypeReinterpretCastCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+void ProTypeReinterpretCastCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(cxxReinterpretCastExpr().bind("cast"), this);
+}
+
+void ProTypeReinterpretCastCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *MatchedCast =
+      Result.Nodes.getNodeAs<CXXReinterpretCastExpr>("cast");
+  diag(MatchedCast->getOperatorLoc(), "do not use reinterpret_cast");
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.h
new file mode 100644
index 0000000..9610546
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.h
@@ -0,0 +1,35 @@
+//===--- ProTypeReinterpretCast.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_PRO_TYPE_REINTERPRETCAST_CHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_REINTERPRETCAST_CHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// Flags all occurrences of reinterpret_cast
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-pro-type-reinterpret-cast.html
+class ProTypeReinterpretCastCheck : public ClangTidyCheck {
+public:
+  ProTypeReinterpretCastCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_REINTERPRETCAST_CHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.cpp
new file mode 100644
index 0000000..f43e4fa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.cpp
@@ -0,0 +1,55 @@
+//===--- ProTypeStaticCastDowncastCheck.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 "ProTypeStaticCastDowncastCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+void ProTypeStaticCastDowncastCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(
+      cxxStaticCastExpr(unless(isInTemplateInstantiation())).bind("cast"),
+      this);
+}
+
+void ProTypeStaticCastDowncastCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *MatchedCast = Result.Nodes.getNodeAs<CXXStaticCastExpr>("cast");
+  if (MatchedCast->getCastKind() != CK_BaseToDerived)
+    return;
+
+  QualType SourceType = MatchedCast->getSubExpr()->getType();
+  const auto *SourceDecl = SourceType->getPointeeCXXRecordDecl();
+  if (!SourceDecl) // The cast is from object to reference
+    SourceDecl = SourceType->getAsCXXRecordDecl();
+  if (!SourceDecl)
+    return;
+
+  if (SourceDecl->isPolymorphic())
+    diag(MatchedCast->getOperatorLoc(),
+         "do not use static_cast to downcast from a base to a derived class; "
+         "use dynamic_cast instead")
+        << FixItHint::CreateReplacement(MatchedCast->getOperatorLoc(),
+                                        "dynamic_cast");
+  else
+    diag(MatchedCast->getOperatorLoc(),
+         "do not use static_cast to downcast from a base to a derived class");
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.h
new file mode 100644
index 0000000..b6d76a6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.h
@@ -0,0 +1,36 @@
+//===--- ProTypeStaticCastDowncastCheck.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_PRO_TYPE_STATIC_CAST_DOWNCAST_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_STATIC_CAST_DOWNCAST_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// Checks for usages of static_cast, where a base class is downcasted to a
+/// derived class.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-pro-type-static-cast-downcast.html
+class ProTypeStaticCastDowncastCheck : public ClangTidyCheck {
+public:
+  ProTypeStaticCastDowncastCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_STATIC_CAST_DOWNCAST_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.cpp
new file mode 100644
index 0000000..09752f6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.cpp
@@ -0,0 +1,38 @@
+//===--- ProTypeUnionAccessCheck.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 "ProTypeUnionAccessCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+void ProTypeUnionAccessCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(
+      memberExpr(hasObjectExpression(hasType(recordDecl(isUnion()))))
+          .bind("expr"),
+      this);
+}
+
+void ProTypeUnionAccessCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Matched = Result.Nodes.getNodeAs<MemberExpr>("expr");
+  diag(Matched->getMemberLoc(),
+       "do not access members of unions; use (boost::)variant instead");
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.h
new file mode 100644
index 0000000..fc7dd67
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.h
@@ -0,0 +1,36 @@
+//===--- ProTypeUnionAccessCheck.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_PRO_TYPE_UNION_ACCESS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_UNION_ACCESS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// This check flags all access to members of unions.
+/// Access to a union as a whole (e.g. passing to a function) is not flagged.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-pro-type-union-access.html
+class ProTypeUnionAccessCheck : public ClangTidyCheck {
+public:
+  ProTypeUnionAccessCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_UNION_ACCESS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp
new file mode 100644
index 0000000..56227b2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp
@@ -0,0 +1,76 @@
+//===--- ProTypeVarargCheck.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 "ProTypeVarargCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+const internal::VariadicDynCastAllOfMatcher<Stmt, VAArgExpr> vAArgExpr;
+
+void ProTypeVarargCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(vAArgExpr().bind("va_use"), this);
+
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(isVariadic()))).bind("callvararg"), this);
+}
+
+static bool hasSingleVariadicArgumentWithValue(const CallExpr *C, uint64_t I) {
+  const auto *FDecl = dyn_cast<FunctionDecl>(C->getCalleeDecl());
+  if (!FDecl)
+    return false;
+
+  auto N = FDecl->getNumParams(); // Number of parameters without '...'
+  if (C->getNumArgs() != N + 1)
+    return false; // more/less than one argument passed to '...'
+
+  const auto *IntLit =
+      dyn_cast<IntegerLiteral>(C->getArg(N)->IgnoreParenImpCasts());
+  if (!IntLit)
+    return false;
+
+  if (IntLit->getValue() != I)
+    return false;
+
+  return true;
+}
+
+void ProTypeVarargCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *Matched = Result.Nodes.getNodeAs<CallExpr>("callvararg")) {
+    if (hasSingleVariadicArgumentWithValue(Matched, 0))
+      return;
+    diag(Matched->getExprLoc(), "do not call c-style vararg functions");
+  }
+
+  if (const auto *Matched = Result.Nodes.getNodeAs<Expr>("va_use")) {
+    diag(Matched->getExprLoc(),
+         "do not use va_start/va_arg to define c-style vararg functions; "
+         "use variadic templates instead");
+  }
+
+  if (const auto *Matched = Result.Nodes.getNodeAs<VarDecl>("va_list")) {
+    auto SR = Matched->getSourceRange();
+    if (SR.isInvalid())
+      return; // some implicitly generated builtins take va_list
+    diag(SR.getBegin(), "do not declare variables of type va_list; "
+                        "use variadic templates instead");
+  }
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.h
new file mode 100644
index 0000000..558c856
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.h
@@ -0,0 +1,36 @@
+//===--- ProTypeVarargCheck.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_PRO_TYPE_VARARG_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_VARARG_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// This check flags all calls to c-style variadic functions and all use
+/// of va_arg.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-pro-type-vararg.html
+class ProTypeVarargCheck : public ClangTidyCheck {
+public:
+  ProTypeVarargCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_VARARG_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp
new file mode 100644
index 0000000..53b2f72
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp
@@ -0,0 +1,136 @@
+//===--- SlicingCheck.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 "SlicingCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+void SlicingCheck::registerMatchers(MatchFinder *Finder) {
+  // When we see:
+  //   class B : public A { ... };
+  //   A a;
+  //   B b;
+  //   a = b;
+  // The assignment is OK if:
+  //   - the assignment operator is defined as taking a B as second parameter,
+  //   or
+  //   - B does not define any additional members (either variables or
+  //   overrides) wrt A.
+  //
+  // The same holds for copy ctor calls. This also captures stuff like:
+  //   void f(A a);
+  //   f(b);
+
+  //  Helpers.
+  const auto OfBaseClass = ofClass(cxxRecordDecl().bind("BaseDecl"));
+  const auto IsDerivedFromBaseDecl =
+      cxxRecordDecl(isDerivedFrom(equalsBoundNode("BaseDecl")))
+          .bind("DerivedDecl");
+  const auto HasTypeDerivedFromBaseDecl =
+      anyOf(hasType(IsDerivedFromBaseDecl),
+            hasType(references(IsDerivedFromBaseDecl)));
+  const auto IsWithinDerivedCtor =
+      hasParent(cxxConstructorDecl(ofClass(equalsBoundNode("DerivedDecl"))));
+
+  // Assignement slicing: "a = b;" and "a = std::move(b);" variants.
+  const auto SlicesObjectInAssignment =
+      callExpr(callee(cxxMethodDecl(anyOf(isCopyAssignmentOperator(),
+                                          isMoveAssignmentOperator()),
+                                    OfBaseClass)),
+               hasArgument(1, HasTypeDerivedFromBaseDecl));
+
+  // Construction slicing: "A a{b};" and "f(b);" variants. Note that in case of
+  // slicing the letter will create a temporary and therefore call a ctor.
+  const auto SlicesObjectInCtor = cxxConstructExpr(
+      hasDeclaration(cxxConstructorDecl(
+          anyOf(isCopyConstructor(), isMoveConstructor()), OfBaseClass)),
+      hasArgument(0, HasTypeDerivedFromBaseDecl),
+      // We need to disable matching on the call to the base copy/move
+      // constructor in DerivedDecl's constructors.
+      unless(IsWithinDerivedCtor));
+
+  Finder->addMatcher(
+      expr(anyOf(SlicesObjectInAssignment, SlicesObjectInCtor)).bind("Call"),
+      this);
+}
+
+/// Warns on methods overridden in DerivedDecl with respect to BaseDecl.
+/// FIXME: this warns on all overrides outside of the sliced path in case of
+/// multiple inheritance.
+void SlicingCheck::DiagnoseSlicedOverriddenMethods(
+    const Expr &Call, const CXXRecordDecl &DerivedDecl,
+    const CXXRecordDecl &BaseDecl) {
+  if (DerivedDecl.getCanonicalDecl() == BaseDecl.getCanonicalDecl())
+    return;
+  for (const auto &Method : DerivedDecl.methods()) {
+    // Virtual destructors are OK. We're ignoring constructors since they are
+    // tagged as overrides.
+    if (isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method))
+      continue;
+    if (Method->size_overridden_methods() > 0) {
+      diag(Call.getExprLoc(),
+           "slicing object from type %0 to %1 discards override %2")
+          << &DerivedDecl << &BaseDecl << Method;
+    }
+  }
+  // Recursively process bases.
+  for (const auto &Base : DerivedDecl.bases()) {
+    if (const auto *BaseRecordType = Base.getType()->getAs<RecordType>()) {
+      if (const auto *BaseRecord = cast_or_null<CXXRecordDecl>(
+              BaseRecordType->getDecl()->getDefinition()))
+        DiagnoseSlicedOverriddenMethods(Call, *BaseRecord, BaseDecl);
+    }
+  }
+}
+
+void SlicingCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *BaseDecl = Result.Nodes.getNodeAs<CXXRecordDecl>("BaseDecl");
+  const auto *DerivedDecl =
+      Result.Nodes.getNodeAs<CXXRecordDecl>("DerivedDecl");
+  const auto *Call = Result.Nodes.getNodeAs<Expr>("Call");
+  assert(BaseDecl != nullptr);
+  assert(DerivedDecl != nullptr);
+  assert(Call != nullptr);
+
+  // Warn when slicing the vtable.
+  // We're looking through all the methods in the derived class and see if they
+  // override some methods in the base class.
+  // It's not enough to just test whether the class is polymorphic because we
+  // would be fine slicing B to A if no method in B (or its bases) overrides
+  // anything in A:
+  //   class A { virtual void f(); };
+  //   class B : public A {};
+  // because in that case calling A::f is the same as calling B::f.
+  DiagnoseSlicedOverriddenMethods(*Call, *DerivedDecl, *BaseDecl);
+
+  // Warn when slicing member variables.
+  const auto &BaseLayout =
+      BaseDecl->getASTContext().getASTRecordLayout(BaseDecl);
+  const auto &DerivedLayout =
+      DerivedDecl->getASTContext().getASTRecordLayout(DerivedDecl);
+  const CharUnits StateSize =
+      DerivedLayout.getDataSize() - BaseLayout.getDataSize();
+  if (StateSize.isPositive()) {
+    diag(Call->getExprLoc(), "slicing object from type %0 to %1 discards "
+                             "%2 bytes of state")
+        << DerivedDecl << BaseDecl << static_cast<int>(StateSize.getQuantity());
+  }
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.h
new file mode 100644
index 0000000..9ee91bc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.h
@@ -0,0 +1,45 @@
+//===--- SlicingCheck.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_SLICING_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SLICING_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// Flags slicing (incomplete copying of an object's state) of member variables
+/// or vtable. See:
+///   - https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es63-dont-slice
+///     for the former, and
+///   - https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c145-access-polymorphic-objects-through-pointers-and-references
+///     for the latter
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-slicing.html
+class SlicingCheck : public ClangTidyCheck {
+public:
+  SlicingCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void DiagnoseSlicedOverriddenMethods(const Expr &call,
+                                       const CXXRecordDecl &DerivedDecl,
+                                       const CXXRecordDecl &BaseDecl);
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SLICING_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp
new file mode 100644
index 0000000..df3c279
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp
@@ -0,0 +1,191 @@
+//===--- SpecialMemberFunctionsCheck.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 "SpecialMemberFunctionsCheck.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/StringExtras.h"
+
+#define DEBUG_TYPE "clang-tidy"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+SpecialMemberFunctionsCheck::SpecialMemberFunctionsCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      AllowMissingMoveFunctions(Options.get("AllowMissingMoveFunctions", 0)),
+      AllowSoleDefaultDtor(Options.get("AllowSoleDefaultDtor", 0)) {}
+
+void SpecialMemberFunctionsCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "AllowMissingMoveFunctions", AllowMissingMoveFunctions);
+  Options.store(Opts, "AllowSoleDefaultDtor", AllowSoleDefaultDtor);
+}
+
+void SpecialMemberFunctionsCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+  Finder->addMatcher(
+      cxxRecordDecl(
+          eachOf(
+              has(cxxDestructorDecl(unless(isImplicit())).bind("dtor")),
+              has(cxxConstructorDecl(isCopyConstructor(), unless(isImplicit()))
+                      .bind("copy-ctor")),
+              has(cxxMethodDecl(isCopyAssignmentOperator(),
+                                unless(isImplicit()))
+                      .bind("copy-assign")),
+              has(cxxConstructorDecl(isMoveConstructor(), unless(isImplicit()))
+                      .bind("move-ctor")),
+              has(cxxMethodDecl(isMoveAssignmentOperator(),
+                                unless(isImplicit()))
+                      .bind("move-assign"))))
+          .bind("class-def"),
+      this);
+}
+
+static llvm::StringRef
+toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K) {
+  switch (K) {
+  case SpecialMemberFunctionsCheck::SpecialMemberFunctionKind::Destructor:
+    return "a destructor";
+  case SpecialMemberFunctionsCheck::SpecialMemberFunctionKind::
+      DefaultDestructor:
+    return "a default destructor";
+  case SpecialMemberFunctionsCheck::SpecialMemberFunctionKind::
+      NonDefaultDestructor:
+    return "a non-default destructor";
+  case SpecialMemberFunctionsCheck::SpecialMemberFunctionKind::CopyConstructor:
+    return "a copy constructor";
+  case SpecialMemberFunctionsCheck::SpecialMemberFunctionKind::CopyAssignment:
+    return "a copy assignment operator";
+  case SpecialMemberFunctionsCheck::SpecialMemberFunctionKind::MoveConstructor:
+    return "a move constructor";
+  case SpecialMemberFunctionsCheck::SpecialMemberFunctionKind::MoveAssignment:
+    return "a move assignment operator";
+  }
+  llvm_unreachable("Unhandled SpecialMemberFunctionKind");
+}
+
+static std::string
+join(ArrayRef<SpecialMemberFunctionsCheck::SpecialMemberFunctionKind> SMFS,
+     llvm::StringRef AndOr) {
+
+  assert(!SMFS.empty() &&
+         "List of defined or undefined members should never be empty.");
+  std::string Buffer;
+  llvm::raw_string_ostream Stream(Buffer);
+
+  Stream << toString(SMFS[0]);
+  size_t LastIndex = SMFS.size() - 1;
+  for (size_t i = 1; i < LastIndex; ++i) {
+    Stream << ", " << toString(SMFS[i]);
+  }
+  if (LastIndex != 0) {
+    Stream << AndOr << toString(SMFS[LastIndex]);
+  }
+  return Stream.str();
+}
+
+void SpecialMemberFunctionsCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<CXXRecordDecl>("class-def");
+  if (!MatchedDecl)
+    return;
+
+  ClassDefId ID(MatchedDecl->getLocation(), MatchedDecl->getName());
+
+  auto StoreMember = [this, &ID](SpecialMemberFunctionKind Kind) {
+    llvm::SmallVectorImpl<SpecialMemberFunctionKind> &Members =
+        ClassWithSpecialMembers[ID];
+    if (!llvm::is_contained(Members, Kind))
+      Members.push_back(Kind);
+  };
+
+  if (const auto *Dtor = Result.Nodes.getNodeAs<CXXMethodDecl>("dtor")) {
+    StoreMember(Dtor->isDefaulted()
+                    ? SpecialMemberFunctionKind::DefaultDestructor
+                    : SpecialMemberFunctionKind::NonDefaultDestructor);
+  }
+
+  std::initializer_list<std::pair<std::string, SpecialMemberFunctionKind>>
+      Matchers = {{"copy-ctor", SpecialMemberFunctionKind::CopyConstructor},
+                  {"copy-assign", SpecialMemberFunctionKind::CopyAssignment},
+                  {"move-ctor", SpecialMemberFunctionKind::MoveConstructor},
+                  {"move-assign", SpecialMemberFunctionKind::MoveAssignment}};
+
+  for (const auto &KV : Matchers)
+    if (Result.Nodes.getNodeAs<CXXMethodDecl>(KV.first)) {
+      StoreMember(KV.second);
+    }
+}
+
+void SpecialMemberFunctionsCheck::onEndOfTranslationUnit() {
+  for (const auto &C : ClassWithSpecialMembers) {
+    checkForMissingMembers(C.first, C.second);
+  }
+}
+
+void SpecialMemberFunctionsCheck::checkForMissingMembers(
+    const ClassDefId &ID,
+    llvm::ArrayRef<SpecialMemberFunctionKind> DefinedMembers) {
+  llvm::SmallVector<SpecialMemberFunctionKind, 5> MissingMembers;
+
+  auto HasMember = [&](SpecialMemberFunctionKind Kind) {
+    return llvm::is_contained(DefinedMembers, Kind);
+  };
+
+  auto RequireMember = [&](SpecialMemberFunctionKind Kind) {
+    if (!HasMember(Kind))
+      MissingMembers.push_back(Kind);
+  };
+
+  bool RequireThree =
+      HasMember(SpecialMemberFunctionKind::NonDefaultDestructor) ||
+      (!AllowSoleDefaultDtor &&
+       HasMember(SpecialMemberFunctionKind::DefaultDestructor)) ||
+      HasMember(SpecialMemberFunctionKind::CopyConstructor) ||
+      HasMember(SpecialMemberFunctionKind::CopyAssignment) ||
+      HasMember(SpecialMemberFunctionKind::MoveConstructor) ||
+      HasMember(SpecialMemberFunctionKind::MoveAssignment);
+
+  bool RequireFive = (!AllowMissingMoveFunctions && RequireThree &&
+                      getLangOpts().CPlusPlus11) ||
+                     HasMember(SpecialMemberFunctionKind::MoveConstructor) ||
+                     HasMember(SpecialMemberFunctionKind::MoveAssignment);
+
+  if (RequireThree) {
+    if (!HasMember(SpecialMemberFunctionKind::DefaultDestructor) &&
+        !HasMember(SpecialMemberFunctionKind::NonDefaultDestructor))
+      MissingMembers.push_back(SpecialMemberFunctionKind::Destructor);
+
+    RequireMember(SpecialMemberFunctionKind::CopyConstructor);
+    RequireMember(SpecialMemberFunctionKind::CopyAssignment);
+  }
+
+  if (RequireFive) {
+    assert(RequireThree);
+    RequireMember(SpecialMemberFunctionKind::MoveConstructor);
+    RequireMember(SpecialMemberFunctionKind::MoveAssignment);
+  }
+
+  if (!MissingMembers.empty())
+    diag(ID.first, "class '%0' defines %1 but does not define %2")
+        << ID.second << cppcoreguidelines::join(DefinedMembers, " and ")
+        << cppcoreguidelines::join(MissingMembers, " or ");
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h
new file mode 100644
index 0000000..8ab0c92
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h
@@ -0,0 +1,105 @@
+//===--- SpecialMemberFunctionsCheck.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_SPECIAL_MEMBER_FUNCTIONS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SPECIAL_MEMBER_FUNCTIONS_H
+
+#include "../ClangTidy.h"
+
+#include "llvm/ADT/DenseMapInfo.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// Checks for classes where some, but not all, of the special member functions
+/// are defined.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-special-member-functions.html
+class SpecialMemberFunctionsCheck : public ClangTidyCheck {
+public:
+  SpecialMemberFunctionsCheck(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;
+  void onEndOfTranslationUnit() override;
+
+  enum class SpecialMemberFunctionKind : uint8_t {
+    Destructor,
+    DefaultDestructor,
+    NonDefaultDestructor,
+    CopyConstructor,
+    CopyAssignment,
+    MoveConstructor,
+    MoveAssignment
+  };
+
+  using ClassDefId = std::pair<SourceLocation, std::string>;
+
+  using ClassDefiningSpecialMembersMap =
+      llvm::DenseMap<ClassDefId,
+                     llvm::SmallVector<SpecialMemberFunctionKind, 5>>;
+
+private:
+  void checkForMissingMembers(
+      const ClassDefId &ID,
+      llvm::ArrayRef<SpecialMemberFunctionKind> DefinedSpecialMembers);
+
+  const bool AllowMissingMoveFunctions;
+  const bool AllowSoleDefaultDtor;
+  ClassDefiningSpecialMembersMap ClassWithSpecialMembers;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+namespace llvm {
+/// Specialisation of DenseMapInfo to allow ClassDefId objects in DenseMaps
+/// FIXME: Move this to the corresponding cpp file as is done for
+/// clang-tidy/readability/IdentifierNamingCheck.cpp.
+template <>
+struct DenseMapInfo<
+    clang::tidy::cppcoreguidelines::SpecialMemberFunctionsCheck::ClassDefId> {
+  using ClassDefId =
+      clang::tidy::cppcoreguidelines::SpecialMemberFunctionsCheck::ClassDefId;
+
+  static inline ClassDefId getEmptyKey() {
+    return ClassDefId(
+        clang::SourceLocation::getFromRawEncoding(static_cast<unsigned>(-1)),
+        "EMPTY");
+  }
+
+  static inline ClassDefId getTombstoneKey() {
+    return ClassDefId(
+        clang::SourceLocation::getFromRawEncoding(static_cast<unsigned>(-2)),
+        "TOMBSTONE");
+  }
+
+  static unsigned getHashValue(ClassDefId Val) {
+    assert(Val != getEmptyKey() && "Cannot hash the empty key!");
+    assert(Val != getTombstoneKey() && "Cannot hash the tombstone key!");
+
+    std::hash<ClassDefId::second_type> SecondHash;
+    return Val.first.getRawEncoding() + SecondHash(Val.second);
+  }
+
+  static bool isEqual(const ClassDefId &LHS, const ClassDefId &RHS) {
+    if (RHS == getEmptyKey())
+      return LHS == getEmptyKey();
+    if (RHS == getTombstoneKey())
+      return LHS == getTombstoneKey();
+    return LHS == RHS;
+  }
+};
+
+} // namespace llvm
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SPECIAL_MEMBER_FUNCTIONS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/CMakeLists.txt
new file mode 100644
index 0000000..b69a5c0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/CMakeLists.txt
@@ -0,0 +1,21 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyFuchsiaModule
+  DefaultArgumentsCheck.cpp
+  FuchsiaTidyModule.cpp
+  MultipleInheritanceCheck.cpp
+  OverloadedOperatorCheck.cpp
+  RestrictSystemIncludesCheck.cpp
+  StaticallyConstructedObjectsCheck.cpp
+  TrailingReturnCheck.cpp
+  VirtualInheritanceCheck.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyGoogleModule
+  clangTidyUtils
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/DefaultArgumentsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/DefaultArgumentsCheck.cpp
new file mode 100644
index 0000000..493ce9a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/DefaultArgumentsCheck.cpp
@@ -0,0 +1,64 @@
+//===--- DefaultArgumentsCheck.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 "DefaultArgumentsCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+void DefaultArgumentsCheck::registerMatchers(MatchFinder *Finder) {
+  // Calling a function which uses default arguments is disallowed.
+  Finder->addMatcher(cxxDefaultArgExpr().bind("stmt"), this);
+  // Declaring default parameters is disallowed.
+  Finder->addMatcher(parmVarDecl(hasDefaultArgument()).bind("decl"), this);
+}
+
+void DefaultArgumentsCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *S =
+          Result.Nodes.getNodeAs<CXXDefaultArgExpr>("stmt")) {
+    diag(S->getUsedLocation(),
+         "calling a function that uses a default argument is disallowed");
+    diag(S->getParam()->getLocStart(),
+        "default parameter was declared here",
+         DiagnosticIDs::Note);
+  } else if (const ParmVarDecl *D =
+          Result.Nodes.getNodeAs<ParmVarDecl>("decl")) {
+    SourceRange DefaultArgRange = D->getDefaultArgRange();
+
+    if (DefaultArgRange.getEnd() != D->getLocEnd()) {
+      return;
+    } else if (DefaultArgRange.getBegin().isMacroID()) {
+      diag(D->getLocStart(),
+           "declaring a parameter with a default argument is disallowed");
+    } else {
+      SourceLocation StartLocation = D->getName().empty() ?
+              D->getLocStart() : D->getLocation();
+
+      SourceRange RemovalRange(Lexer::getLocForEndOfToken(
+             StartLocation, 0,
+             *Result.SourceManager,
+             Result.Context->getLangOpts()
+           ),
+           DefaultArgRange.getEnd()
+         );
+
+      diag(D->getLocStart(),
+          "declaring a parameter with a default argument is disallowed")
+          << D
+          << FixItHint::CreateRemoval(RemovalRange);
+    }
+  }
+}
+
+} // namespace fuchsia
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/DefaultArgumentsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/DefaultArgumentsCheck.h
new file mode 100644
index 0000000..f54fd96
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/DefaultArgumentsCheck.h
@@ -0,0 +1,35 @@
+//===--- DefaultArgumentsCheck.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_FUCHSIA_DEFAULT_ARGUMENTS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_DEFAULT_ARGUMENTS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+/// Default arguments are not allowed in declared or called functions.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-default-arguments.html
+class DefaultArgumentsCheck : public ClangTidyCheck {
+public:
+  DefaultArgumentsCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace fuchsia
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_DEFAULT_ARGUMENTS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp
new file mode 100644
index 0000000..0d3bbfe
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp
@@ -0,0 +1,60 @@
+//===--- FuchsiaTidyModule.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 "../google/UnnamedNamespaceInHeaderCheck.h"
+#include "DefaultArgumentsCheck.h"
+#include "MultipleInheritanceCheck.h"
+#include "OverloadedOperatorCheck.h"
+#include "RestrictSystemIncludesCheck.h"
+#include "StaticallyConstructedObjectsCheck.h"
+#include "TrailingReturnCheck.h"
+#include "VirtualInheritanceCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+/// This module is for Fuchsia-specific checks.
+class FuchsiaModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<DefaultArgumentsCheck>(
+        "fuchsia-default-arguments");
+    CheckFactories.registerCheck<google::build::UnnamedNamespaceInHeaderCheck>(
+        "fuchsia-header-anon-namespaces");
+    CheckFactories.registerCheck<MultipleInheritanceCheck>(
+        "fuchsia-multiple-inheritance");
+    CheckFactories.registerCheck<OverloadedOperatorCheck>(
+        "fuchsia-overloaded-operator");
+    CheckFactories.registerCheck<RestrictSystemIncludesCheck>(
+        "fuchsia-restrict-system-includes");
+    CheckFactories.registerCheck<StaticallyConstructedObjectsCheck>(
+        "fuchsia-statically-constructed-objects");
+    CheckFactories.registerCheck<TrailingReturnCheck>(
+        "fuchsia-trailing-return");
+    CheckFactories.registerCheck<VirtualInheritanceCheck>(
+        "fuchsia-virtual-inheritance");
+  }
+};
+// Register the FuchsiaTidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<FuchsiaModule>
+    X("fuchsia-module", "Adds Fuchsia platform checks.");
+} // namespace fuchsia
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the FuchsiaModule.
+volatile int FuchsiaModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp
new file mode 100644
index 0000000..35504c9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp
@@ -0,0 +1,132 @@
+//===--- MultipleInheritanceCheck.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 "MultipleInheritanceCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang;
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+namespace {
+AST_MATCHER(CXXRecordDecl, hasBases) {
+  if (Node.hasDefinition())
+    return Node.getNumBases() > 0;
+  return false;
+}
+} // namespace
+
+// Adds a node (by name) to the interface map, if it was not present in the map
+// previously.
+void MultipleInheritanceCheck::addNodeToInterfaceMap(const CXXRecordDecl *Node,
+                                                     bool isInterface) {
+  assert(Node->getIdentifier());
+  StringRef Name = Node->getIdentifier()->getName();
+  InterfaceMap.insert(std::make_pair(Name, isInterface));
+}
+
+// Returns "true" if the boolean "isInterface" has been set to the
+// interface status of the current Node. Return "false" if the
+// interface status for the current node is not yet known.
+bool MultipleInheritanceCheck::getInterfaceStatus(const CXXRecordDecl *Node,
+                                                  bool &isInterface) const {
+  assert(Node->getIdentifier());
+  StringRef Name = Node->getIdentifier()->getName();
+  llvm::StringMapConstIterator<bool> Pair = InterfaceMap.find(Name);
+  if (Pair == InterfaceMap.end())
+    return false;
+  isInterface = Pair->second;
+  return true;
+}
+
+bool MultipleInheritanceCheck::isCurrentClassInterface(
+    const CXXRecordDecl *Node) const {
+  // Interfaces should have no fields.
+  if (!Node->field_empty()) return false;
+
+  // Interfaces should have exclusively pure methods.
+  return llvm::none_of(Node->methods(), [](const CXXMethodDecl *M) {
+    return M->isUserProvided() && !M->isPure() && !M->isStatic();
+  });
+}
+
+bool MultipleInheritanceCheck::isInterface(const CXXRecordDecl *Node) {
+  if (!Node->getIdentifier())
+    return false;
+
+  // Short circuit the lookup if we have analyzed this record before.
+  bool PreviousIsInterfaceResult;
+  if (getInterfaceStatus(Node, PreviousIsInterfaceResult))
+    return PreviousIsInterfaceResult;
+
+  // To be an interface, all base classes must be interfaces as well.
+  for (const auto &I : Node->bases()) {
+    if (I.isVirtual()) continue;
+    const auto *Ty = I.getType()->getAs<RecordType>();
+    if (!Ty) continue;
+    const RecordDecl *D = Ty->getDecl()->getDefinition();
+    if (!D) continue;
+    const auto *Base = cast<CXXRecordDecl>(D);
+    if (!isInterface(Base)) {
+      addNodeToInterfaceMap(Node, false);
+      return false;
+    }
+  }
+
+  bool CurrentClassIsInterface = isCurrentClassInterface(Node);
+  addNodeToInterfaceMap(Node, CurrentClassIsInterface);
+  return CurrentClassIsInterface;
+}
+
+void MultipleInheritanceCheck::registerMatchers(MatchFinder *Finder) {
+  // Requires C++.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // Match declarations which have bases.
+  Finder->addMatcher(cxxRecordDecl(hasBases()).bind("decl"), this);
+}
+
+void MultipleInheritanceCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *D = Result.Nodes.getNodeAs<CXXRecordDecl>("decl")) {
+    // Check against map to see if if the class inherits from multiple
+    // concrete classes
+    unsigned NumConcrete = 0;
+    for (const auto &I : D->bases()) {
+      if (I.isVirtual()) continue;
+      const auto *Ty = I.getType()->getAs<RecordType>();
+      if (!Ty) continue;
+      const auto *Base = cast<CXXRecordDecl>(Ty->getDecl()->getDefinition());
+      if (!isInterface(Base)) NumConcrete++;
+    }
+    
+    // Check virtual bases to see if there is more than one concrete 
+    // non-virtual base.
+    for (const auto &V : D->vbases()) {
+      const auto *Ty = V.getType()->getAs<RecordType>();
+      if (!Ty) continue;
+      const auto *Base = cast<CXXRecordDecl>(Ty->getDecl()->getDefinition());
+      if (!isInterface(Base)) NumConcrete++;
+    }
+
+    if (NumConcrete > 1) {
+      diag(D->getLocStart(),
+           "inheriting mulitple classes that aren't "
+           "pure virtual is discouraged");
+    }
+  }
+}
+
+}  // namespace fuchsia
+}  // namespace tidy
+}  // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.h
new file mode 100644
index 0000000..6250e3e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.h
@@ -0,0 +1,48 @@
+//===--- MultipleInheritanceCheck.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_FUCHSIA_MULTIPLE_INHERITANCE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_MULTIPLE_INHERITANCE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+/// Mulitple implementation inheritance is discouraged.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-multiple-inheritance.html
+class MultipleInheritanceCheck : public ClangTidyCheck {
+public:
+  MultipleInheritanceCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+  void onEndOfTranslationUnit() override { InterfaceMap.clear(); }
+
+private:
+  void addNodeToInterfaceMap(const CXXRecordDecl *Node, bool isInterface);
+  bool getInterfaceStatus(const CXXRecordDecl *Node, bool &isInterface) const;
+  bool isCurrentClassInterface(const CXXRecordDecl *Node) const;
+  bool isInterface(const CXXRecordDecl *Node);
+
+  // Contains the identity of each named CXXRecord as an interface.  This is
+  // used to memoize lookup speeds and improve performance from O(N^2) to O(N),
+  // where N is the number of classes.
+  llvm::StringMap<bool> InterfaceMap;
+};
+
+} // namespace fuchsia
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_MULTIPLE_INHERITANCE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/OverloadedOperatorCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/OverloadedOperatorCheck.cpp
new file mode 100644
index 0000000..847f763
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/OverloadedOperatorCheck.cpp
@@ -0,0 +1,45 @@
+//===--- OverloadedOperatorCheck.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 "OverloadedOperatorCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+namespace {
+AST_MATCHER(FunctionDecl, isFuchsiaOverloadedOperator) {
+  if (const auto *CXXMethodNode = dyn_cast<CXXMethodDecl>(&Node)) {
+    if (CXXMethodNode->isCopyAssignmentOperator() ||
+        CXXMethodNode->isMoveAssignmentOperator())
+      return false;
+  }
+  return Node.isOverloadedOperator();
+}
+} // namespace
+
+void OverloadedOperatorCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(functionDecl(isFuchsiaOverloadedOperator()).bind("decl"),
+                     this);
+}
+
+void OverloadedOperatorCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *D = Result.Nodes.getNodeAs<FunctionDecl>("decl");
+  assert(D && "No FunctionDecl captured!");
+  
+  SourceLocation Loc = D->getLocStart();
+  if (Loc.isValid())
+    diag(Loc, "overloading %0 is disallowed") << D;
+}
+
+} // namespace fuchsia
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/OverloadedOperatorCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/OverloadedOperatorCheck.h
new file mode 100644
index 0000000..a22e5ae
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/OverloadedOperatorCheck.h
@@ -0,0 +1,35 @@
+//===--- OverloadedOperatorCheck.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_FUCHSIA_OVERLOADED_OPERATOR_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_OVERLOADED_OPERATOR_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+/// Overloading operators is disallowed by the Fuchsia coding standard.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-overloaded-operator.html
+class OverloadedOperatorCheck : public ClangTidyCheck {
+public:
+  OverloadedOperatorCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace fuchsia
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_OVERLOADED_OPERATOR_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.cpp
new file mode 100644
index 0000000..4817e90
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.cpp
@@ -0,0 +1,118 @@
+//===--- RestrictSystemIncludesCheck.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 "RestrictSystemIncludesCheck.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Path.h"
+#include <cstring>
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+class RestrictedIncludesPPCallbacks : public PPCallbacks {
+public:
+  explicit RestrictedIncludesPPCallbacks(RestrictSystemIncludesCheck &Check,
+                                         SourceManager &SM)
+      : Check(Check), SM(SM) {}
+
+  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+                          StringRef FileName, bool IsAngled,
+                          CharSourceRange FilenameRange, const FileEntry *File,
+                          StringRef SearchPath, StringRef RelativePath,
+                          const Module *Imported,
+                          SrcMgr::CharacteristicKind FileType) override;
+  void EndOfMainFile() override;
+
+private:
+  struct IncludeDirective {
+    IncludeDirective() = default;
+    IncludeDirective(SourceLocation Loc, CharSourceRange Range,
+                     StringRef Filename, StringRef FullPath, bool IsInMainFile)
+        : Loc(Loc), Range(Range), IncludeFile(Filename), IncludePath(FullPath),
+          IsInMainFile(IsInMainFile) {}
+
+    SourceLocation Loc;      // '#' location in the include directive
+    CharSourceRange Range;   // SourceRange for the file name
+    std::string IncludeFile; // Filename as a string
+    std::string IncludePath; // Full file path as a string
+    bool IsInMainFile;       // Whether or not the include is in the main file
+  };
+
+  using FileIncludes = llvm::SmallVector<IncludeDirective, 8>;
+  llvm::SmallDenseMap<FileID, FileIncludes> IncludeDirectives;
+
+  RestrictSystemIncludesCheck &Check;
+  SourceManager &SM;
+};
+
+void RestrictedIncludesPPCallbacks::InclusionDirective(
+    SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
+    bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
+    StringRef SearchPath, StringRef RelativePath, const Module *Imported,
+    SrcMgr::CharacteristicKind FileType) {
+  if (!Check.contains(FileName) && SrcMgr::isSystem(FileType)) {
+    SmallString<256> FullPath;
+    llvm::sys::path::append(FullPath, SearchPath);
+    llvm::sys::path::append(FullPath, RelativePath);
+    // Bucket the allowed include directives by the id of the file they were
+    // declared in.
+    IncludeDirectives[SM.getFileID(HashLoc)].emplace_back(
+        HashLoc, FilenameRange, FileName, FullPath.str(),
+        SM.isInMainFile(HashLoc));
+  }
+}
+
+void RestrictedIncludesPPCallbacks::EndOfMainFile() {
+  for (const auto &Bucket : IncludeDirectives) {
+    const FileIncludes &FileDirectives = Bucket.second;
+
+    // Emit fixits for all restricted includes.
+    for (const auto &Include : FileDirectives) {
+      // Fetch the length of the include statement from the start to just after
+      // the newline, for finding the end (including the newline).
+      unsigned ToLen = std::strcspn(SM.getCharacterData(Include.Loc), "\n") + 1;
+      CharSourceRange ToRange = CharSourceRange::getCharRange(
+          Include.Loc, Include.Loc.getLocWithOffset(ToLen));
+
+      if (!Include.IsInMainFile) {
+        auto D = Check.diag(
+            Include.Loc,
+            "system include %0 not allowed, transitively included from %1");
+        D << Include.IncludeFile << SM.getFilename(Include.Loc);
+        D << FixItHint::CreateRemoval(ToRange);
+        continue;
+      }
+      auto D = Check.diag(Include.Loc, "system include %0 not allowed");
+      D << Include.IncludeFile;
+      D << FixItHint::CreateRemoval(ToRange);
+    }
+  }
+}
+
+void RestrictSystemIncludesCheck::registerPPCallbacks(
+    CompilerInstance &Compiler) {
+  Compiler.getPreprocessor().addPPCallbacks(
+      llvm::make_unique<RestrictedIncludesPPCallbacks>(
+          *this, Compiler.getSourceManager()));
+}
+
+void RestrictSystemIncludesCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "Includes", AllowedIncludes);
+}
+
+} // namespace fuchsia
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h
new file mode 100644
index 0000000..d4e5ac1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h
@@ -0,0 +1,48 @@
+//===--- RestrictSystemIncludesCheck.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_FUCHSIA_RESTRICTINCLUDESSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_RESTRICTINCLUDESSCHECK_H
+
+#include "../ClangTidy.h"
+#include "../ClangTidyDiagnosticConsumer.h"
+#include "../utils/OptionsUtils.h"
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+/// Checks for allowed includes and suggests removal of any others. If no
+/// includes are specified, the check will exit without issuing any warnings.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-restrict-system-includes.html
+class RestrictSystemIncludesCheck : public ClangTidyCheck {
+public:
+  RestrictSystemIncludesCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context),
+        AllowedIncludes(Options.get("Includes", "*")),
+        AllowedIncludesGlobList(AllowedIncludes) {}
+
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  bool contains(StringRef FileName) {
+    return AllowedIncludesGlobList.contains(FileName);
+  }
+
+private:
+  std::string AllowedIncludes;
+  GlobList AllowedIncludesGlobList;
+};
+
+} // namespace fuchsia
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_RESTRICTINCLUDESSCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp
new file mode 100644
index 0000000..16a534b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp
@@ -0,0 +1,60 @@
+//===--- StaticallyConstructedObjectsCheck.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 "StaticallyConstructedObjectsCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+namespace {
+AST_MATCHER(Expr, isConstantInitializer) {
+  return Node.isConstantInitializer(Finder->getASTContext(), false);
+}
+
+AST_MATCHER(VarDecl, isGlobalStatic) {
+  return Node.getStorageDuration() == SD_Static && !Node.isLocalVarDecl();
+}
+} // namespace
+
+void StaticallyConstructedObjectsCheck::registerMatchers(MatchFinder *Finder) {
+  // Constructing global, non-trivial objects with static storage is
+  // disallowed, unless the object is statically initialized with a constexpr 
+  // constructor or has no explicit constructor.
+
+  // Constexpr requires C++11 or later.
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  Finder->addMatcher(
+      varDecl(allOf(
+                  // Match global, statically stored objects...
+                  isGlobalStatic(),
+                  // ... that have C++ constructors...
+                  hasDescendant(cxxConstructExpr(unless(allOf(
+                      // ... unless it is constexpr ...
+                      hasDeclaration(cxxConstructorDecl(isConstexpr())),
+                      // ... and is statically initialized.
+                      isConstantInitializer()))))))
+          .bind("decl"),
+      this);
+}
+
+void StaticallyConstructedObjectsCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  if (const auto *D = Result.Nodes.getNodeAs<VarDecl>("decl"))
+    diag(D->getLocStart(), "static objects are disallowed; if possible, use a "
+                           "constexpr constructor instead");
+}
+
+} // namespace fuchsia
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.h
new file mode 100644
index 0000000..6df9b1c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.h
@@ -0,0 +1,37 @@
+//===--- StaticallyConstructedObjectsCheck.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_FUCHSIA_STATICALLY_CONSTRUCTED_OBJECTS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_STATICALLY_CONSTRUCTED_OBJECTS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+/// Constructing global, non-trivial objects with static storage is
+/// disallowed, unless the object is statically initialized with a constexpr 
+/// constructor or has no explicit constructor.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-statically-constructed-objects.html
+class StaticallyConstructedObjectsCheck : public ClangTidyCheck {
+public:
+  StaticallyConstructedObjectsCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace fuchsia
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_STATICALLY_CONSTRUCTED_OBJECTS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/TrailingReturnCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/TrailingReturnCheck.cpp
new file mode 100644
index 0000000..7af0c9c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/TrailingReturnCheck.cpp
@@ -0,0 +1,52 @@
+//===--- TrailingReturnCheck.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 "TrailingReturnCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchersInternal.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+namespace {
+AST_MATCHER(FunctionDecl, hasTrailingReturn) {
+  return Node.getType()->castAs<FunctionProtoType>()->hasTrailingReturn();
+}
+} // namespace
+
+void TrailingReturnCheck::registerMatchers(MatchFinder *Finder) {
+
+  // Requires C++11 or later.
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  // Functions that have trailing returns are disallowed, except for those
+  // using decltype specifiers and lambda with otherwise unutterable
+  // return types.
+  Finder->addMatcher(
+      functionDecl(allOf(hasTrailingReturn(),
+                         unless(anyOf(returns(decltypeType()),
+                                      hasParent(cxxRecordDecl(isLambda()))))))
+          .bind("decl"),
+      this);
+}
+
+void TrailingReturnCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *D = Result.Nodes.getNodeAs<Decl>("decl"))
+    diag(D->getLocStart(),
+         "a trailing return type is disallowed for this type of declaration");
+}
+
+} // namespace fuchsia
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/TrailingReturnCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/TrailingReturnCheck.h
new file mode 100644
index 0000000..4a16c4e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/TrailingReturnCheck.h
@@ -0,0 +1,37 @@
+//===--- TrailingReturnCheck.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_FUCHSIA_TRAILING_RETURN_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_TRAILING_RETURN_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+/// Functions that have trailing returns are disallowed, except for those 
+/// using decltype specifiers and lambda with otherwise unutterable 
+/// return types.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-trailing-return.html
+class TrailingReturnCheck : public ClangTidyCheck {
+public:
+  TrailingReturnCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace fuchsia
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_TRAILING_RETURN_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.cpp
new file mode 100644
index 0000000..f3da2b6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.cpp
@@ -0,0 +1,43 @@
+//===--- VirtualInheritanceCheck.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 "VirtualInheritanceCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+namespace {
+AST_MATCHER(CXXRecordDecl, hasDirectVirtualBaseClass) {
+  if (!Node.hasDefinition()) return false;
+  if (!Node.getNumVBases()) return false;
+  for (const CXXBaseSpecifier &Base : Node.bases())
+    if (Base.isVirtual()) return true;
+  return false;
+}
+} // namespace
+
+void VirtualInheritanceCheck::registerMatchers(MatchFinder *Finder) {
+  // Defining classes using direct virtual inheritance is disallowed.
+  Finder->addMatcher(cxxRecordDecl(hasDirectVirtualBaseClass()).bind("decl"),
+                     this);
+}
+
+void VirtualInheritanceCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *D = Result.Nodes.getNodeAs<CXXRecordDecl>("decl"))
+    diag(D->getLocStart(), "direct virtual inheritance is disallowed");
+}
+
+}  // namespace fuchsia
+}  // namespace tidy
+}  // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.h
new file mode 100644
index 0000000..b2c84c4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.h
@@ -0,0 +1,35 @@
+//===--- VirtualInheritanceCheck.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_FUCHSIA_VIRTUAL_INHERITANCE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_VIRTUAL_INHERITANCE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+/// Defining classes with virtual inheritance is disallowed.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-virtual-inheritance.html
+class VirtualInheritanceCheck : public ClangTidyCheck {
+ public:
+  VirtualInheritanceCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+}  // namespace fuchsia
+}  // namespace tidy
+}  // namespace clang
+
+#endif  // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_VIRTUAL_INHERITANCE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp
new file mode 100644
index 0000000..4c7c164
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp
@@ -0,0 +1,221 @@
+//===--- AvoidCStyleCastsCheck.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 "AvoidCStyleCastsCheck.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 readability {
+
+void AvoidCStyleCastsCheck::registerMatchers(
+    ast_matchers::MatchFinder *Finder) {
+  Finder->addMatcher(
+      cStyleCastExpr(
+          // Filter out (EnumType)IntegerLiteral construct, which is generated
+          // for non-type template arguments of enum types.
+          // FIXME: Remove this once this is fixed in the AST.
+          unless(hasParent(substNonTypeTemplateParmExpr())),
+          // Avoid matches in template instantiations.
+          unless(isInTemplateInstantiation()))
+          .bind("cast"),
+      this);
+}
+
+static bool needsConstCast(QualType SourceType, QualType DestType) {
+  while ((SourceType->isPointerType() && DestType->isPointerType()) ||
+         (SourceType->isReferenceType() && DestType->isReferenceType())) {
+    SourceType = SourceType->getPointeeType();
+    DestType = DestType->getPointeeType();
+    if (SourceType.isConstQualified() && !DestType.isConstQualified()) {
+      return (SourceType->isPointerType() == DestType->isPointerType()) &&
+             (SourceType->isReferenceType() == DestType->isReferenceType());
+    }
+  }
+  return false;
+}
+
+static bool pointedUnqualifiedTypesAreEqual(QualType T1, QualType T2) {
+  while ((T1->isPointerType() && T2->isPointerType()) ||
+         (T1->isReferenceType() && T2->isReferenceType())) {
+    T1 = T1->getPointeeType();
+    T2 = T2->getPointeeType();
+  }
+  return T1.getUnqualifiedType() == T2.getUnqualifiedType();
+}
+
+void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *CastExpr = Result.Nodes.getNodeAs<CStyleCastExpr>("cast");
+
+  // Ignore casts in macros.
+  if (CastExpr->getExprLoc().isMacroID())
+    return;
+
+  // Casting to void is an idiomatic way to mute "unused variable" and similar
+  // warnings.
+  if (CastExpr->getCastKind() == CK_ToVoid)
+    return;
+
+  auto isFunction = [](QualType T) {
+    T = T.getCanonicalType().getNonReferenceType();
+    return T->isFunctionType() || T->isFunctionPointerType() ||
+           T->isMemberFunctionPointerType();
+  };
+
+  const QualType DestTypeAsWritten =
+      CastExpr->getTypeAsWritten().getUnqualifiedType();
+  const QualType SourceTypeAsWritten =
+      CastExpr->getSubExprAsWritten()->getType().getUnqualifiedType();
+  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);
+
+  if (CastExpr->getCastKind() == CK_NoOp && !FnToFnCast) {
+    // Function pointer/reference casts may be needed to resolve ambiguities in
+    // case of overloaded functions, so detection of redundant casts is trickier
+    // in this case. Don't emit "redundant cast" warnings for function
+    // pointer/reference types.
+    if (SourceTypeAsWritten == DestTypeAsWritten) {
+      diag(CastExpr->getLocStart(), "redundant cast to the same type")
+          << FixItHint::CreateRemoval(ReplaceRange);
+      return;
+    }
+  }
+
+  // The rest of this check is only relevant to C++.
+  // We also disable it for Objective-C++.
+  if (!getLangOpts().CPlusPlus || getLangOpts().ObjC1 || getLangOpts().ObjC2)
+    return;
+  // Ignore code inside extern "C" {} blocks.
+  if (!match(expr(hasAncestor(linkageSpecDecl())), *CastExpr, *Result.Context)
+           .empty())
+    return;
+  // Ignore code in .c files and headers included from them, even if they are
+  // compiled as C++.
+  if (getCurrentMainFile().endswith(".c"))
+    return;
+
+  SourceManager &SM = *Result.SourceManager;
+
+  // Ignore code in .c files #included in other files (which shouldn't be done,
+  // but people still do this for test and other purposes).
+  if (SM.getFilename(SM.getSpellingLoc(CastExpr->getLocStart())).endswith(".c"))
+    return;
+
+  // Leave type spelling exactly as it was (unlike
+  // getTypeAsWritten().getAsString() which would spell enum types 'enum X').
+  StringRef DestTypeString =
+      Lexer::getSourceText(CharSourceRange::getTokenRange(
+                               CastExpr->getLParenLoc().getLocWithOffset(1),
+                               CastExpr->getRParenLoc().getLocWithOffset(-1)),
+                           SM, getLangOpts());
+
+  auto Diag =
+      diag(CastExpr->getLocStart(), "C-style casts are discouraged; use %0");
+
+  auto ReplaceWithCast = [&](std::string CastText) {
+    const Expr *SubExpr = CastExpr->getSubExprAsWritten()->IgnoreImpCasts();
+    if (!isa<ParenExpr>(SubExpr)) {
+      CastText.push_back('(');
+      Diag << FixItHint::CreateInsertion(
+          Lexer::getLocForEndOfToken(SubExpr->getLocEnd(), 0, SM,
+                                     getLangOpts()),
+          ")");
+    }
+    Diag << FixItHint::CreateReplacement(ReplaceRange, CastText);
+  };
+  auto ReplaceWithNamedCast = [&](StringRef CastType) {
+    Diag << CastType;
+    ReplaceWithCast((CastType + "<" + DestTypeString + ">").str());
+  };
+
+  // Suggest appropriate C++ cast. See [expr.cast] for cast notation semantics.
+  switch (CastExpr->getCastKind()) {
+  case CK_FunctionToPointerDecay:
+    ReplaceWithNamedCast("static_cast");
+    return;
+  case CK_ConstructorConversion:
+    if (!CastExpr->getTypeAsWritten().hasQualifiers() &&
+        DestTypeAsWritten->isRecordType() &&
+        !DestTypeAsWritten->isElaboratedTypeSpecifier()) {
+      Diag << "constructor call syntax";
+      // FIXME: Validate DestTypeString, maybe.
+      ReplaceWithCast(DestTypeString.str());
+    } else {
+      ReplaceWithNamedCast("static_cast");
+    }
+    return;
+  case CK_NoOp:
+    if (FnToFnCast) {
+      ReplaceWithNamedCast("static_cast");
+      return;
+    }
+    if (SourceType == DestType) {
+      Diag << "static_cast (if needed, the cast may be redundant)";
+      ReplaceWithCast(("static_cast<" + DestTypeString + ">").str());
+      return;
+    }
+    if (needsConstCast(SourceType, DestType) &&
+        pointedUnqualifiedTypesAreEqual(SourceType, DestType)) {
+      ReplaceWithNamedCast("const_cast");
+      return;
+    }
+    if (DestType->isReferenceType()) {
+      QualType Dest = DestType.getNonReferenceType();
+      QualType Source = SourceType.getNonReferenceType();
+      if (Source == Dest.withConst() ||
+          SourceType.getNonReferenceType() == DestType.getNonReferenceType()) {
+        ReplaceWithNamedCast("const_cast");
+        return;
+      }
+      break;
+    }
+  // FALLTHROUGH
+  case clang::CK_IntegralCast:
+    // Convert integral and no-op casts between builtin types and enums to
+    // static_cast. A cast from enum to integer may be unnecessary, but it's
+    // still retained.
+    if ((SourceType->isBuiltinType() || SourceType->isEnumeralType()) &&
+        (DestType->isBuiltinType() || DestType->isEnumeralType())) {
+      ReplaceWithNamedCast("static_cast");
+      return;
+    }
+    break;
+  case CK_BitCast:
+    // FIXME: Suggest const_cast<...>(reinterpret_cast<...>(...)) replacement.
+    if (!needsConstCast(SourceType, DestType)) {
+      if (SourceType->isVoidPointerType())
+        ReplaceWithNamedCast("static_cast");
+      else
+        ReplaceWithNamedCast("reinterpret_cast");
+      return;
+    }
+    break;
+  default:
+    break;
+  }
+
+  Diag << "static_cast/const_cast/reinterpret_cast";
+}
+
+} // namespace readability
+} // namespace google
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h
new file mode 100644
index 0000000..ea7e34c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h
@@ -0,0 +1,42 @@
+//===--- AvoidCStyleCastsCheck.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_AVOIDCSTYLECASTSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDCSTYLECASTSCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace readability {
+
+/// Finds usages of C-style casts.
+///
+/// https://google.github.io/styleguide/cppguide.html#Casting
+///
+/// Corresponding cpplint.py check name: 'readability/casting'.
+///
+/// This check is similar to `-Wold-style-cast`, but it suggests automated fixes
+/// in some cases. The reported locations should not be different from the
+/// ones generated by `-Wold-style-cast`.
+class AvoidCStyleCastsCheck : public ClangTidyCheck {
+public:
+  AvoidCStyleCastsCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace google
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDCSTYLECASTSCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp
new file mode 100644
index 0000000..aa91ff0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp
@@ -0,0 +1,52 @@
+//===--- AvoidThrowingObjCExceptionCheck.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 "AvoidThrowingObjCExceptionCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace objc {
+
+void AvoidThrowingObjCExceptionCheck::registerMatchers(MatchFinder *Finder) {
+  // this check should only be applied to ObjC sources.
+  if (!getLangOpts().ObjC1 && !getLangOpts().ObjC2) {
+    return;
+  }
+
+  Finder->addMatcher(objcThrowStmt().bind("throwStmt"), this);
+  Finder->addMatcher(
+      objcMessageExpr(anyOf(hasSelector("raise:format:"),
+                            hasSelector("raise:format:arguments:")),
+                      hasReceiverType(asString("NSException")))
+          .bind("raiseException"),
+      this);
+}
+
+void AvoidThrowingObjCExceptionCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *MatchedStmt =
+      Result.Nodes.getNodeAs<ObjCAtThrowStmt>("throwStmt");
+  const auto *MatchedExpr =
+      Result.Nodes.getNodeAs<ObjCMessageExpr>("raiseException");
+  auto SourceLoc = MatchedStmt == nullptr ? MatchedExpr->getSelectorStartLoc()
+                                          : MatchedStmt->getThrowLoc();
+  diag(SourceLoc,
+       "pass in NSError ** instead of throwing exception to indicate "
+       "Objective-C errors");
+}
+
+}  // namespace objc
+}  // namespace google
+}  // namespace tidy
+}  // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.h
new file mode 100644
index 0000000..9498226
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.h
@@ -0,0 +1,39 @@
+//===--- AvoidThrowingObjCExceptionCheck.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_OBJC_AVOID_THROWING_EXCEPTION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_AVOID_THROWING_EXCEPTION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace objc {
+
+/// The check is to find usage of @throw invocation in Objective-C code.
+/// We should avoid using @throw for Objective-C exceptions according to
+/// the Google Objective-C Style Guide.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/google-objc-avoid-throwing-exception.html
+class AvoidThrowingObjCExceptionCheck : public ClangTidyCheck {
+ public:
+  AvoidThrowingObjCExceptionCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+}  // namespace objc
+}  // namespace google
+}  // namespace tidy
+}  // namespace clang
+
+#endif  // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_AVOID_THROWING_EXCEPTION_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/CMakeLists.txt
new file mode 100644
index 0000000..1a7dd87
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/CMakeLists.txt
@@ -0,0 +1,27 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyGoogleModule
+  AvoidCStyleCastsCheck.cpp
+  AvoidThrowingObjCExceptionCheck.cpp
+  DefaultArgumentsCheck.cpp
+  ExplicitConstructorCheck.cpp
+  ExplicitMakePairCheck.cpp
+  GlobalNamesInHeadersCheck.cpp
+  GlobalVariableDeclarationCheck.cpp
+  GoogleTidyModule.cpp
+  IntegerTypesCheck.cpp
+  NonConstReferences.cpp
+  OverloadedUnaryAndCheck.cpp
+  TodoCommentCheck.cpp
+  UnnamedNamespaceInHeaderCheck.cpp
+  UsingNamespaceDirectiveCheck.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyReadabilityModule
+  clangTidyUtils
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.cpp
new file mode 100644
index 0000000..ccbd870
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.cpp
@@ -0,0 +1,36 @@
+//===--- DefaultArgumentsCheck.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 "DefaultArgumentsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace google {
+
+void DefaultArgumentsCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      cxxMethodDecl(anyOf(isOverride(), isVirtual()),
+                    hasAnyParameter(parmVarDecl(hasInitializer(expr()))))
+          .bind("Decl"),
+      this);
+}
+
+void DefaultArgumentsCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<CXXMethodDecl>("Decl");
+  diag(MatchedDecl->getLocation(),
+       "default arguments on virtual or override methods are prohibited");
+}
+
+} // namespace google
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.h
new file mode 100644
index 0000000..1457a09
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.h
@@ -0,0 +1,34 @@
+//===--- DefaultArgumentsCheck.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_DEFAULT_ARGUMENTS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_DEFAULT_ARGUMENTS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+
+/// Checks that default parameters are not given for virtual methods.
+///
+/// See https://google.github.io/styleguide/cppguide.html#Default_Arguments
+class DefaultArgumentsCheck : public ClangTidyCheck {
+public:
+  DefaultArgumentsCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace google
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_DEFAULT_ARGUMENTS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp
new file mode 100644
index 0000000..a03fb56
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp
@@ -0,0 +1,156 @@
+//===--- ExplicitConstructorCheck.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 "ExplicitConstructorCheck.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 {
+
+void ExplicitConstructorCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus)
+    return;
+  Finder->addMatcher(
+      cxxConstructorDecl(unless(anyOf(isImplicit(), // Compiler-generated.
+                                      isDeleted(), isInstantiated())))
+          .bind("ctor"),
+      this);
+  Finder->addMatcher(
+      cxxConversionDecl(unless(anyOf(isExplicit(), // Already marked explicit.
+                                     isImplicit(), // Compiler-generated.
+                                     isDeleted(), isInstantiated())))
+
+          .bind("conversion"),
+      this);
+}
+
+// Looks for the token matching the predicate and returns the range of the found
+// token including trailing whitespace.
+static SourceRange FindToken(const SourceManager &Sources,
+                             const LangOptions &LangOpts,
+                             SourceLocation StartLoc, SourceLocation EndLoc,
+                             bool (*Pred)(const Token &)) {
+  if (StartLoc.isMacroID() || EndLoc.isMacroID())
+    return SourceRange();
+  FileID File = Sources.getFileID(Sources.getSpellingLoc(StartLoc));
+  StringRef Buf = Sources.getBufferData(File);
+  const char *StartChar = Sources.getCharacterData(StartLoc);
+  Lexer Lex(StartLoc, LangOpts, StartChar, StartChar, Buf.end());
+  Lex.SetCommentRetentionState(true);
+  Token Tok;
+  do {
+    Lex.LexFromRawLexer(Tok);
+    if (Pred(Tok)) {
+      Token NextTok;
+      Lex.LexFromRawLexer(NextTok);
+      return SourceRange(Tok.getLocation(), NextTok.getLocation());
+    }
+  } while (Tok.isNot(tok::eof) && Tok.getLocation() < EndLoc);
+
+  return SourceRange();
+}
+
+static bool declIsStdInitializerList(const NamedDecl *D) {
+  // First use the fast getName() method to avoid unnecessary calls to the
+  // slow getQualifiedNameAsString().
+  return D->getName() == "initializer_list" &&
+         D->getQualifiedNameAsString() == "std::initializer_list";
+}
+
+static bool isStdInitializerList(QualType Type) {
+  Type = Type.getCanonicalType();
+  if (const auto *TS = Type->getAs<TemplateSpecializationType>()) {
+    if (const TemplateDecl *TD = TS->getTemplateName().getAsTemplateDecl())
+      return declIsStdInitializerList(TD);
+  }
+  if (const auto *RT = Type->getAs<RecordType>()) {
+    if (const auto *Specialization =
+            dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()))
+      return declIsStdInitializerList(Specialization->getSpecializedTemplate());
+  }
+  return false;
+}
+
+void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) {
+  constexpr char WarningMessage[] =
+      "%0 must be marked explicit to avoid unintentional implicit conversions";
+
+  if (const auto *Conversion =
+      Result.Nodes.getNodeAs<CXXConversionDecl>("conversion")) {
+    if (Conversion->isOutOfLine())
+      return;
+    SourceLocation Loc = Conversion->getLocation();
+    // Ignore all macros until we learn to ignore specific ones (e.g. used in
+    // gmock to define matchers).
+    if (Loc.isMacroID())
+      return;
+    diag(Loc, WarningMessage)
+        << Conversion << FixItHint::CreateInsertion(Loc, "explicit ");
+    return;
+  }
+
+  const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
+  if (Ctor->isOutOfLine() || Ctor->getNumParams() == 0 ||
+      Ctor->getMinRequiredArguments() > 1)
+    return;
+
+  bool takesInitializerList = isStdInitializerList(
+      Ctor->getParamDecl(0)->getType().getNonReferenceType());
+  if (Ctor->isExplicit() &&
+      (Ctor->isCopyOrMoveConstructor() || takesInitializerList)) {
+    auto isKWExplicit = [](const Token &Tok) {
+      return Tok.is(tok::raw_identifier) &&
+             Tok.getRawIdentifier() == "explicit";
+    };
+    SourceRange ExplicitTokenRange =
+        FindToken(*Result.SourceManager, getLangOpts(),
+                  Ctor->getOuterLocStart(), Ctor->getLocEnd(), isKWExplicit);
+    StringRef ConstructorDescription;
+    if (Ctor->isMoveConstructor())
+      ConstructorDescription = "move";
+    else if (Ctor->isCopyConstructor())
+      ConstructorDescription = "copy";
+    else
+      ConstructorDescription = "initializer-list";
+
+    auto Diag = diag(Ctor->getLocation(),
+                     "%0 constructor should not be declared explicit")
+                << ConstructorDescription;
+    if (ExplicitTokenRange.isValid()) {
+      Diag << FixItHint::CreateRemoval(
+          CharSourceRange::getCharRange(ExplicitTokenRange));
+    }
+    return;
+  }
+
+  if (Ctor->isExplicit() || Ctor->isCopyOrMoveConstructor() ||
+      takesInitializerList)
+    return;
+
+  bool SingleArgument =
+      Ctor->getNumParams() == 1 && !Ctor->getParamDecl(0)->isParameterPack();
+  SourceLocation Loc = Ctor->getLocation();
+  diag(Loc, WarningMessage)
+      << (SingleArgument
+              ? "single-argument constructors"
+              : "constructors that are callable with a single argument")
+      << FixItHint::CreateInsertion(Loc, "explicit ");
+}
+
+} // namespace google
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h
new file mode 100644
index 0000000..81e6679
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h
@@ -0,0 +1,34 @@
+//===--- ExplicitConstructorCheck.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_EXPLICITCONSTRUCTORCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_EXPLICITCONSTRUCTORCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+
+/// Checks that all single-argument constructors are explicit.
+///
+/// See https://google.github.io/styleguide/cppguide.html#Explicit_Constructors
+class ExplicitConstructorCheck : public ClangTidyCheck {
+public:
+  ExplicitConstructorCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace google
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_EXPLICITCONSTRUCTORCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/ExplicitMakePairCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/ExplicitMakePairCheck.cpp
new file mode 100644
index 0000000..6c2f0a3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/ExplicitMakePairCheck.cpp
@@ -0,0 +1,78 @@
+//===--- ExplicitMakePairCheck.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 "ExplicitMakePairCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace {
+AST_MATCHER(DeclRefExpr, hasExplicitTemplateArgs) {
+  return Node.hasExplicitTemplateArgs();
+}
+} // namespace
+
+namespace tidy {
+namespace google {
+namespace build {
+
+void ExplicitMakePairCheck::registerMatchers(
+    ast_matchers::MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // Look for std::make_pair with explicit template args. Ignore calls in
+  // templates.
+  Finder->addMatcher(
+      callExpr(unless(isInTemplateInstantiation()),
+               callee(expr(ignoringParenImpCasts(
+                   declRefExpr(hasExplicitTemplateArgs(),
+                               to(functionDecl(hasName("::std::make_pair"))))
+                       .bind("declref")))))
+          .bind("call"),
+      this);
+}
+
+void ExplicitMakePairCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
+  const auto *DeclRef = Result.Nodes.getNodeAs<DeclRefExpr>("declref");
+
+  // Sanity check: The use might have overriden ::std::make_pair.
+  if (Call->getNumArgs() != 2)
+    return;
+
+  const Expr *Arg0 = Call->getArg(0)->IgnoreParenImpCasts();
+  const Expr *Arg1 = Call->getArg(1)->IgnoreParenImpCasts();
+
+  // If types don't match, we suggest replacing with std::pair and explicit
+  // template arguments. Otherwise just remove the template arguments from
+  // make_pair.
+  if (Arg0->getType() != Call->getArg(0)->getType() ||
+      Arg1->getType() != Call->getArg(1)->getType()) {
+    diag(Call->getLocStart(), "for C++11-compatibility, use pair directly")
+        << FixItHint::CreateReplacement(
+               SourceRange(DeclRef->getLocStart(), DeclRef->getLAngleLoc()),
+               "std::pair<");
+  } else {
+    diag(Call->getLocStart(),
+         "for C++11-compatibility, omit template arguments from make_pair")
+        << FixItHint::CreateRemoval(
+               SourceRange(DeclRef->getLAngleLoc(), DeclRef->getRAngleLoc()));
+  }
+}
+
+} // namespace build
+} // namespace google
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/ExplicitMakePairCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/ExplicitMakePairCheck.h
new file mode 100644
index 0000000..a29825f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/ExplicitMakePairCheck.h
@@ -0,0 +1,39 @@
+//===--- ExplicitMakePairCheck.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_EXPLICITMAKEPAIRCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_EXPLICITMAKEPAIRCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace build {
+
+/// Check that `make_pair`'s template arguments are deduced.
+///
+/// G++ 4.6 in C++11 mode fails badly if `make_pair`'s template arguments are
+/// specified explicitly, and such use isn't intended in any case.
+///
+/// Corresponding cpplint.py check name: 'build/explicit_make_pair'.
+class ExplicitMakePairCheck : public ClangTidyCheck {
+public:
+  ExplicitMakePairCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace build
+} // namespace google
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_EXPLICITMAKEPAIRCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp
new file mode 100644
index 0000000..45c5b70
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp
@@ -0,0 +1,80 @@
+//===--- GlobalNamesInHeadersCheck.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 "GlobalNamesInHeadersCheck.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 readability {
+
+GlobalNamesInHeadersCheck::GlobalNamesInHeadersCheck(StringRef Name,
+                                                     ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      RawStringHeaderFileExtensions(Options.getLocalOrGlobal(
+          "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) {
+  if (!utils::parseHeaderFileExtensions(RawStringHeaderFileExtensions,
+                                        HeaderFileExtensions, ',')) {
+    llvm::errs() << "Invalid header file extension: "
+                 << RawStringHeaderFileExtensions << "\n";
+  }
+}
+
+void GlobalNamesInHeadersCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
+}
+
+void GlobalNamesInHeadersCheck::registerMatchers(
+    ast_matchers::MatchFinder *Finder) {
+  Finder->addMatcher(decl(anyOf(usingDecl(), usingDirectiveDecl()),
+                          hasDeclContext(translationUnitDecl()))
+                         .bind("using_decl"),
+                     this);
+}
+
+void GlobalNamesInHeadersCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *D = Result.Nodes.getNodeAs<Decl>("using_decl");
+  // If it comes from a macro, we'll assume it is fine.
+  if (D->getLocStart().isMacroID())
+    return;
+
+  // Ignore if it comes from the "main" file ...
+  if (Result.SourceManager->isInMainFile(
+          Result.SourceManager->getExpansionLoc(D->getLocStart()))) {
+    // unless that file is a header.
+    if (!utils::isSpellingLocInHeaderFile(
+            D->getLocStart(), *Result.SourceManager, HeaderFileExtensions))
+      return;
+  }
+
+  if (const auto *UsingDirective = dyn_cast<UsingDirectiveDecl>(D)) {
+    if (UsingDirective->getNominatedNamespace()->isAnonymousNamespace()) {
+      // Anynoumous namespaces inject a using directive into the AST to import
+      // the names into the containing namespace.
+      // We should not have them in headers, but there is another warning for
+      // that.
+      return;
+    }
+  }
+
+  diag(D->getLocStart(),
+       "using declarations in the global namespace in headers are prohibited");
+}
+
+} // namespace readability
+} // namespace google
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.h
new file mode 100644
index 0000000..79a6e28
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.h
@@ -0,0 +1,47 @@
+//===--- GlobalNamesInHeadersCheck.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_GLOBALNAMESINHEADERSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_GLOBALNAMESINHEADERSCHECK_H
+
+#include "../ClangTidy.h"
+#include "../utils/HeaderFileExtensionsUtils.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace readability {
+
+/// Flag global namespace pollution in header files.
+/// Right now it only triggers on using declarations and directives.
+///
+/// The check supports these options:
+///   - `HeaderFileExtensions`: a comma-separated list of filename extensions
+///     of header files (the filename extensions should not contain "." prefix).
+///     "h" by default.
+///     For extension-less header files, using an empty string or leaving an
+///     empty string between "," if there are other filename extensions.
+class GlobalNamesInHeadersCheck : public ClangTidyCheck {
+public:
+  GlobalNamesInHeadersCheck(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 std::string RawStringHeaderFileExtensions;
+  utils::HeaderFileExtensionsSet HeaderFileExtensions;
+};
+
+} // namespace readability
+} // namespace google
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_GLOBALNAMESINHEADERSCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.cpp
new file mode 100644
index 0000000..928d334
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.cpp
@@ -0,0 +1,99 @@
+//===--- GlobalVariableDeclarationCheck.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 "GlobalVariableDeclarationCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace objc {
+
+namespace {
+
+AST_MATCHER(VarDecl, isLocalVariable) {
+  return Node.isLocalVarDecl();
+}
+
+FixItHint generateFixItHint(const VarDecl *Decl, bool IsConst) {
+  char FC = Decl->getName()[0];
+  if (!llvm::isAlpha(FC) || Decl->getName().size() == 1) {
+    // No fix available if first character is not alphabetical character, or it
+    // is a single-character variable, since it is difficult to determine the 
+    // proper fix in this case. Users should create a proper variable name by
+    // their own.
+    return FixItHint();
+  }
+  char SC = Decl->getName()[1];
+  if ((FC == 'k' || FC == 'g') && !llvm::isAlpha(SC)) {
+    // No fix available if the prefix is correct but the second character is not
+    // alphabetical, since it is difficult to determine the proper fix in this
+    // case.
+    return FixItHint();
+  }
+  auto NewName = (IsConst ? "k" : "g") +
+                 llvm::StringRef(std::string(1, FC)).upper() +
+                 Decl->getName().substr(1).str();
+  return FixItHint::CreateReplacement(
+      CharSourceRange::getTokenRange(SourceRange(Decl->getLocation())),
+      llvm::StringRef(NewName));
+}
+}  // namespace
+
+void GlobalVariableDeclarationCheck::registerMatchers(MatchFinder *Finder) {
+  // The relevant Style Guide rule only applies to Objective-C.
+  if (!getLangOpts().ObjC1 && !getLangOpts().ObjC2) {
+    return;
+  }
+  // need to add two matchers since we need to bind different ids to distinguish
+  // constants and variables. Since bind() can only be called on node matchers,
+  // we cannot make it in one matcher.
+  //
+  // Note that hasGlobalStorage() matches static variables declared locally
+  // inside a function or method, so we need to exclude those with
+  // isLocalVariable().
+  Finder->addMatcher(
+      varDecl(hasGlobalStorage(), unless(hasType(isConstQualified())),
+              unless(isLocalVariable()), unless(matchesName("::g[A-Z]")))
+          .bind("global_var"),
+      this);
+  Finder->addMatcher(varDecl(hasGlobalStorage(), hasType(isConstQualified()),
+                             unless(isLocalVariable()),
+                             unless(matchesName("::(k[A-Z]|[A-Z]{2,})")))
+                         .bind("global_const"),
+                     this);
+}
+
+void GlobalVariableDeclarationCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  if (const auto *Decl = Result.Nodes.getNodeAs<VarDecl>("global_var")) {
+    diag(Decl->getLocation(),
+         "non-const global variable '%0' must have a name which starts with "
+         "'g[A-Z]'")
+        << Decl->getName() << generateFixItHint(Decl, false);
+  }
+  if (const auto *Decl = Result.Nodes.getNodeAs<VarDecl>("global_const")) {
+    diag(Decl->getLocation(),
+         "const global variable '%0' must have a name which starts with "
+         "an appropriate prefix")
+        << Decl->getName() << generateFixItHint(Decl, true);
+  }
+}
+
+}  // namespace objc
+}  // namespace google
+}  // namespace tidy
+}  // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.h
new file mode 100644
index 0000000..ed0352b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.h
@@ -0,0 +1,39 @@
+//===--- GlobalVariableDeclarationCheck.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_OBJC_GLOBAL_VARIABLE_DECLARATION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_GLOBAL_VARIABLE_DECLARATION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace objc {
+
+/// The check for Objective-C global variables and constants naming convention.
+/// The declaration should follow the patterns of 'k[A-Z].*' (constants) or
+/// 'g[A-Z].*' (variables).
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/google-objc-global-variable-declaration.html
+class GlobalVariableDeclarationCheck : public ClangTidyCheck {
+ public:
+  GlobalVariableDeclarationCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+}  // namespace objc
+}  // namespace google
+}  // namespace tidy
+}  // namespace clang
+
+#endif  // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_GLOBAL_VARIABLE_DECLARATION_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
new file mode 100644
index 0000000..f4f4118
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
@@ -0,0 +1,98 @@
+//===--- GoogleTidyModule.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 "../readability/BracesAroundStatementsCheck.h"
+#include "../readability/FunctionSizeCheck.h"
+#include "../readability/NamespaceCommentCheck.h"
+#include "AvoidCStyleCastsCheck.h"
+#include "AvoidThrowingObjCExceptionCheck.h"
+#include "DefaultArgumentsCheck.h"
+#include "ExplicitConstructorCheck.h"
+#include "ExplicitMakePairCheck.h"
+#include "GlobalNamesInHeadersCheck.h"
+#include "GlobalVariableDeclarationCheck.h"
+#include "IntegerTypesCheck.h"
+#include "NonConstReferences.h"
+#include "OverloadedUnaryAndCheck.h"
+#include "TodoCommentCheck.h"
+#include "UnnamedNamespaceInHeaderCheck.h"
+#include "UsingNamespaceDirectiveCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace google {
+
+class GoogleModule : public ClangTidyModule {
+ public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<build::ExplicitMakePairCheck>(
+        "google-build-explicit-make-pair");
+    CheckFactories.registerCheck<build::UnnamedNamespaceInHeaderCheck>(
+        "google-build-namespaces");
+    CheckFactories.registerCheck<build::UsingNamespaceDirectiveCheck>(
+        "google-build-using-namespace");
+    CheckFactories.registerCheck<DefaultArgumentsCheck>(
+        "google-default-arguments");
+    CheckFactories.registerCheck<ExplicitConstructorCheck>(
+        "google-explicit-constructor");
+    CheckFactories.registerCheck<readability::GlobalNamesInHeadersCheck>(
+        "google-global-names-in-headers");
+    CheckFactories.registerCheck<objc::AvoidThrowingObjCExceptionCheck>(
+        "google-objc-avoid-throwing-exception");
+    CheckFactories.registerCheck<objc::GlobalVariableDeclarationCheck>(
+        "google-objc-global-variable-declaration");
+    CheckFactories.registerCheck<runtime::IntegerTypesCheck>(
+        "google-runtime-int");
+    CheckFactories.registerCheck<runtime::OverloadedUnaryAndCheck>(
+        "google-runtime-operator");
+    CheckFactories.registerCheck<runtime::NonConstReferences>(
+        "google-runtime-references");
+    CheckFactories.registerCheck<readability::AvoidCStyleCastsCheck>(
+        "google-readability-casting");
+    CheckFactories.registerCheck<readability::TodoCommentCheck>(
+        "google-readability-todo");
+    CheckFactories
+        .registerCheck<clang::tidy::readability::BracesAroundStatementsCheck>(
+            "google-readability-braces-around-statements");
+    CheckFactories.registerCheck<clang::tidy::readability::FunctionSizeCheck>(
+        "google-readability-function-size");
+    CheckFactories
+        .registerCheck<clang::tidy::readability::NamespaceCommentCheck>(
+            "google-readability-namespace-comments");
+  }
+
+  ClangTidyOptions getModuleOptions() override {
+    ClangTidyOptions Options;
+    auto &Opts = Options.CheckOptions;
+    Opts["google-readability-braces-around-statements.ShortStatementLines"] =
+        "1";
+    Opts["google-readability-function-size.StatementThreshold"] = "800";
+    Opts["google-readability-namespace-comments.ShortNamespaceLines"] = "10";
+    Opts["google-readability-namespace-comments.SpacesBeforeComments"] = "2";
+    return Options;
+  }
+};
+
+// Register the GoogleTidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<GoogleModule> X("google-module",
+                                                    "Adds Google lint checks.");
+
+}  // namespace google
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the GoogleModule.
+volatile int GoogleModuleAnchorSource = 0;
+
+}  // namespace tidy
+}  // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp
new file mode 100644
index 0000000..7f0b765
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp
@@ -0,0 +1,154 @@
+//===--- IntegerTypesCheck.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 "IntegerTypesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/AttrKinds.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Lexer.h"
+
+namespace clang {
+
+using namespace ast_matchers;
+
+static Token getTokenAtLoc(SourceLocation Loc,
+                           const MatchFinder::MatchResult &MatchResult,
+                           IdentifierTable &IdentTable) {
+  Token Tok;
+  if (Lexer::getRawToken(Loc, Tok, *MatchResult.SourceManager,
+                         MatchResult.Context->getLangOpts(), false))
+    return Tok;
+
+  if (Tok.is(tok::raw_identifier)) {
+    IdentifierInfo &Info = IdentTable.get(Tok.getRawIdentifier());
+    Tok.setIdentifierInfo(&Info);
+    Tok.setKind(Info.getTokenID());
+  }
+  return Tok;
+}
+
+namespace tidy {
+namespace google {
+namespace runtime {
+
+IntegerTypesCheck::IntegerTypesCheck(StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      UnsignedTypePrefix(Options.get("UnsignedTypePrefix", "uint")),
+      SignedTypePrefix(Options.get("SignedTypePrefix", "int")),
+      TypeSuffix(Options.get("TypeSuffix", "")) {}
+
+void IntegerTypesCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "UnsignedTypePrefix", UnsignedTypePrefix);
+  Options.store(Opts, "SignedTypePrefix", SignedTypePrefix);
+  Options.store(Opts, "TypeSuffix", TypeSuffix);
+}
+
+void IntegerTypesCheck::registerMatchers(MatchFinder *Finder) {
+  // Find all TypeLocs. The relevant Style Guide rule only applies to C++.
+  if (!getLangOpts().CPlusPlus)
+    return;
+  // Match any integer types, unless they are passed to a printf-based API:
+  //
+  // http://google.github.io/styleguide/cppguide.html#64-bit_Portability
+  // "Where possible, avoid passing arguments of types specified by
+  // bitwidth typedefs to printf-based APIs."
+  Finder->addMatcher(typeLoc(loc(isInteger()),
+                             unless(hasAncestor(callExpr(
+                                 callee(functionDecl(hasAttr(attr::Format)))))))
+                         .bind("tl"),
+                     this);
+  IdentTable = llvm::make_unique<IdentifierTable>(getLangOpts());
+}
+
+void IntegerTypesCheck::check(const MatchFinder::MatchResult &Result) {
+  auto TL = *Result.Nodes.getNodeAs<TypeLoc>("tl");
+  SourceLocation Loc = TL.getLocStart();
+
+  if (Loc.isInvalid() || Loc.isMacroID())
+    return;
+
+  // Look through qualification.
+  if (auto QualLoc = TL.getAs<QualifiedTypeLoc>())
+    TL = QualLoc.getUnqualifiedLoc();
+
+  auto BuiltinLoc = TL.getAs<BuiltinTypeLoc>();
+  if (!BuiltinLoc)
+    return;
+
+  Token Tok = getTokenAtLoc(Loc, Result, *IdentTable);
+  // Ensure the location actually points to one of the builting integral type
+  // names we're interested in. Otherwise, we might be getting this match from
+  // implicit code (e.g. an implicit assignment operator of a class containing
+  // an array of non-POD types).
+  if (!Tok.isOneOf(tok::kw_short, tok::kw_long, tok::kw_unsigned,
+                   tok::kw_signed))
+    return;
+
+  bool IsSigned;
+  unsigned Width;
+  const TargetInfo &TargetInfo = Result.Context->getTargetInfo();
+
+  // Look for uses of short, long, long long and their unsigned versions.
+  switch (BuiltinLoc.getTypePtr()->getKind()) {
+  case BuiltinType::Short:
+    Width = TargetInfo.getShortWidth();
+    IsSigned = true;
+    break;
+  case BuiltinType::Long:
+    Width = TargetInfo.getLongWidth();
+    IsSigned = true;
+    break;
+  case BuiltinType::LongLong:
+    Width = TargetInfo.getLongLongWidth();
+    IsSigned = true;
+    break;
+  case BuiltinType::UShort:
+    Width = TargetInfo.getShortWidth();
+    IsSigned = false;
+    break;
+  case BuiltinType::ULong:
+    Width = TargetInfo.getLongWidth();
+    IsSigned = false;
+    break;
+  case BuiltinType::ULongLong:
+    Width = TargetInfo.getLongLongWidth();
+    IsSigned = false;
+    break;
+  default:
+    return;
+  }
+
+  // We allow "unsigned short port" as that's reasonably common and required by
+  // the sockets API.
+  const StringRef Port = "unsigned short port";
+  const char *Data = Result.SourceManager->getCharacterData(Loc);
+  if (!std::strncmp(Data, Port.data(), Port.size()) &&
+      !isIdentifierBody(Data[Port.size()]))
+    return;
+
+  std::string Replacement =
+      ((IsSigned ? SignedTypePrefix : UnsignedTypePrefix) + Twine(Width) +
+       TypeSuffix)
+          .str();
+
+  // We don't add a fix-it as changing the type can easily break code,
+  // e.g. when a function requires a 'long' argument on all platforms.
+  // QualTypes are printed with implicit quotes.
+  diag(Loc, "consider replacing %0 with '%1'") << BuiltinLoc.getType()
+                                               << Replacement;
+}
+
+} // namespace runtime
+} // namespace google
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h
new file mode 100644
index 0000000..8d8f903
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h
@@ -0,0 +1,49 @@
+//===--- IntegerTypesCheck.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_INTEGERTYPESCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_INTEGERTYPESCHECK_H
+
+#include "../ClangTidy.h"
+
+#include <memory>
+
+namespace clang {
+
+class IdentifierTable;
+
+namespace tidy {
+namespace google {
+namespace runtime {
+
+/// Finds uses of `short`, `long` and `long long` and suggest replacing them
+/// with `u?intXX(_t)?`.
+///
+/// Correspondig cpplint.py check: 'runtime/int'.
+class IntegerTypesCheck : public ClangTidyCheck {
+public:
+  IntegerTypesCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Options) override;
+
+private:
+  const std::string UnsignedTypePrefix;
+  const std::string SignedTypePrefix;
+  const std::string TypeSuffix;
+
+  std::unique_ptr<IdentifierTable> IdentTable;
+};
+
+} // namespace runtime
+} // namespace google
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_INTEGERTYPESCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/NonConstReferences.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/NonConstReferences.cpp
new file mode 100644
index 0000000..856bc5b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/NonConstReferences.cpp
@@ -0,0 +1,149 @@
+//===--- NonConstReferences.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 "NonConstReferences.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace runtime {
+
+NonConstReferences::NonConstReferences(StringRef Name,
+                                       ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      WhiteListTypes(
+          utils::options::parseStringList(Options.get("WhiteListTypes", ""))) {}
+
+void NonConstReferences::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "WhiteListTypes",
+                utils::options::serializeStringList(WhiteListTypes));
+}
+
+void NonConstReferences::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(
+      parmVarDecl(
+          unless(isInstantiated()),
+          hasType(references(
+              qualType(unless(isConstQualified())).bind("referenced_type"))),
+          unless(hasType(rValueReferenceType())))
+          .bind("param"),
+      this);
+}
+
+void NonConstReferences::check(const MatchFinder::MatchResult &Result) {
+  const auto *Parameter = Result.Nodes.getNodeAs<ParmVarDecl>("param");
+  const auto *Function =
+      dyn_cast_or_null<FunctionDecl>(Parameter->getParentFunctionOrMethod());
+
+  if (Function == nullptr || Function->isImplicit())
+    return;
+
+  if (!Function->isCanonicalDecl())
+    return;
+
+  if (const auto *Method = dyn_cast<CXXMethodDecl>(Function)) {
+    // Don't warn on implementations of an interface using references.
+    if (Method->begin_overridden_methods() != Method->end_overridden_methods())
+      return;
+    // Don't warn on lambdas, as they frequently have to conform to the
+    // interface defined elsewhere.
+    if (Method->getParent()->isLambda())
+      return;
+  }
+
+  auto ReferencedType = *Result.Nodes.getNodeAs<QualType>("referenced_type");
+
+  if (std::find_if(WhiteListTypes.begin(), WhiteListTypes.end(),
+                   [&](llvm::StringRef WhiteListType) {
+                     return ReferencedType.getCanonicalType().getAsString(
+                                Result.Context->getPrintingPolicy()) ==
+                            WhiteListType;
+                   }) != WhiteListTypes.end())
+    return;
+
+  // Don't warn on function references, they shouldn't be constant.
+  if (ReferencedType->isFunctionProtoType())
+    return;
+
+  // Don't warn on dependent types in templates.
+  if (ReferencedType->isDependentType())
+    return;
+
+  if (Function->isOverloadedOperator()) {
+    switch (Function->getOverloadedOperator()) {
+      case clang::OO_LessLess:
+      case clang::OO_PlusPlus:
+      case clang::OO_MinusMinus:
+      case clang::OO_PlusEqual:
+      case clang::OO_MinusEqual:
+      case clang::OO_StarEqual:
+      case clang::OO_SlashEqual:
+      case clang::OO_PercentEqual:
+      case clang::OO_LessLessEqual:
+      case clang::OO_GreaterGreaterEqual:
+      case clang::OO_PipeEqual:
+      case clang::OO_CaretEqual:
+      case clang::OO_AmpEqual:
+        // Don't warn on the first parameter of operator<<(Stream&, ...),
+        // operator++, operator-- and operation+assignment operators.
+        if (Function->getParamDecl(0) == Parameter)
+          return;
+        break;
+      case clang::OO_GreaterGreater: {
+        auto isNonConstRef = [](clang::QualType T) {
+          return T->isReferenceType() &&
+                 !T.getNonReferenceType().isConstQualified();
+        };
+        // Don't warn on parameters of stream extractors:
+        //   Stream& operator>>(Stream&, Value&);
+        // Both parameters should be non-const references by convention.
+        if (isNonConstRef(Function->getParamDecl(0)->getType()) &&
+            (Function->getNumParams() < 2 || // E.g. member operator>>.
+             isNonConstRef(Function->getParamDecl(1)->getType())) &&
+            isNonConstRef(Function->getReturnType()))
+          return;
+        break;
+      }
+      default:
+        break;
+    }
+  }
+
+  // Some functions use references to comply with established standards.
+  if (Function->getDeclName().isIdentifier() && Function->getName() == "swap")
+    return;
+
+  // iostream parameters are typically passed by non-const reference.
+  if (StringRef(ReferencedType.getAsString()).endswith("stream"))
+    return;
+
+  if (Parameter->getName().empty()) {
+    diag(Parameter->getLocation(), "non-const reference parameter at index %0, "
+                                   "make it const or use a pointer")
+        << Parameter->getFunctionScopeIndex();
+  } else {
+    diag(Parameter->getLocation(),
+         "non-const reference parameter %0, make it const or use a pointer")
+        << Parameter;
+  }
+}
+
+} // namespace runtime
+} // namespace google
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/NonConstReferences.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/NonConstReferences.h
new file mode 100644
index 0000000..a665813
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/NonConstReferences.h
@@ -0,0 +1,39 @@
+//===--- NonConstReferences.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_NON_CONST_REFERENCES_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_NON_CONST_REFERENCES_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace runtime {
+
+/// \brief Checks the usage of non-constant references in function parameters.
+///
+/// https://google.github.io/styleguide/cppguide.html#Reference_Arguments
+class NonConstReferences : public ClangTidyCheck {
+public:
+  NonConstReferences(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  const std::vector<std::string> WhiteListTypes;
+};
+
+} // namespace runtime
+} // namespace google
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_NON_CONST_REFERENCES_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/OverloadedUnaryAndCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/OverloadedUnaryAndCheck.cpp
new file mode 100644
index 0000000..84abb5f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/OverloadedUnaryAndCheck.cpp
@@ -0,0 +1,53 @@
+//===--- OverloadedUnaryAndCheck.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 "OverloadedUnaryAndCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace runtime {
+
+void OverloadedUnaryAndCheck::registerMatchers(
+    ast_matchers::MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // Match unary methods that overload operator&.
+  Finder->addMatcher(
+      cxxMethodDecl(parameterCountIs(0), hasOverloadedOperatorName("&"))
+          .bind("overload"),
+      this);
+  // Also match freestanding unary operator& overloads. Be careful not to match
+  // binary methods.
+  Finder->addMatcher(
+      functionDecl(allOf(
+          unless(cxxMethodDecl()),
+          functionDecl(parameterCountIs(1), hasOverloadedOperatorName("&"))
+              .bind("overload"))),
+      this);
+}
+
+void OverloadedUnaryAndCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Decl = Result.Nodes.getNodeAs<FunctionDecl>("overload");
+  diag(Decl->getLocStart(),
+       "do not overload unary operator&, it is dangerous.");
+}
+
+} // namespace runtime
+} // namespace google
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/OverloadedUnaryAndCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/OverloadedUnaryAndCheck.h
new file mode 100644
index 0000000..5492eba
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/OverloadedUnaryAndCheck.h
@@ -0,0 +1,38 @@
+//===--- OverloadedUnaryAndCheck.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_OVERLOADEDUNARYANDCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OVERLOADEDUNARYANDCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace runtime {
+
+/// Finds overloads of unary `operator &`.
+///
+/// https://google.github.io/styleguide/cppguide.html#Operator_Overloading
+///
+/// Corresponding cpplint.py check name: 'runtime/operator'.
+class OverloadedUnaryAndCheck : public ClangTidyCheck {
+public:
+  OverloadedUnaryAndCheck(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_OVERLOADEDUNARYANDCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/TodoCommentCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/TodoCommentCheck.cpp
new file mode 100644
index 0000000..f1c79ce
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/TodoCommentCheck.cpp
@@ -0,0 +1,66 @@
+//===--- TodoCommentCheck.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 "TodoCommentCheck.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Preprocessor.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace readability {
+
+class TodoCommentCheck::TodoCommentHandler : public CommentHandler {
+public:
+  TodoCommentHandler(TodoCommentCheck &Check, llvm::Optional<std::string> User)
+      : Check(Check), User(User ? *User : "unknown"),
+        TodoMatch("^// *TODO *(\\(.*\\))?:?( )?(.*)$") {}
+
+  bool HandleComment(Preprocessor &PP, SourceRange Range) override {
+    StringRef Text =
+        Lexer::getSourceText(CharSourceRange::getCharRange(Range),
+                             PP.getSourceManager(), PP.getLangOpts());
+
+    SmallVector<StringRef, 4> Matches;
+    if (!TodoMatch.match(Text, &Matches))
+      return false;
+
+    StringRef Username = Matches[1];
+    StringRef Comment = Matches[3];
+
+    if (!Username.empty())
+      return false;
+
+    std::string NewText = ("// TODO(" + Twine(User) + "): " + Comment).str();
+
+    Check.diag(Range.getBegin(), "missing username/bug in TODO")
+        << FixItHint::CreateReplacement(CharSourceRange::getCharRange(Range),
+                                        NewText);
+    return false;
+  }
+
+private:
+  TodoCommentCheck &Check;
+  std::string User;
+  llvm::Regex TodoMatch;
+};
+
+TodoCommentCheck::TodoCommentCheck(StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      Handler(llvm::make_unique<TodoCommentHandler>(
+          *this, Context->getOptions().User)) {}
+
+void TodoCommentCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  Compiler.getPreprocessor().addCommentHandler(Handler.get());
+}
+
+} // namespace readability
+} // namespace google
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h
new file mode 100644
index 0000000..dbdc366
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h
@@ -0,0 +1,38 @@
+//===--- TodoCommentCheck.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_TODOCOMMENTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_TODOCOMMENTCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace readability {
+
+/// Finds TODO comments without a username or bug number.
+///
+/// Corresponding cpplint.py check: 'readability/todo'
+class TodoCommentCheck : public ClangTidyCheck {
+public:
+  TodoCommentCheck(StringRef Name, ClangTidyContext *Context);
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+
+private:
+  class TodoCommentHandler;
+  std::unique_ptr<TodoCommentHandler> Handler;
+};
+
+} // namespace readability
+} // namespace google
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_TODOCOMMENTCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp
new file mode 100644
index 0000000..32ff6e0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp
@@ -0,0 +1,63 @@
+//===--- UnnamedNamespaceInHeaderCheck.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 "UnnamedNamespaceInHeaderCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace build {
+
+UnnamedNamespaceInHeaderCheck::UnnamedNamespaceInHeaderCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      RawStringHeaderFileExtensions(Options.getLocalOrGlobal(
+          "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) {
+  if (!utils::parseHeaderFileExtensions(RawStringHeaderFileExtensions,
+                                        HeaderFileExtensions, ',')) {
+    llvm::errs() << "Invalid header file extension: "
+                 << RawStringHeaderFileExtensions << "\n";
+  }
+}
+
+void UnnamedNamespaceInHeaderCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
+}
+
+void UnnamedNamespaceInHeaderCheck::registerMatchers(
+    ast_matchers::MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (getLangOpts().CPlusPlus)
+    Finder->addMatcher(namespaceDecl(isAnonymous()).bind("anonymousNamespace"),
+                       this);
+}
+
+void UnnamedNamespaceInHeaderCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *N = Result.Nodes.getNodeAs<NamespaceDecl>("anonymousNamespace");
+  SourceLocation Loc = N->getLocStart();
+  if (!Loc.isValid())
+    return;
+
+  if (utils::isPresumedLocInHeaderFile(Loc, *Result.SourceManager,
+                                       HeaderFileExtensions))
+    diag(Loc, "do not use unnamed namespaces in header files");
+}
+
+} // namespace build
+} // namespace google
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h
new file mode 100644
index 0000000..4d310f5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h
@@ -0,0 +1,50 @@
+//===--- UnnamedNamespaceInHeaderCheck.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_UNNAMEDNAMESPACEINHEADERCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_UNNAMEDNAMESPACEINHEADERCHECK_H
+
+#include "../ClangTidy.h"
+#include "../utils/HeaderFileExtensionsUtils.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace build {
+
+/// Finds anonymous namespaces in headers.
+///
+/// The check supports these options:
+///   - `HeaderFileExtensions`: a comma-separated list of filename extensions of
+///     header files (The filename extensions should not contain "." prefix).
+///     "h,hh,hpp,hxx" by default.
+///     For extension-less header files, using an empty string or leaving an
+///     empty string between "," if there are other filename extensions.
+///
+/// https://google.github.io/styleguide/cppguide.html#Namespaces
+///
+/// Corresponding cpplint.py check name: 'build/namespaces'.
+class UnnamedNamespaceInHeaderCheck : public ClangTidyCheck {
+public:
+  UnnamedNamespaceInHeaderCheck(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 std::string RawStringHeaderFileExtensions;
+  utils::HeaderFileExtensionsSet HeaderFileExtensions;
+};
+
+} // namespace build
+} // namespace google
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_UNNAMEDNAMESPACEINHEADERCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.cpp
new file mode 100644
index 0000000..60a46f8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.cpp
@@ -0,0 +1,66 @@
+//===--- UsingNamespaceDirectiveCheck.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 "UsingNamespaceDirectiveCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace build {
+
+void UsingNamespaceDirectiveCheck::registerMatchers(
+    ast_matchers::MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (getLangOpts().CPlusPlus)
+    Finder->addMatcher(usingDirectiveDecl().bind("usingNamespace"), this);
+}
+
+void UsingNamespaceDirectiveCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *U = Result.Nodes.getNodeAs<UsingDirectiveDecl>("usingNamespace");
+  SourceLocation Loc = U->getLocStart();
+  if (U->isImplicit() || !Loc.isValid())
+    return;
+
+  // Do not warn if namespace is a std namespace with user-defined literals. The
+  // user-defined literals can only be used with a using directive.
+  if (isStdLiteralsNamespace(U->getNominatedNamespace()))
+    return;
+
+  diag(Loc, "do not use namespace using-directives; "
+            "use using-declarations instead");
+  // TODO: We could suggest a list of using directives replacing the using
+  //       namespace directive.
+}
+
+bool UsingNamespaceDirectiveCheck::isStdLiteralsNamespace(
+    const NamespaceDecl *NS) {
+  if (!NS->getName().endswith("literals"))
+    return false;
+
+  const auto *Parent = dyn_cast_or_null<NamespaceDecl>(NS->getParent());
+  if (!Parent)
+    return false;
+
+  if (Parent->isStdNamespace())
+    return true;
+
+  return Parent->getName() == "literals" && Parent->getParent() &&
+         Parent->getParent()->isStdNamespace();
+}
+} // namespace build
+} // namespace google
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.h
new file mode 100644
index 0000000..2be65c1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.h
@@ -0,0 +1,51 @@
+//===--- UsingNamespaceDirectiveCheck.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_USINGNAMESPACEDIRECTIVECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_USINGNAMESPACEDIRECTIVECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace build {
+
+/// Finds using namespace directives.
+///
+/// https://google.github.io/styleguide/cppguide.html#Namespaces
+///
+/// The check implements the following rule of the Google C++ Style Guide:
+///
+///   You may not use a using-directive to make all names from a namespace
+///   available.
+///
+///   \code
+///     // Forbidden -- This pollutes the namespace.
+///     using namespace foo;
+///   \endcode
+///
+/// Corresponding cpplint.py check name: `build/namespaces`.
+class UsingNamespaceDirectiveCheck : public ClangTidyCheck {
+public:
+  UsingNamespaceDirectiveCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  static bool isStdLiteralsNamespace(const NamespaceDecl *NS);
+};
+
+} // namespace build
+} // namespace google
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_USINGNAMESPACEDIRECTIVECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/CMakeLists.txt
new file mode 100644
index 0000000..eeccf62
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/CMakeLists.txt
@@ -0,0 +1,24 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyHICPPModule
+  ExceptionBaseclassCheck.cpp
+  MultiwayPathsCoveredCheck.cpp
+  NoAssemblerCheck.cpp
+  HICPPTidyModule.cpp
+  SignedBitwiseCheck.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyBugproneModule
+  clangTidyCppCoreGuidelinesModule
+  clangTidyGoogleModule
+  clangTidyMiscModule
+  clangTidyModernizeModule
+  clangTidyPerformanceModule
+  clangTidyReadabilityModule
+  clangTidyUtils
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
new file mode 100644
index 0000000..298759f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.h
new file mode 100644
index 0000000..778979d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/HICPPTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/HICPPTidyModule.cpp
new file mode 100644
index 0000000..d2b9fc6d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/HICPPTidyModule.cpp
@@ -0,0 +1,119 @@
+//===------- HICPPTidyModule.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 "../bugprone/UseAfterMoveCheck.h"
+#include "../cppcoreguidelines/AvoidGotoCheck.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/NewDeleteOverloadsCheck.h"
+#include "../misc/StaticAssertCheck.h"
+#include "../bugprone/UndelegatedConstructorCheck.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 "../performance/MoveConstArgCheck.h"
+#include "../performance/NoexceptMoveConstructorCheck.h"
+#include "../readability/BracesAroundStatementsCheck.h"
+#include "../readability/FunctionSizeCheck.h"
+#include "../readability/IdentifierNamingCheck.h"
+#include "ExceptionBaseclassCheck.h"
+#include "MultiwayPathsCoveredCheck.h"
+#include "NoAssemblerCheck.h"
+#include "SignedBitwiseCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace hicpp {
+
+class HICPPModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<cppcoreguidelines::AvoidGotoCheck>(
+        "hicpp-avoid-goto");
+    CheckFactories.registerCheck<readability::BracesAroundStatementsCheck>(
+        "hicpp-braces-around-statements");
+    CheckFactories.registerCheck<modernize::DeprecatedHeadersCheck>(
+        "hicpp-deprecated-headers");
+    CheckFactories.registerCheck<ExceptionBaseclassCheck>(
+        "hicpp-exception-baseclass");
+    CheckFactories.registerCheck<MultiwayPathsCoveredCheck>(
+        "hicpp-multiway-paths-covered");
+    CheckFactories.registerCheck<SignedBitwiseCheck>("hicpp-signed-bitwise");
+    CheckFactories.registerCheck<google::ExplicitConstructorCheck>(
+        "hicpp-explicit-conversions");
+    CheckFactories.registerCheck<readability::FunctionSizeCheck>(
+        "hicpp-function-size");
+    CheckFactories.registerCheck<readability::IdentifierNamingCheck>(
+        "hicpp-named-parameter");
+    CheckFactories.registerCheck<bugprone::UseAfterMoveCheck>(
+        "hicpp-invalid-access-moved");
+    CheckFactories.registerCheck<cppcoreguidelines::ProTypeMemberInitCheck>(
+        "hicpp-member-init");
+    CheckFactories.registerCheck<performance::MoveConstArgCheck>(
+        "hicpp-move-const-arg");
+    CheckFactories.registerCheck<misc::NewDeleteOverloadsCheck>(
+        "hicpp-new-delete-operators");
+    CheckFactories.registerCheck<performance::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<bugprone::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");
+  }
+};
+
+// Register the HICPPModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<HICPPModule>
+    X("hicpp-module", "Adds High-Integrity C++ checks.");
+
+} // namespace hicpp
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the HICPPModule.
+volatile int HICPPModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/LICENSE.TXT b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/LICENSE.TXT
new file mode 100644
index 0000000..fb8f513
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/LICENSE.TXT
@@ -0,0 +1,12 @@
+------------------------------------------------------------------------------
+clang-tidy High-Integrity C++ Files
+------------------------------------------------------------------------------
+All clang-tidy files are licensed under the LLVM license with the following
+additions:
+
+Any file referencing a High-Integrity C++ Coding guideline:
+
+HIC++ Coding Standard as created by PRQA.
+
+Please see http://www.codingstandard.com/section/conditions-of-use/ for more
+information.
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp
new file mode 100644
index 0000000..68ae54e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp
@@ -0,0 +1,181 @@
+//===--- MultiwayPathsCoveredCheck.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 "MultiwayPathsCoveredCheck.h"
+#include "clang/AST/ASTContext.h"
+
+#include <limits>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace hicpp {
+
+void MultiwayPathsCoveredCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "WarnOnMissingElse", WarnOnMissingElse);
+}
+
+void MultiwayPathsCoveredCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      switchStmt(
+          hasCondition(allOf(
+              // Match on switch statements that have either a bit-field or
+              // an integer condition. The ordering in 'anyOf()' is
+              // important because the last condition is the most general.
+              anyOf(ignoringImpCasts(memberExpr(hasDeclaration(
+                        fieldDecl(isBitField()).bind("bitfield")))),
+                    ignoringImpCasts(declRefExpr().bind("non-enum-condition"))),
+              // 'unless()' must be the last match here and must be bound,
+              // otherwise the matcher does not work correctly, because it
+              // will not explicitly ignore enum conditions.
+              unless(ignoringImpCasts(
+                  declRefExpr(hasType(enumType())).bind("enum-condition"))))))
+          .bind("switch"),
+      this);
+
+  // This option is noisy, therefore matching is configurable.
+  if (WarnOnMissingElse) {
+    Finder->addMatcher(
+        ifStmt(allOf(hasParent(ifStmt()), unless(hasElse(anything()))))
+            .bind("else-if"),
+        this);
+  }
+}
+
+static std::pair<std::size_t, bool> countCaseLabels(const SwitchStmt *Switch) {
+  std::size_t CaseCount = 0;
+  bool HasDefault = false;
+
+  const SwitchCase *CurrentCase = Switch->getSwitchCaseList();
+  while (CurrentCase) {
+    ++CaseCount;
+    if (isa<DefaultStmt>(CurrentCase))
+      HasDefault = true;
+
+    CurrentCase = CurrentCase->getNextSwitchCase();
+  }
+
+  return std::make_pair(CaseCount, HasDefault);
+}
+
+/// This function calculate 2 ** Bits and returns
+/// numeric_limits<std::size_t>::max() if an overflow occured.
+static std::size_t twoPow(std::size_t Bits) {
+  return Bits >= std::numeric_limits<std::size_t>::digits
+             ? std::numeric_limits<std::size_t>::max()
+             : static_cast<size_t>(1) << Bits;
+}
+
+/// Get the number of possible values that can be switched on for the type T.
+///
+/// \return - 0 if bitcount could not be determined
+///         - numeric_limits<std::size_t>::max() when overflow appeared due to
+///           more than 64 bits type size.
+static std::size_t getNumberOfPossibleValues(QualType T,
+                                             const ASTContext &Context) {
+  // `isBooleanType` must come first because `bool` is an integral type as well
+  // and would not return 2 as result.
+  if (T->isBooleanType())
+    return 2;
+  else if (T->isIntegralType(Context))
+    return twoPow(Context.getTypeSize(T));
+  else
+    return 1;
+}
+
+void MultiwayPathsCoveredCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *ElseIfWithoutElse =
+          Result.Nodes.getNodeAs<IfStmt>("else-if")) {
+    diag(ElseIfWithoutElse->getLocStart(),
+         "potentially uncovered codepath; add an ending else statement");
+    return;
+  }
+  const auto *Switch = Result.Nodes.getNodeAs<SwitchStmt>("switch");
+  std::size_t SwitchCaseCount;
+  bool SwitchHasDefault;
+  std::tie(SwitchCaseCount, SwitchHasDefault) = countCaseLabels(Switch);
+
+  // Checks the sanity of 'switch' statements that actually do define
+  // a default branch but might be degenerated by having no or only one case.
+  if (SwitchHasDefault) {
+    handleSwitchWithDefault(Switch, SwitchCaseCount);
+    return;
+  }
+  // Checks all 'switch' statements that do not define a default label.
+  // Here the heavy lifting happens.
+  if (!SwitchHasDefault && SwitchCaseCount > 0) {
+    handleSwitchWithoutDefault(Switch, SwitchCaseCount, Result);
+    return;
+  }
+  // Warns for degenerated 'switch' statements that neither define a case nor
+  // a default label.
+  // FIXME: Evaluate, if emitting a fix-it to simplify that statement is 
+  // reasonable.
+  if (!SwitchHasDefault && SwitchCaseCount == 0) {
+    diag(Switch->getLocStart(),
+         "switch statement without labels has no effect");
+    return;
+  }
+  llvm_unreachable("matched a case, that was not explicitly handled");
+}
+
+void MultiwayPathsCoveredCheck::handleSwitchWithDefault(
+    const SwitchStmt *Switch, std::size_t CaseCount) {
+  assert(CaseCount > 0 && "Switch statement with supposedly one default "
+                          "branch did not contain any case labels");
+  if (CaseCount == 1 || CaseCount == 2)
+    diag(Switch->getLocStart(),
+         CaseCount == 1
+             ? "degenerated switch with default label only"
+             : "switch could be better written as an if/else statement");
+}
+
+void MultiwayPathsCoveredCheck::handleSwitchWithoutDefault(
+    const SwitchStmt *Switch, std::size_t CaseCount,
+    const MatchFinder::MatchResult &Result) {
+  // The matcher only works because some nodes are explicitly matched and
+  // bound but ignored. This is necessary to build the excluding logic for
+  // enums and 'switch' statements without a 'default' branch.
+  assert(!Result.Nodes.getNodeAs<DeclRefExpr>("enum-condition") &&
+         "switch over enum is handled by warnings already, explicitly ignoring "
+         "them");
+  // Determine the number of case labels. Because 'default' is not present
+  // and duplicating case labels is not allowed this number represents
+  // the number of codepaths. It can be directly compared to 'MaxPathsPossible'
+  // to see if some cases are missing.
+  // CaseCount == 0 is caught in DegenerateSwitch. Necessary because the
+  // matcher used for here does not match on degenerate 'switch'.
+  assert(CaseCount > 0 && "Switch statement without any case found. This case "
+                          "should be excluded by the matcher and is handled "
+                          "separatly.");
+  std::size_t MaxPathsPossible = [&]() {
+    if (const auto *GeneralCondition =
+            Result.Nodes.getNodeAs<DeclRefExpr>("non-enum-condition")) {
+      return getNumberOfPossibleValues(GeneralCondition->getType(),
+                                       *Result.Context);
+    }
+    if (const auto *BitfieldDecl =
+            Result.Nodes.getNodeAs<FieldDecl>("bitfield")) {
+      return twoPow(BitfieldDecl->getBitWidthValue(*Result.Context));
+    }
+
+    return static_cast<std::size_t>(0);
+  }();
+
+  // FIXME: Transform the 'switch' into an 'if' for CaseCount == 1.
+  if (CaseCount < MaxPathsPossible)
+    diag(Switch->getLocStart(),
+         CaseCount == 1 ? "switch with only one case; use an if statement"
+                        : "potential uncovered code path; add a default label");
+}
+} // namespace hicpp
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.h
new file mode 100644
index 0000000..498dad6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.h
@@ -0,0 +1,51 @@
+//===--- MultiwayPathsCoveredCheck.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_MULTIWAY_PATHS_COVERED_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_HICPP_MULTIWAY_PATHS_COVERED_H
+
+#include "../ClangTidy.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include <iostream>
+
+namespace clang {
+namespace tidy {
+namespace hicpp {
+
+/// Find occasions where not all codepaths are explicitly covered in code.
+/// This includes 'switch' without a 'default'-branch and 'if'-'else if'-chains
+/// without a final 'else'-branch.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/hicpp-multiway-paths-covered.html
+class MultiwayPathsCoveredCheck : public ClangTidyCheck {
+public:
+  MultiwayPathsCoveredCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context),
+        WarnOnMissingElse(Options.get("WarnOnMissingElse", 0)) {}
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void handleSwitchWithDefault(const SwitchStmt *Switch, std::size_t CaseCount);
+  void handleSwitchWithoutDefault(
+      const SwitchStmt *Switch, std::size_t CaseCount,
+      const ast_matchers::MatchFinder::MatchResult &Result);
+  /// This option can be configured to warn on missing 'else' branches in an
+  /// 'if-else if' chain. The default is false because this option might be
+  /// noisy on some code bases.
+  const bool WarnOnMissingElse;
+};
+
+} // namespace hicpp
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_HICPP_MULTIWAY_PATHS_COVERED_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/NoAssemblerCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/NoAssemblerCheck.cpp
new file mode 100644
index 0000000..06969a8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/NoAssemblerCheck.cpp
@@ -0,0 +1,50 @@
+//===--- NoAssemblerCheck.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 "NoAssemblerCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace hicpp {
+
+namespace {
+AST_MATCHER(VarDecl, isAsm) { return Node.hasAttr<clang::AsmLabelAttr>(); }
+const ast_matchers::internal::VariadicDynCastAllOfMatcher<Decl,
+                                                          FileScopeAsmDecl>
+    fileScopeAsmDecl;
+} // namespace
+
+void NoAssemblerCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(asmStmt().bind("asm-stmt"), this);
+  Finder->addMatcher(fileScopeAsmDecl().bind("asm-file-scope"), this);
+  Finder->addMatcher(varDecl(isAsm()).bind("asm-var"), this);
+}
+
+void NoAssemblerCheck::check(const MatchFinder::MatchResult &Result) {
+  SourceLocation ASMLocation;
+  if (const auto *ASM = Result.Nodes.getNodeAs<AsmStmt>("asm-stmt"))
+    ASMLocation = ASM->getAsmLoc();
+  else if (const auto *ASM =
+               Result.Nodes.getNodeAs<FileScopeAsmDecl>("asm-file-scope"))
+    ASMLocation = ASM->getAsmLoc();
+  else if (const auto *ASM = Result.Nodes.getNodeAs<VarDecl>("asm-var"))
+    ASMLocation = ASM->getLocation();
+  else
+    llvm_unreachable("Unhandled case in matcher.");
+
+  diag(ASMLocation, "do not use inline assembler in safety-critical code");
+}
+
+} // namespace hicpp
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/NoAssemblerCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/NoAssemblerCheck.h
new file mode 100644
index 0000000..416ccb0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/NoAssemblerCheck.h
@@ -0,0 +1,35 @@
+//===--- NoAssemblerCheck.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_NO_ASSEMBLER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_HICPP_NO_ASSEMBLER_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace hicpp {
+
+/// Find assembler statements. No fix is offered.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/hicpp-no-assembler.html
+class NoAssemblerCheck : public ClangTidyCheck {
+public:
+  NoAssemblerCheck(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_NO_ASSEMBLER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/SignedBitwiseCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/SignedBitwiseCheck.cpp
new file mode 100644
index 0000000..0390052
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/SignedBitwiseCheck.cpp
@@ -0,0 +1,96 @@
+//===--- 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");
+
+  // The standard [bitmask.types] allows some integral types to be implemented
+  // as signed types. Exclude these types from diagnosing for bitwise or(|) and
+  // bitwise and(&). Shifting and complementing such values is still not
+  // allowed.
+  const auto BitmaskType = namedDecl(anyOf(
+      hasName("::std::locale::category"), hasName("::std::ctype_base::mask"),
+      hasName("::std::ios_base::fmtflags"), hasName("::std::ios_base::iostate"),
+      hasName("::std::ios_base::openmode")));
+  const auto IsStdBitmask = ignoringImpCasts(declRefExpr(hasType(BitmaskType)));
+
+  // Match binary bitwise operations on signed integer arguments.
+  Finder->addMatcher(
+      binaryOperator(
+          allOf(anyOf(hasOperatorName("^"), hasOperatorName("|"),
+                      hasOperatorName("&"), hasOperatorName("^="),
+                      hasOperatorName("|="), hasOperatorName("&=")),
+
+                unless(allOf(hasLHS(IsStdBitmask), hasRHS(IsStdBitmask))),
+
+                hasEitherOperand(SignedIntegerOperand),
+                hasLHS(hasType(isInteger())), hasRHS(hasType(isInteger()))))
+          .bind("binary-no-sign-interference"),
+      this);
+
+  // Shifting and complement is not allowed for any signed integer type because
+  // the sign bit may corrupt the result.
+  Finder->addMatcher(
+      binaryOperator(
+          allOf(anyOf(hasOperatorName("<<"), hasOperatorName(">>"),
+                      hasOperatorName("<<="), hasOperatorName(">>=")),
+                hasEitherOperand(SignedIntegerOperand),
+                hasLHS(hasType(isInteger())), hasRHS(hasType(isInteger()))))
+          .bind("binary-sign-interference"),
+      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 *SignedOperand = N.getNodeAs<Expr>("signed-operand");
+  assert(SignedOperand &&
+         "No signed operand found in problematic bitwise operations");
+
+  bool IsUnary = false;
+  SourceLocation Location;
+
+  if (const auto *UnaryOp = N.getNodeAs<UnaryOperator>("unary-signed")) {
+    IsUnary = true;
+    Location = UnaryOp->getLocStart();
+  } else {
+    if (const auto *BinaryOp =
+            N.getNodeAs<BinaryOperator>("binary-no-sign-interference"))
+      Location = BinaryOp->getLocStart();
+    else if (const auto *BinaryOp =
+                 N.getNodeAs<BinaryOperator>("binary-sign-interference"))
+      Location = BinaryOp->getLocStart();
+    else
+      llvm_unreachable("unexpected matcher result");
+  }
+  diag(Location, "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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/SignedBitwiseCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/hicpp/SignedBitwiseCheck.h
new file mode 100644
index 0000000..24338ad
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
new file mode 100644
index 0000000..ce69c05
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
@@ -0,0 +1,18 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyLLVMModule
+  HeaderGuardCheck.cpp
+  IncludeOrderCheck.cpp
+  LLVMTidyModule.cpp
+  TwineLocalCheck.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyReadabilityModule
+  clangTidyUtils
+  clangTooling
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.cpp
new file mode 100644
index 0000000..c0e449e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.cpp
@@ -0,0 +1,55 @@
+//===--- HeaderGuardCheck.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 "HeaderGuardCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace llvm {
+
+LLVMHeaderGuardCheck::LLVMHeaderGuardCheck(StringRef Name,
+                                           ClangTidyContext *Context)
+    : HeaderGuardCheck(Name, Context) {}
+
+std::string LLVMHeaderGuardCheck::getHeaderGuard(StringRef Filename,
+                                                 StringRef OldGuard) {
+  std::string Guard = tooling::getAbsolutePath(Filename);
+
+  // Sanitize the path. There are some rules for compatibility with the historic
+  // style in include/llvm and include/clang which we want to preserve.
+
+  // We don't want _INCLUDE_ in our guards.
+  size_t PosInclude = Guard.rfind("include/");
+  if (PosInclude != StringRef::npos)
+    Guard = Guard.substr(PosInclude + std::strlen("include/"));
+
+  // For clang we drop the _TOOLS_.
+  size_t PosToolsClang = Guard.rfind("tools/clang/");
+  if (PosToolsClang != StringRef::npos)
+    Guard = Guard.substr(PosToolsClang + std::strlen("tools/"));
+
+  // The remainder is LLVM_FULL_PATH_TO_HEADER_H
+  size_t PosLLVM = Guard.rfind("llvm/");
+  if (PosLLVM != StringRef::npos)
+    Guard = Guard.substr(PosLLVM);
+
+  std::replace(Guard.begin(), Guard.end(), '/', '_');
+  std::replace(Guard.begin(), Guard.end(), '.', '_');
+  std::replace(Guard.begin(), Guard.end(), '-', '_');
+
+  // The prevalent style in clang is LLVM_CLANG_FOO_BAR_H
+  if (StringRef(Guard).startswith("clang"))
+    Guard = "LLVM_" + Guard;
+
+  return StringRef(Guard).upper();
+}
+
+} // namespace llvm
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.h
new file mode 100644
index 0000000..ca2d7ef
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.h
@@ -0,0 +1,40 @@
+//===--- HeaderGuardCheck.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_LLVM_HEADER_GUARD_CHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_HEADER_GUARD_CHECK_H
+
+#include "../utils/HeaderGuard.h"
+
+namespace clang {
+namespace tidy {
+namespace llvm {
+
+/// Finds and fixes header guards that do not adhere to LLVM style.
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/llvm-header-guard.html
+/// The check supports these options:
+///   - `HeaderFileExtensions`: a comma-separated list of filename extensions of
+///     header files (The filename extension should not contain "." prefix).
+///     ",h,hh,hpp,hxx" by default.
+///     For extension-less header files, using an empty string or leaving an
+///     empty string between "," if there are other filename extensions.
+class LLVMHeaderGuardCheck : public utils::HeaderGuardCheck {
+public:
+  LLVMHeaderGuardCheck(StringRef Name, ClangTidyContext *Context);
+
+  bool shouldSuggestEndifComment(StringRef Filename) override { return false; }
+  std::string getHeaderGuard(StringRef Filename, StringRef OldGuard) override;
+};
+
+} // namespace llvm
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_HEADER_GUARD_CHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/IncludeOrderCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/IncludeOrderCheck.cpp
new file mode 100644
index 0000000..f1fdb39
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/IncludeOrderCheck.cpp
@@ -0,0 +1,181 @@
+//===--- IncludeOrderCheck.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 "IncludeOrderCheck.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+
+#include <map>
+
+namespace clang {
+namespace tidy {
+namespace llvm {
+
+namespace {
+class IncludeOrderPPCallbacks : public PPCallbacks {
+public:
+  explicit IncludeOrderPPCallbacks(ClangTidyCheck &Check, SourceManager &SM)
+      : LookForMainModule(true), Check(Check), SM(SM) {}
+
+  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+                          StringRef FileName, bool IsAngled,
+                          CharSourceRange FilenameRange, const FileEntry *File,
+                          StringRef SearchPath, StringRef RelativePath,
+                          const Module *Imported,
+                          SrcMgr::CharacteristicKind FileType) override;
+  void EndOfMainFile() override;
+
+private:
+  struct IncludeDirective {
+    SourceLocation Loc;    ///< '#' location in the include directive
+    CharSourceRange Range; ///< SourceRange for the file name
+    std::string Filename;  ///< Filename as a string
+    bool IsAngled;         ///< true if this was an include with angle brackets
+    bool IsMainModule;     ///< true if this was the first include in a file
+  };
+
+  typedef std::vector<IncludeDirective> FileIncludes;
+  std::map<clang::FileID, FileIncludes> IncludeDirectives;
+  bool LookForMainModule;
+
+  ClangTidyCheck &Check;
+  SourceManager &SM;
+};
+} // namespace
+
+void IncludeOrderCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  Compiler.getPreprocessor().addPPCallbacks(
+      ::llvm::make_unique<IncludeOrderPPCallbacks>(
+          *this, Compiler.getSourceManager()));
+}
+
+static int getPriority(StringRef Filename, bool IsAngled, bool IsMainModule) {
+  // We leave the main module header at the top.
+  if (IsMainModule)
+    return 0;
+
+  // LLVM and clang headers are in the penultimate position.
+  if (Filename.startswith("llvm/") || Filename.startswith("llvm-c/") ||
+      Filename.startswith("clang/") || Filename.startswith("clang-c/"))
+    return 2;
+
+  // System headers are sorted to the end.
+  if (IsAngled || Filename.startswith("gtest/"))
+    return 3;
+
+  // Other headers are inserted between the main module header and LLVM headers.
+  return 1;
+}
+
+void IncludeOrderPPCallbacks::InclusionDirective(
+    SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
+    bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
+    StringRef SearchPath, StringRef RelativePath, const Module *Imported,
+    SrcMgr::CharacteristicKind FileType) {
+  // We recognize the first include as a special main module header and want
+  // to leave it in the top position.
+  IncludeDirective ID = {HashLoc, FilenameRange, FileName, IsAngled, false};
+  if (LookForMainModule && !IsAngled) {
+    ID.IsMainModule = true;
+    LookForMainModule = false;
+  }
+
+  // Bucket the include directives by the id of the file they were declared in.
+  IncludeDirectives[SM.getFileID(HashLoc)].push_back(std::move(ID));
+}
+
+void IncludeOrderPPCallbacks::EndOfMainFile() {
+  LookForMainModule = true;
+  if (IncludeDirectives.empty())
+    return;
+
+  // TODO: find duplicated includes.
+
+  // Form blocks of includes. We don't want to sort across blocks. This also
+  // implicitly makes us never reorder over #defines or #if directives.
+  // FIXME: We should be more careful about sorting below comments as we don't
+  // know if the comment refers to the next include or the whole block that
+  // follows.
+  for (auto &Bucket : IncludeDirectives) {
+    auto &FileDirectives = Bucket.second;
+    std::vector<unsigned> Blocks(1, 0);
+    for (unsigned I = 1, E = FileDirectives.size(); I != E; ++I)
+      if (SM.getExpansionLineNumber(FileDirectives[I].Loc) !=
+          SM.getExpansionLineNumber(FileDirectives[I - 1].Loc) + 1)
+        Blocks.push_back(I);
+    Blocks.push_back(FileDirectives.size()); // Sentinel value.
+
+    // Get a vector of indices.
+    std::vector<unsigned> IncludeIndices;
+    for (unsigned I = 0, E = FileDirectives.size(); I != E; ++I)
+      IncludeIndices.push_back(I);
+
+    // Sort the includes. We first sort by priority, then lexicographically.
+    for (unsigned BI = 0, BE = Blocks.size() - 1; BI != BE; ++BI)
+      std::sort(IncludeIndices.begin() + Blocks[BI],
+                IncludeIndices.begin() + Blocks[BI + 1],
+                [&FileDirectives](unsigned LHSI, unsigned RHSI) {
+                  IncludeDirective &LHS = FileDirectives[LHSI];
+                  IncludeDirective &RHS = FileDirectives[RHSI];
+
+                  int PriorityLHS =
+                      getPriority(LHS.Filename, LHS.IsAngled, LHS.IsMainModule);
+                  int PriorityRHS =
+                      getPriority(RHS.Filename, RHS.IsAngled, RHS.IsMainModule);
+
+                  return std::tie(PriorityLHS, LHS.Filename) <
+                         std::tie(PriorityRHS, RHS.Filename);
+                });
+
+    // Emit a warning for each block and fixits for all changes within that
+    // block.
+    for (unsigned BI = 0, BE = Blocks.size() - 1; BI != BE; ++BI) {
+      // Find the first include that's not in the right position.
+      unsigned I, E;
+      for (I = Blocks[BI], E = Blocks[BI + 1]; I != E; ++I)
+        if (IncludeIndices[I] != I)
+          break;
+
+      if (I == E)
+        continue;
+
+      // Emit a warning.
+      auto D = Check.diag(FileDirectives[I].Loc,
+                          "#includes are not sorted properly");
+
+      // Emit fix-its for all following includes in this block.
+      for (; I != E; ++I) {
+        if (IncludeIndices[I] == I)
+          continue;
+        const IncludeDirective &CopyFrom = FileDirectives[IncludeIndices[I]];
+
+        SourceLocation FromLoc = CopyFrom.Range.getBegin();
+        const char *FromData = SM.getCharacterData(FromLoc);
+        unsigned FromLen = std::strcspn(FromData, "\n");
+
+        StringRef FixedName(FromData, FromLen);
+
+        SourceLocation ToLoc = FileDirectives[I].Range.getBegin();
+        const char *ToData = SM.getCharacterData(ToLoc);
+        unsigned ToLen = std::strcspn(ToData, "\n");
+        auto ToRange =
+            CharSourceRange::getCharRange(ToLoc, ToLoc.getLocWithOffset(ToLen));
+
+        D << FixItHint::CreateReplacement(ToRange, FixedName);
+      }
+    }
+  }
+
+  IncludeDirectives.clear();
+}
+
+} // namespace llvm
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/IncludeOrderCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/IncludeOrderCheck.h
new file mode 100644
index 0000000..ad876b9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/IncludeOrderCheck.h
@@ -0,0 +1,33 @@
+//===--- IncludeOrderCheck.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_LLVM_INCLUDE_ORDER_CHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_INCLUDE_ORDER_CHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace llvm {
+
+/// Checks the correct order of `#includes`.
+///
+/// See http://llvm.org/docs/CodingStandards.html#include-style
+class IncludeOrderCheck : public ClangTidyCheck {
+public:
+  IncludeOrderCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+};
+
+} // namespace llvm
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_INCLUDE_ORDER_CHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
new file mode 100644
index 0000000..ea46ca9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
@@ -0,0 +1,44 @@
+//===--- LLVMTidyModule.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 "../readability/NamespaceCommentCheck.h"
+#include "HeaderGuardCheck.h"
+#include "IncludeOrderCheck.h"
+#include "TwineLocalCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace llvm {
+
+class LLVMModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<LLVMHeaderGuardCheck>("llvm-header-guard");
+    CheckFactories.registerCheck<IncludeOrderCheck>("llvm-include-order");
+    CheckFactories.registerCheck<readability::NamespaceCommentCheck>(
+        "llvm-namespace-comment");
+    CheckFactories.registerCheck<TwineLocalCheck>("llvm-twine-local");
+  }
+};
+
+// Register the LLVMTidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<LLVMModule> X("llvm-module",
+                                                  "Adds LLVM lint checks.");
+
+} // namespace llvm
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the LLVMModule.
+volatile int LLVMModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/TwineLocalCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/TwineLocalCheck.cpp
new file mode 100644
index 0000000..67c85a6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/TwineLocalCheck.cpp
@@ -0,0 +1,66 @@
+//===--- TwineLocalCheck.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 "TwineLocalCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace llvm {
+
+void TwineLocalCheck::registerMatchers(MatchFinder *Finder) {
+  auto TwineType =
+      qualType(hasDeclaration(recordDecl(hasName("::llvm::Twine"))));
+  Finder->addMatcher(varDecl(hasType(TwineType)).bind("variable"), this);
+}
+
+void TwineLocalCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *VD = Result.Nodes.getNodeAs<VarDecl>("variable");
+  auto Diag = diag(VD->getLocation(),
+                   "twine variables are prone to use-after-free bugs");
+
+  // If this VarDecl has an initializer try to fix it.
+  if (VD->hasInit()) {
+    // Peel away implicit constructors and casts so we can see the actual type
+    // of the initializer.
+    const Expr *C = VD->getInit()->IgnoreImplicit();
+
+    while (isa<CXXConstructExpr>(C)) {
+      if (cast<CXXConstructExpr>(C)->getNumArgs() == 0)
+        break;
+      C = cast<CXXConstructExpr>(C)->getArg(0)->IgnoreParenImpCasts();
+    }
+
+    SourceRange TypeRange =
+        VD->getTypeSourceInfo()->getTypeLoc().getSourceRange();
+
+    // A real Twine, turn it into a std::string.
+    if (VD->getType()->getCanonicalTypeUnqualified() ==
+        C->getType()->getCanonicalTypeUnqualified()) {
+      SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+          VD->getInit()->getLocEnd(), 0, *Result.SourceManager, getLangOpts());
+      Diag << FixItHint::CreateReplacement(TypeRange, "std::string")
+           << FixItHint::CreateInsertion(VD->getInit()->getLocStart(), "(")
+           << FixItHint::CreateInsertion(EndLoc, ").str()");
+    } else {
+      // Just an implicit conversion. Insert the real type.
+      Diag << FixItHint::CreateReplacement(
+          TypeRange,
+          C->getType().getAsString(Result.Context->getPrintingPolicy()));
+    }
+  }
+}
+
+} // namespace llvm
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/TwineLocalCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/TwineLocalCheck.h
new file mode 100644
index 0000000..9f7979b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/llvm/TwineLocalCheck.h
@@ -0,0 +1,33 @@
+//===--- TwineLocalCheck.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_LLVM_TWINE_LOCAL_CHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_TWINE_LOCAL_CHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace llvm {
+
+/// Looks for local `Twine` variables which are prone to use after frees and
+/// should be generally avoided.
+class TwineLocalCheck : public ClangTidyCheck {
+public:
+  TwineLocalCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace llvm
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_TWINE_LOCAL_CHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
new file mode 100644
index 0000000..3806398
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
@@ -0,0 +1,27 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyMiscModule
+  MisplacedConstCheck.cpp
+  UnconventionalAssignOperatorCheck.cpp
+  DefinitionsInHeadersCheck.cpp
+  MiscTidyModule.cpp
+  NewDeleteOverloadsCheck.cpp
+  NonCopyableObjects.cpp
+  RedundantExpressionCheck.cpp
+  StaticAssertCheck.cpp
+  ThrowByValueCatchByReferenceCheck.cpp
+  UniqueptrResetReleaseCheck.cpp
+  UnusedAliasDeclsCheck.cpp
+  UnusedParametersCheck.cpp
+  UnusedUsingDeclsCheck.cpp
+
+  LINK_LIBS
+  clangAnalysis
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyUtils
+  clangTooling
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
new file mode 100644
index 0000000..69ef3ef
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
@@ -0,0 +1,158 @@
+//===--- DefinitionsInHeadersCheck.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 "DefinitionsInHeadersCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+namespace {
+
+AST_MATCHER_P(NamedDecl, usesHeaderFileExtension,
+              utils::HeaderFileExtensionsSet, HeaderFileExtensions) {
+  return utils::isExpansionLocInHeaderFile(
+      Node.getLocStart(), Finder->getASTContext().getSourceManager(),
+      HeaderFileExtensions);
+}
+
+} // namespace
+
+DefinitionsInHeadersCheck::DefinitionsInHeadersCheck(StringRef Name,
+                                                     ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      UseHeaderFileExtension(Options.get("UseHeaderFileExtension", true)),
+      RawStringHeaderFileExtensions(Options.getLocalOrGlobal(
+          "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) {
+  if (!utils::parseHeaderFileExtensions(RawStringHeaderFileExtensions,
+                                        HeaderFileExtensions, ',')) {
+    // FIXME: Find a more suitable way to handle invalid configuration
+    // options.
+    llvm::errs() << "Invalid header file extension: "
+                 << RawStringHeaderFileExtensions << "\n";
+  }
+}
+
+void DefinitionsInHeadersCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "UseHeaderFileExtension", UseHeaderFileExtension);
+  Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
+}
+
+void DefinitionsInHeadersCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+  auto DefinitionMatcher =
+      anyOf(functionDecl(isDefinition(), unless(isDeleted())),
+            varDecl(isDefinition()));
+  if (UseHeaderFileExtension) {
+    Finder->addMatcher(namedDecl(DefinitionMatcher,
+                                 usesHeaderFileExtension(HeaderFileExtensions))
+                           .bind("name-decl"),
+                       this);
+  } else {
+    Finder->addMatcher(
+        namedDecl(DefinitionMatcher,
+                  anyOf(usesHeaderFileExtension(HeaderFileExtensions),
+                        unless(isExpansionInMainFile())))
+            .bind("name-decl"),
+        this);
+  }
+}
+
+void DefinitionsInHeadersCheck::check(const MatchFinder::MatchResult &Result) {
+  // Don't run the check in failing TUs.
+  if (Result.Context->getDiagnostics().hasUncompilableErrorOccurred())
+    return;
+
+  // C++ [basic.def.odr] p6:
+  // There can be more than one definition of a class type, enumeration type,
+  // inline function with external linkage, class template, non-static function
+  // template, static data member of a class template, member function of a
+  // class template, or template specialization for which some template
+  // parameters are not specifiedin a program provided that each definition
+  // appears in a different translation unit, and provided the definitions
+  // satisfy the following requirements.
+  const auto *ND = Result.Nodes.getNodeAs<NamedDecl>("name-decl");
+  assert(ND);
+  if (ND->isInvalidDecl())
+    return;
+
+  // Internal linkage variable definitions are ignored for now:
+  //   const int a = 1;
+  //   static int b = 1;
+  //
+  // Although these might also cause ODR violations, we can be less certain and
+  // should try to keep the false-positive rate down.
+  //
+  // 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)) {
+    // Inline functions are allowed.
+    if (FD->isInlined())
+      return;
+    // Function templates are allowed.
+    if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
+      return;
+    // Ignore instantiated functions.
+    if (FD->isTemplateInstantiation())
+      return;
+    // Member function of a class template and member function of a nested class
+    // in a class template are allowed.
+    if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+      const auto *DC = MD->getDeclContext();
+      while (DC->isRecord()) {
+        if (const auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
+          if (isa<ClassTemplatePartialSpecializationDecl>(RD))
+            return;
+          if (RD->getDescribedClassTemplate())
+            return;
+        }
+        DC = DC->getParent();
+      }
+    }
+
+    bool is_full_spec = FD->getTemplateSpecializationKind() != TSK_Undeclared;
+    diag(FD->getLocation(),
+         "%select{function|full function template specialization}0 %1 defined "
+         "in a header file; function definitions in header files can lead to "
+         "ODR violations")
+        << is_full_spec << FD << FixItHint::CreateInsertion(
+                     FD->getReturnTypeSourceRange().getBegin(), "inline ");
+  } else if (const auto *VD = dyn_cast<VarDecl>(ND)) {
+    // Static data members of a class template are allowed.
+    if (VD->getDeclContext()->isDependentContext() && VD->isStaticDataMember())
+      return;
+    // Ignore instantiated static data members of classes.
+    if (isTemplateInstantiation(VD->getTemplateSpecializationKind()))
+      return;
+    // 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; "
+         "variable definitions in header files can lead to ODR violations")
+        << VD;
+  }
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.h
new file mode 100644
index 0000000..428b05c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.h
@@ -0,0 +1,51 @@
+//===--- DefinitionsInHeadersCheck.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_MISC_DEFINITIONS_IN_HEADERS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_DEFINITIONS_IN_HEADERS_H
+
+#include "../ClangTidy.h"
+#include "../utils/HeaderFileExtensionsUtils.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Finds non-extern non-inline function and variable definitions in header
+/// files, which can lead to potential ODR violations.
+///
+/// The check supports these options:
+///   - `UseHeaderFileExtension`: Whether to use file extension to distinguish
+///     header files. True by default.
+///   - `HeaderFileExtensions`: a comma-separated list of filename extensions of
+///     header files (The filename extension should not contain "." prefix).
+///     ",h,hh,hpp,hxx" by default.
+///     For extension-less header files, using an empty string or leaving an
+///     empty string between "," if there are other filename extensions.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-definitions-in-headers.html
+class DefinitionsInHeadersCheck : public ClangTidyCheck {
+public:
+  DefinitionsInHeadersCheck(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 UseHeaderFileExtension;
+  const std::string RawStringHeaderFileExtensions;
+  utils::HeaderFileExtensionsSet HeaderFileExtensions;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_DEFINITIONS_IN_HEADERS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
new file mode 100644
index 0000000..241689a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
@@ -0,0 +1,69 @@
+//===--- MiscTidyModule.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 "DefinitionsInHeadersCheck.h"
+#include "MisplacedConstCheck.h"
+#include "NewDeleteOverloadsCheck.h"
+#include "NonCopyableObjects.h"
+#include "RedundantExpressionCheck.h"
+#include "StaticAssertCheck.h"
+#include "ThrowByValueCatchByReferenceCheck.h"
+#include "UnconventionalAssignOperatorCheck.h"
+#include "UniqueptrResetReleaseCheck.h"
+#include "UnusedAliasDeclsCheck.h"
+#include "UnusedParametersCheck.h"
+#include "UnusedUsingDeclsCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+class MiscModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<MisplacedConstCheck>("misc-misplaced-const");
+    CheckFactories.registerCheck<UnconventionalAssignOperatorCheck>(
+        "misc-unconventional-assign-operator");
+    CheckFactories.registerCheck<DefinitionsInHeadersCheck>(
+        "misc-definitions-in-headers");
+    CheckFactories.registerCheck<NewDeleteOverloadsCheck>(
+        "misc-new-delete-overloads");
+    CheckFactories.registerCheck<NonCopyableObjectsCheck>(
+        "misc-non-copyable-objects");
+    CheckFactories.registerCheck<RedundantExpressionCheck>(
+        "misc-redundant-expression");
+    CheckFactories.registerCheck<StaticAssertCheck>("misc-static-assert");
+    CheckFactories.registerCheck<ThrowByValueCatchByReferenceCheck>(
+        "misc-throw-by-value-catch-by-reference");
+    CheckFactories.registerCheck<UniqueptrResetReleaseCheck>(
+        "misc-uniqueptr-reset-release");
+    CheckFactories.registerCheck<UnusedAliasDeclsCheck>(
+        "misc-unused-alias-decls");
+    CheckFactories.registerCheck<UnusedParametersCheck>(
+        "misc-unused-parameters");
+    CheckFactories.registerCheck<UnusedUsingDeclsCheck>(
+        "misc-unused-using-decls");
+  }
+};
+
+} // namespace misc
+
+// Register the MiscTidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<misc::MiscModule>
+    X("misc-module", "Adds miscellaneous lint checks.");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the MiscModule.
+volatile int MiscModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/MisplacedConstCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/MisplacedConstCheck.cpp
new file mode 100644
index 0000000..515b22c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/MisplacedConstCheck.cpp
@@ -0,0 +1,63 @@
+//===--- MisplacedConstCheck.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 "MisplacedConstCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+void MisplacedConstCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      valueDecl(hasType(isConstQualified()),
+                hasType(typedefType(hasDeclaration(
+                    typedefDecl(hasType(pointerType(unless(pointee(
+                                    anyOf(isConstQualified(),
+                                          ignoringParens(functionType())))))))
+                        .bind("typedef")))))
+          .bind("decl"),
+      this);
+}
+
+static QualType guessAlternateQualification(ASTContext &Context, QualType QT) {
+  // We're given a QualType from a typedef where the qualifiers apply to the
+  // pointer instead of the pointee. Strip the const qualifier from the pointer
+  // type and add it to the pointee instead.
+  if (!QT->isPointerType())
+    return QT;
+
+  Qualifiers Quals = QT.getLocalQualifiers();
+  Quals.removeConst();
+
+  QualType NewQT = Context.getPointerType(
+      QualType(QT->getPointeeType().getTypePtr(), Qualifiers::Const));
+  return NewQT.withCVRQualifiers(Quals.getCVRQualifiers());
+}
+
+void MisplacedConstCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Var = Result.Nodes.getNodeAs<ValueDecl>("decl");
+  const auto *Typedef = Result.Nodes.getNodeAs<TypedefDecl>("typedef");
+  ASTContext &Ctx = *Result.Context;
+  QualType CanQT = Var->getType().getCanonicalType();
+
+  diag(Var->getLocation(), "%0 declared with a const-qualified typedef type; "
+                           "results in the type being '%1' instead of '%2'")
+      << Var << CanQT.getAsString(Ctx.getPrintingPolicy())
+      << guessAlternateQualification(Ctx, CanQT)
+             .getAsString(Ctx.getPrintingPolicy());
+  diag(Typedef->getLocation(), "typedef declared here", DiagnosticIDs::Note);
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/MisplacedConstCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/MisplacedConstCheck.h
new file mode 100644
index 0000000..410edf7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/MisplacedConstCheck.h
@@ -0,0 +1,36 @@
+//===--- MisplacedConstCheck.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_MISC_MISPLACED_CONST_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MISPLACED_CONST_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// This check diagnoses when a const qualifier is applied to a typedef to a
+/// pointer type rather than to the pointee.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-misplaced-const.html
+class MisplacedConstCheck : public ClangTidyCheck {
+public:
+  MisplacedConstCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MISPLACED_CONST_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.cpp
new file mode 100644
index 0000000..5e29119
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.cpp
@@ -0,0 +1,213 @@
+//===--- NewDeleteOverloadsCheck.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 "NewDeleteOverloadsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+namespace {
+
+AST_MATCHER(FunctionDecl, isPlacementOverload) {
+  bool New;
+  switch (Node.getOverloadedOperator()) {
+  default:
+    return false;
+  case OO_New:
+  case OO_Array_New:
+    New = true;
+    break;
+  case OO_Delete:
+  case OO_Array_Delete:
+    New = false;
+    break;
+  }
+
+  // Variadic functions are always placement functions.
+  if (Node.isVariadic())
+    return true;
+
+  // Placement new is easy: it always has more than one parameter (the first
+  // parameter is always the size). If it's an overload of delete or delete[]
+  // that has only one parameter, it's never a placement delete.
+  if (New)
+    return Node.getNumParams() > 1;
+  if (Node.getNumParams() == 1)
+    return false;
+
+  // Placement delete is a little more challenging. They always have more than
+  // one parameter with the first parameter being a pointer. However, the
+  // second parameter can be a size_t for sized deallocation, and that is never
+  // a placement delete operator.
+  if (Node.getNumParams() <= 1 || Node.getNumParams() > 2)
+    return true;
+
+  const auto *FPT = Node.getType()->castAs<FunctionProtoType>();
+  ASTContext &Ctx = Node.getASTContext();
+  if (Ctx.getLangOpts().SizedDeallocation &&
+      Ctx.hasSameType(FPT->getParamType(1), Ctx.getSizeType()))
+    return false;
+
+  return true;
+}
+
+OverloadedOperatorKind getCorrespondingOverload(const FunctionDecl *FD) {
+  switch (FD->getOverloadedOperator()) {
+  default:
+    break;
+  case OO_New:
+    return OO_Delete;
+  case OO_Delete:
+    return OO_New;
+  case OO_Array_New:
+    return OO_Array_Delete;
+  case OO_Array_Delete:
+    return OO_Array_New;
+  }
+  llvm_unreachable("Not an overloaded allocation operator");
+}
+
+const char *getOperatorName(OverloadedOperatorKind K) {
+  switch (K) {
+  default:
+    break;
+  case OO_New:
+    return "operator new";
+  case OO_Delete:
+    return "operator delete";
+  case OO_Array_New:
+    return "operator new[]";
+  case OO_Array_Delete:
+    return "operator delete[]";
+  }
+  llvm_unreachable("Not an overloaded allocation operator");
+}
+
+bool areCorrespondingOverloads(const FunctionDecl *LHS,
+                               const FunctionDecl *RHS) {
+  return RHS->getOverloadedOperator() == getCorrespondingOverload(LHS);
+}
+
+bool hasCorrespondingOverloadInBaseClass(const CXXMethodDecl *MD,
+                                         const CXXRecordDecl *RD = nullptr) {
+  if (RD) {
+    // Check the methods in the given class and accessible to derived classes.
+    for (const auto *BMD : RD->methods())
+      if (BMD->isOverloadedOperator() && BMD->getAccess() != AS_private &&
+          areCorrespondingOverloads(MD, BMD))
+        return true;
+  } else {
+    // Get the parent class of the method; we do not need to care about checking
+    // the methods in this class as the caller has already done that by looking
+    // at the declaration contexts.
+    RD = MD->getParent();
+  }
+
+  for (const auto &BS : RD->bases()) {
+    // We can't say much about a dependent base class, but to avoid false
+    // positives assume it can have a corresponding overload.
+    if (BS.getType()->isDependentType())
+      return true;
+    if (const auto *BaseRD = BS.getType()->getAsCXXRecordDecl())
+      if (hasCorrespondingOverloadInBaseClass(MD, BaseRD))
+        return true;
+  }
+
+  return false;
+}
+
+} // anonymous namespace
+
+void NewDeleteOverloadsCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // Match all operator new and operator delete overloads (including the array
+  // forms). Do not match implicit operators, placement operators, or
+  // deleted/private operators.
+  //
+  // Technically, trivially-defined operator delete seems like a reasonable
+  // thing to also skip. e.g., void operator delete(void *) {}
+  // However, I think it's more reasonable to warn in this case as the user
+  // should really be writing that as a deleted function.
+  Finder->addMatcher(
+      functionDecl(unless(anyOf(isImplicit(), isPlacementOverload(),
+                                isDeleted(), cxxMethodDecl(isPrivate()))),
+                   anyOf(hasOverloadedOperatorName("new"),
+                         hasOverloadedOperatorName("new[]"),
+                         hasOverloadedOperatorName("delete"),
+                         hasOverloadedOperatorName("delete[]")))
+          .bind("func"),
+      this);
+}
+
+void NewDeleteOverloadsCheck::check(const MatchFinder::MatchResult &Result) {
+  // Add any matches we locate to the list of things to be checked at the
+  // end of the translation unit.
+  const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("func");
+  const CXXRecordDecl *RD = nullptr;
+  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
+    RD = MD->getParent();
+  Overloads[RD].push_back(FD);
+}
+
+void NewDeleteOverloadsCheck::onEndOfTranslationUnit() {
+  // Walk over the list of declarations we've found to see if there is a
+  // corresponding overload at the same declaration context or within a base
+  // class. If there is not, add the element to the list of declarations to
+  // diagnose.
+  SmallVector<const FunctionDecl *, 4> Diagnose;
+  for (const auto &RP : Overloads) {
+    // We don't care about the CXXRecordDecl key in the map; we use it as a way
+    // to shard the overloads by declaration context to reduce the algorithmic
+    // complexity when searching for corresponding free store functions.
+    for (const auto *Overload : RP.second) {
+      const auto *Match =
+          std::find_if(RP.second.begin(), RP.second.end(),
+                       [&Overload](const FunctionDecl *FD) {
+                         if (FD == Overload)
+                           return false;
+                         // If the declaration contexts don't match, we don't
+                         // need to check any further.
+                         if (FD->getDeclContext() != Overload->getDeclContext())
+                           return false;
+
+                         // Since the declaration contexts match, see whether
+                         // the current element is the corresponding operator.
+                         if (!areCorrespondingOverloads(Overload, FD))
+                           return false;
+
+                         return true;
+                       });
+
+      if (Match == RP.second.end()) {
+        // Check to see if there is a corresponding overload in a base class
+        // context. If there isn't, or if the overload is not a class member
+        // function, then we should diagnose.
+        const auto *MD = dyn_cast<CXXMethodDecl>(Overload);
+        if (!MD || !hasCorrespondingOverloadInBaseClass(MD))
+          Diagnose.push_back(Overload);
+      }
+    }
+  }
+
+  for (const auto *FD : Diagnose)
+    diag(FD->getLocation(), "declaration of %0 has no matching declaration "
+                            "of '%1' at the same scope")
+        << FD << getOperatorName(getCorrespondingOverload(FD));
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.h
new file mode 100644
index 0000000..3e99892
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.h
@@ -0,0 +1,38 @@
+//===--- NewDeleteOverloadsCheck.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_MISC_NEWDELETEOVERLOADS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_NEWDELETEOVERLOADS_H
+
+#include "../ClangTidy.h"
+#include "llvm/ADT/SmallVector.h"
+#include <map>
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+class NewDeleteOverloadsCheck : public ClangTidyCheck {
+  std::map<const clang::CXXRecordDecl *,
+           llvm::SmallVector<const clang::FunctionDecl *, 4>>
+      Overloads;
+
+public:
+  NewDeleteOverloadsCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void onEndOfTranslationUnit() override;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_NEWDELETEOVERLOADS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/NonCopyableObjects.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/NonCopyableObjects.cpp
new file mode 100644
index 0000000..de15275
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/NonCopyableObjects.cpp
@@ -0,0 +1,74 @@
+//===--- NonCopyableObjects.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 "NonCopyableObjects.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include <algorithm>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+void NonCopyableObjectsCheck::registerMatchers(MatchFinder *Finder) {
+  // There are two ways to get into trouble with objects like FILE *:
+  // dereferencing the pointer type to be a non-pointer type, and declaring
+  // the type as a non-pointer type in the first place. While the declaration
+  // itself could technically be well-formed in the case where the type is not
+  // an opaque type, it's highly suspicious behavior.
+  //
+  // POSIX types are a bit different in that it's reasonable to declare a
+  // non-pointer variable or data member of the type, but it is not reasonable
+  // to dereference a pointer to the type, or declare a parameter of non-pointer
+  // type.
+  // FIXME: it would be good to make a list that is also user-configurable so
+  // that users can add their own elements to the list. However, it may require
+  // some extra thought since POSIX types and FILE types are usable in different
+  // ways.
+
+  auto BadFILEType = hasType(
+      namedDecl(hasAnyName("::FILE", "FILE", "std::FILE")).bind("type_decl"));
+  auto BadPOSIXType =
+      hasType(namedDecl(hasAnyName("::pthread_cond_t", "::pthread_mutex_t",
+                                   "pthread_cond_t", "pthread_mutex_t"))
+                  .bind("type_decl"));
+  auto BadEitherType = anyOf(BadFILEType, BadPOSIXType);
+
+  Finder->addMatcher(
+      namedDecl(anyOf(varDecl(BadFILEType), fieldDecl(BadFILEType)))
+          .bind("decl"),
+      this);
+  Finder->addMatcher(parmVarDecl(BadPOSIXType).bind("decl"), this);
+  Finder->addMatcher(
+      expr(unaryOperator(hasOperatorName("*"), BadEitherType)).bind("expr"),
+      this);
+}
+
+void NonCopyableObjectsCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *D = Result.Nodes.getNodeAs<NamedDecl>("decl");
+  const auto *BD = Result.Nodes.getNodeAs<NamedDecl>("type_decl");
+  const auto *E = Result.Nodes.getNodeAs<Expr>("expr");
+
+  if (D && BD)
+    diag(D->getLocation(), "%0 declared as type '%1', which is unsafe to copy"
+                           "; did you mean '%1 *'?")
+        << D << BD->getName();
+  else if (E)
+    diag(E->getExprLoc(),
+         "expression has opaque data structure type %0; type should only be "
+         "used as a pointer and not dereferenced")
+        << BD;
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/NonCopyableObjects.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/NonCopyableObjects.h
new file mode 100644
index 0000000..38a45fd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/NonCopyableObjects.h
@@ -0,0 +1,33 @@
+//===--- NonCopyableObjects.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_MISC_NONCOPYABLEOBJECTS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_NONCOPYABLEOBJECTS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// The check flags dereferences and non-pointer declarations of objects that
+/// are not meant to be passed by value, such as C FILE objects.
+class NonCopyableObjectsCheck : public ClangTidyCheck {
+public:
+  NonCopyableObjectsCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_NONCOPYABLEOBJECTS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
new file mode 100644
index 0000000..e259b6b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
@@ -0,0 +1,1081 @@
+//===--- RedundantExpressionCheck.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 "RedundantExpressionCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/Casting.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+using namespace clang::ast_matchers;
+using namespace clang::tidy::matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+namespace {
+using llvm::APSInt;
+
+static constexpr llvm::StringLiteral KnownBannedMacroNames[] = {
+    "EAGAIN",
+    "EWOULDBLOCK",
+    "SIGCLD",
+    "SIGCHLD",
+};
+
+static bool incrementWithoutOverflow(const APSInt &Value, APSInt &Result) {
+  Result = Value;
+  ++Result;
+  return Value < Result;
+}
+
+static bool areEquivalentNameSpecifier(const NestedNameSpecifier *Left,
+                                       const NestedNameSpecifier *Right) {
+  llvm::FoldingSetNodeID LeftID, RightID;
+  Left->Profile(LeftID);
+  Right->Profile(RightID);
+  return LeftID == RightID;
+}
+
+static bool areEquivalentExpr(const Expr *Left, const Expr *Right) {
+  if (!Left || !Right)
+    return !Left && !Right;
+
+  Left = Left->IgnoreParens();
+  Right = Right->IgnoreParens();
+
+  // Compare classes.
+  if (Left->getStmtClass() != Right->getStmtClass())
+    return false;
+
+  // Compare children.
+  Expr::const_child_iterator LeftIter = Left->child_begin();
+  Expr::const_child_iterator RightIter = Right->child_begin();
+  while (LeftIter != Left->child_end() && RightIter != Right->child_end()) {
+    if (!areEquivalentExpr(dyn_cast<Expr>(*LeftIter),
+                           dyn_cast<Expr>(*RightIter)))
+      return false;
+    ++LeftIter;
+    ++RightIter;
+  }
+  if (LeftIter != Left->child_end() || RightIter != Right->child_end())
+    return false;
+
+  // Perform extra checks.
+  switch (Left->getStmtClass()) {
+  default:
+    return false;
+
+  case Stmt::CharacterLiteralClass:
+    return cast<CharacterLiteral>(Left)->getValue() ==
+           cast<CharacterLiteral>(Right)->getValue();
+  case Stmt::IntegerLiteralClass: {
+    llvm::APInt LeftLit = cast<IntegerLiteral>(Left)->getValue();
+    llvm::APInt RightLit = cast<IntegerLiteral>(Right)->getValue();
+    return LeftLit.getBitWidth() == RightLit.getBitWidth() &&
+           LeftLit == RightLit;
+  }
+  case Stmt::FloatingLiteralClass:
+    return cast<FloatingLiteral>(Left)->getValue().bitwiseIsEqual(
+        cast<FloatingLiteral>(Right)->getValue());
+  case Stmt::StringLiteralClass:
+    return cast<StringLiteral>(Left)->getBytes() ==
+           cast<StringLiteral>(Right)->getBytes();
+  case Stmt::CXXOperatorCallExprClass:
+    return cast<CXXOperatorCallExpr>(Left)->getOperator() ==
+           cast<CXXOperatorCallExpr>(Right)->getOperator();
+  case Stmt::DependentScopeDeclRefExprClass:
+    if (cast<DependentScopeDeclRefExpr>(Left)->getDeclName() !=
+        cast<DependentScopeDeclRefExpr>(Right)->getDeclName())
+      return false;
+    return areEquivalentNameSpecifier(
+        cast<DependentScopeDeclRefExpr>(Left)->getQualifier(),
+        cast<DependentScopeDeclRefExpr>(Right)->getQualifier());
+  case Stmt::DeclRefExprClass:
+    return cast<DeclRefExpr>(Left)->getDecl() ==
+           cast<DeclRefExpr>(Right)->getDecl();
+  case Stmt::MemberExprClass:
+    return cast<MemberExpr>(Left)->getMemberDecl() ==
+           cast<MemberExpr>(Right)->getMemberDecl();
+  case Stmt::CXXFunctionalCastExprClass:
+  case Stmt::CStyleCastExprClass:
+    return cast<ExplicitCastExpr>(Left)->getTypeAsWritten() ==
+           cast<ExplicitCastExpr>(Right)->getTypeAsWritten();
+  case Stmt::CallExprClass:
+  case Stmt::ImplicitCastExprClass:
+  case Stmt::ArraySubscriptExprClass:
+    return true;
+  case Stmt::UnaryOperatorClass:
+    if (cast<UnaryOperator>(Left)->isIncrementDecrementOp())
+      return false;
+    return cast<UnaryOperator>(Left)->getOpcode() ==
+           cast<UnaryOperator>(Right)->getOpcode();
+  case Stmt::BinaryOperatorClass:
+    return cast<BinaryOperator>(Left)->getOpcode() ==
+           cast<BinaryOperator>(Right)->getOpcode();
+  }
+}
+
+// For a given expression 'x', returns whether the ranges covered by the
+// relational operators are equivalent (i.e.  x <= 4 is equivalent to x < 5).
+static bool areEquivalentRanges(BinaryOperatorKind OpcodeLHS,
+                                const APSInt &ValueLHS,
+                                BinaryOperatorKind OpcodeRHS,
+                                const APSInt &ValueRHS) {
+  assert(APSInt::compareValues(ValueLHS, ValueRHS) <= 0 &&
+         "Values must be ordered");
+  // Handle the case where constants are the same: x <= 4  <==>  x <= 4.
+  if (APSInt::compareValues(ValueLHS, ValueRHS) == 0)
+    return OpcodeLHS == OpcodeRHS;
+
+  // Handle the case where constants are off by one: x <= 4  <==>  x < 5.
+  APSInt ValueLHS_plus1;
+  return ((OpcodeLHS == BO_LE && OpcodeRHS == BO_LT) ||
+          (OpcodeLHS == BO_GT && OpcodeRHS == BO_GE)) &&
+         incrementWithoutOverflow(ValueLHS, ValueLHS_plus1) &&
+         APSInt::compareValues(ValueLHS_plus1, ValueRHS) == 0;
+}
+
+// For a given expression 'x', returns whether the ranges covered by the
+// relational operators are fully disjoint (i.e. x < 4  and  x > 7).
+static bool areExclusiveRanges(BinaryOperatorKind OpcodeLHS,
+                               const APSInt &ValueLHS,
+                               BinaryOperatorKind OpcodeRHS,
+                               const APSInt &ValueRHS) {
+  assert(APSInt::compareValues(ValueLHS, ValueRHS) <= 0 &&
+         "Values must be ordered");
+
+  // Handle cases where the constants are the same.
+  if (APSInt::compareValues(ValueLHS, ValueRHS) == 0) {
+    switch (OpcodeLHS) {
+    case BO_EQ:
+      return OpcodeRHS == BO_NE || OpcodeRHS == BO_GT || OpcodeRHS == BO_LT;
+    case BO_NE:
+      return OpcodeRHS == BO_EQ;
+    case BO_LE:
+      return OpcodeRHS == BO_GT;
+    case BO_GE:
+      return OpcodeRHS == BO_LT;
+    case BO_LT:
+      return OpcodeRHS == BO_EQ || OpcodeRHS == BO_GT || OpcodeRHS == BO_GE;
+    case BO_GT:
+      return OpcodeRHS == BO_EQ || OpcodeRHS == BO_LT || OpcodeRHS == BO_LE;
+    default:
+      return false;
+    }
+  }
+
+  // Handle cases where the constants are different.
+  if ((OpcodeLHS == BO_EQ || OpcodeLHS == BO_LT || OpcodeLHS == BO_LE) &&
+      (OpcodeRHS == BO_EQ || OpcodeRHS == BO_GT || OpcodeRHS == BO_GE))
+    return true;
+
+  // Handle the case where constants are off by one: x > 5 && x < 6.
+  APSInt ValueLHS_plus1;
+  if (OpcodeLHS == BO_GT && OpcodeRHS == BO_LT &&
+      incrementWithoutOverflow(ValueLHS, ValueLHS_plus1) &&
+      APSInt::compareValues(ValueLHS_plus1, ValueRHS) == 0)
+    return true;
+
+  return false;
+}
+
+// Returns whether the ranges covered by the union of both relational
+// expressions cover the whole domain (i.e. x < 10  and  x > 0).
+static bool rangesFullyCoverDomain(BinaryOperatorKind OpcodeLHS,
+                                   const APSInt &ValueLHS,
+                                   BinaryOperatorKind OpcodeRHS,
+                                   const APSInt &ValueRHS) {
+  assert(APSInt::compareValues(ValueLHS, ValueRHS) <= 0 &&
+         "Values must be ordered");
+
+  // Handle cases where the constants are the same:  x < 5 || x >= 5.
+  if (APSInt::compareValues(ValueLHS, ValueRHS) == 0) {
+    switch (OpcodeLHS) {
+    case BO_EQ:
+      return OpcodeRHS == BO_NE;
+    case BO_NE:
+      return OpcodeRHS == BO_EQ;
+    case BO_LE:
+      return OpcodeRHS == BO_GT || OpcodeRHS == BO_GE;
+    case BO_LT:
+      return OpcodeRHS == BO_GE;
+    case BO_GE:
+      return OpcodeRHS == BO_LT || OpcodeRHS == BO_LE;
+    case BO_GT:
+      return OpcodeRHS == BO_LE;
+    default:
+      return false;
+    }
+  }
+
+  // Handle the case where constants are off by one: x <= 4 || x >= 5.
+  APSInt ValueLHS_plus1;
+  if (OpcodeLHS == BO_LE && OpcodeRHS == BO_GE &&
+      incrementWithoutOverflow(ValueLHS, ValueLHS_plus1) &&
+      APSInt::compareValues(ValueLHS_plus1, ValueRHS) == 0)
+    return true;
+
+  // Handle cases where the constants are different: x > 4 || x <= 7.
+  if ((OpcodeLHS == BO_GT || OpcodeLHS == BO_GE) &&
+      (OpcodeRHS == BO_LT || OpcodeRHS == BO_LE))
+    return true;
+
+  // Handle cases where constants are different but both ops are !=, like:
+  // x != 5 || x != 10
+  if (OpcodeLHS == BO_NE && OpcodeRHS == BO_NE)
+    return true;
+
+  return false;
+}
+
+static bool rangeSubsumesRange(BinaryOperatorKind OpcodeLHS,
+                               const APSInt &ValueLHS,
+                               BinaryOperatorKind OpcodeRHS,
+                               const APSInt &ValueRHS) {
+  int Comparison = APSInt::compareValues(ValueLHS, ValueRHS);
+  switch (OpcodeLHS) {
+  case BO_EQ:
+    return OpcodeRHS == BO_EQ && Comparison == 0;
+  case BO_NE:
+    return (OpcodeRHS == BO_NE && Comparison == 0) ||
+           (OpcodeRHS == BO_EQ && Comparison != 0) ||
+           (OpcodeRHS == BO_LT && Comparison >= 0) ||
+           (OpcodeRHS == BO_LE && Comparison > 0) ||
+           (OpcodeRHS == BO_GT && Comparison <= 0) ||
+           (OpcodeRHS == BO_GE && Comparison < 0);
+
+  case BO_LT:
+    return ((OpcodeRHS == BO_LT && Comparison >= 0) ||
+            (OpcodeRHS == BO_LE && Comparison > 0) ||
+            (OpcodeRHS == BO_EQ && Comparison > 0));
+  case BO_GT:
+    return ((OpcodeRHS == BO_GT && Comparison <= 0) ||
+            (OpcodeRHS == BO_GE && Comparison < 0) ||
+            (OpcodeRHS == BO_EQ && Comparison < 0));
+  case BO_LE:
+    return (OpcodeRHS == BO_LT || OpcodeRHS == BO_LE || OpcodeRHS == BO_EQ) &&
+           Comparison >= 0;
+  case BO_GE:
+    return (OpcodeRHS == BO_GT || OpcodeRHS == BO_GE || OpcodeRHS == BO_EQ) &&
+           Comparison <= 0;
+  default:
+    return false;
+  }
+}
+
+static void transformSubToCanonicalAddExpr(BinaryOperatorKind &Opcode,
+                                           APSInt &Value) {
+  if (Opcode == BO_Sub) {
+    Opcode = BO_Add;
+    Value = -Value;
+  }
+}
+
+AST_MATCHER(Expr, isIntegerConstantExpr) {
+  if (Node.isInstantiationDependent())
+    return false;
+  return Node.isIntegerConstantExpr(Finder->getASTContext());
+}
+
+AST_MATCHER(BinaryOperator, operandsAreEquivalent) {
+  return areEquivalentExpr(Node.getLHS(), Node.getRHS());
+}
+
+AST_MATCHER(ConditionalOperator, expressionsAreEquivalent) {
+  return areEquivalentExpr(Node.getTrueExpr(), Node.getFalseExpr());
+}
+
+AST_MATCHER(CallExpr, parametersAreEquivalent) {
+  return Node.getNumArgs() == 2 &&
+         areEquivalentExpr(Node.getArg(0), Node.getArg(1));
+}
+
+AST_MATCHER(BinaryOperator, binaryOperatorIsInMacro) {
+  return Node.getOperatorLoc().isMacroID();
+}
+
+AST_MATCHER(ConditionalOperator, conditionalOperatorIsInMacro) {
+  return Node.getQuestionLoc().isMacroID() || Node.getColonLoc().isMacroID();
+}
+
+AST_MATCHER(Expr, isMacro) { return Node.getExprLoc().isMacroID(); }
+
+AST_MATCHER_P(Expr, expandedByMacro, ArrayRef<llvm::StringLiteral>, Names) {
+  const SourceManager &SM = Finder->getASTContext().getSourceManager();
+  const LangOptions &LO = Finder->getASTContext().getLangOpts();
+  SourceLocation Loc = Node.getExprLoc();
+  while (Loc.isMacroID()) {
+    StringRef MacroName = Lexer::getImmediateMacroName(Loc, SM, LO);
+    if (llvm::is_contained(Names, MacroName))
+      return true;
+    Loc = SM.getImmediateMacroCallerLoc(Loc);
+  }
+  return false;
+}
+
+// Returns a matcher for integer constant expressions.
+static ast_matchers::internal::Matcher<Expr>
+matchIntegerConstantExpr(StringRef Id) {
+  std::string CstId = (Id + "-const").str();
+  return expr(isIntegerConstantExpr()).bind(CstId);
+}
+
+// Retrieves the integer expression matched by 'matchIntegerConstantExpr' with
+// name 'Id' and stores it into 'ConstExpr', the value of the expression is
+// stored into `Value`.
+static bool retrieveIntegerConstantExpr(const MatchFinder::MatchResult &Result,
+                                        StringRef Id, APSInt &Value,
+                                        const Expr *&ConstExpr) {
+  std::string CstId = (Id + "-const").str();
+  ConstExpr = Result.Nodes.getNodeAs<Expr>(CstId);
+  return ConstExpr && ConstExpr->isIntegerConstantExpr(Value, *Result.Context);
+}
+
+// Overloaded `retrieveIntegerConstantExpr` for compatibility.
+static bool retrieveIntegerConstantExpr(const MatchFinder::MatchResult &Result,
+                                        StringRef Id, APSInt &Value) {
+  const Expr *ConstExpr = nullptr;
+  return retrieveIntegerConstantExpr(Result, Id, Value, ConstExpr);
+}
+
+// Returns a matcher for symbolic expressions (matches every expression except
+// ingeter constant expressions).
+static ast_matchers::internal::Matcher<Expr> matchSymbolicExpr(StringRef Id) {
+  std::string SymId = (Id + "-sym").str();
+  return ignoringParenImpCasts(
+      expr(unless(isIntegerConstantExpr())).bind(SymId));
+}
+
+// Retrieves the expression matched by 'matchSymbolicExpr' with name 'Id' and
+// stores it into 'SymExpr'.
+static bool retrieveSymbolicExpr(const MatchFinder::MatchResult &Result,
+                                 StringRef Id, const Expr *&SymExpr) {
+  std::string SymId = (Id + "-sym").str();
+  if (const auto *Node = Result.Nodes.getNodeAs<Expr>(SymId)) {
+    SymExpr = Node;
+    return true;
+  }
+  return false;
+}
+
+// Match a binary operator between a symbolic expression and an integer constant
+// expression.
+static ast_matchers::internal::Matcher<Expr>
+matchBinOpIntegerConstantExpr(StringRef Id) {
+  const auto BinOpCstExpr =
+      expr(
+          anyOf(binaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("|"),
+                                     hasOperatorName("&")),
+                               hasEitherOperand(matchSymbolicExpr(Id)),
+                               hasEitherOperand(matchIntegerConstantExpr(Id))),
+                binaryOperator(hasOperatorName("-"),
+                               hasLHS(matchSymbolicExpr(Id)),
+                               hasRHS(matchIntegerConstantExpr(Id)))))
+          .bind(Id);
+  return ignoringParenImpCasts(BinOpCstExpr);
+}
+
+// Retrieves sub-expressions matched by 'matchBinOpIntegerConstantExpr' with
+// name 'Id'.
+static bool
+retrieveBinOpIntegerConstantExpr(const MatchFinder::MatchResult &Result,
+                                 StringRef Id, BinaryOperatorKind &Opcode,
+                                 const Expr *&Symbol, APSInt &Value) {
+  if (const auto *BinExpr = Result.Nodes.getNodeAs<BinaryOperator>(Id)) {
+    Opcode = BinExpr->getOpcode();
+    return retrieveSymbolicExpr(Result, Id, Symbol) &&
+           retrieveIntegerConstantExpr(Result, Id, Value);
+  }
+  return false;
+}
+
+// Matches relational expressions: 'Expr <op> k' (i.e. x < 2, x != 3, 12 <= x).
+static ast_matchers::internal::Matcher<Expr>
+matchRelationalIntegerConstantExpr(StringRef Id) {
+  std::string CastId = (Id + "-cast").str();
+  std::string SwapId = (Id + "-swap").str();
+  std::string NegateId = (Id + "-negate").str();
+  std::string OverloadId = (Id + "-overload").str();
+
+  const auto RelationalExpr = ignoringParenImpCasts(binaryOperator(
+      isComparisonOperator(), expr().bind(Id),
+      anyOf(allOf(hasLHS(matchSymbolicExpr(Id)),
+                  hasRHS(matchIntegerConstantExpr(Id))),
+            allOf(hasLHS(matchIntegerConstantExpr(Id)),
+                  hasRHS(matchSymbolicExpr(Id)), expr().bind(SwapId)))));
+
+  // A cast can be matched as a comparator to zero. (i.e. if (x) is equivalent
+  // to if (x != 0)).
+  const auto CastExpr =
+      implicitCastExpr(hasCastKind(CK_IntegralToBoolean),
+                       hasSourceExpression(matchSymbolicExpr(Id)))
+          .bind(CastId);
+
+  const auto NegateRelationalExpr =
+      unaryOperator(hasOperatorName("!"),
+                    hasUnaryOperand(anyOf(CastExpr, RelationalExpr)))
+          .bind(NegateId);
+
+  // Do not bind to double negation.
+  const auto NegateNegateRelationalExpr =
+      unaryOperator(hasOperatorName("!"),
+                    hasUnaryOperand(unaryOperator(
+                        hasOperatorName("!"),
+                        hasUnaryOperand(anyOf(CastExpr, RelationalExpr)))));
+
+  const auto OverloadedOperatorExpr =
+      cxxOperatorCallExpr(
+          anyOf(hasOverloadedOperatorName("=="),
+                hasOverloadedOperatorName("!="), hasOverloadedOperatorName("<"),
+                hasOverloadedOperatorName("<="), hasOverloadedOperatorName(">"),
+                hasOverloadedOperatorName(">=")),
+          // Filter noisy false positives.
+          unless(isMacro()), unless(isInTemplateInstantiation()))
+          .bind(OverloadId);
+
+  return anyOf(RelationalExpr, CastExpr, NegateRelationalExpr,
+               NegateNegateRelationalExpr, OverloadedOperatorExpr);
+}
+
+// Checks whether a function param is non constant reference type, and may
+// be modified in the function.
+static bool isNonConstReferenceType(QualType ParamType) {
+  return ParamType->isReferenceType() &&
+         !ParamType.getNonReferenceType().isConstQualified();
+}
+
+// Checks whether the arguments of an overloaded operator can be modified in the
+// function.
+// For operators that take an instance and a constant as arguments, only the
+// first argument (the instance) needs to be checked, since the constant itself
+// is a temporary expression. Whether the second parameter is checked is
+// controlled by the parameter `ParamsToCheckCount`.
+static bool
+canOverloadedOperatorArgsBeModified(const FunctionDecl *OperatorDecl,
+                                    bool checkSecondParam) {
+  unsigned ParamCount = OperatorDecl->getNumParams();
+
+  // Overloaded operators declared inside a class have only one param.
+  // These functions must be declared const in order to not be able to modify
+  // the instance of the class they are called through.
+  if (ParamCount == 1 &&
+      !OperatorDecl->getType()->getAs<FunctionType>()->isConst())
+    return true;
+
+  if (isNonConstReferenceType(OperatorDecl->getParamDecl(0)->getType()))
+    return true;
+
+  return checkSecondParam && ParamCount == 2 &&
+         isNonConstReferenceType(OperatorDecl->getParamDecl(1)->getType());
+}
+
+// Retrieves sub-expressions matched by 'matchRelationalIntegerConstantExpr'
+// with name 'Id'.
+static bool retrieveRelationalIntegerConstantExpr(
+    const MatchFinder::MatchResult &Result, StringRef Id,
+    const Expr *&OperandExpr, BinaryOperatorKind &Opcode, const Expr *&Symbol,
+    APSInt &Value, const Expr *&ConstExpr) {
+  std::string CastId = (Id + "-cast").str();
+  std::string SwapId = (Id + "-swap").str();
+  std::string NegateId = (Id + "-negate").str();
+  std::string OverloadId = (Id + "-overload").str();
+
+  if (const auto *Bin = Result.Nodes.getNodeAs<BinaryOperator>(Id)) {
+    // Operand received with explicit comparator.
+    Opcode = Bin->getOpcode();
+    OperandExpr = Bin;
+
+    if (!retrieveIntegerConstantExpr(Result, Id, Value, ConstExpr))
+      return false;
+  } else if (const auto *Cast = Result.Nodes.getNodeAs<CastExpr>(CastId)) {
+    // Operand received with implicit comparator (cast).
+    Opcode = BO_NE;
+    OperandExpr = Cast;
+    Value = APSInt(32, false);
+  } else if (const auto *OverloadedOperatorExpr =
+                 Result.Nodes.getNodeAs<CXXOperatorCallExpr>(OverloadId)) {
+    const auto *OverloadedFunctionDecl = dyn_cast_or_null<FunctionDecl>(OverloadedOperatorExpr->getCalleeDecl());
+    if (!OverloadedFunctionDecl)
+      return false;
+
+    if (canOverloadedOperatorArgsBeModified(OverloadedFunctionDecl, false))
+      return false;
+
+    if (canOverloadedOperatorArgsBeModified(OverloadedFunctionDecl, false))
+      return false;
+
+    if (!OverloadedOperatorExpr->getArg(1)->isIntegerConstantExpr(
+            Value, *Result.Context))
+      return false;
+
+    Symbol = OverloadedOperatorExpr->getArg(0);
+    OperandExpr = OverloadedOperatorExpr;
+    Opcode = BinaryOperator::getOverloadedOpcode(OverloadedOperatorExpr->getOperator());
+
+    return BinaryOperator::isComparisonOp(Opcode);
+  } else {
+    return false;
+  }
+
+  if (!retrieveSymbolicExpr(Result, Id, Symbol))
+    return false;
+
+  if (Result.Nodes.getNodeAs<Expr>(SwapId))
+    Opcode = BinaryOperator::reverseComparisonOp(Opcode);
+  if (Result.Nodes.getNodeAs<Expr>(NegateId))
+    Opcode = BinaryOperator::negateComparisonOp(Opcode);
+  return true;
+}
+
+// Checks for expressions like (X == 4) && (Y != 9)
+static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const ASTContext *AstCtx) {
+  const auto *LhsBinOp = dyn_cast<BinaryOperator>(BinOp->getLHS());
+  const auto *RhsBinOp = dyn_cast<BinaryOperator>(BinOp->getRHS());
+
+  if (!LhsBinOp || !RhsBinOp)
+    return false;
+
+  if ((LhsBinOp->getLHS()->isIntegerConstantExpr(*AstCtx) ||
+       LhsBinOp->getRHS()->isIntegerConstantExpr(*AstCtx)) &&
+      (RhsBinOp->getLHS()->isIntegerConstantExpr(*AstCtx) ||
+       RhsBinOp->getRHS()->isIntegerConstantExpr(*AstCtx)))
+    return true;
+  return false;
+}
+
+// Retrieves integer constant subexpressions from binary operator expressions
+// that have two equivalent sides.
+// E.g.: from (X == 5) && (X == 5) retrieves 5 and 5.
+static bool retrieveConstExprFromBothSides(const BinaryOperator *&BinOp,
+                                           BinaryOperatorKind &MainOpcode,
+                                           BinaryOperatorKind &SideOpcode,
+                                           const Expr *&LhsConst,
+                                           const Expr *&RhsConst,
+                                           const ASTContext *AstCtx) {
+  assert(areSidesBinaryConstExpressions(BinOp, AstCtx) &&
+         "Both sides of binary operator must be constant expressions!");
+
+  MainOpcode = BinOp->getOpcode();
+
+  const auto *BinOpLhs = cast<BinaryOperator>(BinOp->getLHS());
+  const auto *BinOpRhs = cast<BinaryOperator>(BinOp->getRHS());
+
+  LhsConst = BinOpLhs->getLHS()->isIntegerConstantExpr(*AstCtx)
+                 ? BinOpLhs->getLHS()
+                 : BinOpLhs->getRHS();
+  RhsConst = BinOpRhs->getLHS()->isIntegerConstantExpr(*AstCtx)
+                 ? BinOpRhs->getLHS()
+                 : BinOpRhs->getRHS();
+
+  if (!LhsConst || !RhsConst)
+    return false;
+
+  assert(BinOpLhs->getOpcode() == BinOpRhs->getOpcode() &&
+         "Sides of the binary operator must be equivalent expressions!");
+
+  SideOpcode = BinOpLhs->getOpcode();
+
+  return true;
+}
+
+static bool areExprsFromDifferentMacros(const Expr *LhsExpr,
+                                        const Expr *RhsExpr,
+                                        const ASTContext *AstCtx) {
+  if (!LhsExpr || !RhsExpr)
+    return false;
+
+  SourceLocation LhsLoc = LhsExpr->getExprLoc();
+  SourceLocation RhsLoc = RhsExpr->getExprLoc();
+
+  if (!LhsLoc.isMacroID() || !RhsLoc.isMacroID())
+    return false;
+
+  const SourceManager &SM = AstCtx->getSourceManager();
+  const LangOptions &LO = AstCtx->getLangOpts();
+
+  return !(Lexer::getImmediateMacroName(LhsLoc, SM, LO) ==
+          Lexer::getImmediateMacroName(RhsLoc, SM, LO));
+}
+
+static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr,
+                                     const Expr *&RhsExpr) {
+  if (!LhsExpr || !RhsExpr)
+    return false;
+
+  SourceLocation LhsLoc = LhsExpr->getExprLoc();
+  SourceLocation RhsLoc = RhsExpr->getExprLoc();
+
+  return LhsLoc.isMacroID() != RhsLoc.isMacroID();
+}
+} // namespace
+
+void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) {
+  const auto AnyLiteralExpr = ignoringParenImpCasts(
+      anyOf(cxxBoolLiteral(), characterLiteral(), integerLiteral()));
+
+  const auto BannedIntegerLiteral =
+      integerLiteral(expandedByMacro(KnownBannedMacroNames));
+
+  // Binary with equivalent operands, like (X != 2 && X != 2).
+  Finder->addMatcher(
+      binaryOperator(anyOf(hasOperatorName("-"), hasOperatorName("/"),
+                           hasOperatorName("%"), hasOperatorName("|"),
+                           hasOperatorName("&"), hasOperatorName("^"),
+                           matchers::isComparisonOperator(),
+                           hasOperatorName("&&"), hasOperatorName("||"),
+                           hasOperatorName("=")),
+                     operandsAreEquivalent(),
+                     // Filter noisy false positives.
+                     unless(isInTemplateInstantiation()),
+                     unless(binaryOperatorIsInMacro()),
+                     unless(hasType(realFloatingPointType())),
+                     unless(hasEitherOperand(hasType(realFloatingPointType()))),
+                     unless(hasLHS(AnyLiteralExpr)),
+                     unless(hasDescendant(BannedIntegerLiteral)))
+          .bind("binary"),
+      this);
+
+  // Conditional (trenary) operator with equivalent operands, like (Y ? X : X).
+  Finder->addMatcher(conditionalOperator(expressionsAreEquivalent(),
+                                         // Filter noisy false positives.
+                                         unless(conditionalOperatorIsInMacro()),
+                                         unless(isInTemplateInstantiation()))
+                         .bind("cond"),
+                     this);
+
+  // Overloaded operators with equivalent operands.
+  Finder->addMatcher(
+      cxxOperatorCallExpr(
+          anyOf(
+              hasOverloadedOperatorName("-"), hasOverloadedOperatorName("/"),
+              hasOverloadedOperatorName("%"), hasOverloadedOperatorName("|"),
+              hasOverloadedOperatorName("&"), hasOverloadedOperatorName("^"),
+              hasOverloadedOperatorName("=="), hasOverloadedOperatorName("!="),
+              hasOverloadedOperatorName("<"), hasOverloadedOperatorName("<="),
+              hasOverloadedOperatorName(">"), hasOverloadedOperatorName(">="),
+              hasOverloadedOperatorName("&&"), hasOverloadedOperatorName("||"),
+              hasOverloadedOperatorName("=")),
+          parametersAreEquivalent(),
+          // Filter noisy false positives.
+          unless(isMacro()), unless(isInTemplateInstantiation()))
+          .bind("call"),
+      this);
+
+  // Match expressions like: !(1 | 2 | 3)
+  Finder->addMatcher(
+      implicitCastExpr(
+          hasImplicitDestinationType(isInteger()),
+          has(unaryOperator(
+                  hasOperatorName("!"),
+                  hasUnaryOperand(ignoringParenImpCasts(binaryOperator(
+                      anyOf(hasOperatorName("|"), hasOperatorName("&")),
+                      hasLHS(anyOf(binaryOperator(anyOf(hasOperatorName("|"),
+                                                        hasOperatorName("&"))),
+                                   integerLiteral())),
+                      hasRHS(integerLiteral())))))
+                  .bind("logical-bitwise-confusion"))),
+      this);
+
+  // Match expressions like: (X << 8) & 0xFF
+  Finder->addMatcher(
+      binaryOperator(hasOperatorName("&"),
+                     hasEitherOperand(ignoringParenImpCasts(binaryOperator(
+                         hasOperatorName("<<"),
+                         hasRHS(ignoringParenImpCasts(
+                             integerLiteral().bind("shift-const")))))),
+                     hasEitherOperand(ignoringParenImpCasts(
+                         integerLiteral().bind("and-const"))))
+          .bind("left-right-shift-confusion"),
+      this);
+
+  // Match common expressions and apply more checks to find redundant
+  // sub-expressions.
+  //   a) Expr <op> K1 == K2
+  //   b) Expr <op> K1 == Expr
+  //   c) Expr <op> K1 == Expr <op> K2
+  // see: 'checkArithmeticExpr' and 'checkBitwiseExpr'
+  const auto BinOpCstLeft = matchBinOpIntegerConstantExpr("lhs");
+  const auto BinOpCstRight = matchBinOpIntegerConstantExpr("rhs");
+  const auto CstRight = matchIntegerConstantExpr("rhs");
+  const auto SymRight = matchSymbolicExpr("rhs");
+
+  // Match expressions like: x <op> 0xFF == 0xF00.
+  Finder->addMatcher(binaryOperator(isComparisonOperator(),
+                                    hasEitherOperand(BinOpCstLeft),
+                                    hasEitherOperand(CstRight))
+                         .bind("binop-const-compare-to-const"),
+                     this);
+
+  // Match expressions like: x <op> 0xFF == x.
+  Finder->addMatcher(
+      binaryOperator(isComparisonOperator(),
+                     anyOf(allOf(hasLHS(BinOpCstLeft), hasRHS(SymRight)),
+                           allOf(hasLHS(SymRight), hasRHS(BinOpCstLeft))))
+          .bind("binop-const-compare-to-sym"),
+      this);
+
+  // Match expressions like: x <op> 10 == x <op> 12.
+  Finder->addMatcher(binaryOperator(isComparisonOperator(),
+                                    hasLHS(BinOpCstLeft), hasRHS(BinOpCstRight),
+                                    // Already reported as redundant.
+                                    unless(operandsAreEquivalent()))
+                         .bind("binop-const-compare-to-binop-const"),
+                     this);
+
+  // Match relational expressions combined with logical operators and find
+  // redundant sub-expressions.
+  // see: 'checkRelationalExpr'
+
+  // Match expressions like: x < 2 && x > 2.
+  const auto ComparisonLeft = matchRelationalIntegerConstantExpr("lhs");
+  const auto ComparisonRight = matchRelationalIntegerConstantExpr("rhs");
+  Finder->addMatcher(
+      binaryOperator(anyOf(hasOperatorName("||"), hasOperatorName("&&")),
+                     hasLHS(ComparisonLeft), hasRHS(ComparisonRight),
+                     // Already reported as redundant.
+                     unless(operandsAreEquivalent()))
+          .bind("comparisons-of-symbol-and-const"),
+      this);
+}
+
+void RedundantExpressionCheck::checkArithmeticExpr(
+    const MatchFinder::MatchResult &Result) {
+  APSInt LhsValue, RhsValue;
+  const Expr *LhsSymbol = nullptr, *RhsSymbol = nullptr;
+  BinaryOperatorKind LhsOpcode, RhsOpcode;
+
+  if (const auto *ComparisonOperator = Result.Nodes.getNodeAs<BinaryOperator>(
+          "binop-const-compare-to-sym")) {
+    BinaryOperatorKind Opcode = ComparisonOperator->getOpcode();
+    if (!retrieveBinOpIntegerConstantExpr(Result, "lhs", LhsOpcode, LhsSymbol,
+                                          LhsValue) ||
+        !retrieveSymbolicExpr(Result, "rhs", RhsSymbol) ||
+        !areEquivalentExpr(LhsSymbol, RhsSymbol))
+      return;
+
+    // Check expressions: x + k == x  or  x - k == x.
+    if (LhsOpcode == BO_Add || LhsOpcode == BO_Sub) {
+      if ((LhsValue != 0 && Opcode == BO_EQ) ||
+          (LhsValue == 0 && Opcode == BO_NE))
+        diag(ComparisonOperator->getOperatorLoc(),
+             "logical expression is always false");
+      else if ((LhsValue == 0 && Opcode == BO_EQ) ||
+               (LhsValue != 0 && Opcode == BO_NE))
+        diag(ComparisonOperator->getOperatorLoc(),
+             "logical expression is always true");
+    }
+  } else if (const auto *ComparisonOperator =
+                 Result.Nodes.getNodeAs<BinaryOperator>(
+                     "binop-const-compare-to-binop-const")) {
+    BinaryOperatorKind Opcode = ComparisonOperator->getOpcode();
+
+    if (!retrieveBinOpIntegerConstantExpr(Result, "lhs", LhsOpcode, LhsSymbol,
+                                          LhsValue) ||
+        !retrieveBinOpIntegerConstantExpr(Result, "rhs", RhsOpcode, RhsSymbol,
+                                          RhsValue) ||
+        !areEquivalentExpr(LhsSymbol, RhsSymbol))
+      return;
+
+    transformSubToCanonicalAddExpr(LhsOpcode, LhsValue);
+    transformSubToCanonicalAddExpr(RhsOpcode, RhsValue);
+
+    // Check expressions: x + 1 == x + 2  or  x + 1 != x + 2.
+    if (LhsOpcode == BO_Add && RhsOpcode == BO_Add) {
+      if ((Opcode == BO_EQ && APSInt::compareValues(LhsValue, RhsValue) == 0) ||
+          (Opcode == BO_NE && APSInt::compareValues(LhsValue, RhsValue) != 0)) {
+        diag(ComparisonOperator->getOperatorLoc(),
+             "logical expression is always true");
+      } else if ((Opcode == BO_EQ &&
+                  APSInt::compareValues(LhsValue, RhsValue) != 0) ||
+                 (Opcode == BO_NE &&
+                  APSInt::compareValues(LhsValue, RhsValue) == 0)) {
+        diag(ComparisonOperator->getOperatorLoc(),
+             "logical expression is always false");
+      }
+    }
+  }
+}
+
+static bool exprEvaluatesToZero(BinaryOperatorKind Opcode, APSInt Value) {
+  return (Opcode == BO_And || Opcode == BO_AndAssign) && Value == 0;
+}
+
+static bool exprEvaluatesToBitwiseNegatedZero(BinaryOperatorKind Opcode,
+                                              APSInt Value) {
+  return (Opcode == BO_Or || Opcode == BO_OrAssign) && ~Value == 0;
+}
+
+static bool exprEvaluatesToSymbolic(BinaryOperatorKind Opcode, APSInt Value) {
+  return ((Opcode == BO_Or || Opcode == BO_OrAssign) && Value == 0) ||
+         ((Opcode == BO_And || Opcode == BO_AndAssign) && ~Value == 0);
+}
+
+
+void RedundantExpressionCheck::checkBitwiseExpr(
+    const MatchFinder::MatchResult &Result) {
+  if (const auto *ComparisonOperator = Result.Nodes.getNodeAs<BinaryOperator>(
+          "binop-const-compare-to-const")) {
+    BinaryOperatorKind Opcode = ComparisonOperator->getOpcode();
+
+    APSInt LhsValue, RhsValue;
+    const Expr *LhsSymbol = nullptr;
+    BinaryOperatorKind LhsOpcode;
+    if (!retrieveBinOpIntegerConstantExpr(Result, "lhs", LhsOpcode, LhsSymbol,
+                                          LhsValue) ||
+        !retrieveIntegerConstantExpr(Result, "rhs", RhsValue))
+      return;
+
+    uint64_t LhsConstant = LhsValue.getZExtValue();
+    uint64_t RhsConstant = RhsValue.getZExtValue();
+    SourceLocation Loc = ComparisonOperator->getOperatorLoc();
+
+    // Check expression: x & k1 == k2  (i.e. x & 0xFF == 0xF00)
+    if (LhsOpcode == BO_And && (LhsConstant & RhsConstant) != RhsConstant) {
+      if (Opcode == BO_EQ)
+        diag(Loc, "logical expression is always false");
+      else if (Opcode == BO_NE)
+        diag(Loc, "logical expression is always true");
+    }
+
+    // Check expression: x | k1 == k2  (i.e. x | 0xFF == 0xF00)
+    if (LhsOpcode == BO_Or && (LhsConstant | RhsConstant) != RhsConstant) {
+      if (Opcode == BO_EQ)
+        diag(Loc, "logical expression is always false");
+      else if (Opcode == BO_NE)
+        diag(Loc, "logical expression is always true");
+    }
+  } else if (const auto *IneffectiveOperator =
+                 Result.Nodes.getNodeAs<BinaryOperator>(
+                     "ineffective-bitwise")) {
+    APSInt Value;
+    const Expr *Sym = nullptr, *ConstExpr = nullptr;
+
+    if (!retrieveSymbolicExpr(Result, "ineffective-bitwise", Sym) ||
+        !retrieveIntegerConstantExpr(Result, "ineffective-bitwise", Value,
+                                     ConstExpr))
+      return;
+
+    if((Value != 0 && ~Value != 0) || Sym->getExprLoc().isMacroID())
+        return;
+
+    SourceLocation Loc = IneffectiveOperator->getOperatorLoc();
+
+    BinaryOperatorKind Opcode = IneffectiveOperator->getOpcode();
+    if (exprEvaluatesToZero(Opcode, Value)) {
+      diag(Loc, "expression always evaluates to 0");
+    } else if (exprEvaluatesToBitwiseNegatedZero(Opcode, Value)) {
+      SourceRange ConstExprRange(ConstExpr->getLocStart(),
+                                 ConstExpr->getLocEnd());
+      StringRef ConstExprText = Lexer::getSourceText(
+          CharSourceRange::getTokenRange(ConstExprRange), *Result.SourceManager,
+          Result.Context->getLangOpts());
+
+      diag(Loc, "expression always evaluates to '%0'") << ConstExprText;
+
+    } else if (exprEvaluatesToSymbolic(Opcode, Value)) {
+      SourceRange SymExprRange(Sym->getLocStart(), Sym->getLocEnd());
+
+      StringRef ExprText = Lexer::getSourceText(
+          CharSourceRange::getTokenRange(SymExprRange), *Result.SourceManager,
+          Result.Context->getLangOpts());
+
+      diag(Loc, "expression always evaluates to '%0'") << ExprText;
+    }
+  }
+}
+
+void RedundantExpressionCheck::checkRelationalExpr(
+    const MatchFinder::MatchResult &Result) {
+  if (const auto *ComparisonOperator = Result.Nodes.getNodeAs<BinaryOperator>(
+          "comparisons-of-symbol-and-const")) {
+    // Matched expressions are: (x <op> k1) <REL> (x <op> k2).
+    // E.g.: (X < 2) && (X > 4)
+    BinaryOperatorKind Opcode = ComparisonOperator->getOpcode();
+
+    const Expr *LhsExpr = nullptr, *RhsExpr = nullptr;
+    const Expr *LhsSymbol = nullptr, *RhsSymbol = nullptr;
+    const Expr *LhsConst = nullptr, *RhsConst = nullptr;
+    BinaryOperatorKind LhsOpcode, RhsOpcode;
+    APSInt LhsValue, RhsValue;
+
+    if (!retrieveRelationalIntegerConstantExpr(
+            Result, "lhs", LhsExpr, LhsOpcode, LhsSymbol, LhsValue, LhsConst) ||
+        !retrieveRelationalIntegerConstantExpr(
+            Result, "rhs", RhsExpr, RhsOpcode, RhsSymbol, RhsValue, RhsConst) ||
+        !areEquivalentExpr(LhsSymbol, RhsSymbol))
+      return;
+
+    // Bring expr to a canonical form: smallest constant must be on the left.
+    if (APSInt::compareValues(LhsValue, RhsValue) > 0) {
+      std::swap(LhsExpr, RhsExpr);
+      std::swap(LhsValue, RhsValue);
+      std::swap(LhsSymbol, RhsSymbol);
+      std::swap(LhsOpcode, RhsOpcode);
+    }
+
+    // Constants come from two different macros, or one of them is a macro.
+    if (areExprsFromDifferentMacros(LhsConst, RhsConst, Result.Context) ||
+        areExprsMacroAndNonMacro(LhsConst, RhsConst))
+      return;
+
+    if ((Opcode == BO_LAnd || Opcode == BO_LOr) &&
+        areEquivalentRanges(LhsOpcode, LhsValue, RhsOpcode, RhsValue)) {
+      diag(ComparisonOperator->getOperatorLoc(),
+           "equivalent expression on both sides of logical operator");
+      return;
+    }
+
+    if (Opcode == BO_LAnd) {
+      if (areExclusiveRanges(LhsOpcode, LhsValue, RhsOpcode, RhsValue)) {
+        diag(ComparisonOperator->getOperatorLoc(),
+             "logical expression is always false");
+      } else if (rangeSubsumesRange(LhsOpcode, LhsValue, RhsOpcode, RhsValue)) {
+        diag(LhsExpr->getExprLoc(), "expression is redundant");
+      } else if (rangeSubsumesRange(RhsOpcode, RhsValue, LhsOpcode, LhsValue)) {
+        diag(RhsExpr->getExprLoc(), "expression is redundant");
+      }
+    }
+
+    if (Opcode == BO_LOr) {
+      if (rangesFullyCoverDomain(LhsOpcode, LhsValue, RhsOpcode, RhsValue)) {
+        diag(ComparisonOperator->getOperatorLoc(),
+             "logical expression is always true");
+      } else if (rangeSubsumesRange(LhsOpcode, LhsValue, RhsOpcode, RhsValue)) {
+        diag(RhsExpr->getExprLoc(), "expression is redundant");
+      } else if (rangeSubsumesRange(RhsOpcode, RhsValue, LhsOpcode, LhsValue)) {
+        diag(LhsExpr->getExprLoc(), "expression is redundant");
+      }
+    }
+  }
+}
+
+void RedundantExpressionCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("binary")) {
+    // If the expression's constants are macros, check whether they are
+    // intentional.
+    if (areSidesBinaryConstExpressions(BinOp, Result.Context)) {
+      const Expr *LhsConst = nullptr, *RhsConst = nullptr;
+      BinaryOperatorKind MainOpcode, SideOpcode;
+
+      if (!retrieveConstExprFromBothSides(BinOp, MainOpcode, SideOpcode,
+                                          LhsConst, RhsConst, Result.Context))
+        return;
+
+      if (areExprsFromDifferentMacros(LhsConst, RhsConst, Result.Context) ||
+          areExprsMacroAndNonMacro(LhsConst, RhsConst))
+        return;
+    }
+
+    diag(BinOp->getOperatorLoc(), "both sides of operator are equivalent");
+  }
+
+  if (const auto *CondOp =
+          Result.Nodes.getNodeAs<ConditionalOperator>("cond")) {
+    const Expr *TrueExpr = CondOp->getTrueExpr();
+    const Expr *FalseExpr = CondOp->getFalseExpr();
+
+    if (areExprsFromDifferentMacros(TrueExpr, FalseExpr, Result.Context) ||
+        areExprsMacroAndNonMacro(TrueExpr, FalseExpr))
+      return;
+    diag(CondOp->getColonLoc(),
+         "'true' and 'false' expressions are equivalent");
+  }
+
+  if (const auto *Call = Result.Nodes.getNodeAs<CXXOperatorCallExpr>("call")) {
+    const auto *OverloadedFunctionDecl = dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl());
+    if (!OverloadedFunctionDecl)
+      return;
+
+    if (canOverloadedOperatorArgsBeModified(OverloadedFunctionDecl, true))
+      return;
+
+    diag(Call->getOperatorLoc(),
+         "both sides of overloaded operator are equivalent");
+  }
+
+  if (const auto *NegateOperator =
+          Result.Nodes.getNodeAs<UnaryOperator>("logical-bitwise-confusion")) {
+    SourceLocation OperatorLoc = NegateOperator->getOperatorLoc();
+
+    auto Diag =
+        diag(OperatorLoc,
+             "ineffective logical negation operator used; did you mean '~'?");
+    SourceLocation LogicalNotLocation = OperatorLoc.getLocWithOffset(1);
+
+    if (!LogicalNotLocation.isMacroID())
+      Diag << FixItHint::CreateReplacement(
+          CharSourceRange::getCharRange(OperatorLoc, LogicalNotLocation), "~");
+  }
+
+  if (const auto *BinaryAndExpr = Result.Nodes.getNodeAs<BinaryOperator>(
+          "left-right-shift-confusion")) {
+    const auto *ShiftingConst = Result.Nodes.getNodeAs<Expr>("shift-const");
+    assert(ShiftingConst && "Expr* 'ShiftingConst' is nullptr!");
+    APSInt ShiftingValue;
+
+    if (!ShiftingConst->isIntegerConstantExpr(ShiftingValue, *Result.Context))
+      return;
+
+    const auto *AndConst = Result.Nodes.getNodeAs<Expr>("and-const");
+    assert(AndConst && "Expr* 'AndCont' is nullptr!");
+    APSInt AndValue;
+    if (!AndConst->isIntegerConstantExpr(AndValue, *Result.Context))
+      return;
+
+    // If ShiftingConst is shifted left with more bits than the position of the
+    // leftmost 1 in the bit representation of AndValue, AndConstant is
+    // ineffective.
+    if (AndValue.getActiveBits() > ShiftingValue)
+      return;
+
+    auto Diag = diag(BinaryAndExpr->getOperatorLoc(),
+                     "ineffective bitwise and operation");
+  }
+
+  // Check for the following bound expressions:
+  // - "binop-const-compare-to-sym",
+  // - "binop-const-compare-to-binop-const",
+  // Produced message:
+  // -> "logical expression is always false/true"
+  checkArithmeticExpr(Result);
+
+  // Check for the following bound expression:
+  // - "binop-const-compare-to-const",
+  // - "ineffective-bitwise"
+  // Produced message:
+  // -> "logical expression is always false/true"
+  // -> "expression always evaluates to ..."
+  checkBitwiseExpr(Result);
+
+  // Check for te following bound expression:
+  // - "comparisons-of-symbol-and-const",
+  // Produced messages:
+  // -> "equivalent expression on both sides of logical operator",
+  // -> "logical expression is always false/true"
+  // -> "expression is redundant"
+  checkRelationalExpr(Result);
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.h
new file mode 100644
index 0000000..c0f8bf5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.h
@@ -0,0 +1,41 @@
+//===--- RedundantExpressionCheck.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_MISC_REDUNDANT_EXPRESSION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANT_EXPRESSION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// The checker detects expressions that are redundant, because they contain
+/// ineffective, useless parts.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-redundant-expression.html
+class RedundantExpressionCheck : public ClangTidyCheck {
+public:
+  RedundantExpressionCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void checkArithmeticExpr(const ast_matchers::MatchFinder::MatchResult &R);
+  void checkBitwiseExpr(const ast_matchers::MatchFinder::MatchResult &R);
+  void checkRelationalExpr(const ast_matchers::MatchFinder::MatchResult &R);
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANT_EXPRESSION_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp
new file mode 100644
index 0000000..77fb58d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp
@@ -0,0 +1,177 @@
+//===--- StaticAssertCheck.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 "StaticAssertCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+StaticAssertCheck::StaticAssertCheck(StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context) {}
+
+void StaticAssertCheck::registerMatchers(MatchFinder *Finder) {
+  // This checker only makes sense for languages that have static assertion
+  // capabilities: C++11 and C11.
+  if (!(getLangOpts().CPlusPlus11 || getLangOpts().C11))
+    return;
+
+  auto NegatedString = unaryOperator(
+      hasOperatorName("!"), hasUnaryOperand(ignoringImpCasts(stringLiteral())));
+  auto IsAlwaysFalse =
+      expr(anyOf(cxxBoolLiteral(equals(false)), integerLiteral(equals(0)),
+                 cxxNullPtrLiteralExpr(), gnuNullExpr(), NegatedString))
+          .bind("isAlwaysFalse");
+  auto IsAlwaysFalseWithCast = ignoringParenImpCasts(anyOf(
+      IsAlwaysFalse, cStyleCastExpr(has(ignoringParenImpCasts(IsAlwaysFalse)))
+                         .bind("castExpr")));
+  auto AssertExprRoot = anyOf(
+      binaryOperator(
+          anyOf(hasOperatorName("&&"), hasOperatorName("==")),
+          hasEitherOperand(ignoringImpCasts(stringLiteral().bind("assertMSG"))),
+          anyOf(binaryOperator(hasEitherOperand(IsAlwaysFalseWithCast)),
+                anything()))
+          .bind("assertExprRoot"),
+      IsAlwaysFalse);
+  auto NonConstexprFunctionCall =
+      callExpr(hasDeclaration(functionDecl(unless(isConstexpr()))));
+  auto AssertCondition =
+      expr(
+          anyOf(expr(ignoringParenCasts(anyOf(
+                    AssertExprRoot, unaryOperator(hasUnaryOperand(
+                                        ignoringParenCasts(AssertExprRoot)))))),
+                anything()),
+          unless(findAll(NonConstexprFunctionCall)))
+          .bind("condition");
+  auto Condition =
+      anyOf(ignoringParenImpCasts(callExpr(
+                hasDeclaration(functionDecl(hasName("__builtin_expect"))),
+                hasArgument(0, AssertCondition))),
+            AssertCondition);
+
+  Finder->addMatcher(conditionalOperator(hasCondition(Condition),
+                                         unless(isInTemplateInstantiation()))
+                         .bind("condStmt"),
+                     this);
+
+  Finder->addMatcher(
+      ifStmt(hasCondition(Condition), unless(isInTemplateInstantiation()))
+          .bind("condStmt"),
+      this);
+}
+
+void StaticAssertCheck::check(const MatchFinder::MatchResult &Result) {
+  const ASTContext *ASTCtx = Result.Context;
+  const LangOptions &Opts = ASTCtx->getLangOpts();
+  const SourceManager &SM = ASTCtx->getSourceManager();
+  const auto *CondStmt = Result.Nodes.getNodeAs<Stmt>("condStmt");
+  const auto *Condition = Result.Nodes.getNodeAs<Expr>("condition");
+  const auto *IsAlwaysFalse = Result.Nodes.getNodeAs<Expr>("isAlwaysFalse");
+  const auto *AssertMSG = Result.Nodes.getNodeAs<StringLiteral>("assertMSG");
+  const auto *AssertExprRoot =
+      Result.Nodes.getNodeAs<BinaryOperator>("assertExprRoot");
+  const auto *CastExpr = Result.Nodes.getNodeAs<CStyleCastExpr>("castExpr");
+  SourceLocation AssertExpansionLoc = CondStmt->getLocStart();
+
+  if (!AssertExpansionLoc.isValid() || !AssertExpansionLoc.isMacroID())
+    return;
+
+  StringRef MacroName =
+      Lexer::getImmediateMacroName(AssertExpansionLoc, SM, Opts);
+
+  if (MacroName != "assert" || Condition->isValueDependent() ||
+      Condition->isTypeDependent() || Condition->isInstantiationDependent() ||
+      !Condition->isEvaluatable(*ASTCtx))
+    return;
+
+  // False literal is not the result of macro expansion.
+  if (IsAlwaysFalse && (!CastExpr || CastExpr->getType()->isPointerType())) {
+    SourceLocation FalseLiteralLoc =
+        SM.getImmediateSpellingLoc(IsAlwaysFalse->getExprLoc());
+    if (!FalseLiteralLoc.isMacroID())
+      return;
+
+    StringRef FalseMacroName =
+        Lexer::getImmediateMacroName(FalseLiteralLoc, SM, Opts);
+    if (FalseMacroName.compare_lower("false") == 0 ||
+        FalseMacroName.compare_lower("null") == 0)
+      return;
+  }
+
+  SourceLocation AssertLoc = SM.getImmediateMacroCallerLoc(AssertExpansionLoc);
+
+  SmallVector<FixItHint, 4> FixItHints;
+  SourceLocation LastParenLoc;
+  if (AssertLoc.isValid() && !AssertLoc.isMacroID() &&
+      (LastParenLoc = getLastParenLoc(ASTCtx, AssertLoc)).isValid()) {
+    FixItHints.push_back(
+        FixItHint::CreateReplacement(SourceRange(AssertLoc), "static_assert"));
+
+    std::string StaticAssertMSG = ", \"\"";
+    if (AssertExprRoot) {
+      FixItHints.push_back(FixItHint::CreateRemoval(
+          SourceRange(AssertExprRoot->getOperatorLoc())));
+      FixItHints.push_back(FixItHint::CreateRemoval(
+          SourceRange(AssertMSG->getLocStart(), AssertMSG->getLocEnd())));
+      StaticAssertMSG = (Twine(", \"") + AssertMSG->getString() + "\"").str();
+    }
+
+    FixItHints.push_back(
+        FixItHint::CreateInsertion(LastParenLoc, StaticAssertMSG));
+  }
+
+  diag(AssertLoc, "found assert() that could be replaced by static_assert()")
+      << FixItHints;
+}
+
+SourceLocation StaticAssertCheck::getLastParenLoc(const ASTContext *ASTCtx,
+                                                  SourceLocation AssertLoc) {
+  const LangOptions &Opts = ASTCtx->getLangOpts();
+  const SourceManager &SM = ASTCtx->getSourceManager();
+
+  llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getFileID(AssertLoc));
+  if (!Buffer)
+    return SourceLocation();
+
+  const char *BufferPos = SM.getCharacterData(AssertLoc);
+
+  Token Token;
+  Lexer Lexer(SM.getLocForStartOfFile(SM.getFileID(AssertLoc)), Opts,
+              Buffer->getBufferStart(), BufferPos, Buffer->getBufferEnd());
+
+  //        assert                          first left parenthesis
+  if (Lexer.LexFromRawLexer(Token) || Lexer.LexFromRawLexer(Token) ||
+      !Token.is(tok::l_paren))
+    return SourceLocation();
+
+  unsigned int ParenCount = 1;
+  while (ParenCount && !Lexer.LexFromRawLexer(Token)) {
+    if (Token.is(tok::l_paren))
+      ++ParenCount;
+    else if (Token.is(tok::r_paren))
+      --ParenCount;
+  }
+
+  return Token.getLocation();
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.h
new file mode 100644
index 0000000..faefce1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.h
@@ -0,0 +1,41 @@
+//===--- StaticAssertCheck.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_MISC_STATICASSERTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_STATICASSERTCHECK_H
+
+#include "../ClangTidy.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Replaces `assert()` with `static_assert()` if the condition is evaluatable
+/// at compile time.
+///
+/// The condition of `static_assert()` is evaluated at compile time which is
+/// safer and more efficient.
+class StaticAssertCheck : public ClangTidyCheck {
+public:
+  StaticAssertCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  SourceLocation getLastParenLoc(const ASTContext *ASTCtx,
+                                 SourceLocation AssertLoc);
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_STATICASSERTCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.cpp
new file mode 100644
index 0000000..90398cc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.cpp
@@ -0,0 +1,161 @@
+//===--- ThrowByValueCatchByReferenceCheck.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 "ThrowByValueCatchByReferenceCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+ThrowByValueCatchByReferenceCheck::ThrowByValueCatchByReferenceCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      CheckAnonymousTemporaries(Options.get("CheckThrowTemporaries", true)) {}
+
+void ThrowByValueCatchByReferenceCheck::registerMatchers(MatchFinder *Finder) {
+  // This is a C++ only check thus we register the matchers only for C++
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(cxxThrowExpr().bind("throw"), this);
+  Finder->addMatcher(cxxCatchStmt().bind("catch"), this);
+}
+
+void ThrowByValueCatchByReferenceCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "CheckThrowTemporaries", true);
+}
+
+void ThrowByValueCatchByReferenceCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  diagnoseThrowLocations(Result.Nodes.getNodeAs<CXXThrowExpr>("throw"));
+  diagnoseCatchLocations(Result.Nodes.getNodeAs<CXXCatchStmt>("catch"),
+                         *Result.Context);
+}
+
+bool ThrowByValueCatchByReferenceCheck::isFunctionParameter(
+    const DeclRefExpr *declRefExpr) {
+  return isa<ParmVarDecl>(declRefExpr->getDecl());
+}
+
+bool ThrowByValueCatchByReferenceCheck::isCatchVariable(
+    const DeclRefExpr *declRefExpr) {
+  auto *valueDecl = declRefExpr->getDecl();
+  if (auto *varDecl = dyn_cast<VarDecl>(valueDecl))
+    return varDecl->isExceptionVariable();
+  return false;
+}
+
+bool ThrowByValueCatchByReferenceCheck::isFunctionOrCatchVar(
+    const DeclRefExpr *declRefExpr) {
+  return isFunctionParameter(declRefExpr) || isCatchVariable(declRefExpr);
+}
+
+void ThrowByValueCatchByReferenceCheck::diagnoseThrowLocations(
+    const CXXThrowExpr *throwExpr) {
+  if (!throwExpr)
+    return;
+  auto *subExpr = throwExpr->getSubExpr();
+  if (!subExpr)
+    return;
+  auto qualType = subExpr->getType();
+  if (qualType->isPointerType()) {
+    // The code is throwing a pointer.
+    // In case it is strng literal, it is safe and we return.
+    auto *inner = subExpr->IgnoreParenImpCasts();
+    if (isa<StringLiteral>(inner))
+      return;
+    // If it's a variable from a catch statement, we return as well.
+    auto *declRef = dyn_cast<DeclRefExpr>(inner);
+    if (declRef && isCatchVariable(declRef)) {
+      return;
+    }
+    diag(subExpr->getLocStart(), "throw expression throws a pointer; it should "
+                                 "throw a non-pointer value instead");
+  }
+  // If the throw statement does not throw by pointer then it throws by value
+  // which is ok.
+  // There are addition checks that emit diagnosis messages if the thrown value
+  // is not an RValue. See:
+  // https://www.securecoding.cert.org/confluence/display/cplusplus/ERR09-CPP.+Throw+anonymous+temporaries
+  // This behavior can be influenced by an option.
+
+  // If we encounter a CXXThrowExpr, we move through all casts until you either
+  // encounter a DeclRefExpr or a CXXConstructExpr.
+  // If it's a DeclRefExpr, we emit a message if the referenced variable is not
+  // a catch variable or function parameter.
+  // When encountering a CopyOrMoveConstructor: emit message if after casts,
+  // the expression is a LValue
+  if (CheckAnonymousTemporaries) {
+    bool emit = false;
+    auto *currentSubExpr = subExpr->IgnoreImpCasts();
+    const auto *variableReference = dyn_cast<DeclRefExpr>(currentSubExpr);
+    const auto *constructorCall = dyn_cast<CXXConstructExpr>(currentSubExpr);
+    // If we have a DeclRefExpr, we flag for emitting a diagnosis message in
+    // case the referenced variable is neither a function parameter nor a
+    // variable declared in the catch statement.
+    if (variableReference)
+      emit = !isFunctionOrCatchVar(variableReference);
+    else if (constructorCall &&
+             constructorCall->getConstructor()->isCopyOrMoveConstructor()) {
+      // If we have a copy / move construction, we emit a diagnosis message if
+      // the object that we copy construct from is neither a function parameter
+      // nor a variable declared in a catch statement
+      auto argIter =
+          constructorCall
+              ->arg_begin(); // there's only one for copy constructors
+      auto *currentSubExpr = (*argIter)->IgnoreImpCasts();
+      if (currentSubExpr->isLValue()) {
+        if (auto *tmp = dyn_cast<DeclRefExpr>(currentSubExpr))
+          emit = !isFunctionOrCatchVar(tmp);
+        else if (isa<CallExpr>(currentSubExpr))
+          emit = true;
+      }
+    }
+    if (emit)
+      diag(subExpr->getLocStart(),
+           "throw expression should throw anonymous temporary values instead");
+  }
+}
+
+void ThrowByValueCatchByReferenceCheck::diagnoseCatchLocations(
+    const CXXCatchStmt *catchStmt, ASTContext &context) {
+  if (!catchStmt)
+    return;
+  auto caughtType = catchStmt->getCaughtType();
+  if (caughtType.isNull())
+    return;
+  auto *varDecl = catchStmt->getExceptionDecl();
+  if (const auto *PT = caughtType.getCanonicalType()->getAs<PointerType>()) {
+    const char *diagMsgCatchReference = "catch handler catches a pointer value; "
+                                        "should throw a non-pointer value and "
+                                        "catch by reference instead";
+    // We do not diagnose when catching pointer to strings since we also allow
+    // throwing string literals.
+    if (!PT->getPointeeType()->isAnyCharacterType())
+      diag(varDecl->getLocStart(), diagMsgCatchReference);
+  } else if (!caughtType->isReferenceType()) {
+    const char *diagMsgCatchReference = "catch handler catches by value; "
+                                        "should catch by reference instead";
+    // If it's not a pointer and not a reference then it must be caught "by
+    // value". In this case we should emit a diagnosis message unless the type
+    // is trivial.
+    if (!caughtType.isTrivialType(context))
+      diag(varDecl->getLocStart(), diagMsgCatchReference);
+  }
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h
new file mode 100644
index 0000000..a2e7df7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h
@@ -0,0 +1,51 @@
+//===--- ThrowByValueCatchByReferenceCheck.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_MISC_THROW_BY_VALUE_CATCH_BY_REFERENCE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_THROW_BY_VALUE_CATCH_BY_REFERENCE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+///\brief checks for locations that do not throw by value
+// or catch by reference.
+// The check is C++ only. It checks that all throw locations
+// throw by value and not by pointer. Additionally it
+// contains an option ("CheckThrowTemporaries", default value "true") that
+// checks that thrown objects are anonymous temporaries. It is also
+// acceptable for this check to throw string literals.
+// This test checks that exceptions are caught by reference
+// and not by value or pointer. It will not warn when catching
+// pointer to char, wchar_t, char16_t or char32_t. This is
+// due to not warning on throwing string literals.
+class ThrowByValueCatchByReferenceCheck : public ClangTidyCheck {
+public:
+  ThrowByValueCatchByReferenceCheck(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:
+  void diagnoseThrowLocations(const CXXThrowExpr *throwExpr);
+  void diagnoseCatchLocations(const CXXCatchStmt *catchStmt,
+                              ASTContext &context);
+  bool isFunctionParameter(const DeclRefExpr *declRefExpr);
+  bool isCatchVariable(const DeclRefExpr *declRefExpr);
+  bool isFunctionOrCatchVar(const DeclRefExpr *declRefExpr);
+  const bool CheckAnonymousTemporaries;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_THROW_BY_VALUE_CATCH_BY_REFERENCE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp
new file mode 100644
index 0000000..0fd7e77
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp
@@ -0,0 +1,94 @@
+//===--- UnconventionalAssignOperatorCheck.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 "UnconventionalAssignOperatorCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+void UnconventionalAssignOperatorCheck::registerMatchers(
+    ast_matchers::MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  const auto HasGoodReturnType = cxxMethodDecl(returns(lValueReferenceType(
+      pointee(unless(isConstQualified()),
+              anyOf(autoType(), hasDeclaration(equalsBoundNode("class")))))));
+
+  const auto IsSelf = qualType(
+      anyOf(hasDeclaration(equalsBoundNode("class")),
+            referenceType(pointee(hasDeclaration(equalsBoundNode("class"))))));
+  const auto IsAssign =
+      cxxMethodDecl(unless(anyOf(isDeleted(), isPrivate(), isImplicit())),
+                    hasName("operator="), ofClass(recordDecl().bind("class")))
+          .bind("method");
+  const auto IsSelfAssign =
+      cxxMethodDecl(IsAssign, hasParameter(0, parmVarDecl(hasType(IsSelf))))
+          .bind("method");
+
+  Finder->addMatcher(
+      cxxMethodDecl(IsAssign, unless(HasGoodReturnType)).bind("ReturnType"),
+      this);
+
+  const auto BadSelf = referenceType(
+      anyOf(lValueReferenceType(pointee(unless(isConstQualified()))),
+            rValueReferenceType(pointee(isConstQualified()))));
+
+  Finder->addMatcher(
+      cxxMethodDecl(IsSelfAssign,
+                    hasParameter(0, parmVarDecl(hasType(BadSelf))))
+          .bind("ArgumentType"),
+      this);
+
+  Finder->addMatcher(
+      cxxMethodDecl(IsSelfAssign, anyOf(isConst(), isVirtual())).bind("cv"),
+      this);
+
+  const auto IsBadReturnStatement = returnStmt(unless(has(ignoringParenImpCasts(
+      anyOf(unaryOperator(hasOperatorName("*"), hasUnaryOperand(cxxThisExpr())),
+            cxxOperatorCallExpr(argumentCountIs(1),
+                                callee(unresolvedLookupExpr()),
+                                hasArgument(0, cxxThisExpr())))))));
+  const auto IsGoodAssign = cxxMethodDecl(IsAssign, HasGoodReturnType);
+
+  Finder->addMatcher(returnStmt(IsBadReturnStatement, forFunction(IsGoodAssign))
+                         .bind("returnStmt"),
+                     this);
+}
+
+void UnconventionalAssignOperatorCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  if (const auto *RetStmt = Result.Nodes.getNodeAs<ReturnStmt>("returnStmt")) {
+    diag(RetStmt->getLocStart(), "operator=() should always return '*this'");
+  } else {
+    static const char *const Messages[][2] = {
+        {"ReturnType", "operator=() should return '%0&'"},
+        {"ArgumentType", "operator=() should take '%0 const&', '%0&&' or '%0'"},
+        {"cv", "operator=() should not be marked '%1'"}};
+
+    const auto *Method = Result.Nodes.getNodeAs<CXXMethodDecl>("method");
+    for (const auto &Message : Messages) {
+      if (Result.Nodes.getNodeAs<Decl>(Message[0]))
+        diag(Method->getLocStart(), Message[1])
+            << Method->getParent()->getName()
+            << (Method->isConst() ? "const" : "virtual");
+    }
+  }
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnconventionalAssignOperatorCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnconventionalAssignOperatorCheck.h
new file mode 100644
index 0000000..ee91dca
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnconventionalAssignOperatorCheck.h
@@ -0,0 +1,42 @@
+//===--- UnconventionalAssignOperatorCheck.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_MISC_ASSIGNOPERATORSIGNATURECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_ASSIGNOPERATORSIGNATURECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Finds declarations of assignment operators with the wrong return and/or
+/// argument types and definitions with good return type but wrong return
+/// statements.
+///
+///   * The return type must be `Class&`.
+///   * Works with move-assign and assign by value.
+///   * Private and deleted operators are ignored.
+///   * The operator must always return ``*this``.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-unconventional-assign-operator.html
+class UnconventionalAssignOperatorCheck : public ClangTidyCheck {
+public:
+  UnconventionalAssignOperatorCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_ASSIGNOPERATORSIGNATURECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UniqueptrResetReleaseCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UniqueptrResetReleaseCheck.cpp
new file mode 100644
index 0000000..99758d3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UniqueptrResetReleaseCheck.cpp
@@ -0,0 +1,136 @@
+//===--- UniqueptrResetReleaseCheck.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 "UniqueptrResetReleaseCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+void UniqueptrResetReleaseCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++11; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  Finder->addMatcher(
+      cxxMemberCallExpr(
+          on(expr().bind("left")), callee(memberExpr().bind("reset_member")),
+          callee(
+              cxxMethodDecl(hasName("reset"),
+                            ofClass(cxxRecordDecl(hasName("::std::unique_ptr"),
+                                                  decl().bind("left_class"))))),
+          has(ignoringParenImpCasts(cxxMemberCallExpr(
+              on(expr().bind("right")),
+              callee(memberExpr().bind("release_member")),
+              callee(cxxMethodDecl(
+                  hasName("release"),
+                  ofClass(cxxRecordDecl(hasName("::std::unique_ptr"),
+                                        decl().bind("right_class")))))))))
+          .bind("reset_call"),
+      this);
+}
+
+namespace {
+const Type *getDeleterForUniquePtr(const MatchFinder::MatchResult &Result,
+                                   StringRef ID) {
+  const auto *Class =
+      Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>(ID);
+  if (!Class)
+    return nullptr;
+  auto DeleterArgument = Class->getTemplateArgs()[1];
+  if (DeleterArgument.getKind() != TemplateArgument::Type)
+    return nullptr;
+  return DeleterArgument.getAsType().getTypePtr();
+}
+
+bool areDeletersCompatible(const MatchFinder::MatchResult &Result) {
+  const Type *LeftDeleterType = getDeleterForUniquePtr(Result, "left_class");
+  const Type *RightDeleterType = getDeleterForUniquePtr(Result, "right_class");
+
+  if (LeftDeleterType->getUnqualifiedDesugaredType() ==
+      RightDeleterType->getUnqualifiedDesugaredType()) {
+    // Same type. We assume they are compatible.
+    // This check handles the case where the deleters are function pointers.
+    return true;
+  }
+
+  const CXXRecordDecl *LeftDeleter = LeftDeleterType->getAsCXXRecordDecl();
+  const CXXRecordDecl *RightDeleter = RightDeleterType->getAsCXXRecordDecl();
+  if (!LeftDeleter || !RightDeleter)
+    return false;
+
+  if (LeftDeleter->getCanonicalDecl() == RightDeleter->getCanonicalDecl()) {
+    // Same class. We assume they are compatible.
+    return true;
+  }
+
+  const auto *LeftAsTemplate =
+      dyn_cast<ClassTemplateSpecializationDecl>(LeftDeleter);
+  const auto *RightAsTemplate =
+      dyn_cast<ClassTemplateSpecializationDecl>(RightDeleter);
+  if (LeftAsTemplate && RightAsTemplate &&
+      LeftAsTemplate->getSpecializedTemplate() ==
+          RightAsTemplate->getSpecializedTemplate()) {
+    // They are different instantiations of the same template. We assume they
+    // are compatible.
+    // This handles things like std::default_delete<Base> vs.
+    // std::default_delete<Derived>.
+    return true;
+  }
+  return false;
+}
+
+} // namespace
+
+void UniqueptrResetReleaseCheck::check(const MatchFinder::MatchResult &Result) {
+  if (!areDeletersCompatible(Result))
+    return;
+
+  const auto *ResetMember = Result.Nodes.getNodeAs<MemberExpr>("reset_member");
+  const auto *ReleaseMember =
+      Result.Nodes.getNodeAs<MemberExpr>("release_member");
+  const auto *Right = Result.Nodes.getNodeAs<Expr>("right");
+  const auto *Left = Result.Nodes.getNodeAs<Expr>("left");
+  const auto *ResetCall =
+      Result.Nodes.getNodeAs<CXXMemberCallExpr>("reset_call");
+
+  std::string LeftText = clang::Lexer::getSourceText(
+      CharSourceRange::getTokenRange(Left->getSourceRange()),
+      *Result.SourceManager, getLangOpts());
+  std::string RightText = clang::Lexer::getSourceText(
+      CharSourceRange::getTokenRange(Right->getSourceRange()),
+      *Result.SourceManager, getLangOpts());
+
+  if (ResetMember->isArrow())
+    LeftText = "*" + LeftText;
+  if (ReleaseMember->isArrow())
+    RightText = "*" + RightText;
+  std::string DiagText;
+  // Even if x was rvalue, *x is not rvalue anymore.
+  if (!Right->isRValue() || ReleaseMember->isArrow()) {
+    RightText = "std::move(" + RightText + ")";
+    DiagText = "prefer ptr1 = std::move(ptr2) over ptr1.reset(ptr2.release())";
+  } else {
+    DiagText =
+        "prefer ptr = ReturnUnique() over ptr.reset(ReturnUnique().release())";
+  }
+  std::string NewText = LeftText + " = " + RightText;
+
+  diag(ResetMember->getExprLoc(), DiagText) << FixItHint::CreateReplacement(
+      CharSourceRange::getTokenRange(ResetCall->getSourceRange()), NewText);
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UniqueptrResetReleaseCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UniqueptrResetReleaseCheck.h
new file mode 100644
index 0000000..cf18a5a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UniqueptrResetReleaseCheck.h
@@ -0,0 +1,43 @@
+//===--- UniqueptrResetReleaseCheck.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_MISC_UNIQUEPTRRESETRELEASECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNIQUEPTRRESETRELEASECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Find and replace `unique_ptr::reset(release())` with `std::move()`.
+///
+/// Example:
+///
+/// \code
+///   std::unique_ptr<Foo> x, y;
+///   x.reset(y.release()); -> x = std::move(y);
+/// \endcode
+///
+/// If `y` is already rvalue, `std::move()` is not added.  `x` and `y` can also
+/// be `std::unique_ptr<Foo>*`.
+class UniqueptrResetReleaseCheck : public ClangTidyCheck {
+public:
+  UniqueptrResetReleaseCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNIQUEPTRRESETRELEASECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp
new file mode 100644
index 0000000..07165d6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp
@@ -0,0 +1,64 @@
+//===--- UnusedAliasDeclsCheck.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 "UnusedAliasDeclsCheck.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 misc {
+
+void UnusedAliasDeclsCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++11; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  // We cannot do anything about headers (yet), as the alias declarations
+  // used in one header could be used by some other translation unit.
+  Finder->addMatcher(namespaceAliasDecl(isExpansionInMainFile()).bind("alias"),
+                     this);
+  Finder->addMatcher(nestedNameSpecifier().bind("nns"), this);
+}
+
+void UnusedAliasDeclsCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *AliasDecl = Result.Nodes.getNodeAs<NamedDecl>("alias")) {
+    FoundDecls[AliasDecl] = CharSourceRange::getCharRange(
+        AliasDecl->getLocStart(),
+        Lexer::findLocationAfterToken(
+            AliasDecl->getLocEnd(), tok::semi, *Result.SourceManager,
+            getLangOpts(),
+            /*SkipTrailingWhitespaceAndNewLine=*/true));
+    return;
+  }
+
+  if (const auto *NestedName =
+          Result.Nodes.getNodeAs<NestedNameSpecifier>("nns")) {
+    if (const auto *AliasDecl = NestedName->getAsNamespaceAlias()) {
+      FoundDecls[AliasDecl] = CharSourceRange();
+    }
+  }
+}
+
+void UnusedAliasDeclsCheck::onEndOfTranslationUnit() {
+  for (const auto &FoundDecl : FoundDecls) {
+    if (!FoundDecl.second.isValid())
+      continue;
+    diag(FoundDecl.first->getLocation(), "namespace alias decl %0 is unused")
+        << FoundDecl.first << FixItHint::CreateRemoval(FoundDecl.second);
+  }
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.h
new file mode 100644
index 0000000..8cce3756
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.h
@@ -0,0 +1,37 @@
+//===--- UnusedAliasDeclsCheck.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_MISC_UNUSED_ALIAS_DECLS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNUSED_ALIAS_DECLS_H
+
+#include "../ClangTidy.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Finds unused namespace alias declarations.
+class UnusedAliasDeclsCheck : public ClangTidyCheck {
+public:
+  UnusedAliasDeclsCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void onEndOfTranslationUnit() override;
+
+private:
+  llvm::DenseMap<const NamedDecl *, CharSourceRange> FoundDecls;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNUSED_ALIAS_DECLS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp
new file mode 100644
index 0000000..1e342d1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp
@@ -0,0 +1,193 @@
+//===--- UnusedParametersCheck.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 "UnusedParametersCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/STLExtras.h"
+#include <unordered_set>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+namespace {
+bool isOverrideMethod(const FunctionDecl *Function) {
+  if (const auto *MD = dyn_cast<CXXMethodDecl>(Function))
+    return MD->size_overridden_methods() > 0 || MD->hasAttr<OverrideAttr>();
+  return false;
+}
+} // namespace
+
+void UnusedParametersCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      functionDecl(isDefinition(), hasBody(stmt()), hasAnyParameter(decl()))
+          .bind("function"),
+      this);
+}
+
+template <typename T>
+static CharSourceRange removeNode(const MatchFinder::MatchResult &Result,
+                                  const T *PrevNode, const T *Node,
+                                  const T *NextNode) {
+  if (NextNode)
+    return CharSourceRange::getCharRange(Node->getLocStart(),
+                                         NextNode->getLocStart());
+
+  if (PrevNode)
+    return CharSourceRange::getTokenRange(
+        Lexer::getLocForEndOfToken(PrevNode->getLocEnd(), 0,
+                                   *Result.SourceManager,
+                                   Result.Context->getLangOpts()),
+        Node->getLocEnd());
+
+  return CharSourceRange::getTokenRange(Node->getSourceRange());
+}
+
+static FixItHint removeParameter(const MatchFinder::MatchResult &Result,
+                                 const FunctionDecl *Function, unsigned Index) {
+  return FixItHint::CreateRemoval(removeNode(
+      Result, Index > 0 ? Function->getParamDecl(Index - 1) : nullptr,
+      Function->getParamDecl(Index),
+      Index + 1 < Function->getNumParams() ? Function->getParamDecl(Index + 1)
+                                           : nullptr));
+}
+
+static FixItHint removeArgument(const MatchFinder::MatchResult &Result,
+                                const CallExpr *Call, unsigned Index) {
+  return FixItHint::CreateRemoval(removeNode(
+      Result, Index > 0 ? Call->getArg(Index - 1) : nullptr,
+      Call->getArg(Index),
+      Index + 1 < Call->getNumArgs() ? Call->getArg(Index + 1) : nullptr));
+}
+
+class UnusedParametersCheck::IndexerVisitor
+    : public RecursiveASTVisitor<IndexerVisitor> {
+public:
+  IndexerVisitor(TranslationUnitDecl *Top) { TraverseDecl(Top); }
+
+  const std::unordered_set<const CallExpr *> &
+  getFnCalls(const FunctionDecl *Fn) {
+    return Index[Fn->getCanonicalDecl()].Calls;
+  }
+
+  const std::unordered_set<const DeclRefExpr *> &
+  getOtherRefs(const FunctionDecl *Fn) {
+    return Index[Fn->getCanonicalDecl()].OtherRefs;
+  }
+
+  bool shouldTraversePostOrder() const { return true; }
+
+  bool WalkUpFromDeclRefExpr(DeclRefExpr *DeclRef) {
+    if (const auto *Fn = dyn_cast<FunctionDecl>(DeclRef->getDecl())) {
+      Fn = Fn->getCanonicalDecl();
+      Index[Fn].OtherRefs.insert(DeclRef);
+    }
+    return true;
+  }
+
+  bool WalkUpFromCallExpr(CallExpr *Call) {
+    if (const auto *Fn =
+            dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl())) {
+      Fn = Fn->getCanonicalDecl();
+      if (const auto *Ref =
+              dyn_cast<DeclRefExpr>(Call->getCallee()->IgnoreImplicit())) {
+        Index[Fn].OtherRefs.erase(Ref);
+      }
+      Index[Fn].Calls.insert(Call);
+    }
+    return true;
+  }
+
+private:
+  struct IndexEntry {
+    std::unordered_set<const CallExpr *> Calls;
+    std::unordered_set<const DeclRefExpr *> OtherRefs;
+  };
+
+  std::unordered_map<const FunctionDecl *, IndexEntry> Index;
+};
+
+UnusedParametersCheck::~UnusedParametersCheck() = default;
+
+UnusedParametersCheck::UnusedParametersCheck(StringRef Name,
+                                             ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      StrictMode(Options.getLocalOrGlobal("StrictMode", 0) != 0) {}
+
+void UnusedParametersCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "StrictMode", StrictMode);
+}
+
+void UnusedParametersCheck::warnOnUnusedParameter(
+    const MatchFinder::MatchResult &Result, const FunctionDecl *Function,
+    unsigned ParamIndex) {
+  const auto *Param = Function->getParamDecl(ParamIndex);
+  auto MyDiag = diag(Param->getLocation(), "parameter %0 is unused") << Param;
+
+  if (!Indexer) {
+    Indexer = llvm::make_unique<IndexerVisitor>(
+        Result.Context->getTranslationUnitDecl());
+  }
+
+  // Comment out parameter name for non-local functions.
+  if (Function->isExternallyVisible() ||
+      !Result.SourceManager->isInMainFile(Function->getLocation()) ||
+      !Indexer->getOtherRefs(Function).empty() || isOverrideMethod(Function)) {
+    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.
+    MyDiag << FixItHint::CreateReplacement(
+        RemovalRange, (Twine(" /*") + Param->getName() + "*/").str());
+    return;
+  }
+
+  // Fix all redeclarations.
+  for (const FunctionDecl *FD : Function->redecls())
+    if (FD->param_size())
+      MyDiag << removeParameter(Result, FD, ParamIndex);
+
+  // Fix all call sites.
+  for (const CallExpr *Call : Indexer->getFnCalls(Function))
+    if (ParamIndex < Call->getNumArgs()) // See PR38055 for example.
+      MyDiag << removeArgument(Result, Call, ParamIndex);
+}
+
+void UnusedParametersCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Function = Result.Nodes.getNodeAs<FunctionDecl>("function");
+  if (!Function->hasWrittenPrototype() || Function->isTemplateInstantiation())
+    return;
+  if (const auto *Method = dyn_cast<CXXMethodDecl>(Function))
+    if (Method->isLambdaStaticInvoker())
+      return;
+  for (unsigned i = 0, e = Function->getNumParams(); i != e; ++i) {
+    const auto *Param = Function->getParamDecl(i);
+    if (Param->isUsed() || Param->isReferenced() || !Param->getDeclName() ||
+        Param->hasAttr<UnusedAttr>())
+      continue;
+
+    // In non-strict mode ignore function definitions with empty bodies
+    // (constructor initializer counts for non-empty body).
+    if (StrictMode ||
+        (Function->getBody()->child_begin() !=
+         Function->getBody()->child_end()) ||
+        (isa<CXXConstructorDecl>(Function) &&
+         cast<CXXConstructorDecl>(Function)->getNumCtorInitializers() > 0))
+      warnOnUnusedParameter(Result, Function, i);
+  }
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.h
new file mode 100644
index 0000000..b9bae26
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.h
@@ -0,0 +1,43 @@
+//===--- UnusedParametersCheck.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_MISC_UNUSED_PARAMETERS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNUSED_PARAMETERS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Finds unused parameters and fixes them, so that `-Wunused-parameter` can be
+/// turned on.
+class UnusedParametersCheck : public ClangTidyCheck {
+public:
+  UnusedParametersCheck(StringRef Name, ClangTidyContext *Context);
+  ~UnusedParametersCheck();
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  const bool StrictMode;
+  class IndexerVisitor;
+  std::unique_ptr<IndexerVisitor> Indexer;
+
+  void
+  warnOnUnusedParameter(const ast_matchers::MatchFinder::MatchResult &Result,
+                        const FunctionDecl *Function, unsigned ParamIndex);
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNUSED_PARAMETERS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
new file mode 100644
index 0000000..b3eabdc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
@@ -0,0 +1,167 @@
+//===--- UnusedUsingDeclsCheck.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 "UnusedUsingDeclsCheck.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 misc {
+
+// A function that helps to tell whether a TargetDecl in a UsingDecl will be
+// checked. Only variable, function, function template, class template, class,
+// enum declaration and enum constant declaration are considered.
+static bool ShouldCheckDecl(const Decl *TargetDecl) {
+  return isa<RecordDecl>(TargetDecl) || isa<ClassTemplateDecl>(TargetDecl) ||
+         isa<FunctionDecl>(TargetDecl) || isa<VarDecl>(TargetDecl) ||
+         isa<FunctionTemplateDecl>(TargetDecl) || isa<EnumDecl>(TargetDecl) ||
+         isa<EnumConstantDecl>(TargetDecl);
+}
+
+void UnusedUsingDeclsCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(usingDecl(isExpansionInMainFile()).bind("using"), this);
+  auto DeclMatcher = hasDeclaration(namedDecl().bind("used"));
+  Finder->addMatcher(loc(enumType(DeclMatcher)), this);
+  Finder->addMatcher(loc(recordType(DeclMatcher)), this);
+  Finder->addMatcher(loc(templateSpecializationType(DeclMatcher)), this);
+  Finder->addMatcher(declRefExpr().bind("used"), this);
+  Finder->addMatcher(callExpr(callee(unresolvedLookupExpr().bind("used"))),
+                     this);
+  Finder->addMatcher(
+      callExpr(hasDeclaration(functionDecl(hasAnyTemplateArgument(
+          anyOf(refersToTemplate(templateName().bind("used")),
+                refersToDeclaration(functionDecl().bind("used"))))))),
+      this);
+  Finder->addMatcher(loc(templateSpecializationType(hasAnyTemplateArgument(
+                         templateArgument().bind("used")))),
+                     this);
+}
+
+void UnusedUsingDeclsCheck::check(const MatchFinder::MatchResult &Result) {
+  if (Result.Context->getDiagnostics().hasUncompilableErrorOccurred())
+    return;
+
+  if (const auto *Using = Result.Nodes.getNodeAs<UsingDecl>("using")) {
+    // Ignores using-declarations defined in macros.
+    if (Using->getLocation().isMacroID())
+      return;
+
+    // Ignores using-declarations defined in class definition.
+    if (isa<CXXRecordDecl>(Using->getDeclContext()))
+      return;
+
+    // FIXME: We ignore using-decls defined in function definitions at the
+    // moment because of false positives caused by ADL and different function
+    // scopes.
+    if (isa<FunctionDecl>(Using->getDeclContext()))
+      return;
+
+    UsingDeclContext Context(Using);
+    Context.UsingDeclRange = CharSourceRange::getCharRange(
+        Using->getLocStart(),
+        Lexer::findLocationAfterToken(
+            Using->getLocEnd(), tok::semi, *Result.SourceManager, getLangOpts(),
+            /*SkipTrailingWhitespaceAndNewLine=*/true));
+    for (const auto *UsingShadow : Using->shadows()) {
+      const auto *TargetDecl = UsingShadow->getTargetDecl()->getCanonicalDecl();
+      if (ShouldCheckDecl(TargetDecl))
+        Context.UsingTargetDecls.insert(TargetDecl);
+    }
+    if (!Context.UsingTargetDecls.empty())
+      Contexts.push_back(Context);
+    return;
+  }
+  // Mark using declarations as used by setting FoundDecls' value to zero. As
+  // the AST is walked in order, usages are only marked after a the
+  // corresponding using declaration has been found.
+  // FIXME: This currently doesn't look at whether the type reference is
+  // actually found with the help of the using declaration.
+  if (const auto *Used = Result.Nodes.getNodeAs<NamedDecl>("used")) {
+    if (const auto *FD = dyn_cast<FunctionDecl>(Used)) {
+      removeFromFoundDecls(FD->getPrimaryTemplate());
+    } else if (const auto *Specialization =
+                   dyn_cast<ClassTemplateSpecializationDecl>(Used)) {
+      Used = Specialization->getSpecializedTemplate();
+    }
+    removeFromFoundDecls(Used);
+    return;
+  }
+
+  if (const auto *Used = Result.Nodes.getNodeAs<TemplateArgument>("used")) {
+    // FIXME: Support non-type template parameters.
+    if (Used->getKind() == TemplateArgument::Template) {
+      if (const auto *TD = Used->getAsTemplate().getAsTemplateDecl())
+        removeFromFoundDecls(TD);
+    } else if (Used->getKind() == TemplateArgument::Type) {
+      if (auto *RD = Used->getAsType()->getAsCXXRecordDecl())
+        removeFromFoundDecls(RD);
+    }
+    return;
+  }
+
+  if (const auto *Used = Result.Nodes.getNodeAs<TemplateName>("used")) {
+    removeFromFoundDecls(Used->getAsTemplateDecl());
+    return;
+  }
+
+  if (const auto *DRE = Result.Nodes.getNodeAs<DeclRefExpr>("used")) {
+    if (const auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
+      if (const auto *FDT = FD->getPrimaryTemplate())
+        removeFromFoundDecls(FDT);
+      else
+        removeFromFoundDecls(FD);
+    } else if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+      removeFromFoundDecls(VD);
+    } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
+      removeFromFoundDecls(ECD);
+      if (const auto *ET = ECD->getType()->getAs<EnumType>())
+        removeFromFoundDecls(ET->getDecl());
+    }
+  }
+  // Check the uninstantiated template function usage.
+  if (const auto *ULE = Result.Nodes.getNodeAs<UnresolvedLookupExpr>("used")) {
+    for (const NamedDecl *ND : ULE->decls()) {
+      if (const auto *USD = dyn_cast<UsingShadowDecl>(ND))
+        removeFromFoundDecls(USD->getTargetDecl()->getCanonicalDecl());
+    }
+  }
+}
+
+void UnusedUsingDeclsCheck::removeFromFoundDecls(const Decl *D) {
+  if (!D)
+    return;
+  // FIXME: Currently, we don't handle the using-decls being used in different
+  // scopes (such as different namespaces, different functions). Instead of
+  // giving an incorrect message, we mark all of them as used.
+  //
+  // FIXME: Use a more efficient way to find a matching context.
+  for (auto &Context : Contexts) {
+    if (Context.UsingTargetDecls.count(D->getCanonicalDecl()) > 0)
+      Context.IsUsed = true;
+  }
+}
+
+void UnusedUsingDeclsCheck::onEndOfTranslationUnit() {
+  for (const auto &Context : Contexts) {
+    if (!Context.IsUsed) {
+      diag(Context.FoundUsingDecl->getLocation(), "using decl %0 is unused")
+          << Context.FoundUsingDecl
+          << FixItHint::CreateRemoval(Context.UsingDeclRange);
+    }
+  }
+  Contexts.clear();
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.h
new file mode 100644
index 0000000..2a41a8f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.h
@@ -0,0 +1,58 @@
+//===--- UnusedUsingDeclsCheck.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_MISC_UNUSED_USING_DECLS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNUSED_USING_DECLS_H
+
+#include "../ClangTidy.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include <vector>
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Finds unused using declarations.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-unused-using-decls.html
+class UnusedUsingDeclsCheck : public ClangTidyCheck {
+public:
+  UnusedUsingDeclsCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void onEndOfTranslationUnit() override;
+
+private:
+  void removeFromFoundDecls(const Decl *D);
+
+  struct UsingDeclContext {
+    explicit UsingDeclContext(const UsingDecl *FoundUsingDecl)
+        : FoundUsingDecl(FoundUsingDecl), IsUsed(false) {}
+    // A set saves all UsingShadowDecls introduced by a UsingDecl. A UsingDecl
+    // can introduce multiple UsingShadowDecls in some cases (such as
+    // overloaded functions).
+    llvm::SmallPtrSet<const Decl *, 4> UsingTargetDecls;
+    // The original UsingDecl.
+    const UsingDecl *FoundUsingDecl;
+    // The source range of the UsingDecl.
+    CharSourceRange UsingDeclRange;
+    // Whether the UsingDecl is used.
+    bool IsUsed;
+  };
+
+  std::vector<UsingDeclContext> Contexts;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNUSED_USING_DECLS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp
new file mode 100644
index 0000000..7cdbb66
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp
@@ -0,0 +1,181 @@
+//===--- AvoidBindCheck.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 "AvoidBindCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cstddef>
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+namespace {
+
+enum BindArgumentKind { BK_Temporary, BK_Placeholder, BK_CallExpr, BK_Other };
+
+struct BindArgument {
+  StringRef Tokens;
+  BindArgumentKind Kind = BK_Other;
+  size_t PlaceHolderIndex = 0;
+};
+
+} // end namespace
+
+static SmallVector<BindArgument, 4>
+buildBindArguments(const MatchFinder::MatchResult &Result, const CallExpr *C) {
+  SmallVector<BindArgument, 4> BindArguments;
+  llvm::Regex MatchPlaceholder("^_([0-9]+)$");
+
+  // Start at index 1 as first argument to bind is the function name.
+  for (size_t I = 1, ArgCount = C->getNumArgs(); I < ArgCount; ++I) {
+    const Expr *E = C->getArg(I);
+    BindArgument B;
+    if (const auto *M = dyn_cast<MaterializeTemporaryExpr>(E)) {
+      const auto *TE = M->GetTemporaryExpr();
+      B.Kind = isa<CallExpr>(TE) ? BK_CallExpr : BK_Temporary;
+    }
+
+    B.Tokens = Lexer::getSourceText(
+        CharSourceRange::getTokenRange(E->getLocStart(), E->getLocEnd()),
+        *Result.SourceManager, Result.Context->getLangOpts());
+
+    SmallVector<StringRef, 2> Matches;
+    if (B.Kind == BK_Other && MatchPlaceholder.match(B.Tokens, &Matches)) {
+      B.Kind = BK_Placeholder;
+      B.PlaceHolderIndex = std::stoi(Matches[1]);
+    }
+    BindArguments.push_back(B);
+  }
+  return BindArguments;
+}
+
+static void addPlaceholderArgs(const ArrayRef<BindArgument> Args,
+                               llvm::raw_ostream &Stream) {
+  auto MaxPlaceholderIt =
+      std::max_element(Args.begin(), Args.end(),
+                       [](const BindArgument &B1, const BindArgument &B2) {
+                         return B1.PlaceHolderIndex < B2.PlaceHolderIndex;
+                       });
+
+  // Placeholders (if present) have index 1 or greater.
+  if (MaxPlaceholderIt == Args.end() || MaxPlaceholderIt->PlaceHolderIndex == 0)
+    return;
+
+  size_t PlaceholderCount = MaxPlaceholderIt->PlaceHolderIndex;
+  Stream << "(";
+  StringRef Delimiter = "";
+  for (size_t I = 1; I <= PlaceholderCount; ++I) {
+    Stream << Delimiter << "auto && arg" << I;
+    Delimiter = ", ";
+  }
+  Stream << ")";
+}
+
+static void addFunctionCallArgs(const ArrayRef<BindArgument> Args,
+                                llvm::raw_ostream &Stream) {
+  StringRef Delimiter = "";
+  for (const auto &B : Args) {
+    if (B.PlaceHolderIndex)
+      Stream << Delimiter << "arg" << B.PlaceHolderIndex;
+    else
+      Stream << Delimiter << B.Tokens;
+    Delimiter = ", ";
+  }
+}
+
+static bool isPlaceHolderIndexRepeated(const ArrayRef<BindArgument> Args) {
+  llvm::SmallSet<size_t, 4> PlaceHolderIndices;
+  for (const BindArgument &B : Args) {
+    if (B.PlaceHolderIndex) {
+      if (!PlaceHolderIndices.insert(B.PlaceHolderIndex).second)
+        return true;
+    }
+  }
+  return false;
+}
+
+void AvoidBindCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus14) // Need C++14 for generic lambdas.
+    return;
+
+  Finder->addMatcher(
+      callExpr(
+          callee(namedDecl(hasName("::std::bind"))),
+          hasArgument(0, declRefExpr(to(functionDecl().bind("f"))).bind("ref")))
+          .bind("bind"),
+      this);
+}
+
+void AvoidBindCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<CallExpr>("bind");
+  auto Diag = diag(MatchedDecl->getLocStart(), "prefer a lambda to std::bind");
+
+  const auto Args = buildBindArguments(Result, MatchedDecl);
+
+  // Do not attempt to create fixits for nested call expressions.
+  // FIXME: Create lambda capture variables to capture output of calls.
+  // NOTE: Supporting nested std::bind will be more difficult due to placeholder
+  // sharing between outer and inner std:bind invocations.
+  if (llvm::any_of(Args,
+                   [](const BindArgument &B) { return B.Kind == BK_CallExpr; }))
+    return;
+
+  // Do not attempt to create fixits when placeholders are reused.
+  // Unused placeholders are supported by requiring C++14 generic lambdas.
+  // FIXME: Support this case by deducing the common type.
+  if (isPlaceHolderIndexRepeated(Args))
+    return;
+
+  const auto *F = Result.Nodes.getNodeAs<FunctionDecl>("f");
+
+  // std::bind can support argument count mismatch between its arguments and the
+  // bound function's arguments. Do not attempt to generate a fixit for such
+  // cases.
+  // FIXME: Support this case by creating unused lambda capture variables.
+  if (F->getNumParams() != Args.size())
+    return;
+
+  std::string Buffer;
+  llvm::raw_string_ostream Stream(Buffer);
+
+  bool HasCapturedArgument = llvm::any_of(
+      Args, [](const BindArgument &B) { return B.Kind == BK_Other; });
+  const auto *Ref = Result.Nodes.getNodeAs<DeclRefExpr>("ref");
+  Stream << "[" << (HasCapturedArgument ? "=" : "") << "]";
+  addPlaceholderArgs(Args, Stream);
+  Stream << " { return ";
+  Ref->printPretty(Stream, nullptr, Result.Context->getPrintingPolicy());
+  Stream << "(";
+  addFunctionCallArgs(Args, Stream);
+  Stream << "); };";
+
+  Diag << FixItHint::CreateReplacement(MatchedDecl->getSourceRange(),
+                                       Stream.str());
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.h
new file mode 100644
index 0000000..5ae0241
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.h
@@ -0,0 +1,36 @@
+//===--- AvoidBindCheck.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_AVOID_BIND_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_AVOID_BIND_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Replace simple uses of std::bind with a lambda.
+///
+/// FIXME: Add support for function references and member function references.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-avoid-std-bind.html
+class AvoidBindCheck : public ClangTidyCheck {
+public:
+  AvoidBindCheck(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_AVOID_BIND_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
new file mode 100644
index 0000000..f02b2ae
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -0,0 +1,42 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyModernizeModule
+  AvoidBindCheck.cpp
+  DeprecatedHeadersCheck.cpp
+  LoopConvertCheck.cpp
+  LoopConvertUtils.cpp
+  MakeSmartPtrCheck.cpp
+  MakeSharedCheck.cpp
+  MakeUniqueCheck.cpp
+  ModernizeTidyModule.cpp
+  PassByValueCheck.cpp
+  RawStringLiteralCheck.cpp
+  RedundantVoidArgCheck.cpp
+  ReplaceAutoPtrCheck.cpp
+  ReplaceRandomShuffleCheck.cpp
+  ReturnBracedInitListCheck.cpp
+  ShrinkToFitCheck.cpp
+  UnaryStaticAssertCheck.cpp
+  UseAutoCheck.cpp
+  UseBoolLiteralsCheck.cpp
+  UseDefaultMemberInitCheck.cpp
+  UseEmplaceCheck.cpp
+  UseEqualsDefaultCheck.cpp
+  UseEqualsDeleteCheck.cpp
+  UseNoexceptCheck.cpp
+  UseNullptrCheck.cpp
+  UseOverrideCheck.cpp
+  UseTransparentFunctorsCheck.cpp
+  UseUncaughtExceptionsCheck.cpp
+  UseUsingCheck.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyReadabilityModule
+  clangTidyUtils
+  clangTooling
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp
new file mode 100644
index 0000000..1ff3f89
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp
@@ -0,0 +1,125 @@
+//===--- DeprecatedHeadersCheck.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 "DeprecatedHeadersCheck.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
+
+#include <vector>
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+namespace {
+class IncludeModernizePPCallbacks : public PPCallbacks {
+public:
+  explicit IncludeModernizePPCallbacks(ClangTidyCheck &Check,
+                                       LangOptions LangOpts);
+
+  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+                          StringRef FileName, bool IsAngled,
+                          CharSourceRange FilenameRange, const FileEntry *File,
+                          StringRef SearchPath, StringRef RelativePath,
+                          const Module *Imported,
+                          SrcMgr::CharacteristicKind FileType) override;
+
+private:
+  ClangTidyCheck &Check;
+  LangOptions LangOpts;
+  llvm::StringMap<std::string> CStyledHeaderToCxx;
+  llvm::StringSet<> DeleteHeaders;
+};
+} // namespace
+
+void DeprecatedHeadersCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  if (this->getLangOpts().CPlusPlus) {
+    Compiler.getPreprocessor().addPPCallbacks(
+        ::llvm::make_unique<IncludeModernizePPCallbacks>(*this,
+                                                         this->getLangOpts()));
+  }
+}
+
+IncludeModernizePPCallbacks::IncludeModernizePPCallbacks(ClangTidyCheck &Check,
+                                                         LangOptions LangOpts)
+    : Check(Check), LangOpts(LangOpts) {
+  for (const auto &KeyValue :
+       std::vector<std::pair<llvm::StringRef, std::string>>(
+           {{"assert.h", "cassert"},
+            {"complex.h", "complex"},
+            {"ctype.h", "cctype"},
+            {"errno.h", "cerrno"},
+            {"float.h", "cfloat"},
+            {"limits.h", "climits"},
+            {"locale.h", "clocale"},
+            {"math.h", "cmath"},
+            {"setjmp.h", "csetjmp"},
+            {"signal.h", "csignal"},
+            {"stdarg.h", "cstdarg"},
+            {"stddef.h", "cstddef"},
+            {"stdio.h", "cstdio"},
+            {"stdlib.h", "cstdlib"},
+            {"string.h", "cstring"},
+            {"time.h", "ctime"},
+            {"wchar.h", "cwchar"},
+            {"wctype.h", "cwctype"}})) {
+    CStyledHeaderToCxx.insert(KeyValue);
+  }
+  // Add C++ 11 headers.
+  if (LangOpts.CPlusPlus11) {
+    for (const auto &KeyValue :
+         std::vector<std::pair<llvm::StringRef, std::string>>(
+             {{"fenv.h", "cfenv"},
+              {"stdint.h", "cstdint"},
+              {"inttypes.h", "cinttypes"},
+              {"tgmath.h", "ctgmath"},
+              {"uchar.h", "cuchar"}})) {
+      CStyledHeaderToCxx.insert(KeyValue);
+    }
+  }
+  for (const auto &Key :
+       std::vector<std::string>({"stdalign.h", "stdbool.h", "iso646.h"})) {
+    DeleteHeaders.insert(Key);
+  }
+}
+
+void IncludeModernizePPCallbacks::InclusionDirective(
+    SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
+    bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
+    StringRef SearchPath, StringRef RelativePath, const Module *Imported,
+    SrcMgr::CharacteristicKind FileType) {
+  // FIXME: Take care of library symbols from the global namespace.
+  //
+  // Reasonable options for the check:
+  //
+  // 1. Insert std prefix for every such symbol occurrence.
+  // 2. Insert `using namespace std;` to the beginning of TU.
+  // 3. Do nothing and let the user deal with the migration himself.
+  if (CStyledHeaderToCxx.count(FileName) != 0) {
+    std::string Replacement =
+        (llvm::Twine("<") + CStyledHeaderToCxx[FileName] + ">").str();
+    Check.diag(FilenameRange.getBegin(), "inclusion of deprecated C++ header "
+                                         "'%0'; consider using '%1' instead")
+        << FileName << CStyledHeaderToCxx[FileName]
+        << FixItHint::CreateReplacement(FilenameRange.getAsRange(),
+                                        Replacement);
+  } else if (DeleteHeaders.count(FileName) != 0) {
+    Check.diag(FilenameRange.getBegin(),
+               "including '%0' has no effect in C++; consider removing it")
+        << FileName << FixItHint::CreateRemoval(
+                           SourceRange(HashLoc, FilenameRange.getEnd()));
+  }
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.h
new file mode 100644
index 0000000..ee7254e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.h
@@ -0,0 +1,47 @@
+//===--- DeprecatedHeadersCheck.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_C_HEADERS_TO_CXX_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_C_HEADERS_TO_CXX_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// This check replaces deprecated C library headers with their C++ STL
+/// alternatives.
+///
+/// Before:
+/// ~~~{.cpp}
+/// #include <header.h>
+/// ~~~
+///
+/// After:
+/// ~~~{.cpp}
+/// #include <cheader>
+/// ~~~
+///
+/// Example: ``<stdio.h> => <cstdio>``
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-deprecated-headers.html
+class DeprecatedHeadersCheck : public ClangTidyCheck {
+public:
+  DeprecatedHeadersCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_C_HEADERS_TO_CXX_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
new file mode 100644
index 0000000..54bf941
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
@@ -0,0 +1,920 @@
+//===--- LoopConvertCheck.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 "LoopConvertCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <cstring>
+#include <utility>
+
+using namespace clang::ast_matchers;
+using namespace llvm;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+static const char LoopNameArray[] = "forLoopArray";
+static const char LoopNameIterator[] = "forLoopIterator";
+static const char LoopNamePseudoArray[] = "forLoopPseudoArray";
+static const char ConditionBoundName[] = "conditionBound";
+static const char ConditionVarName[] = "conditionVar";
+static const char IncrementVarName[] = "incrementVar";
+static const char InitVarName[] = "initVar";
+static const char BeginCallName[] = "beginCall";
+static const char EndCallName[] = "endCall";
+static const char ConditionEndVarName[] = "conditionEndVar";
+static const char EndVarName[] = "endVar";
+static const char DerefByValueResultName[] = "derefByValueResult";
+static const char DerefByRefResultName[] = "derefByRefResult";
+
+// shared matchers
+static const TypeMatcher AnyType = anything();
+
+static const StatementMatcher IntegerComparisonMatcher =
+    expr(ignoringParenImpCasts(
+        declRefExpr(to(varDecl(hasType(isInteger())).bind(ConditionVarName)))));
+
+static const DeclarationMatcher InitToZeroMatcher =
+    varDecl(hasInitializer(ignoringParenImpCasts(integerLiteral(equals(0)))))
+        .bind(InitVarName);
+
+static const StatementMatcher IncrementVarMatcher =
+    declRefExpr(to(varDecl(hasType(isInteger())).bind(IncrementVarName)));
+
+/// \brief The matcher for loops over arrays.
+///
+/// In this general example, assuming 'j' and 'k' are of integral type:
+/// \code
+///   for (int i = 0; j < 3 + 2; ++k) { ... }
+/// \endcode
+/// The following string identifiers are bound to these parts of the AST:
+///   ConditionVarName: 'j' (as a VarDecl)
+///   ConditionBoundName: '3 + 2' (as an Expr)
+///   InitVarName: 'i' (as a VarDecl)
+///   IncrementVarName: 'k' (as a VarDecl)
+///   LoopName: The entire for loop (as a ForStmt)
+///
+/// Client code will need to make sure that:
+///   - The three index variables identified by the matcher are the same
+///     VarDecl.
+///   - The index variable is only used as an array index.
+///   - All arrays indexed by the loop are the same.
+StatementMatcher makeArrayLoopMatcher() {
+  StatementMatcher ArrayBoundMatcher =
+      expr(hasType(isInteger())).bind(ConditionBoundName);
+
+  return forStmt(
+             unless(isInTemplateInstantiation()),
+             hasLoopInit(declStmt(hasSingleDecl(InitToZeroMatcher))),
+             hasCondition(anyOf(
+                 binaryOperator(hasOperatorName("<"),
+                                hasLHS(IntegerComparisonMatcher),
+                                hasRHS(ArrayBoundMatcher)),
+                 binaryOperator(hasOperatorName(">"), hasLHS(ArrayBoundMatcher),
+                                hasRHS(IntegerComparisonMatcher)))),
+             hasIncrement(unaryOperator(hasOperatorName("++"),
+                                        hasUnaryOperand(IncrementVarMatcher))))
+      .bind(LoopNameArray);
+}
+
+/// \brief The matcher used for iterator-based for loops.
+///
+/// This matcher is more flexible than array-based loops. It will match
+/// catch loops of the following textual forms (regardless of whether the
+/// iterator type is actually a pointer type or a class type):
+///
+/// Assuming f, g, and h are of type containerType::iterator,
+/// \code
+///   for (containerType::iterator it = container.begin(),
+///        e = createIterator(); f != g; ++h) { ... }
+///   for (containerType::iterator it = container.begin();
+///        f != anotherContainer.end(); ++h) { ... }
+/// \endcode
+/// The following string identifiers are bound to the parts of the AST:
+///   InitVarName: 'it' (as a VarDecl)
+///   ConditionVarName: 'f' (as a VarDecl)
+///   LoopName: The entire for loop (as a ForStmt)
+///   In the first example only:
+///     EndVarName: 'e' (as a VarDecl)
+///     ConditionEndVarName: 'g' (as a VarDecl)
+///   In the second example only:
+///     EndCallName: 'container.end()' (as a CXXMemberCallExpr)
+///
+/// Client code will need to make sure that:
+///   - The iterator variables 'it', 'f', and 'h' are the same.
+///   - The two containers on which 'begin' and 'end' are called are the same.
+///   - If the end iterator variable 'g' is defined, it is the same as 'f'.
+StatementMatcher makeIteratorLoopMatcher() {
+  StatementMatcher BeginCallMatcher =
+      cxxMemberCallExpr(
+          argumentCountIs(0),
+          callee(cxxMethodDecl(anyOf(hasName("begin"), hasName("cbegin")))))
+          .bind(BeginCallName);
+
+  DeclarationMatcher InitDeclMatcher =
+      varDecl(hasInitializer(anyOf(ignoringParenImpCasts(BeginCallMatcher),
+                                   materializeTemporaryExpr(
+                                       ignoringParenImpCasts(BeginCallMatcher)),
+                                   hasDescendant(BeginCallMatcher))))
+          .bind(InitVarName);
+
+  DeclarationMatcher EndDeclMatcher =
+      varDecl(hasInitializer(anything())).bind(EndVarName);
+
+  StatementMatcher EndCallMatcher = cxxMemberCallExpr(
+      argumentCountIs(0),
+      callee(cxxMethodDecl(anyOf(hasName("end"), hasName("cend")))));
+
+  StatementMatcher IteratorBoundMatcher =
+      expr(anyOf(ignoringParenImpCasts(
+                     declRefExpr(to(varDecl().bind(ConditionEndVarName)))),
+                 ignoringParenImpCasts(expr(EndCallMatcher).bind(EndCallName)),
+                 materializeTemporaryExpr(ignoringParenImpCasts(
+                     expr(EndCallMatcher).bind(EndCallName)))));
+
+  StatementMatcher IteratorComparisonMatcher = expr(
+      ignoringParenImpCasts(declRefExpr(to(varDecl().bind(ConditionVarName)))));
+
+  auto OverloadedNEQMatcher = ignoringImplicit(
+      cxxOperatorCallExpr(hasOverloadedOperatorName("!="), argumentCountIs(2),
+                          hasArgument(0, IteratorComparisonMatcher),
+                          hasArgument(1, IteratorBoundMatcher)));
+
+  // This matcher tests that a declaration is a CXXRecordDecl that has an
+  // 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(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()),
+             hasLoopInit(anyOf(declStmt(declCountIs(2),
+                                        containsDeclaration(0, InitDeclMatcher),
+                                        containsDeclaration(1, EndDeclMatcher)),
+                               declStmt(hasSingleDecl(InitDeclMatcher)))),
+             hasCondition(
+                 anyOf(binaryOperator(hasOperatorName("!="),
+                                      hasLHS(IteratorComparisonMatcher),
+                                      hasRHS(IteratorBoundMatcher)),
+                       binaryOperator(hasOperatorName("!="),
+                                      hasLHS(IteratorBoundMatcher),
+                                      hasRHS(IteratorComparisonMatcher)),
+                       OverloadedNEQMatcher)),
+             hasIncrement(anyOf(
+                 unaryOperator(hasOperatorName("++"),
+                               hasUnaryOperand(declRefExpr(
+                                   to(varDecl(hasType(pointsTo(AnyType)))
+                                          .bind(IncrementVarName))))),
+                 cxxOperatorCallExpr(
+                     hasOverloadedOperatorName("++"),
+                     hasArgument(
+                         0, declRefExpr(to(varDecl(TestDerefReturnsByValue)
+                                               .bind(IncrementVarName))))))))
+      .bind(LoopNameIterator);
+}
+
+/// \brief The matcher used for array-like containers (pseudoarrays).
+///
+/// This matcher is more flexible than array-based loops. It will match
+/// loops of the following textual forms (regardless of whether the
+/// iterator type is actually a pointer type or a class type):
+///
+/// Assuming f, g, and h are of type containerType::iterator,
+/// \code
+///   for (int i = 0, j = container.size(); f < g; ++h) { ... }
+///   for (int i = 0; f < container.size(); ++h) { ... }
+/// \endcode
+/// The following string identifiers are bound to the parts of the AST:
+///   InitVarName: 'i' (as a VarDecl)
+///   ConditionVarName: 'f' (as a VarDecl)
+///   LoopName: The entire for loop (as a ForStmt)
+///   In the first example only:
+///     EndVarName: 'j' (as a VarDecl)
+///     ConditionEndVarName: 'g' (as a VarDecl)
+///   In the second example only:
+///     EndCallName: 'container.size()' (as a CXXMemberCallExpr)
+///
+/// Client code will need to make sure that:
+///   - The index variables 'i', 'f', and 'h' are the same.
+///   - The containers on which 'size()' is called is the container indexed.
+///   - The index variable is only used in overloaded operator[] or
+///     container.at().
+///   - If the end iterator variable 'g' is defined, it is the same as 'j'.
+///   - The container's iterators would not be invalidated during the loop.
+StatementMatcher makePseudoArrayLoopMatcher() {
+  // Test that the incoming type has a record declaration that has methods
+  // called 'begin' and 'end'. If the incoming type is const, then make sure
+  // these methods are also marked const.
+  //
+  // FIXME: To be completely thorough this matcher should also ensure the
+  // return type of begin/end is an iterator that dereferences to the same as
+  // what operator[] or at() returns. Such a test isn't likely to fail except
+  // for pathological cases.
+  //
+  // FIXME: Also, a record doesn't necessarily need begin() and end(). Free
+  // functions called begin() and end() taking the container as an argument
+  // are also allowed.
+  TypeMatcher RecordWithBeginEnd = qualType(anyOf(
+      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(
+      argumentCountIs(0),
+      callee(cxxMethodDecl(anyOf(hasName("size"), hasName("length")))),
+      on(anyOf(hasType(pointsTo(RecordWithBeginEnd)),
+               hasType(RecordWithBeginEnd))));
+
+  StatementMatcher EndInitMatcher =
+      expr(anyOf(ignoringParenImpCasts(expr(SizeCallMatcher).bind(EndCallName)),
+                 explicitCastExpr(hasSourceExpression(ignoringParenImpCasts(
+                     expr(SizeCallMatcher).bind(EndCallName))))));
+
+  DeclarationMatcher EndDeclMatcher =
+      varDecl(hasInitializer(EndInitMatcher)).bind(EndVarName);
+
+  StatementMatcher IndexBoundMatcher =
+      expr(anyOf(ignoringParenImpCasts(declRefExpr(to(
+                     varDecl(hasType(isInteger())).bind(ConditionEndVarName)))),
+                 EndInitMatcher));
+
+  return forStmt(
+             unless(isInTemplateInstantiation()),
+             hasLoopInit(
+                 anyOf(declStmt(declCountIs(2),
+                                containsDeclaration(0, InitToZeroMatcher),
+                                containsDeclaration(1, EndDeclMatcher)),
+                       declStmt(hasSingleDecl(InitToZeroMatcher)))),
+             hasCondition(anyOf(
+                 binaryOperator(hasOperatorName("<"),
+                                hasLHS(IntegerComparisonMatcher),
+                                hasRHS(IndexBoundMatcher)),
+                 binaryOperator(hasOperatorName(">"), hasLHS(IndexBoundMatcher),
+                                hasRHS(IntegerComparisonMatcher)))),
+             hasIncrement(unaryOperator(hasOperatorName("++"),
+                                        hasUnaryOperand(IncrementVarMatcher))))
+      .bind(LoopNamePseudoArray);
+}
+
+/// \brief Determine whether Init appears to be an initializing an iterator.
+///
+/// If it is, returns the object whose begin() or end() method is called, and
+/// the output parameter isArrow is set to indicate whether the initialization
+/// is called via . or ->.
+static const Expr *getContainerFromBeginEndCall(const Expr *Init, bool IsBegin,
+                                                bool *IsArrow) {
+  // FIXME: Maybe allow declaration/initialization outside of the for loop.
+  const auto *TheCall =
+      dyn_cast_or_null<CXXMemberCallExpr>(digThroughConstructors(Init));
+  if (!TheCall || TheCall->getNumArgs() != 0)
+    return nullptr;
+
+  const auto *Member = dyn_cast<MemberExpr>(TheCall->getCallee());
+  if (!Member)
+    return nullptr;
+  StringRef Name = Member->getMemberDecl()->getName();
+  StringRef TargetName = IsBegin ? "begin" : "end";
+  StringRef ConstTargetName = IsBegin ? "cbegin" : "cend";
+  if (Name != TargetName && Name != ConstTargetName)
+    return nullptr;
+
+  const Expr *SourceExpr = Member->getBase();
+  if (!SourceExpr)
+    return nullptr;
+
+  *IsArrow = Member->isArrow();
+  return SourceExpr;
+}
+
+/// \brief Determines the container whose begin() and end() functions are called
+/// for an iterator-based loop.
+///
+/// BeginExpr must be a member call to a function named "begin()", and EndExpr
+/// must be a member.
+static const Expr *findContainer(ASTContext *Context, const Expr *BeginExpr,
+                                 const Expr *EndExpr,
+                                 bool *ContainerNeedsDereference) {
+  // Now that we know the loop variable and test expression, make sure they are
+  // valid.
+  bool BeginIsArrow = false;
+  bool EndIsArrow = false;
+  const Expr *BeginContainerExpr =
+      getContainerFromBeginEndCall(BeginExpr, /*IsBegin=*/true, &BeginIsArrow);
+  if (!BeginContainerExpr)
+    return nullptr;
+
+  const Expr *EndContainerExpr =
+      getContainerFromBeginEndCall(EndExpr, /*IsBegin=*/false, &EndIsArrow);
+  // Disallow loops that try evil things like this (note the dot and arrow):
+  //  for (IteratorType It = Obj.begin(), E = Obj->end(); It != E; ++It) { }
+  if (!EndContainerExpr || BeginIsArrow != EndIsArrow ||
+      !areSameExpr(Context, EndContainerExpr, BeginContainerExpr))
+    return nullptr;
+
+  *ContainerNeedsDereference = BeginIsArrow;
+  return BeginContainerExpr;
+}
+
+/// \brief Obtain the original source code text from a SourceRange.
+static StringRef getStringFromRange(SourceManager &SourceMgr,
+                                    const LangOptions &LangOpts,
+                                    SourceRange Range) {
+  if (SourceMgr.getFileID(Range.getBegin()) !=
+      SourceMgr.getFileID(Range.getEnd())) {
+    return StringRef(); // Empty string.
+  }
+
+  return Lexer::getSourceText(CharSourceRange(Range, true), SourceMgr,
+                              LangOpts);
+}
+
+/// \brief If the given expression is actually a DeclRefExpr or a MemberExpr,
+/// find and return the underlying ValueDecl; otherwise, return NULL.
+static const ValueDecl *getReferencedVariable(const Expr *E) {
+  if (const DeclRefExpr *DRE = getDeclRef(E))
+    return dyn_cast<VarDecl>(DRE->getDecl());
+  if (const auto *Mem = dyn_cast<MemberExpr>(E->IgnoreParenImpCasts()))
+    return dyn_cast<FieldDecl>(Mem->getMemberDecl());
+  return nullptr;
+}
+
+/// \brief Returns true when the given expression is a member expression
+/// whose base is `this` (implicitly or not).
+static bool isDirectMemberExpr(const Expr *E) {
+  if (const auto *Member = dyn_cast<MemberExpr>(E->IgnoreParenImpCasts()))
+    return isa<CXXThisExpr>(Member->getBase()->IgnoreParenImpCasts());
+  return false;
+}
+
+/// \brief Given an expression that represents an usage of an element from the
+/// containter that we are iterating over, returns false when it can be
+/// guaranteed this element cannot be modified as a result of this usage.
+static bool canBeModified(ASTContext *Context, const Expr *E) {
+  if (E->getType().isConstQualified())
+    return false;
+  auto Parents = Context->getParents(*E);
+  if (Parents.size() != 1)
+    return true;
+  if (const auto *Cast = Parents[0].get<ImplicitCastExpr>()) {
+    if ((Cast->getCastKind() == CK_NoOp &&
+         Cast->getType() == E->getType().withConst()) ||
+        (Cast->getCastKind() == CK_LValueToRValue &&
+         !Cast->getType().isNull() && Cast->getType()->isFundamentalType()))
+      return false;
+  }
+  // FIXME: Make this function more generic.
+  return true;
+}
+
+/// \brief Returns true when it can be guaranteed that the elements of the
+/// container are not being modified.
+static bool usagesAreConst(ASTContext *Context, const UsageResult &Usages) {
+  for (const Usage &U : Usages) {
+    // Lambda captures are just redeclarations (VarDecl) of the same variable,
+    // not expressions. If we want to know if a variable that is captured by
+    // reference can be modified in an usage inside the lambda's body, we need
+    // to find the expression corresponding to that particular usage, later in
+    // this loop.
+    if (U.Kind != Usage::UK_CaptureByCopy && U.Kind != Usage::UK_CaptureByRef &&
+        canBeModified(Context, U.Expression))
+      return false;
+  }
+  return true;
+}
+
+/// \brief Returns true if the elements of the container are never accessed
+/// by reference.
+static bool usagesReturnRValues(const UsageResult &Usages) {
+  for (const auto &U : Usages) {
+    if (U.Expression && !U.Expression->isRValue())
+      return false;
+  }
+  return true;
+}
+
+/// \brief Returns true if the container is const-qualified.
+static bool containerIsConst(const Expr *ContainerExpr, bool Dereference) {
+  if (const auto *VDec = getReferencedVariable(ContainerExpr)) {
+    QualType CType = VDec->getType();
+    if (Dereference) {
+      if (!CType->isPointerType())
+        return false;
+      CType = CType->getPointeeType();
+    }
+    // If VDec is a reference to a container, Dereference is false,
+    // but we still need to check the const-ness of the underlying container
+    // type.
+    CType = CType.getNonReferenceType();
+    return CType.isConstQualified();
+  }
+  return false;
+}
+
+LoopConvertCheck::RangeDescriptor::RangeDescriptor()
+    : ContainerNeedsDereference(false), DerefByConstRef(false),
+      DerefByValue(false) {}
+
+LoopConvertCheck::LoopConvertCheck(StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context), TUInfo(new TUTrackingInfo),
+      MaxCopySize(std::stoull(Options.get("MaxCopySize", "16"))),
+      MinConfidence(StringSwitch<Confidence::Level>(
+                        Options.get("MinConfidence", "reasonable"))
+                        .Case("safe", Confidence::CL_Safe)
+                        .Case("risky", Confidence::CL_Risky)
+                        .Default(Confidence::CL_Reasonable)),
+      NamingStyle(StringSwitch<VariableNamer::NamingStyle>(
+                      Options.get("NamingStyle", "CamelCase"))
+                      .Case("camelBack", VariableNamer::NS_CamelBack)
+                      .Case("lower_case", VariableNamer::NS_LowerCase)
+                      .Case("UPPER_CASE", VariableNamer::NS_UpperCase)
+                      .Default(VariableNamer::NS_CamelCase)) {}
+
+void LoopConvertCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "MaxCopySize", std::to_string(MaxCopySize));
+  SmallVector<std::string, 3> Confs{"risky", "reasonable", "safe"};
+  Options.store(Opts, "MinConfidence", Confs[static_cast<int>(MinConfidence)]);
+
+  SmallVector<std::string, 4> Styles{"camelBack", "CamelCase", "lower_case",
+                                     "UPPER_CASE"};
+  Options.store(Opts, "NamingStyle", Styles[static_cast<int>(NamingStyle)]);
+}
+
+void LoopConvertCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++. Because this checker is used for
+  // modernization, it is reasonable to run it on any C++ standard with the
+  // assumption the user is trying to modernize their codebase.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(makeArrayLoopMatcher(), this);
+  Finder->addMatcher(makeIteratorLoopMatcher(), this);
+  Finder->addMatcher(makePseudoArrayLoopMatcher(), this);
+}
+
+/// \brief Given the range of a single declaration, such as:
+/// \code
+///   unsigned &ThisIsADeclarationThatCanSpanSeveralLinesOfCode =
+///       InitializationValues[I];
+///   next_instruction;
+/// \endcode
+/// Finds the range that has to be erased to remove this declaration without
+/// leaving empty lines, by extending the range until the beginning of the
+/// next instruction.
+///
+/// We need to delete a potential newline after the deleted alias, as
+/// clang-format will leave empty lines untouched. For all other formatting we
+/// rely on clang-format to fix it.
+void LoopConvertCheck::getAliasRange(SourceManager &SM, SourceRange &Range) {
+  bool Invalid = false;
+  const char *TextAfter =
+      SM.getCharacterData(Range.getEnd().getLocWithOffset(1), &Invalid);
+  if (Invalid)
+    return;
+  unsigned Offset = std::strspn(TextAfter, " \t\r\n");
+  Range =
+      SourceRange(Range.getBegin(), Range.getEnd().getLocWithOffset(Offset));
+}
+
+/// \brief Computes the changes needed to convert a given for loop, and
+/// applies them.
+void LoopConvertCheck::doConversion(
+    ASTContext *Context, const VarDecl *IndexVar,
+    const ValueDecl *MaybeContainer, const UsageResult &Usages,
+    const DeclStmt *AliasDecl, bool AliasUseRequired, bool AliasFromForInit,
+    const ForStmt *Loop, RangeDescriptor Descriptor) {
+  auto Diag = diag(Loop->getForLoc(), "use range-based for loop instead");
+
+  std::string VarName;
+  bool VarNameFromAlias = (Usages.size() == 1) && AliasDecl;
+  bool AliasVarIsRef = false;
+  bool CanCopy = true;
+
+  if (VarNameFromAlias) {
+    const auto *AliasVar = cast<VarDecl>(AliasDecl->getSingleDecl());
+    VarName = AliasVar->getName().str();
+
+    // Use the type of the alias if it's not the same
+    QualType AliasVarType = AliasVar->getType();
+    assert(!AliasVarType.isNull() && "Type in VarDecl is null");
+    if (AliasVarType->isReferenceType()) {
+      AliasVarType = AliasVarType.getNonReferenceType();
+      AliasVarIsRef = true;
+    }
+    if (Descriptor.ElemType.isNull() ||
+        !Context->hasSameUnqualifiedType(AliasVarType, Descriptor.ElemType))
+      Descriptor.ElemType = AliasVarType;
+
+    // We keep along the entire DeclStmt to keep the correct range here.
+    SourceRange ReplaceRange = AliasDecl->getSourceRange();
+
+    std::string ReplacementText;
+    if (AliasUseRequired) {
+      ReplacementText = VarName;
+    } else if (AliasFromForInit) {
+      // FIXME: Clang includes the location of the ';' but only for DeclStmt's
+      // in a for loop's init clause. Need to put this ';' back while removing
+      // the declaration of the alias variable. This is probably a bug.
+      ReplacementText = ";";
+    } else {
+      // Avoid leaving empty lines or trailing whitespaces.
+      getAliasRange(Context->getSourceManager(), ReplaceRange);
+    }
+
+    Diag << FixItHint::CreateReplacement(
+        CharSourceRange::getTokenRange(ReplaceRange), ReplacementText);
+    // No further replacements are made to the loop, since the iterator or index
+    // was used exactly once - in the initialization of AliasVar.
+  } else {
+    VariableNamer Namer(&TUInfo->getGeneratedDecls(),
+                        &TUInfo->getParentFinder().getStmtToParentStmtMap(),
+                        Loop, IndexVar, MaybeContainer, Context, NamingStyle);
+    VarName = Namer.createIndexName();
+    // First, replace all usages of the array subscript expression with our new
+    // variable.
+    for (const auto &Usage : Usages) {
+      std::string ReplaceText;
+      SourceRange Range = Usage.Range;
+      if (Usage.Expression) {
+        // If this is an access to a member through the arrow operator, after
+        // the replacement it must be accessed through the '.' operator.
+        ReplaceText = Usage.Kind == Usage::UK_MemberThroughArrow ? VarName + "."
+                                                                 : VarName;
+        auto Parents = Context->getParents(*Usage.Expression);
+        if (Parents.size() == 1) {
+          if (const auto *Paren = Parents[0].get<ParenExpr>()) {
+            // Usage.Expression will be replaced with the new index variable,
+            // and parenthesis around a simple DeclRefExpr can always be
+            // removed.
+            Range = Paren->getSourceRange();
+          } else if (const auto *UOP = Parents[0].get<UnaryOperator>()) {
+            // If we are taking the address of the loop variable, then we must
+            // not use a copy, as it would mean taking the address of the loop's
+            // local index instead.
+            // FIXME: This won't catch cases where the address is taken outside
+            // of the loop's body (for instance, in a function that got the
+            // loop's index as a const reference parameter), or where we take
+            // the address of a member (like "&Arr[i].A.B.C").
+            if (UOP->getOpcode() == UO_AddrOf)
+              CanCopy = false;
+          }
+        }
+      } else {
+        // The Usage expression is only null in case of lambda captures (which
+        // are VarDecl). If the index is captured by value, add '&' to capture
+        // by reference instead.
+        ReplaceText =
+            Usage.Kind == Usage::UK_CaptureByCopy ? "&" + VarName : VarName;
+      }
+      TUInfo->getReplacedVars().insert(std::make_pair(Loop, IndexVar));
+      Diag << FixItHint::CreateReplacement(
+          CharSourceRange::getTokenRange(Range), ReplaceText);
+    }
+  }
+
+  // Now, we need to construct the new range expression.
+  SourceRange ParenRange(Loop->getLParenLoc(), Loop->getRParenLoc());
+
+  QualType Type = Context->getAutoDeductType();
+  if (!Descriptor.ElemType.isNull() && Descriptor.ElemType->isFundamentalType())
+    Type = Descriptor.ElemType.getUnqualifiedType();
+
+  // If the new variable name is from the aliased variable, then the reference
+  // type for the new variable should only be used if the aliased variable was
+  // declared as a reference.
+  bool IsCheapToCopy =
+      !Descriptor.ElemType.isNull() &&
+      Descriptor.ElemType.isTriviallyCopyableType(*Context) &&
+      // TypeInfo::Width is in bits.
+      Context->getTypeInfo(Descriptor.ElemType).Width <= 8 * MaxCopySize;
+  bool UseCopy = CanCopy && ((VarNameFromAlias && !AliasVarIsRef) ||
+                             (Descriptor.DerefByConstRef && IsCheapToCopy));
+
+  if (!UseCopy) {
+    if (Descriptor.DerefByConstRef) {
+      Type = Context->getLValueReferenceType(Context->getConstType(Type));
+    } else if (Descriptor.DerefByValue) {
+      if (!IsCheapToCopy)
+        Type = Context->getRValueReferenceType(Type);
+    } else {
+      Type = Context->getLValueReferenceType(Type);
+    }
+  }
+
+  StringRef MaybeDereference = Descriptor.ContainerNeedsDereference ? "*" : "";
+  std::string TypeString = Type.getAsString(getLangOpts());
+  std::string Range = ("(" + TypeString + " " + VarName + " : " +
+                       MaybeDereference + Descriptor.ContainerString + ")")
+                          .str();
+  Diag << FixItHint::CreateReplacement(
+      CharSourceRange::getTokenRange(ParenRange), Range);
+  TUInfo->getGeneratedDecls().insert(make_pair(Loop, VarName));
+}
+
+/// \brief Returns a string which refers to the container iterated over.
+StringRef LoopConvertCheck::getContainerString(ASTContext *Context,
+                                               const ForStmt *Loop,
+                                               const Expr *ContainerExpr) {
+  StringRef ContainerString;
+  if (isa<CXXThisExpr>(ContainerExpr->IgnoreParenImpCasts())) {
+    ContainerString = "this";
+  } else {
+    ContainerString =
+        getStringFromRange(Context->getSourceManager(), Context->getLangOpts(),
+                           ContainerExpr->getSourceRange());
+  }
+
+  return ContainerString;
+}
+
+/// \brief Determines what kind of 'auto' must be used after converting a for
+/// loop that iterates over an array or pseudoarray.
+void LoopConvertCheck::getArrayLoopQualifiers(ASTContext *Context,
+                                              const BoundNodes &Nodes,
+                                              const Expr *ContainerExpr,
+                                              const UsageResult &Usages,
+                                              RangeDescriptor &Descriptor) {
+  // On arrays and pseudoarrays, we must figure out the qualifiers from the
+  // usages.
+  if (usagesAreConst(Context, Usages) ||
+      containerIsConst(ContainerExpr, Descriptor.ContainerNeedsDereference)) {
+    Descriptor.DerefByConstRef = true;
+  }
+  if (usagesReturnRValues(Usages)) {
+    // If the index usages (dereference, subscript, at, ...) return rvalues,
+    // then we should not use a reference, because we need to keep the code
+    // correct if it mutates the returned objects.
+    Descriptor.DerefByValue = true;
+  }
+  // Try to find the type of the elements on the container, to check if
+  // they are trivially copyable.
+  for (const Usage &U : Usages) {
+    if (!U.Expression || U.Expression->getType().isNull())
+      continue;
+    QualType Type = U.Expression->getType().getCanonicalType();
+    if (U.Kind == Usage::UK_MemberThroughArrow) {
+      if (!Type->isPointerType()) {
+        continue;
+      }
+      Type = Type->getPointeeType();
+    }
+    Descriptor.ElemType = Type;
+  }
+}
+
+/// \brief Determines what kind of 'auto' must be used after converting an
+/// iterator based for loop.
+void LoopConvertCheck::getIteratorLoopQualifiers(ASTContext *Context,
+                                                 const BoundNodes &Nodes,
+                                                 RangeDescriptor &Descriptor) {
+  // The matchers for iterator loops provide bound nodes to obtain this
+  // information.
+  const auto *InitVar = Nodes.getNodeAs<VarDecl>(InitVarName);
+  QualType CanonicalInitVarType = InitVar->getType().getCanonicalType();
+  const auto *DerefByValueType =
+      Nodes.getNodeAs<QualType>(DerefByValueResultName);
+  Descriptor.DerefByValue = DerefByValueType;
+
+  if (Descriptor.DerefByValue) {
+    // If the dereference operator returns by value then test for the
+    // canonical const qualification of the init variable type.
+    Descriptor.DerefByConstRef = CanonicalInitVarType.isConstQualified();
+    Descriptor.ElemType = *DerefByValueType;
+  } else {
+    if (const auto *DerefType =
+            Nodes.getNodeAs<QualType>(DerefByRefResultName)) {
+      // A node will only be bound with DerefByRefResultName if we're dealing
+      // with a user-defined iterator type. Test the const qualification of
+      // the reference type.
+      auto ValueType = DerefType->getNonReferenceType();
+
+      Descriptor.DerefByConstRef = ValueType.isConstQualified();
+      Descriptor.ElemType = ValueType;
+    } else {
+      // By nature of the matcher this case is triggered only for built-in
+      // iterator types (i.e. pointers).
+      assert(isa<PointerType>(CanonicalInitVarType) &&
+             "Non-class iterator type is not a pointer type");
+
+      // We test for const qualification of the pointed-at type.
+      Descriptor.DerefByConstRef =
+          CanonicalInitVarType->getPointeeType().isConstQualified();
+      Descriptor.ElemType = CanonicalInitVarType->getPointeeType();
+    }
+  }
+}
+
+/// \brief Determines the parameters needed to build the range replacement.
+void LoopConvertCheck::determineRangeDescriptor(
+    ASTContext *Context, const BoundNodes &Nodes, const ForStmt *Loop,
+    LoopFixerKind FixerKind, const Expr *ContainerExpr,
+    const UsageResult &Usages, RangeDescriptor &Descriptor) {
+  Descriptor.ContainerString = getContainerString(Context, Loop, ContainerExpr);
+
+  if (FixerKind == LFK_Iterator)
+    getIteratorLoopQualifiers(Context, Nodes, Descriptor);
+  else
+    getArrayLoopQualifiers(Context, Nodes, ContainerExpr, Usages, Descriptor);
+}
+
+/// \brief Check some of the conditions that must be met for the loop to be
+/// convertible.
+bool LoopConvertCheck::isConvertible(ASTContext *Context,
+                                     const ast_matchers::BoundNodes &Nodes,
+                                     const ForStmt *Loop,
+                                     LoopFixerKind FixerKind) {
+  // If we already modified the range of this for loop, don't do any further
+  // updates on this iteration.
+  if (TUInfo->getReplacedVars().count(Loop))
+    return false;
+
+  // Check that we have exactly one index variable and at most one end variable.
+  const auto *LoopVar = Nodes.getNodeAs<VarDecl>(IncrementVarName);
+  const auto *CondVar = Nodes.getNodeAs<VarDecl>(ConditionVarName);
+  const auto *InitVar = Nodes.getNodeAs<VarDecl>(InitVarName);
+  if (!areSameVariable(LoopVar, CondVar) || !areSameVariable(LoopVar, InitVar))
+    return false;
+  const auto *EndVar = Nodes.getNodeAs<VarDecl>(EndVarName);
+  const auto *ConditionEndVar = Nodes.getNodeAs<VarDecl>(ConditionEndVarName);
+  if (EndVar && !areSameVariable(EndVar, ConditionEndVar))
+    return false;
+
+  // FIXME: Try to put most of this logic inside a matcher.
+  if (FixerKind == LFK_Iterator) {
+    QualType InitVarType = InitVar->getType();
+    QualType CanonicalInitVarType = InitVarType.getCanonicalType();
+
+    const auto *BeginCall = Nodes.getNodeAs<CXXMemberCallExpr>(BeginCallName);
+    assert(BeginCall && "Bad Callback. No begin call expression");
+    QualType CanonicalBeginType =
+        BeginCall->getMethodDecl()->getReturnType().getCanonicalType();
+    if (CanonicalBeginType->isPointerType() &&
+        CanonicalInitVarType->isPointerType()) {
+      // If the initializer and the variable are both pointers check if the
+      // un-qualified pointee types match, otherwise we don't use auto.
+      if (!Context->hasSameUnqualifiedType(
+              CanonicalBeginType->getPointeeType(),
+              CanonicalInitVarType->getPointeeType()))
+        return false;
+    } else if (!Context->hasSameType(CanonicalInitVarType,
+                                     CanonicalBeginType)) {
+      // Check for qualified types to avoid conversions from non-const to const
+      // iterator types.
+      return false;
+    }
+  } else if (FixerKind == LFK_PseudoArray) {
+    // This call is required to obtain the container.
+    const auto *EndCall = Nodes.getNodeAs<CXXMemberCallExpr>(EndCallName);
+    if (!EndCall || !dyn_cast<MemberExpr>(EndCall->getCallee()))
+      return false;
+  }
+  return true;
+}
+
+void LoopConvertCheck::check(const MatchFinder::MatchResult &Result) {
+  const BoundNodes &Nodes = Result.Nodes;
+  Confidence ConfidenceLevel(Confidence::CL_Safe);
+  ASTContext *Context = Result.Context;
+
+  const ForStmt *Loop;
+  LoopFixerKind FixerKind;
+  RangeDescriptor Descriptor;
+
+  if ((Loop = Nodes.getNodeAs<ForStmt>(LoopNameArray))) {
+    FixerKind = LFK_Array;
+  } else if ((Loop = Nodes.getNodeAs<ForStmt>(LoopNameIterator))) {
+    FixerKind = LFK_Iterator;
+  } else {
+    Loop = Nodes.getNodeAs<ForStmt>(LoopNamePseudoArray);
+    assert(Loop && "Bad Callback. No for statement");
+    FixerKind = LFK_PseudoArray;
+  }
+
+  if (!isConvertible(Context, Nodes, Loop, FixerKind))
+    return;
+
+  const auto *LoopVar = Nodes.getNodeAs<VarDecl>(IncrementVarName);
+  const auto *EndVar = Nodes.getNodeAs<VarDecl>(EndVarName);
+
+  // If the loop calls end()/size() after each iteration, lower our confidence
+  // level.
+  if (FixerKind != LFK_Array && !EndVar)
+    ConfidenceLevel.lowerTo(Confidence::CL_Reasonable);
+
+  // If the end comparison isn't a variable, we can try to work with the
+  // expression the loop variable is being tested against instead.
+  const auto *EndCall = Nodes.getNodeAs<CXXMemberCallExpr>(EndCallName);
+  const auto *BoundExpr = Nodes.getNodeAs<Expr>(ConditionBoundName);
+
+  // Find container expression of iterators and pseudoarrays, and determine if
+  // this expression needs to be dereferenced to obtain the container.
+  // With array loops, the container is often discovered during the
+  // ForLoopIndexUseVisitor traversal.
+  const Expr *ContainerExpr = nullptr;
+  if (FixerKind == LFK_Iterator) {
+    ContainerExpr = findContainer(Context, LoopVar->getInit(),
+                                  EndVar ? EndVar->getInit() : EndCall,
+                                  &Descriptor.ContainerNeedsDereference);
+  } else if (FixerKind == LFK_PseudoArray) {
+    ContainerExpr = EndCall->getImplicitObjectArgument();
+    Descriptor.ContainerNeedsDereference =
+        dyn_cast<MemberExpr>(EndCall->getCallee())->isArrow();
+  }
+
+  // We must know the container or an array length bound.
+  if (!ContainerExpr && !BoundExpr)
+    return;
+
+  ForLoopIndexUseVisitor Finder(Context, LoopVar, EndVar, ContainerExpr,
+                                BoundExpr,
+                                Descriptor.ContainerNeedsDereference);
+
+  // Find expressions and variables on which the container depends.
+  if (ContainerExpr) {
+    ComponentFinderASTVisitor ComponentFinder;
+    ComponentFinder.findExprComponents(ContainerExpr->IgnoreParenImpCasts());
+    Finder.addComponents(ComponentFinder.getComponents());
+  }
+
+  // Find usages of the loop index. If they are not used in a convertible way,
+  // stop here.
+  if (!Finder.findAndVerifyUsages(Loop->getBody()))
+    return;
+  ConfidenceLevel.lowerTo(Finder.getConfidenceLevel());
+
+  // Obtain the container expression, if we don't have it yet.
+  if (FixerKind == LFK_Array) {
+    ContainerExpr = Finder.getContainerIndexed()->IgnoreParenImpCasts();
+
+    // Very few loops are over expressions that generate arrays rather than
+    // array variables. Consider loops over arrays that aren't just represented
+    // by a variable to be risky conversions.
+    if (!getReferencedVariable(ContainerExpr) &&
+        !isDirectMemberExpr(ContainerExpr))
+      ConfidenceLevel.lowerTo(Confidence::CL_Risky);
+  }
+
+  // Find out which qualifiers we have to use in the loop range.
+  const UsageResult &Usages = Finder.getUsages();
+  determineRangeDescriptor(Context, Nodes, Loop, FixerKind, ContainerExpr,
+                           Usages, Descriptor);
+
+  // Ensure that we do not try to move an expression dependent on a local
+  // variable declared inside the loop outside of it.
+  // FIXME: Determine when the external dependency isn't an expression converted
+  // by another loop.
+  TUInfo->getParentFinder().gatherAncestors(Context->getTranslationUnitDecl());
+  DependencyFinderASTVisitor DependencyFinder(
+      &TUInfo->getParentFinder().getStmtToParentStmtMap(),
+      &TUInfo->getParentFinder().getDeclToParentStmtMap(),
+      &TUInfo->getReplacedVars(), Loop);
+
+  if (DependencyFinder.dependsOnInsideVariable(ContainerExpr) ||
+      Descriptor.ContainerString.empty() || Usages.empty() ||
+      ConfidenceLevel.getLevel() < MinConfidence)
+    return;
+
+  doConversion(Context, LoopVar, getReferencedVariable(ContainerExpr), Usages,
+               Finder.getAliasDecl(), Finder.aliasUseRequired(),
+               Finder.aliasFromForInit(), Loop, Descriptor);
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.h
new file mode 100644
index 0000000..75ab25a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.h
@@ -0,0 +1,78 @@
+//===--- LoopConvertCheck.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_LOOP_CONVERT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_LOOP_CONVERT_H
+
+#include "../ClangTidy.h"
+#include "LoopConvertUtils.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+class LoopConvertCheck : public ClangTidyCheck {
+public:
+  LoopConvertCheck(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:
+  struct RangeDescriptor {
+    RangeDescriptor();
+    bool ContainerNeedsDereference;
+    bool DerefByConstRef;
+    bool DerefByValue;
+    std::string ContainerString;
+    QualType ElemType;
+  };
+
+  void getAliasRange(SourceManager &SM, SourceRange &DeclRange);
+
+  void doConversion(ASTContext *Context, const VarDecl *IndexVar,
+                    const ValueDecl *MaybeContainer, const UsageResult &Usages,
+                    const DeclStmt *AliasDecl, bool AliasUseRequired,
+                    bool AliasFromForInit, const ForStmt *Loop,
+                    RangeDescriptor Descriptor);
+
+  StringRef getContainerString(ASTContext *Context, const ForStmt *Loop,
+                               const Expr *ContainerExpr);
+
+  void getArrayLoopQualifiers(ASTContext *Context,
+                              const ast_matchers::BoundNodes &Nodes,
+                              const Expr *ContainerExpr,
+                              const UsageResult &Usages,
+                              RangeDescriptor &Descriptor);
+
+  void getIteratorLoopQualifiers(ASTContext *Context,
+                                 const ast_matchers::BoundNodes &Nodes,
+                                 RangeDescriptor &Descriptor);
+
+  void determineRangeDescriptor(ASTContext *Context,
+                                const ast_matchers::BoundNodes &Nodes,
+                                const ForStmt *Loop, LoopFixerKind FixerKind,
+                                const Expr *ContainerExpr,
+                                const UsageResult &Usages,
+                                RangeDescriptor &Descriptor);
+
+  bool isConvertible(ASTContext *Context, const ast_matchers::BoundNodes &Nodes,
+                     const ForStmt *Loop, LoopFixerKind FixerKind);
+
+  std::unique_ptr<TUTrackingInfo> TUInfo;
+  const unsigned long long MaxCopySize;
+  const Confidence::Level MinConfidence;
+  const VariableNamer::NamingStyle NamingStyle;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_LOOP_CONVERT_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
new file mode 100644
index 0000000..f65f7a1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
@@ -0,0 +1,909 @@
+//===--- LoopConvertUtils.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 "LoopConvertUtils.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Lambda.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TokenKinds.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <string>
+#include <utility>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// \brief Tracks a stack of parent statements during traversal.
+///
+/// All this really does is inject push_back() before running
+/// RecursiveASTVisitor::TraverseStmt() and pop_back() afterwards. The Stmt atop
+/// the stack is the parent of the current statement (NULL for the topmost
+/// statement).
+bool StmtAncestorASTVisitor::TraverseStmt(Stmt *Statement) {
+  StmtAncestors.insert(std::make_pair(Statement, StmtStack.back()));
+  StmtStack.push_back(Statement);
+  RecursiveASTVisitor<StmtAncestorASTVisitor>::TraverseStmt(Statement);
+  StmtStack.pop_back();
+  return true;
+}
+
+/// \brief Keep track of the DeclStmt associated with each VarDecl.
+///
+/// Combined with StmtAncestors, this provides roughly the same information as
+/// Scope, as we can map a VarDecl to its DeclStmt, then walk up the parent tree
+/// using StmtAncestors.
+bool StmtAncestorASTVisitor::VisitDeclStmt(DeclStmt *Decls) {
+  for (const auto *decl : Decls->decls()) {
+    if (const auto *V = dyn_cast<VarDecl>(decl))
+      DeclParents.insert(std::make_pair(V, Decls));
+  }
+  return true;
+}
+
+/// \brief record the DeclRefExpr as part of the parent expression.
+bool ComponentFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *E) {
+  Components.push_back(E);
+  return true;
+}
+
+/// \brief record the MemberExpr as part of the parent expression.
+bool ComponentFinderASTVisitor::VisitMemberExpr(MemberExpr *Member) {
+  Components.push_back(Member);
+  return true;
+}
+
+/// \brief Forward any DeclRefExprs to a check on the referenced variable
+/// declaration.
+bool DependencyFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *DeclRef) {
+  if (auto *V = dyn_cast_or_null<VarDecl>(DeclRef->getDecl()))
+    return VisitVarDecl(V);
+  return true;
+}
+
+/// \brief Determine if any this variable is declared inside the ContainingStmt.
+bool DependencyFinderASTVisitor::VisitVarDecl(VarDecl *V) {
+  const Stmt *Curr = DeclParents->lookup(V);
+  // First, see if the variable was declared within an inner scope of the loop.
+  while (Curr != nullptr) {
+    if (Curr == ContainingStmt) {
+      DependsOnInsideVariable = true;
+      return false;
+    }
+    Curr = StmtParents->lookup(Curr);
+  }
+
+  // Next, check if the variable was removed from existence by an earlier
+  // iteration.
+  for (const auto &I : *ReplacedVars) {
+    if (I.second == V) {
+      DependsOnInsideVariable = true;
+      return false;
+    }
+  }
+  return true;
+}
+
+/// \brief If we already created a variable for TheLoop, check to make sure
+/// that the name was not already taken.
+bool DeclFinderASTVisitor::VisitForStmt(ForStmt *TheLoop) {
+  StmtGeneratedVarNameMap::const_iterator I = GeneratedDecls->find(TheLoop);
+  if (I != GeneratedDecls->end() && I->second == Name) {
+    Found = true;
+    return false;
+  }
+  return true;
+}
+
+/// \brief If any named declaration within the AST subtree has the same name,
+/// then consider Name already taken.
+bool DeclFinderASTVisitor::VisitNamedDecl(NamedDecl *D) {
+  const IdentifierInfo *Ident = D->getIdentifier();
+  if (Ident && Ident->getName() == Name) {
+    Found = true;
+    return false;
+  }
+  return true;
+}
+
+/// \brief Forward any declaration references to the actual check on the
+/// referenced declaration.
+bool DeclFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *DeclRef) {
+  if (auto *D = dyn_cast<NamedDecl>(DeclRef->getDecl()))
+    return VisitNamedDecl(D);
+  return true;
+}
+
+/// \brief If the new variable name conflicts with any type used in the loop,
+/// then we mark that variable name as taken.
+bool DeclFinderASTVisitor::VisitTypeLoc(TypeLoc TL) {
+  QualType QType = TL.getType();
+
+  // Check if our name conflicts with a type, to handle for typedefs.
+  if (QType.getAsString() == Name) {
+    Found = true;
+    return false;
+  }
+  // Check for base type conflicts. For example, when a struct is being
+  // referenced in the body of the loop, the above getAsString() will return the
+  // whole type (ex. "struct s"), but will be caught here.
+  if (const IdentifierInfo *Ident = QType.getBaseTypeIdentifier()) {
+    if (Ident->getName() == Name) {
+      Found = true;
+      return false;
+    }
+  }
+  return true;
+}
+
+/// \brief Look through conversion/copy constructors to find the explicit
+/// initialization expression, returning it is found.
+///
+/// The main idea is that given
+///   vector<int> v;
+/// we consider either of these initializations
+///   vector<int>::iterator it = v.begin();
+///   vector<int>::iterator it(v.begin());
+/// and retrieve `v.begin()` as the expression used to initialize `it` but do
+/// not include
+///   vector<int>::iterator it;
+///   vector<int>::iterator it(v.begin(), 0); // if this constructor existed
+/// as being initialized from `v.begin()`
+const Expr *digThroughConstructors(const Expr *E) {
+  if (!E)
+    return nullptr;
+  E = E->IgnoreImplicit();
+  if (const auto *ConstructExpr = dyn_cast<CXXConstructExpr>(E)) {
+    // The initial constructor must take exactly one parameter, but base class
+    // and deferred constructors can take more.
+    if (ConstructExpr->getNumArgs() != 1 ||
+        ConstructExpr->getConstructionKind() != CXXConstructExpr::CK_Complete)
+      return nullptr;
+    E = ConstructExpr->getArg(0);
+    if (const auto *Temp = dyn_cast<MaterializeTemporaryExpr>(E))
+      E = Temp->GetTemporaryExpr();
+    return digThroughConstructors(E);
+  }
+  return E;
+}
+
+/// \brief Returns true when two Exprs are equivalent.
+bool areSameExpr(ASTContext *Context, const Expr *First, const Expr *Second) {
+  if (!First || !Second)
+    return false;
+
+  llvm::FoldingSetNodeID FirstID, SecondID;
+  First->Profile(FirstID, *Context, true);
+  Second->Profile(SecondID, *Context, true);
+  return FirstID == SecondID;
+}
+
+/// \brief Returns the DeclRefExpr represented by E, or NULL if there isn't one.
+const DeclRefExpr *getDeclRef(const Expr *E) {
+  return dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts());
+}
+
+/// \brief Returns true when two ValueDecls are the same variable.
+bool areSameVariable(const ValueDecl *First, const ValueDecl *Second) {
+  return First && Second &&
+         First->getCanonicalDecl() == Second->getCanonicalDecl();
+}
+
+/// \brief Determines if an expression is a declaration reference to a
+/// particular variable.
+static bool exprReferencesVariable(const ValueDecl *Target, const Expr *E) {
+  if (!Target || !E)
+    return false;
+  const DeclRefExpr *Decl = getDeclRef(E);
+  return Decl && areSameVariable(Target, Decl->getDecl());
+}
+
+/// \brief If the expression is a dereference or call to operator*(), return the
+/// operand. Otherwise, return NULL.
+static const Expr *getDereferenceOperand(const Expr *E) {
+  if (const auto *Uop = dyn_cast<UnaryOperator>(E))
+    return Uop->getOpcode() == UO_Deref ? Uop->getSubExpr() : nullptr;
+
+  if (const auto *OpCall = dyn_cast<CXXOperatorCallExpr>(E)) {
+    return OpCall->getOperator() == OO_Star && OpCall->getNumArgs() == 1
+               ? OpCall->getArg(0)
+               : nullptr;
+  }
+
+  return nullptr;
+}
+
+/// \brief Returns true when the Container contains an Expr equivalent to E.
+template <typename ContainerT>
+static bool containsExpr(ASTContext *Context, const ContainerT *Container,
+                         const Expr *E) {
+  llvm::FoldingSetNodeID ID;
+  E->Profile(ID, *Context, true);
+  for (const auto &I : *Container) {
+    if (ID == I.second)
+      return true;
+  }
+  return false;
+}
+
+/// \brief Returns true when the index expression is a declaration reference to
+/// IndexVar.
+///
+/// If the index variable is `index`, this function returns true on
+///    arrayExpression[index];
+///    containerExpression[index];
+/// but not
+///    containerExpression[notIndex];
+static bool isIndexInSubscriptExpr(const Expr *IndexExpr,
+                                   const VarDecl *IndexVar) {
+  const DeclRefExpr *Idx = getDeclRef(IndexExpr);
+  return Idx && Idx->getType()->isIntegerType() &&
+         areSameVariable(IndexVar, Idx->getDecl());
+}
+
+/// \brief Returns true when the index expression is a declaration reference to
+/// IndexVar, Obj is the same expression as SourceExpr after all parens and
+/// implicit casts are stripped off.
+///
+/// If PermitDeref is true, IndexExpression may
+/// be a dereference (overloaded or builtin operator*).
+///
+/// This function is intended for array-like containers, as it makes sure that
+/// both the container and the index match.
+/// If the loop has index variable `index` and iterates over `container`, then
+/// isIndexInSubscriptExpr returns true for
+/// \code
+///   container[index]
+///   container.at(index)
+///   container->at(index)
+/// \endcode
+/// but not for
+/// \code
+///   container[notIndex]
+///   notContainer[index]
+/// \endcode
+/// If PermitDeref is true, then isIndexInSubscriptExpr additionally returns
+/// true on these expressions:
+/// \code
+///   (*container)[index]
+///   (*container).at(index)
+/// \endcode
+static bool isIndexInSubscriptExpr(ASTContext *Context, const Expr *IndexExpr,
+                                   const VarDecl *IndexVar, const Expr *Obj,
+                                   const Expr *SourceExpr, bool PermitDeref) {
+  if (!SourceExpr || !Obj || !isIndexInSubscriptExpr(IndexExpr, IndexVar))
+    return false;
+
+  if (areSameExpr(Context, SourceExpr->IgnoreParenImpCasts(),
+                  Obj->IgnoreParenImpCasts()))
+    return true;
+
+  if (const Expr *InnerObj = getDereferenceOperand(Obj->IgnoreParenImpCasts()))
+    if (PermitDeref && areSameExpr(Context, SourceExpr->IgnoreParenImpCasts(),
+                                   InnerObj->IgnoreParenImpCasts()))
+      return true;
+
+  return false;
+}
+
+/// \brief Returns true when Opcall is a call a one-parameter dereference of
+/// IndexVar.
+///
+/// For example, if the index variable is `index`, returns true for
+///   *index
+/// but not
+///   index
+///   *notIndex
+static bool isDereferenceOfOpCall(const CXXOperatorCallExpr *OpCall,
+                                  const VarDecl *IndexVar) {
+  return OpCall->getOperator() == OO_Star && OpCall->getNumArgs() == 1 &&
+         exprReferencesVariable(IndexVar, OpCall->getArg(0));
+}
+
+/// \brief Returns true when Uop is a dereference of IndexVar.
+///
+/// For example, if the index variable is `index`, returns true for
+///   *index
+/// but not
+///   index
+///   *notIndex
+static bool isDereferenceOfUop(const UnaryOperator *Uop,
+                               const VarDecl *IndexVar) {
+  return Uop->getOpcode() == UO_Deref &&
+         exprReferencesVariable(IndexVar, Uop->getSubExpr());
+}
+
+/// \brief Determines whether the given Decl defines a variable initialized to
+/// the loop object.
+///
+/// This is intended to find cases such as
+/// \code
+///   for (int i = 0; i < arraySize(arr); ++i) {
+///     T t = arr[i];
+///     // use t, do not use i
+///   }
+/// \endcode
+/// and
+/// \code
+///   for (iterator i = container.begin(), e = container.end(); i != e; ++i) {
+///     T t = *i;
+///     // use t, do not use i
+///   }
+/// \endcode
+static bool isAliasDecl(ASTContext *Context, const Decl *TheDecl,
+                        const VarDecl *IndexVar) {
+  const auto *VDecl = dyn_cast<VarDecl>(TheDecl);
+  if (!VDecl)
+    return false;
+  if (!VDecl->hasInit())
+    return false;
+
+  bool OnlyCasts = true;
+  const Expr *Init = VDecl->getInit()->IgnoreParenImpCasts();
+  if (Init && isa<CXXConstructExpr>(Init)) {
+    Init = digThroughConstructors(Init);
+    OnlyCasts = false;
+  }
+  if (!Init)
+    return false;
+
+  // Check that the declared type is the same as (or a reference to) the
+  // container type.
+  if (!OnlyCasts) {
+    QualType InitType = Init->getType();
+    QualType DeclarationType = VDecl->getType();
+    if (!DeclarationType.isNull() && DeclarationType->isReferenceType())
+      DeclarationType = DeclarationType.getNonReferenceType();
+
+    if (InitType.isNull() || DeclarationType.isNull() ||
+        !Context->hasSameUnqualifiedType(DeclarationType, InitType))
+      return false;
+  }
+
+  switch (Init->getStmtClass()) {
+  case Stmt::ArraySubscriptExprClass: {
+    const auto *E = cast<ArraySubscriptExpr>(Init);
+    // We don't really care which array is used here. We check to make sure
+    // it was the correct one later, since the AST will traverse it next.
+    return isIndexInSubscriptExpr(E->getIdx(), IndexVar);
+  }
+
+  case Stmt::UnaryOperatorClass:
+    return isDereferenceOfUop(cast<UnaryOperator>(Init), IndexVar);
+
+  case Stmt::CXXOperatorCallExprClass: {
+    const auto *OpCall = cast<CXXOperatorCallExpr>(Init);
+    if (OpCall->getOperator() == OO_Star)
+      return isDereferenceOfOpCall(OpCall, IndexVar);
+    if (OpCall->getOperator() == OO_Subscript) {
+      assert(OpCall->getNumArgs() == 2);
+      return isIndexInSubscriptExpr(OpCall->getArg(1), IndexVar);
+    }
+    break;
+  }
+
+  case Stmt::CXXMemberCallExprClass: {
+    const auto *MemCall = cast<CXXMemberCallExpr>(Init);
+    // This check is needed because getMethodDecl can return nullptr if the
+    // callee is a member function pointer.
+    const auto *MDecl = MemCall->getMethodDecl();
+    if (MDecl && !isa<CXXConversionDecl>(MDecl) &&
+        MDecl->getNameAsString() == "at" && MemCall->getNumArgs() == 1) {
+      return isIndexInSubscriptExpr(MemCall->getArg(0), IndexVar);
+    }
+    return false;
+  }
+
+  default:
+    break;
+  }
+  return false;
+}
+
+/// \brief Determines whether the bound of a for loop condition expression is
+/// the same as the statically computable size of ArrayType.
+///
+/// Given
+/// \code
+///   const int N = 5;
+///   int arr[N];
+/// \endcode
+/// This is intended to permit
+/// \code
+///   for (int i = 0; i < N; ++i) {  /* use arr[i] */ }
+///   for (int i = 0; i < arraysize(arr); ++i) { /* use arr[i] */ }
+/// \endcode
+static bool arrayMatchesBoundExpr(ASTContext *Context,
+                                  const QualType &ArrayType,
+                                  const Expr *ConditionExpr) {
+  if (!ConditionExpr || ConditionExpr->isValueDependent())
+    return false;
+  const ConstantArrayType *ConstType =
+      Context->getAsConstantArrayType(ArrayType);
+  if (!ConstType)
+    return false;
+  llvm::APSInt ConditionSize;
+  if (!ConditionExpr->isIntegerConstantExpr(ConditionSize, *Context))
+    return false;
+  llvm::APSInt ArraySize(ConstType->getSize());
+  return llvm::APSInt::isSameValue(ConditionSize, ArraySize);
+}
+
+ForLoopIndexUseVisitor::ForLoopIndexUseVisitor(ASTContext *Context,
+                                               const VarDecl *IndexVar,
+                                               const VarDecl *EndVar,
+                                               const Expr *ContainerExpr,
+                                               const Expr *ArrayBoundExpr,
+                                               bool ContainerNeedsDereference)
+    : Context(Context), IndexVar(IndexVar), EndVar(EndVar),
+      ContainerExpr(ContainerExpr), ArrayBoundExpr(ArrayBoundExpr),
+      ContainerNeedsDereference(ContainerNeedsDereference),
+      OnlyUsedAsIndex(true), AliasDecl(nullptr),
+      ConfidenceLevel(Confidence::CL_Safe), NextStmtParent(nullptr),
+      CurrStmtParent(nullptr), ReplaceWithAliasUse(false),
+      AliasFromForInit(false) {
+  if (ContainerExpr)
+    addComponent(ContainerExpr);
+}
+
+bool ForLoopIndexUseVisitor::findAndVerifyUsages(const Stmt *Body) {
+  TraverseStmt(const_cast<Stmt *>(Body));
+  return OnlyUsedAsIndex && ContainerExpr;
+}
+
+void ForLoopIndexUseVisitor::addComponents(const ComponentVector &Components) {
+  // FIXME: add sort(on ID)+unique to avoid extra work.
+  for (const auto &I : Components)
+    addComponent(I);
+}
+
+void ForLoopIndexUseVisitor::addComponent(const Expr *E) {
+  llvm::FoldingSetNodeID ID;
+  const Expr *Node = E->IgnoreParenImpCasts();
+  Node->Profile(ID, *Context, true);
+  DependentExprs.push_back(std::make_pair(Node, ID));
+}
+
+void ForLoopIndexUseVisitor::addUsage(const Usage &U) {
+  SourceLocation Begin = U.Range.getBegin();
+  if (Begin.isMacroID())
+    Begin = Context->getSourceManager().getSpellingLoc(Begin);
+
+  if (UsageLocations.insert(Begin).second)
+    Usages.push_back(U);
+}
+
+/// \brief If the unary operator is a dereference of IndexVar, include it
+/// as a valid usage and prune the traversal.
+///
+/// For example, if container.begin() and container.end() both return pointers
+/// to int, this makes sure that the initialization for `k` is not counted as an
+/// unconvertible use of the iterator `i`.
+/// \code
+///   for (int *i = container.begin(), *e = container.end(); i != e; ++i) {
+///     int k = *i + 2;
+///   }
+/// \endcode
+bool ForLoopIndexUseVisitor::TraverseUnaryDeref(UnaryOperator *Uop) {
+  // If we dereference an iterator that's actually a pointer, count the
+  // occurrence.
+  if (isDereferenceOfUop(Uop, IndexVar)) {
+    addUsage(Usage(Uop));
+    return true;
+  }
+
+  return VisitorBase::TraverseUnaryOperator(Uop);
+}
+
+/// \brief If the member expression is operator-> (overloaded or not) on
+/// IndexVar, include it as a valid usage and prune the traversal.
+///
+/// For example, given
+/// \code
+///   struct Foo { int bar(); int x; };
+///   vector<Foo> v;
+/// \endcode
+/// the following uses will be considered convertible:
+/// \code
+///   for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
+///     int b = i->bar();
+///     int k = i->x + 1;
+///   }
+/// \endcode
+/// though
+/// \code
+///   for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
+///     int k = i.insert(1);
+///   }
+///   for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
+///     int b = e->bar();
+///   }
+/// \endcode
+/// will not.
+bool ForLoopIndexUseVisitor::TraverseMemberExpr(MemberExpr *Member) {
+  const Expr *Base = Member->getBase();
+  const DeclRefExpr *Obj = getDeclRef(Base);
+  const Expr *ResultExpr = Member;
+  QualType ExprType;
+  if (const auto *Call =
+          dyn_cast<CXXOperatorCallExpr>(Base->IgnoreParenImpCasts())) {
+    // If operator->() is a MemberExpr containing a CXXOperatorCallExpr, then
+    // the MemberExpr does not have the expression we want. We therefore catch
+    // that instance here.
+    // For example, if vector<Foo>::iterator defines operator->(), then the
+    // example `i->bar()` at the top of this function is a CXXMemberCallExpr
+    // referring to `i->` as the member function called. We want just `i`, so
+    // we take the argument to operator->() as the base object.
+    if (Call->getOperator() == OO_Arrow) {
+      assert(Call->getNumArgs() == 1 &&
+             "Operator-> takes more than one argument");
+      Obj = getDeclRef(Call->getArg(0));
+      ResultExpr = Obj;
+      ExprType = Call->getCallReturnType(*Context);
+    }
+  }
+
+  if (Obj && exprReferencesVariable(IndexVar, Obj)) {
+    // Member calls on the iterator with '.' are not allowed.
+    if (!Member->isArrow()) {
+      OnlyUsedAsIndex = false;
+      return true;
+    }
+
+    if (ExprType.isNull())
+      ExprType = Obj->getType();
+
+    if (!ExprType->isPointerType())
+      return false;
+
+    // FIXME: This works around not having the location of the arrow operator.
+    // Consider adding OperatorLoc to MemberExpr?
+    SourceLocation ArrowLoc = Lexer::getLocForEndOfToken(
+        Base->getExprLoc(), 0, Context->getSourceManager(),
+        Context->getLangOpts());
+    // If something complicated is happening (i.e. the next token isn't an
+    // arrow), give up on making this work.
+    if (ArrowLoc.isValid()) {
+      addUsage(Usage(ResultExpr, Usage::UK_MemberThroughArrow,
+                     SourceRange(Base->getExprLoc(), ArrowLoc)));
+      return true;
+    }
+  }
+  return VisitorBase::TraverseMemberExpr(Member);
+}
+
+/// \brief If a member function call is the at() accessor on the container with
+/// IndexVar as the single argument, include it as a valid usage and prune
+/// the traversal.
+///
+/// Member calls on other objects will not be permitted.
+/// Calls on the iterator object are not permitted, unless done through
+/// operator->(). The one exception is allowing vector::at() for pseudoarrays.
+bool ForLoopIndexUseVisitor::TraverseCXXMemberCallExpr(
+    CXXMemberCallExpr *MemberCall) {
+  auto *Member =
+      dyn_cast<MemberExpr>(MemberCall->getCallee()->IgnoreParenImpCasts());
+  if (!Member)
+    return VisitorBase::TraverseCXXMemberCallExpr(MemberCall);
+
+  // We specifically allow an accessor named "at" to let STL in, though
+  // this is restricted to pseudo-arrays by requiring a single, integer
+  // argument.
+  const IdentifierInfo *Ident = Member->getMemberDecl()->getIdentifier();
+  if (Ident && Ident->isStr("at") && MemberCall->getNumArgs() == 1) {
+    if (isIndexInSubscriptExpr(Context, MemberCall->getArg(0), IndexVar,
+                               Member->getBase(), ContainerExpr,
+                               ContainerNeedsDereference)) {
+      addUsage(Usage(MemberCall));
+      return true;
+    }
+  }
+
+  if (containsExpr(Context, &DependentExprs, Member->getBase()))
+    ConfidenceLevel.lowerTo(Confidence::CL_Risky);
+
+  return VisitorBase::TraverseCXXMemberCallExpr(MemberCall);
+}
+
+/// \brief If an overloaded operator call is a dereference of IndexVar or
+/// a subscript of the container with IndexVar as the single argument,
+/// include it as a valid usage and prune the traversal.
+///
+/// For example, given
+/// \code
+///   struct Foo { int bar(); int x; };
+///   vector<Foo> v;
+///   void f(Foo);
+/// \endcode
+/// the following uses will be considered convertible:
+/// \code
+///   for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
+///     f(*i);
+///   }
+///   for (int i = 0; i < v.size(); ++i) {
+///      int i = v[i] + 1;
+///   }
+/// \endcode
+bool ForLoopIndexUseVisitor::TraverseCXXOperatorCallExpr(
+    CXXOperatorCallExpr *OpCall) {
+  switch (OpCall->getOperator()) {
+  case OO_Star:
+    if (isDereferenceOfOpCall(OpCall, IndexVar)) {
+      addUsage(Usage(OpCall));
+      return true;
+    }
+    break;
+
+  case OO_Subscript:
+    if (OpCall->getNumArgs() != 2)
+      break;
+    if (isIndexInSubscriptExpr(Context, OpCall->getArg(1), IndexVar,
+                               OpCall->getArg(0), ContainerExpr,
+                               ContainerNeedsDereference)) {
+      addUsage(Usage(OpCall));
+      return true;
+    }
+    break;
+
+  default:
+    break;
+  }
+  return VisitorBase::TraverseCXXOperatorCallExpr(OpCall);
+}
+
+/// \brief If we encounter an array with IndexVar as the index of an
+/// ArraySubsriptExpression, note it as a consistent usage and prune the
+/// AST traversal.
+///
+/// For example, given
+/// \code
+///   const int N = 5;
+///   int arr[N];
+/// \endcode
+/// This is intended to permit
+/// \code
+///   for (int i = 0; i < N; ++i) {  /* use arr[i] */ }
+/// \endcode
+/// but not
+/// \code
+///   for (int i = 0; i < N; ++i) {  /* use notArr[i] */ }
+/// \endcode
+/// and further checking needs to be done later to ensure that exactly one array
+/// is referenced.
+bool ForLoopIndexUseVisitor::TraverseArraySubscriptExpr(ArraySubscriptExpr *E) {
+  Expr *Arr = E->getBase();
+  if (!isIndexInSubscriptExpr(E->getIdx(), IndexVar))
+    return VisitorBase::TraverseArraySubscriptExpr(E);
+
+  if ((ContainerExpr &&
+       !areSameExpr(Context, Arr->IgnoreParenImpCasts(),
+                    ContainerExpr->IgnoreParenImpCasts())) ||
+      !arrayMatchesBoundExpr(Context, Arr->IgnoreImpCasts()->getType(),
+                             ArrayBoundExpr)) {
+    // If we have already discovered the array being indexed and this isn't it
+    // or this array doesn't match, mark this loop as unconvertible.
+    OnlyUsedAsIndex = false;
+    return VisitorBase::TraverseArraySubscriptExpr(E);
+  }
+
+  if (!ContainerExpr)
+    ContainerExpr = Arr;
+
+  addUsage(Usage(E));
+  return true;
+}
+
+/// \brief If we encounter a reference to IndexVar in an unpruned branch of the
+/// traversal, mark this loop as unconvertible.
+///
+/// This implements the whitelist for convertible loops: any usages of IndexVar
+/// not explicitly considered convertible by this traversal will be caught by
+/// this function.
+///
+/// Additionally, if the container expression is more complex than just a
+/// DeclRefExpr, and some part of it is appears elsewhere in the loop, lower
+/// our confidence in the transformation.
+///
+/// For example, these are not permitted:
+/// \code
+///   for (int i = 0; i < N; ++i) {  printf("arr[%d] = %d", i, arr[i]); }
+///   for (vector<int>::iterator i = container.begin(), e = container.end();
+///        i != e; ++i)
+///     i.insert(0);
+///   for (vector<int>::iterator i = container.begin(), e = container.end();
+///        i != e; ++i)
+///     if (i + 1 != e)
+///       printf("%d", *i);
+/// \endcode
+///
+/// And these will raise the risk level:
+/// \code
+///    int arr[10][20];
+///    int l = 5;
+///    for (int j = 0; j < 20; ++j)
+///      int k = arr[l][j] + l; // using l outside arr[l] is considered risky
+///    for (int i = 0; i < obj.getVector().size(); ++i)
+///      obj.foo(10); // using `obj` is considered risky
+/// \endcode
+bool ForLoopIndexUseVisitor::VisitDeclRefExpr(DeclRefExpr *E) {
+  const ValueDecl *TheDecl = E->getDecl();
+  if (areSameVariable(IndexVar, TheDecl) ||
+      exprReferencesVariable(IndexVar, E) || areSameVariable(EndVar, TheDecl) ||
+      exprReferencesVariable(EndVar, E))
+    OnlyUsedAsIndex = false;
+  if (containsExpr(Context, &DependentExprs, E))
+    ConfidenceLevel.lowerTo(Confidence::CL_Risky);
+  return true;
+}
+
+/// \brief If the loop index is captured by a lambda, replace this capture
+/// by the range-for loop variable.
+///
+/// For example:
+/// \code
+///   for (int i = 0; i < N; ++i) {
+///     auto f = [v, i](int k) {
+///       printf("%d\n", v[i] + k);
+///     };
+///     f(v[i]);
+///   }
+/// \endcode
+///
+/// Will be replaced by:
+/// \code
+///   for (auto & elem : v) {
+///     auto f = [v, elem](int k) {
+///       printf("%d\n", elem + k);
+///     };
+///     f(elem);
+///   }
+/// \endcode
+bool ForLoopIndexUseVisitor::TraverseLambdaCapture(LambdaExpr *LE,
+                                                   const LambdaCapture *C,
+                                                   Expr *Init) {
+  if (C->capturesVariable()) {
+    const VarDecl *VDecl = C->getCapturedVar();
+    if (areSameVariable(IndexVar, cast<ValueDecl>(VDecl))) {
+      // FIXME: if the index is captured, it will count as an usage and the
+      // alias (if any) won't work, because it is only used in case of having
+      // exactly one usage.
+      addUsage(Usage(nullptr,
+                     C->getCaptureKind() == LCK_ByCopy ? Usage::UK_CaptureByCopy
+                                                       : Usage::UK_CaptureByRef,
+                     C->getLocation()));
+    }
+  }
+  return VisitorBase::TraverseLambdaCapture(LE, C, Init);
+}
+
+/// \brief If we find that another variable is created just to refer to the loop
+/// element, note it for reuse as the loop variable.
+///
+/// See the comments for isAliasDecl.
+bool ForLoopIndexUseVisitor::VisitDeclStmt(DeclStmt *S) {
+  if (!AliasDecl && S->isSingleDecl() &&
+      isAliasDecl(Context, S->getSingleDecl(), IndexVar)) {
+    AliasDecl = S;
+    if (CurrStmtParent) {
+      if (isa<IfStmt>(CurrStmtParent) || isa<WhileStmt>(CurrStmtParent) ||
+          isa<SwitchStmt>(CurrStmtParent))
+        ReplaceWithAliasUse = true;
+      else if (isa<ForStmt>(CurrStmtParent)) {
+        if (cast<ForStmt>(CurrStmtParent)->getConditionVariableDeclStmt() == S)
+          ReplaceWithAliasUse = true;
+        else
+          // It's assumed S came the for loop's init clause.
+          AliasFromForInit = true;
+      }
+    }
+  }
+
+  return true;
+}
+
+bool ForLoopIndexUseVisitor::TraverseStmt(Stmt *S) {
+  // If this is an initialization expression for a lambda capture, prune the
+  // traversal so that we don't end up diagnosing the contained DeclRefExpr as
+  // inconsistent usage. No need to record the usage here -- this is done in
+  // TraverseLambdaCapture().
+  if (const auto *LE = dyn_cast_or_null<LambdaExpr>(NextStmtParent)) {
+    // Any child of a LambdaExpr that isn't the body is an initialization
+    // expression.
+    if (S != LE->getBody()) {
+      return true;
+    }
+  }
+
+  // All this pointer swapping is a mechanism for tracking immediate parentage
+  // of Stmts.
+  const Stmt *OldNextParent = NextStmtParent;
+  CurrStmtParent = NextStmtParent;
+  NextStmtParent = S;
+  bool Result = VisitorBase::TraverseStmt(S);
+  NextStmtParent = OldNextParent;
+  return Result;
+}
+
+std::string VariableNamer::createIndexName() {
+  // FIXME: Add in naming conventions to handle:
+  //  - How to handle conflicts.
+  //  - An interactive process for naming.
+  std::string IteratorName;
+  StringRef ContainerName;
+  if (TheContainer)
+    ContainerName = TheContainer->getName();
+
+  size_t Len = ContainerName.size();
+  if (Len > 1 && ContainerName.endswith(Style == NS_UpperCase ? "S" : "s")) {
+    IteratorName = ContainerName.substr(0, Len - 1);
+    // E.g.: (auto thing : things)
+    if (!declarationExists(IteratorName) || IteratorName == OldIndex->getName())
+      return IteratorName;
+  }
+
+  if (Len > 2 && ContainerName.endswith(Style == NS_UpperCase ? "S_" : "s_")) {
+    IteratorName = ContainerName.substr(0, Len - 2);
+    // E.g.: (auto thing : things_)
+    if (!declarationExists(IteratorName) || IteratorName == OldIndex->getName())
+      return IteratorName;
+  }
+
+  return OldIndex->getName();
+}
+
+/// \brief Determines whether or not the the name \a Symbol conflicts with
+/// language keywords or defined macros. Also checks if the name exists in
+/// LoopContext, any of its parent contexts, or any of its child statements.
+///
+/// We also check to see if the same identifier was generated by this loop
+/// converter in a loop nested within SourceStmt.
+bool VariableNamer::declarationExists(StringRef Symbol) {
+  assert(Context != nullptr && "Expected an ASTContext");
+  IdentifierInfo &Ident = Context->Idents.get(Symbol);
+
+  // Check if the symbol is not an identifier (ie. is a keyword or alias).
+  if (!isAnyIdentifier(Ident.getTokenID()))
+    return true;
+
+  // Check for conflicting macro definitions.
+  if (Ident.hasMacroDefinition())
+    return true;
+
+  // Determine if the symbol was generated in a parent context.
+  for (const Stmt *S = SourceStmt; S != nullptr; S = ReverseAST->lookup(S)) {
+    StmtGeneratedVarNameMap::const_iterator I = GeneratedDecls->find(S);
+    if (I != GeneratedDecls->end() && I->second == Symbol)
+      return true;
+  }
+
+  // FIXME: Rather than detecting conflicts at their usages, we should check the
+  // parent context.
+  // For some reason, lookup() always returns the pair (NULL, NULL) because its
+  // StoredDeclsMap is not initialized (i.e. LookupPtr.getInt() is false inside
+  // of DeclContext::lookup()). Why is this?
+
+  // Finally, determine if the symbol was used in the loop or a child context.
+  DeclFinderASTVisitor DeclFinder(Symbol, GeneratedDecls);
+  return DeclFinder.findUsages(SourceStmt);
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h
new file mode 100644
index 0000000..bee77d9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h
@@ -0,0 +1,467 @@
+//===--- LoopConvertUtils.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_LOOP_CONVERT_UTILS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_LOOP_CONVERT_UTILS_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <utility>
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+enum LoopFixerKind { LFK_Array, LFK_Iterator, LFK_PseudoArray };
+
+/// A map used to walk the AST in reverse: maps child Stmt to parent Stmt.
+typedef llvm::DenseMap<const clang::Stmt *, const clang::Stmt *> StmtParentMap;
+
+/// A map used to walk the AST in reverse:
+///  maps VarDecl to the to parent DeclStmt.
+typedef llvm::DenseMap<const clang::VarDecl *, const clang::DeclStmt *>
+    DeclParentMap;
+
+/// A map used to track which variables have been removed by a refactoring pass.
+/// It maps the parent ForStmt to the removed index variable's VarDecl.
+typedef llvm::DenseMap<const clang::ForStmt *, const clang::VarDecl *>
+    ReplacedVarsMap;
+
+/// A map used to remember the variable names generated in a Stmt
+typedef llvm::DenseMap<const clang::Stmt *, std::string>
+    StmtGeneratedVarNameMap;
+
+/// A vector used to store the AST subtrees of an Expr.
+typedef llvm::SmallVector<const clang::Expr *, 16> ComponentVector;
+
+/// \brief Class used build the reverse AST properties needed to detect
+/// name conflicts and free variables.
+class StmtAncestorASTVisitor
+    : public clang::RecursiveASTVisitor<StmtAncestorASTVisitor> {
+public:
+  StmtAncestorASTVisitor() { StmtStack.push_back(nullptr); }
+
+  /// \brief Run the analysis on the TranslationUnitDecl.
+  ///
+  /// In case we're running this analysis multiple times, don't repeat the work.
+  void gatherAncestors(const clang::TranslationUnitDecl *T) {
+    if (StmtAncestors.empty())
+      TraverseDecl(const_cast<clang::TranslationUnitDecl *>(T));
+  }
+
+  /// Accessor for StmtAncestors.
+  const StmtParentMap &getStmtToParentStmtMap() { return StmtAncestors; }
+
+  /// Accessor for DeclParents.
+  const DeclParentMap &getDeclToParentStmtMap() { return DeclParents; }
+
+  friend class clang::RecursiveASTVisitor<StmtAncestorASTVisitor>;
+
+private:
+  StmtParentMap StmtAncestors;
+  DeclParentMap DeclParents;
+  llvm::SmallVector<const clang::Stmt *, 16> StmtStack;
+
+  bool TraverseStmt(clang::Stmt *Statement);
+  bool VisitDeclStmt(clang::DeclStmt *Statement);
+};
+
+/// Class used to find the variables and member expressions on which an
+/// arbitrary expression depends.
+class ComponentFinderASTVisitor
+    : public clang::RecursiveASTVisitor<ComponentFinderASTVisitor> {
+public:
+  ComponentFinderASTVisitor() = default;
+
+  /// Find the components of an expression and place them in a ComponentVector.
+  void findExprComponents(const clang::Expr *SourceExpr) {
+    TraverseStmt(const_cast<clang::Expr *>(SourceExpr));
+  }
+
+  /// Accessor for Components.
+  const ComponentVector &getComponents() { return Components; }
+
+  friend class clang::RecursiveASTVisitor<ComponentFinderASTVisitor>;
+
+private:
+  ComponentVector Components;
+
+  bool VisitDeclRefExpr(clang::DeclRefExpr *E);
+  bool VisitMemberExpr(clang::MemberExpr *Member);
+};
+
+/// Class used to determine if an expression is dependent on a variable declared
+/// inside of the loop where it would be used.
+class DependencyFinderASTVisitor
+    : public clang::RecursiveASTVisitor<DependencyFinderASTVisitor> {
+public:
+  DependencyFinderASTVisitor(const StmtParentMap *StmtParents,
+                             const DeclParentMap *DeclParents,
+                             const ReplacedVarsMap *ReplacedVars,
+                             const clang::Stmt *ContainingStmt)
+      : StmtParents(StmtParents), DeclParents(DeclParents),
+        ContainingStmt(ContainingStmt), ReplacedVars(ReplacedVars) {}
+
+  /// \brief Run the analysis on Body, and return true iff the expression
+  /// depends on some variable declared within ContainingStmt.
+  ///
+  /// This is intended to protect against hoisting the container expression
+  /// outside of an inner context if part of that expression is declared in that
+  /// inner context.
+  ///
+  /// For example,
+  /// \code
+  ///   const int N = 10, M = 20;
+  ///   int arr[N][M];
+  ///   int getRow();
+  ///
+  ///   for (int i = 0; i < M; ++i) {
+  ///     int k = getRow();
+  ///     printf("%d:", arr[k][i]);
+  ///   }
+  /// \endcode
+  /// At first glance, this loop looks like it could be changed to
+  /// \code
+  ///   for (int elem : arr[k]) {
+  ///     int k = getIndex();
+  ///     printf("%d:", elem);
+  ///   }
+  /// \endcode
+  /// But this is malformed, since `k` is used before it is defined!
+  ///
+  /// In order to avoid this, this class looks at the container expression
+  /// `arr[k]` and decides whether or not it contains a sub-expression declared
+  /// within the the loop body.
+  bool dependsOnInsideVariable(const clang::Stmt *Body) {
+    DependsOnInsideVariable = false;
+    TraverseStmt(const_cast<clang::Stmt *>(Body));
+    return DependsOnInsideVariable;
+  }
+
+  friend class clang::RecursiveASTVisitor<DependencyFinderASTVisitor>;
+
+private:
+  const StmtParentMap *StmtParents;
+  const DeclParentMap *DeclParents;
+  const clang::Stmt *ContainingStmt;
+  const ReplacedVarsMap *ReplacedVars;
+  bool DependsOnInsideVariable;
+
+  bool VisitVarDecl(clang::VarDecl *V);
+  bool VisitDeclRefExpr(clang::DeclRefExpr *D);
+};
+
+/// Class used to determine if any declarations used in a Stmt would conflict
+/// with a particular identifier. This search includes the names that don't
+/// actually appear in the AST (i.e. created by a refactoring tool) by including
+/// a map from Stmts to generated names associated with those stmts.
+class DeclFinderASTVisitor
+    : public clang::RecursiveASTVisitor<DeclFinderASTVisitor> {
+public:
+  DeclFinderASTVisitor(const std::string &Name,
+                       const StmtGeneratedVarNameMap *GeneratedDecls)
+      : Name(Name), GeneratedDecls(GeneratedDecls), Found(false) {}
+
+  /// Attempts to find any usages of variables name Name in Body, returning
+  /// true when it is used in Body. This includes the generated loop variables
+  /// of ForStmts which have already been transformed.
+  bool findUsages(const clang::Stmt *Body) {
+    Found = false;
+    TraverseStmt(const_cast<clang::Stmt *>(Body));
+    return Found;
+  }
+
+  friend class clang::RecursiveASTVisitor<DeclFinderASTVisitor>;
+
+private:
+  std::string Name;
+  /// GeneratedDecls keeps track of ForStmts which have been transformed,
+  /// mapping each modified ForStmt to the variable generated in the loop.
+  const StmtGeneratedVarNameMap *GeneratedDecls;
+  bool Found;
+
+  bool VisitForStmt(clang::ForStmt *F);
+  bool VisitNamedDecl(clang::NamedDecl *D);
+  bool VisitDeclRefExpr(clang::DeclRefExpr *D);
+  bool VisitTypeLoc(clang::TypeLoc TL);
+};
+
+/// \brief The information needed to describe a valid convertible usage
+/// of an array index or iterator.
+struct Usage {
+  enum UsageKind {
+    // Regular usages of the loop index (the ones not specified below). Some
+    // examples:
+    // \code
+    //   int X = 8 * Arr[i];
+    //               ^~~~~~
+    //   f(param1, param2, *It);
+    //                     ^~~
+    //   if (Vec[i].SomeBool) {}
+    //       ^~~~~~
+    // \endcode
+    UK_Default,
+    // Indicates whether this is an access to a member through the arrow
+    // operator on pointers or iterators.
+    UK_MemberThroughArrow,
+    // If the variable is being captured by a lambda, indicates whether the
+    // capture was done by value or by reference.
+    UK_CaptureByCopy,
+    UK_CaptureByRef
+  };
+  // The expression that is going to be converted. Null in case of lambda
+  // captures.
+  const Expr *Expression;
+
+  UsageKind Kind;
+
+  // Range that covers this usage.
+  SourceRange Range;
+
+  explicit Usage(const Expr *E)
+      : Expression(E), Kind(UK_Default), Range(Expression->getSourceRange()) {}
+  Usage(const Expr *E, UsageKind Kind, SourceRange Range)
+      : Expression(E), Kind(Kind), Range(std::move(Range)) {}
+};
+
+/// \brief A class to encapsulate lowering of the tool's confidence level.
+class Confidence {
+public:
+  enum Level {
+    // Transformations that are likely to change semantics.
+    CL_Risky,
+
+    // Transformations that might change semantics.
+    CL_Reasonable,
+
+    // Transformations that will not change semantics.
+    CL_Safe
+  };
+  /// \brief Initialize confidence level.
+  explicit Confidence(Confidence::Level Level) : CurrentLevel(Level) {}
+
+  /// \brief Lower the internal confidence level to Level, but do not raise it.
+  void lowerTo(Confidence::Level Level) {
+    CurrentLevel = std::min(Level, CurrentLevel);
+  }
+
+  /// \brief Return the internal confidence level.
+  Level getLevel() const { return CurrentLevel; }
+
+private:
+  Level CurrentLevel;
+};
+
+// The main computational result of ForLoopIndexVisitor.
+typedef llvm::SmallVector<Usage, 8> UsageResult;
+
+// General functions used by ForLoopIndexUseVisitor and LoopConvertCheck.
+const Expr *digThroughConstructors(const Expr *E);
+bool areSameExpr(ASTContext *Context, const Expr *First, const Expr *Second);
+const DeclRefExpr *getDeclRef(const Expr *E);
+bool areSameVariable(const ValueDecl *First, const ValueDecl *Second);
+
+/// \brief Discover usages of expressions consisting of index or iterator
+/// access.
+///
+/// Given an index variable, recursively crawls a for loop to discover if the
+/// index variable is used in a way consistent with range-based for loop access.
+class ForLoopIndexUseVisitor
+    : public RecursiveASTVisitor<ForLoopIndexUseVisitor> {
+public:
+  ForLoopIndexUseVisitor(ASTContext *Context, const VarDecl *IndexVar,
+                         const VarDecl *EndVar, const Expr *ContainerExpr,
+                         const Expr *ArrayBoundExpr,
+                         bool ContainerNeedsDereference);
+
+  /// \brief Finds all uses of IndexVar in Body, placing all usages in Usages,
+  /// and returns true if IndexVar was only used in a way consistent with a
+  /// range-based for loop.
+  ///
+  /// The general strategy is to reject any DeclRefExprs referencing IndexVar,
+  /// with the exception of certain acceptable patterns.
+  /// For arrays, the DeclRefExpr for IndexVar must appear as the index of an
+  /// ArraySubscriptExpression. Iterator-based loops may dereference
+  /// IndexVar or call methods through operator-> (builtin or overloaded).
+  /// Array-like containers may use IndexVar as a parameter to the at() member
+  /// function and in overloaded operator[].
+  bool findAndVerifyUsages(const Stmt *Body);
+
+  /// \brief Add a set of components that we should consider relevant to the
+  /// container.
+  void addComponents(const ComponentVector &Components);
+
+  /// \brief Accessor for Usages.
+  const UsageResult &getUsages() const { return Usages; }
+
+  /// \brief Adds the Usage if it was not added before.
+  void addUsage(const Usage &U);
+
+  /// \brief Get the container indexed by IndexVar, if any.
+  const Expr *getContainerIndexed() const { return ContainerExpr; }
+
+  /// \brief Returns the statement declaring the variable created as an alias
+  /// for the loop element, if any.
+  const DeclStmt *getAliasDecl() const { return AliasDecl; }
+
+  /// \brief Accessor for ConfidenceLevel.
+  Confidence::Level getConfidenceLevel() const {
+    return ConfidenceLevel.getLevel();
+  }
+
+  /// \brief Indicates if the alias declaration was in a place where it cannot
+  /// simply be removed but rather replaced with a use of the alias variable.
+  /// For example, variables declared in the condition of an if, switch, or for
+  /// stmt.
+  bool aliasUseRequired() const { return ReplaceWithAliasUse; }
+
+  /// \brief Indicates if the alias declaration came from the init clause of a
+  /// nested for loop. SourceRanges provided by Clang for DeclStmts in this
+  /// case need to be adjusted.
+  bool aliasFromForInit() const { return AliasFromForInit; }
+
+private:
+  /// Typedef used in CRTP functions.
+  typedef RecursiveASTVisitor<ForLoopIndexUseVisitor> VisitorBase;
+  friend class RecursiveASTVisitor<ForLoopIndexUseVisitor>;
+
+  /// Overriden methods for RecursiveASTVisitor's traversal.
+  bool TraverseArraySubscriptExpr(ArraySubscriptExpr *E);
+  bool TraverseCXXMemberCallExpr(CXXMemberCallExpr *MemberCall);
+  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *OpCall);
+  bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
+                             Expr *Init);
+  bool TraverseMemberExpr(MemberExpr *Member);
+  bool TraverseUnaryDeref(UnaryOperator *Uop);
+  bool VisitDeclRefExpr(DeclRefExpr *E);
+  bool VisitDeclStmt(DeclStmt *S);
+  bool TraverseStmt(Stmt *S);
+
+  /// \brief Add an expression to the list of expressions on which the container
+  /// expression depends.
+  void addComponent(const Expr *E);
+
+  // Input member variables:
+  ASTContext *Context;
+  /// The index variable's VarDecl.
+  const VarDecl *IndexVar;
+  /// The loop's 'end' variable, which cannot be mentioned at all.
+  const VarDecl *EndVar;
+  /// The Expr which refers to the container.
+  const Expr *ContainerExpr;
+  /// The Expr which refers to the terminating condition for array-based loops.
+  const Expr *ArrayBoundExpr;
+  bool ContainerNeedsDereference;
+
+  // Output member variables:
+  /// A container which holds all usages of IndexVar as the index of
+  /// ArraySubscriptExpressions.
+  UsageResult Usages;
+  llvm::SmallSet<SourceLocation, 8> UsageLocations;
+  bool OnlyUsedAsIndex;
+  /// The DeclStmt for an alias to the container element.
+  const DeclStmt *AliasDecl;
+  Confidence ConfidenceLevel;
+  /// \brief A list of expressions on which ContainerExpr depends.
+  ///
+  /// If any of these expressions are encountered outside of an acceptable usage
+  /// of the loop element, lower our confidence level.
+  llvm::SmallVector<std::pair<const Expr *, llvm::FoldingSetNodeID>, 16>
+      DependentExprs;
+
+  /// The parent-in-waiting. Will become the real parent once we traverse down
+  /// one level in the AST.
+  const Stmt *NextStmtParent;
+  /// The actual parent of a node when Visit*() calls are made. Only the
+  /// parentage of DeclStmt's to possible iteration/selection statements is of
+  /// importance.
+  const Stmt *CurrStmtParent;
+
+  /// \see aliasUseRequired().
+  bool ReplaceWithAliasUse;
+  /// \see aliasFromForInit().
+  bool AliasFromForInit;
+};
+
+struct TUTrackingInfo {
+  /// \brief Reset and initialize per-TU tracking information.
+  ///
+  /// Must be called before using container accessors.
+  TUTrackingInfo() : ParentFinder(new StmtAncestorASTVisitor) {}
+
+  StmtAncestorASTVisitor &getParentFinder() { return *ParentFinder; }
+  StmtGeneratedVarNameMap &getGeneratedDecls() { return GeneratedDecls; }
+  ReplacedVarsMap &getReplacedVars() { return ReplacedVars; }
+
+private:
+  std::unique_ptr<StmtAncestorASTVisitor> ParentFinder;
+  StmtGeneratedVarNameMap GeneratedDecls;
+  ReplacedVarsMap ReplacedVars;
+};
+
+/// \brief Create names for generated variables within a particular statement.
+///
+/// VariableNamer uses a DeclContext as a reference point, checking for any
+/// conflicting declarations higher up in the context or within SourceStmt.
+/// It creates a variable name using hints from a source container and the old
+/// index, if they exist.
+class VariableNamer {
+public:
+  // Supported naming styles.
+  enum NamingStyle {
+    NS_CamelBack,
+    NS_CamelCase,
+    NS_LowerCase,
+    NS_UpperCase,
+  };
+
+  VariableNamer(StmtGeneratedVarNameMap *GeneratedDecls,
+                const StmtParentMap *ReverseAST, const clang::Stmt *SourceStmt,
+                const clang::VarDecl *OldIndex,
+                const clang::ValueDecl *TheContainer,
+                const clang::ASTContext *Context, NamingStyle Style)
+      : GeneratedDecls(GeneratedDecls), ReverseAST(ReverseAST),
+        SourceStmt(SourceStmt), OldIndex(OldIndex), TheContainer(TheContainer),
+        Context(Context), Style(Style) {}
+
+  /// \brief Generate a new index name.
+  ///
+  /// Generates the name to be used for an inserted iterator. It relies on
+  /// declarationExists() to determine that there are no naming conflicts, and
+  /// tries to use some hints from the container name and the old index name.
+  std::string createIndexName();
+
+private:
+  StmtGeneratedVarNameMap *GeneratedDecls;
+  const StmtParentMap *ReverseAST;
+  const clang::Stmt *SourceStmt;
+  const clang::VarDecl *OldIndex;
+  const clang::ValueDecl *TheContainer;
+  const clang::ASTContext *Context;
+  const NamingStyle Style;
+
+  // Determine whether or not a declaration that would conflict with Symbol
+  // exists in an outer context or in any statement contained in SourceStmt.
+  bool declarationExists(llvm::StringRef Symbol);
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_LOOP_CONVERT_UTILS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.cpp
new file mode 100644
index 0000000..541c2cb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.cpp
@@ -0,0 +1,32 @@
+//===--- MakeSharedCheck.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 "MakeSharedCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+MakeSharedCheck::MakeSharedCheck(StringRef Name, ClangTidyContext *Context)
+    : MakeSmartPtrCheck(Name, Context, "std::make_shared") {}
+
+MakeSharedCheck::SmartPtrTypeMatcher
+MakeSharedCheck::getSmartPointerTypeMatcher() const {
+  return qualType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(classTemplateSpecializationDecl(
+          hasName("::std::shared_ptr"), templateArgumentCountIs(1),
+          hasTemplateArgument(0, templateArgument(refersToType(
+                                     qualType().bind(PointerType)))))))));
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.h
new file mode 100644
index 0000000..cf01446
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.h
@@ -0,0 +1,43 @@
+//===--- MakeSharedCheck.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_MAKE_SHARED_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKE_SHARED_H
+
+#include "MakeSmartPtrCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Replace the pattern:
+/// \code
+///   std::shared_ptr<type>(new type(args...))
+/// \endcode
+///
+/// With the safer version:
+/// \code
+///   std::make_shared<type>(args...)
+/// \endcode
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-make-shared.html
+class MakeSharedCheck : public MakeSmartPtrCheck {
+public:
+  MakeSharedCheck(StringRef Name, ClangTidyContext *Context);
+
+protected:
+  SmartPtrTypeMatcher getSmartPointerTypeMatcher() const override;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKE_SHARED_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
new file mode 100644
index 0000000..8deaa83
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
@@ -0,0 +1,382 @@
+//===--- MakeSmartPtrCheck.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 "MakeSharedCheck.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+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,
+                                     StringRef MakeSmartPtrFunctionName)
+    : ClangTidyCheck(Name, Context),
+      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);
+}
+
+bool MakeSmartPtrCheck::isLanguageVersionSupported(
+    const LangOptions &LangOpts) const {
+  return LangOpts.CPlusPlus11;
+}
+
+void MakeSmartPtrCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  if (isLanguageVersionSupported(getLangOpts())) {
+    Inserter.reset(new utils::IncludeInserter(
+        Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle));
+    Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+  }
+}
+
+void MakeSmartPtrCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
+  if (!isLanguageVersionSupported(getLangOpts()))
+    return;
+
+  // Calling make_smart_ptr from within a member function of a type with a
+  // private or protected constructor would be ill-formed.
+  auto CanCallCtor = unless(has(ignoringImpCasts(
+      cxxConstructExpr(hasDeclaration(decl(unless(isPublic())))))));
+
+  Finder->addMatcher(
+      cxxBindTemporaryExpr(has(ignoringParenImpCasts(
+          cxxConstructExpr(
+              hasType(getSmartPointerTypeMatcher()), argumentCountIs(1),
+              hasArgument(0,
+                          cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType(
+                                         equalsBoundNode(PointerType))))),
+                                     CanCallCtor)
+                              .bind(NewExpression)),
+              unless(isInTemplateInstantiation()))
+              .bind(ConstructorCall)))),
+      this);
+
+  Finder->addMatcher(
+      cxxMemberCallExpr(
+          thisPointerType(getSmartPointerTypeMatcher()),
+          callee(cxxMethodDecl(hasName("reset"))),
+          hasArgument(0, cxxNewExpr(CanCallCtor).bind(NewExpression)),
+          unless(isInTemplateInstantiation()))
+          .bind(ResetCall),
+      this);
+}
+
+void MakeSmartPtrCheck::check(const MatchFinder::MatchResult &Result) {
+  // 'smart_ptr' refers to 'std::shared_ptr' or 'std::unique_ptr' or other
+  // pointer, 'make_smart_ptr' refers to 'std::make_shared' or
+  // 'std::make_unique' or other function that creates smart_ptr.
+
+  SourceManager &SM = *Result.SourceManager;
+  const auto *Construct =
+      Result.Nodes.getNodeAs<CXXConstructExpr>(ConstructorCall);
+  const auto *Reset = Result.Nodes.getNodeAs<CXXMemberCallExpr>(ResetCall);
+  const auto *Type = Result.Nodes.getNodeAs<QualType>(PointerType);
+  const auto *New = Result.Nodes.getNodeAs<CXXNewExpr>(NewExpression);
+
+  if (New->getNumPlacementArgs() != 0)
+    return;
+
+  if (Construct)
+    checkConstruct(SM, Construct, Type, New);
+  else if (Reset)
+    checkReset(SM, Reset, New);
+}
+
+void MakeSmartPtrCheck::checkConstruct(SourceManager &SM,
+                                       const CXXConstructExpr *Construct,
+                                       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, getLangOpts(), &Invalid);
+  if (Invalid)
+    return;
+
+  auto Diag = diag(ConstructCallStart, "use %0 instead")
+              << 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("<");
+  SourceLocation ConstructCallEnd;
+  if (LAngle == StringRef::npos) {
+    // If the template argument is missing (because it is part of the alias)
+    // we have to add it back.
+    ConstructCallEnd = ConstructCallStart.getLocWithOffset(ExprStr.size());
+    Diag << FixItHint::CreateInsertion(
+        ConstructCallEnd,
+        "<" + GetNewExprName(New, SM, getLangOpts()) + ">");
+  } else {
+    ConstructCallEnd = ConstructCallStart.getLocWithOffset(LAngle);
+  }
+
+  Diag << FixItHint::CreateReplacement(
+      CharSourceRange::getCharRange(ConstructCallStart, ConstructCallEnd),
+      MakeSmartPtrFunctionName);
+
+  // If the smart_ptr is built with brace enclosed direct initialization, use
+  // parenthesis instead.
+  if (Construct->isListInitialization()) {
+    SourceRange BraceRange = Construct->getParenOrBraceRange();
+    Diag << FixItHint::CreateReplacement(
+        CharSourceRange::getCharRange(
+            BraceRange.getBegin(), BraceRange.getBegin().getLocWithOffset(1)),
+        "(");
+    Diag << FixItHint::CreateReplacement(
+        CharSourceRange::getCharRange(BraceRange.getEnd(),
+                                      BraceRange.getEnd().getLocWithOffset(1)),
+        ")");
+  }
+
+  insertHeader(Diag, SM.getFileID(ConstructCallStart));
+}
+
+void MakeSmartPtrCheck::checkReset(SourceManager &SM,
+                                   const CXXMemberCallExpr *Reset,
+                                   const CXXNewExpr *New) {
+  const auto *Expr = cast<MemberExpr>(Reset->getCallee());
+  SourceLocation OperatorLoc = Expr->getOperatorLoc();
+  SourceLocation ResetCallStart = Reset->getExprLoc();
+  SourceLocation ExprStart = Expr->getLocStart();
+  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;
+
+  // Disable the fix in macros.
+  if (InMacro) {
+    return;
+  }
+
+  if (!replaceNew(Diag, New, SM)) {
+    return;
+  }
+
+  Diag << FixItHint::CreateReplacement(
+      CharSourceRange::getCharRange(OperatorLoc, ExprEnd),
+      (llvm::Twine(" = ") + MakeSmartPtrFunctionName + "<" +
+       GetNewExprName(New, SM, getLangOpts()) + ">")
+          .str());
+
+  if (Expr->isArrow())
+    Diag << FixItHint::CreateInsertion(ExprStart, "*");
+
+  insertHeader(Diag, SM.getFileID(OperatorLoc));
+}
+
+bool MakeSmartPtrCheck::replaceNew(DiagnosticBuilder &Diag,
+                                   const CXXNewExpr *New,
+                                   SourceManager& SM) {
+  SourceLocation NewStart = New->getSourceRange().getBegin();
+  SourceLocation NewEnd = New->getSourceRange().getEnd();
+
+  // Skip when the source location of the new expression is invalid.
+  if (NewStart.isInvalid() || NewEnd.isInvalid())
+    return false;
+
+  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: {
+    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: {
+    // 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 whether we construct a class from a std::initializer_list.
+        // If so, we won't generate the fixes.
+        auto IsStdInitListInitConstructExpr = [](const Expr* E) {
+          assert(E);
+          if (const auto *ImplicitCE = dyn_cast<CXXConstructExpr>(E)) {
+            if (ImplicitCE->isStdInitListInitialization())
+              return true;
+          }
+          return false;
+        };
+        if (IsStdInitListInitConstructExpr(Arg->IgnoreImplicit()))
+          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()) {
+      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});
+      // Has to be replaced with:
+      //   smart_ptr<Pair>(Pair{first, second});
+      InitRange = SourceRange(
+          New->getAllocatedTypeSourceInfo()->getTypeLoc().getLocStart(),
+          New->getInitializer()->getSourceRange().getEnd());
+    }
+    Diag << FixItHint::CreateRemoval(
+        CharSourceRange::getCharRange(NewStart, InitRange.getBegin()));
+    Diag << FixItHint::CreateRemoval(
+        SourceRange(InitRange.getEnd().getLocWithOffset(1), NewEnd));
+    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
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h
new file mode 100644
index 0000000..6622482
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h
@@ -0,0 +1,73 @@
+//===--- MakeSmartPtrCheck.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_MAKE_SMART_PTR_H
+#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"
+#include <string>
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Base class for MakeSharedCheck and MakeUniqueCheck.
+class MakeSmartPtrCheck : public ClangTidyCheck {
+public:
+  MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context,
+                    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>;
+
+  /// Returns matcher that match with different smart pointer types.
+  ///
+  /// Requires to bind pointer type (qualType) with PointerType string declared
+  /// in this class.
+  virtual SmartPtrTypeMatcher getSmartPointerTypeMatcher() const = 0;
+
+  /// Returns whether the C++ version is compatible with current check.
+  virtual bool isLanguageVersionSupported(const LangOptions &LangOpts) const;
+
+  static const char PointerType[];
+  static const char ConstructorCall[];
+  static const char ResetCall[];
+  static const char NewExpression[];
+
+private:
+  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);
+
+  /// 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
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKE_SMART_PTR_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.cpp
new file mode 100644
index 0000000..3ebbb07
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.cpp
@@ -0,0 +1,47 @@
+//===--- MakeUniqueCheck.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 "MakeUniqueCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+MakeUniqueCheck::MakeUniqueCheck(StringRef Name,
+                                 clang::tidy::ClangTidyContext *Context)
+    : MakeSmartPtrCheck(Name, Context, "std::make_unique"),
+      RequireCPlusPlus14(Options.get("MakeSmartPtrFunction", "").empty()) {}
+
+MakeUniqueCheck::SmartPtrTypeMatcher
+MakeUniqueCheck::getSmartPointerTypeMatcher() const {
+  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))))))))))))))));
+}
+
+bool MakeUniqueCheck::isLanguageVersionSupported(
+    const LangOptions &LangOpts) const {
+  return RequireCPlusPlus14 ? LangOpts.CPlusPlus14 : LangOpts.CPlusPlus11;
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.h
new file mode 100644
index 0000000..587b41e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.h
@@ -0,0 +1,45 @@
+//===--- MakeUniqueCheck.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_MAKE_UNIQUE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKE_UNIQUE_H
+
+#include "MakeSmartPtrCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Replace the pattern:
+/// \code
+///   std::unique_ptr<type>(new type(args...))
+/// \endcode
+///
+/// With the C++14 version:
+/// \code
+///   std::make_unique<type>(args...)
+/// \endcode
+class MakeUniqueCheck : public MakeSmartPtrCheck {
+public:
+  MakeUniqueCheck(StringRef Name, ClangTidyContext *Context);
+
+protected:
+  SmartPtrTypeMatcher getSmartPointerTypeMatcher() const override;
+
+  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override;
+
+private:
+  const bool RequireCPlusPlus14;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKE_UNIQUE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
new file mode 100644
index 0000000..63b7d02
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -0,0 +1,116 @@
+//===--- ModernizeTidyModule.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 "AvoidBindCheck.h"
+#include "DeprecatedHeadersCheck.h"
+#include "LoopConvertCheck.h"
+#include "MakeSharedCheck.h"
+#include "MakeUniqueCheck.h"
+#include "PassByValueCheck.h"
+#include "RawStringLiteralCheck.h"
+#include "RedundantVoidArgCheck.h"
+#include "ReplaceAutoPtrCheck.h"
+#include "ReplaceRandomShuffleCheck.h"
+#include "ReturnBracedInitListCheck.h"
+#include "ShrinkToFitCheck.h"
+#include "UnaryStaticAssertCheck.h"
+#include "UseAutoCheck.h"
+#include "UseBoolLiteralsCheck.h"
+#include "UseDefaultMemberInitCheck.h"
+#include "UseEmplaceCheck.h"
+#include "UseEqualsDefaultCheck.h"
+#include "UseEqualsDeleteCheck.h"
+#include "UseNoexceptCheck.h"
+#include "UseNullptrCheck.h"
+#include "UseOverrideCheck.h"
+#include "UseTransparentFunctorsCheck.h"
+#include "UseUncaughtExceptionsCheck.h"
+#include "UseUsingCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+class ModernizeModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<AvoidBindCheck>("modernize-avoid-bind");
+    CheckFactories.registerCheck<DeprecatedHeadersCheck>(
+        "modernize-deprecated-headers");
+    CheckFactories.registerCheck<LoopConvertCheck>("modernize-loop-convert");
+    CheckFactories.registerCheck<MakeSharedCheck>("modernize-make-shared");
+    CheckFactories.registerCheck<MakeUniqueCheck>("modernize-make-unique");
+    CheckFactories.registerCheck<PassByValueCheck>("modernize-pass-by-value");
+    CheckFactories.registerCheck<RawStringLiteralCheck>(
+        "modernize-raw-string-literal");
+    CheckFactories.registerCheck<RedundantVoidArgCheck>(
+        "modernize-redundant-void-arg");
+    CheckFactories.registerCheck<ReplaceAutoPtrCheck>(
+        "modernize-replace-auto-ptr");
+    CheckFactories.registerCheck<ReplaceRandomShuffleCheck>(
+        "modernize-replace-random-shuffle");
+    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");
+    CheckFactories.registerCheck<UseDefaultMemberInitCheck>(
+        "modernize-use-default-member-init");
+    CheckFactories.registerCheck<UseEmplaceCheck>("modernize-use-emplace");
+    CheckFactories.registerCheck<UseEqualsDefaultCheck>("modernize-use-equals-default");
+    CheckFactories.registerCheck<UseEqualsDeleteCheck>(
+        "modernize-use-equals-delete");
+    CheckFactories.registerCheck<UseNoexceptCheck>("modernize-use-noexcept");
+    CheckFactories.registerCheck<UseNullptrCheck>("modernize-use-nullptr");
+    CheckFactories.registerCheck<UseOverrideCheck>("modernize-use-override");
+    CheckFactories.registerCheck<UseTransparentFunctorsCheck>(
+        "modernize-use-transparent-functors");
+    CheckFactories.registerCheck<UseUncaughtExceptionsCheck>(
+        "modernize-use-uncaught-exceptions");
+    CheckFactories.registerCheck<UseUsingCheck>("modernize-use-using");
+  }
+
+  ClangTidyOptions getModuleOptions() override {
+    ClangTidyOptions Options;
+    auto &Opts = Options.CheckOptions;
+    // For types whose size in bytes is above this threshold, we prefer taking a
+    // const-reference than making a copy.
+    Opts["modernize-loop-convert.MaxCopySize"] = "16";
+
+    Opts["modernize-loop-convert.MinConfidence"] = "reasonable";
+    Opts["modernize-loop-convert.NamingStyle"] = "CamelCase";
+    Opts["modernize-pass-by-value.IncludeStyle"] = "llvm";    // Also: "google".
+    Opts["modernize-replace-auto-ptr.IncludeStyle"] = "llvm"; // Also: "google".
+
+    // Comma-separated list of macros that behave like NULL.
+    Opts["modernize-use-nullptr.NullMacros"] = "NULL";
+    return Options;
+  }
+};
+
+// Register the ModernizeTidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<ModernizeModule> X("modernize-module",
+                                                       "Add modernize checks.");
+
+} // namespace modernize
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the ModernizeModule.
+volatile int ModernizeModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp
new file mode 100644
index 0000000..1ab73d5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp
@@ -0,0 +1,234 @@
+//===--- PassByValueCheck.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 "PassByValueCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang::ast_matchers;
+using namespace llvm;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+namespace {
+/// \brief Matches move-constructible classes.
+///
+/// Given
+/// \code
+///   // POD types are trivially move constructible.
+///   struct Foo { int a; };
+///
+///   struct Bar {
+///     Bar(Bar &&) = deleted;
+///     int a;
+///   };
+/// \endcode
+/// recordDecl(isMoveConstructible())
+///   matches "Foo".
+AST_MATCHER(CXXRecordDecl, isMoveConstructible) {
+  for (const CXXConstructorDecl *Ctor : Node.ctors()) {
+    if (Ctor->isMoveConstructor() && !Ctor->isDeleted())
+      return true;
+  }
+  return false;
+}
+} // namespace
+
+static TypeMatcher constRefType() {
+  return lValueReferenceType(pointee(isConstQualified()));
+}
+
+static TypeMatcher nonConstValueType() {
+  return qualType(unless(anyOf(referenceType(), isConstQualified())));
+}
+
+/// \brief Whether or not \p ParamDecl is used exactly one time in \p Ctor.
+///
+/// Checks both in the init-list and the body of the constructor.
+static bool paramReferredExactlyOnce(const CXXConstructorDecl *Ctor,
+                                     const ParmVarDecl *ParamDecl) {
+  /// \brief \c clang::RecursiveASTVisitor that checks that the given
+  /// \c ParmVarDecl is used exactly one time.
+  ///
+  /// \see ExactlyOneUsageVisitor::hasExactlyOneUsageIn()
+  class ExactlyOneUsageVisitor
+      : public RecursiveASTVisitor<ExactlyOneUsageVisitor> {
+    friend class RecursiveASTVisitor<ExactlyOneUsageVisitor>;
+
+  public:
+    ExactlyOneUsageVisitor(const ParmVarDecl *ParamDecl)
+        : ParamDecl(ParamDecl) {}
+
+    /// \brief Whether or not the parameter variable is referred only once in
+    /// the
+    /// given constructor.
+    bool hasExactlyOneUsageIn(const CXXConstructorDecl *Ctor) {
+      Count = 0;
+      TraverseDecl(const_cast<CXXConstructorDecl *>(Ctor));
+      return Count == 1;
+    }
+
+  private:
+    /// \brief Counts the number of references to a variable.
+    ///
+    /// Stops the AST traversal if more than one usage is found.
+    bool VisitDeclRefExpr(DeclRefExpr *D) {
+      if (const ParmVarDecl *To = dyn_cast<ParmVarDecl>(D->getDecl())) {
+        if (To == ParamDecl) {
+          ++Count;
+          if (Count > 1) {
+            // No need to look further, used more than once.
+            return false;
+          }
+        }
+      }
+      return true;
+    }
+
+    const ParmVarDecl *ParamDecl;
+    unsigned Count;
+  };
+
+  return ExactlyOneUsageVisitor(ParamDecl).hasExactlyOneUsageIn(Ctor);
+}
+
+/// \brief Find all references to \p ParamDecl across all of the
+/// redeclarations of \p Ctor.
+static SmallVector<const ParmVarDecl *, 2>
+collectParamDecls(const CXXConstructorDecl *Ctor,
+                  const ParmVarDecl *ParamDecl) {
+  SmallVector<const ParmVarDecl *, 2> Results;
+  unsigned ParamIdx = ParamDecl->getFunctionScopeIndex();
+
+  for (const FunctionDecl *Redecl : Ctor->redecls())
+    Results.push_back(Redecl->getParamDecl(ParamIdx));
+  return Results;
+}
+
+PassByValueCheck::PassByValueCheck(StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
+          Options.getLocalOrGlobal("IncludeStyle", "llvm"))),
+      ValuesOnly(Options.get("ValuesOnly", 0) != 0) {}
+
+void PassByValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle",
+                utils::IncludeSorter::toString(IncludeStyle));
+  Options.store(Opts, "ValuesOnly", ValuesOnly);
+}
+
+void PassByValueCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(
+      cxxConstructorDecl(
+          forEachConstructorInitializer(
+              cxxCtorInitializer(
+                  unless(isBaseInitializer()),
+                  // Clang builds a CXXConstructExpr only when it knows which
+                  // constructor will be called. In dependent contexts a
+                  // ParenListExpr is generated instead of a CXXConstructExpr,
+                  // filtering out templates automatically for us.
+                  withInitializer(cxxConstructExpr(
+                      has(ignoringParenImpCasts(declRefExpr(to(
+                          parmVarDecl(
+                              hasType(qualType(
+                                  // Match only const-ref or a non-const value
+                                  // parameters. Rvalues and const-values
+                                  // shouldn't be modified.
+                                  ValuesOnly ? nonConstValueType()
+                                             : anyOf(constRefType(),
+                                                     nonConstValueType()))))
+                              .bind("Param"))))),
+                      hasDeclaration(cxxConstructorDecl(
+                          isCopyConstructor(), unless(isDeleted()),
+                          hasDeclContext(
+                              cxxRecordDecl(isMoveConstructible())))))))
+                  .bind("Initializer")))
+          .bind("Ctor"),
+      this);
+}
+
+void PassByValueCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  // Only register the preprocessor callbacks for C++; the functionality
+  // currently does not provide any benefit to other languages, despite being
+  // benign.
+  if (getLangOpts().CPlusPlus) {
+    Inserter.reset(new utils::IncludeInserter(
+        Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle));
+    Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+  }
+}
+
+void PassByValueCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("Ctor");
+  const auto *ParamDecl = Result.Nodes.getNodeAs<ParmVarDecl>("Param");
+  const auto *Initializer =
+      Result.Nodes.getNodeAs<CXXCtorInitializer>("Initializer");
+  SourceManager &SM = *Result.SourceManager;
+
+  // If the parameter is used or anything other than the copy, do not apply
+  // the changes.
+  if (!paramReferredExactlyOnce(Ctor, ParamDecl))
+    return;
+
+  // If the parameter is trivial to copy, don't move it. Moving a trivivally
+  // copyable type will cause a problem with performance-move-const-arg
+  if (ParamDecl->getType().getNonReferenceType().isTriviallyCopyableType(
+          *Result.Context))
+    return;
+
+  auto Diag = diag(ParamDecl->getLocStart(), "pass by value and use std::move");
+
+  // Iterate over all declarations of the constructor.
+  for (const ParmVarDecl *ParmDecl : collectParamDecls(Ctor, ParamDecl)) {
+    auto ParamTL = ParmDecl->getTypeSourceInfo()->getTypeLoc();
+    auto RefTL = ParamTL.getAs<ReferenceTypeLoc>();
+
+    // Do not replace if it is already a value, skip.
+    if (RefTL.isNull())
+      continue;
+
+    TypeLoc ValueTL = RefTL.getPointeeLoc();
+    auto TypeRange = CharSourceRange::getTokenRange(ParmDecl->getLocStart(),
+                                                    ParamTL.getLocEnd());
+    std::string ValueStr = Lexer::getSourceText(CharSourceRange::getTokenRange(
+                                                    ValueTL.getSourceRange()),
+                                                SM, getLangOpts())
+                               .str();
+    ValueStr += ' ';
+    Diag << FixItHint::CreateReplacement(TypeRange, ValueStr);
+  }
+
+  // Use std::move in the initialization list.
+  Diag << FixItHint::CreateInsertion(Initializer->getRParenLoc(), ")")
+       << FixItHint::CreateInsertion(
+              Initializer->getLParenLoc().getLocWithOffset(1), "std::move(");
+
+  if (auto IncludeFixit = Inserter->CreateIncludeInsertion(
+          Result.SourceManager->getFileID(Initializer->getSourceLocation()),
+          "utility",
+          /*IsAngled=*/true)) {
+    Diag << *IncludeFixit;
+  }
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.h
new file mode 100644
index 0000000..37deb3f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.h
@@ -0,0 +1,40 @@
+//===--- PassByValueCheck.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_PASS_BY_VALUE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_PASS_BY_VALUE_H
+
+#include "../ClangTidy.h"
+#include "../utils/IncludeInserter.h"
+
+#include <memory>
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+class PassByValueCheck : public ClangTidyCheck {
+public:
+  PassByValueCheck(StringRef Name, ClangTidyContext *Context);
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  void registerPPCallbacks(clang::CompilerInstance &Compiler) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  std::unique_ptr<utils::IncludeInserter> Inserter;
+  const utils::IncludeSorter::IncludeStyle IncludeStyle;
+  const bool ValuesOnly;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_PASS_BY_VALUE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.cpp
new file mode 100644
index 0000000..868c5c7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.cpp
@@ -0,0 +1,158 @@
+//===--- RawStringLiteralCheck.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 "RawStringLiteralCheck.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 modernize {
+
+namespace {
+
+bool containsEscapes(StringRef HayStack, StringRef Escapes) {
+  size_t BackSlash = HayStack.find('\\');
+  if (BackSlash == StringRef::npos)
+    return false;
+
+  while (BackSlash != StringRef::npos) {
+    if (Escapes.find(HayStack[BackSlash + 1]) == StringRef::npos)
+      return false;
+    BackSlash = HayStack.find('\\', BackSlash + 2);
+  }
+
+  return true;
+}
+
+bool isRawStringLiteral(StringRef Text) {
+  // Already a raw string literal if R comes before ".
+  const size_t QuotePos = Text.find('"');
+  assert(QuotePos != StringRef::npos);
+  return (QuotePos > 0) && (Text[QuotePos - 1] == 'R');
+}
+
+bool containsEscapedCharacters(const MatchFinder::MatchResult &Result,
+                               const StringLiteral *Literal,
+                               const CharsBitSet &DisallowedChars) {
+  // FIXME: Handle L"", u8"", u"" and U"" literals.
+  if (!Literal->isAscii())
+    return false;
+
+  for (const unsigned char C : Literal->getBytes())
+    if (DisallowedChars.test(C))
+      return false;
+
+  CharSourceRange CharRange = Lexer::makeFileCharRange(
+      CharSourceRange::getTokenRange(Literal->getSourceRange()),
+      *Result.SourceManager, Result.Context->getLangOpts());
+  StringRef Text = Lexer::getSourceText(CharRange, *Result.SourceManager,
+                                        Result.Context->getLangOpts());
+  if (isRawStringLiteral(Text))
+    return false;
+
+  return containsEscapes(Text, R"('\"?x01)");
+}
+
+bool containsDelimiter(StringRef Bytes, const std::string &Delimiter) {
+  return Bytes.find(Delimiter.empty()
+                        ? std::string(R"lit()")lit")
+                        : (")" + Delimiter + R"(")")) != StringRef::npos;
+}
+
+std::string asRawStringLiteral(const StringLiteral *Literal,
+                               const std::string &DelimiterStem) {
+  const StringRef Bytes = Literal->getBytes();
+  std::string Delimiter;
+  for (int I = 0; containsDelimiter(Bytes, Delimiter); ++I) {
+    Delimiter = (I == 0) ? DelimiterStem : DelimiterStem + std::to_string(I);
+  }
+
+  if (Delimiter.empty())
+    return (R"(R"()" + Bytes + R"lit()")lit").str();
+
+  return (R"(R")" + Delimiter + "(" + Bytes + ")" + Delimiter + R"(")").str();
+}
+
+} // namespace
+
+RawStringLiteralCheck::RawStringLiteralCheck(StringRef Name,
+                                             ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      DelimiterStem(Options.get("DelimiterStem", "lit")),
+      ReplaceShorterLiterals(Options.get("ReplaceShorterLiterals", false)) {
+  // Non-printing characters are disallowed:
+  // \007 = \a bell
+  // \010 = \b backspace
+  // \011 = \t horizontal tab
+  // \012 = \n new line
+  // \013 = \v vertical tab
+  // \014 = \f form feed
+  // \015 = \r carriage return
+  // \177 = delete
+  for (const unsigned char C : StringRef("\000\001\002\003\004\005\006\a"
+                                         "\b\t\n\v\f\r\016\017"
+                                         "\020\021\022\023\024\025\026\027"
+                                         "\030\031\032\033\034\035\036\037"
+                                         "\177",
+                                         33))
+    DisallowedChars.set(C);
+
+  // Non-ASCII are disallowed too.
+  for (unsigned int C = 0x80u; C <= 0xFFu; ++C)
+    DisallowedChars.set(static_cast<unsigned char>(C));
+}
+
+void RawStringLiteralCheck::storeOptions(ClangTidyOptions::OptionMap &Options) {
+  ClangTidyCheck::storeOptions(Options);
+  this->Options.store(Options, "ReplaceShorterLiterals",
+                      ReplaceShorterLiterals);
+}
+
+void RawStringLiteralCheck::registerMatchers(MatchFinder *Finder) {
+  // Raw string literals require C++11 or later.
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  Finder->addMatcher(
+      stringLiteral(unless(hasParent(predefinedExpr()))).bind("lit"), this);
+}
+
+void RawStringLiteralCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Literal = Result.Nodes.getNodeAs<StringLiteral>("lit");
+  if (Literal->getLocStart().isMacroID())
+    return;
+
+  if (containsEscapedCharacters(Result, Literal, DisallowedChars)) {
+    std::string Replacement = asRawStringLiteral(Literal, DelimiterStem);
+    if (ReplaceShorterLiterals ||
+        Replacement.length() <=
+            Lexer::MeasureTokenLength(Literal->getLocStart(),
+                                      *Result.SourceManager, getLangOpts()))
+      replaceWithRawStringLiteral(Result, Literal, Replacement);
+  }
+}
+
+void RawStringLiteralCheck::replaceWithRawStringLiteral(
+    const MatchFinder::MatchResult &Result, const StringLiteral *Literal,
+    StringRef Replacement) {
+  CharSourceRange CharRange = Lexer::makeFileCharRange(
+      CharSourceRange::getTokenRange(Literal->getSourceRange()),
+      *Result.SourceManager, getLangOpts());
+  diag(Literal->getLocStart(),
+       "escaped string literal can be written as a raw string literal")
+      << FixItHint::CreateReplacement(CharRange, Replacement);
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.h
new file mode 100644
index 0000000..f7721f6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.h
@@ -0,0 +1,49 @@
+//===--- RawStringLiteralCheck.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_RAW_STRING_LITERAL_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_RAW_STRING_LITERAL_H
+
+#include "../ClangTidy.h"
+#include <bitset>
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+using CharsBitSet = std::bitset<1 << CHAR_BIT>;
+
+/// This check replaces string literals with escaped characters to
+/// raw string literals.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-raw-string-literal.html
+class RawStringLiteralCheck : public ClangTidyCheck {
+public:
+  RawStringLiteralCheck(StringRef Name, ClangTidyContext *Context);
+
+  void storeOptions(ClangTidyOptions::OptionMap &Options) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void replaceWithRawStringLiteral(
+      const ast_matchers::MatchFinder::MatchResult &Result,
+      const StringLiteral *Literal, StringRef Replacement);
+
+  std::string DelimiterStem;
+  CharsBitSet DisallowedChars;
+  const bool ReplaceShorterLiterals;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_RAW_STRING_LITERAL_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp
new file mode 100644
index 0000000..6701fa4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp
@@ -0,0 +1,248 @@
+//===- RedundantVoidArgCheck.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 "RedundantVoidArgCheck.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+namespace {
+
+// Determine if the given QualType is a nullary function or pointer to same.
+bool protoTypeHasNoParms(QualType QT) {
+  if (auto PT = QT->getAs<PointerType>()) {
+    QT = PT->getPointeeType();
+  }
+  if (auto *MPT = QT->getAs<MemberPointerType>()) {
+    QT = MPT->getPointeeType();
+  }
+  if (auto FP = QT->getAs<FunctionProtoType>()) {
+    return FP->getNumParams() == 0;
+  }
+  return false;
+}
+
+const char FunctionId[] = "function";
+const char TypedefId[] = "typedef";
+const char FieldId[] = "field";
+const char VarId[] = "var";
+const char NamedCastId[] = "named-cast";
+const char CStyleCastId[] = "c-style-cast";
+const char ExplicitCastId[] = "explicit-cast";
+const char LambdaId[] = "lambda";
+
+} // namespace
+
+void RedundantVoidArgCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(functionDecl(parameterCountIs(0), unless(isImplicit()),
+                                  unless(isExternC()))
+                         .bind(FunctionId),
+                     this);
+  Finder->addMatcher(typedefNameDecl().bind(TypedefId), this);
+  auto ParenFunctionType = parenType(innerType(functionType()));
+  auto PointerToFunctionType = pointee(ParenFunctionType);
+  auto FunctionOrMemberPointer =
+      anyOf(hasType(pointerType(PointerToFunctionType)),
+            hasType(memberPointerType(PointerToFunctionType)));
+  Finder->addMatcher(fieldDecl(FunctionOrMemberPointer).bind(FieldId), this);
+  Finder->addMatcher(varDecl(FunctionOrMemberPointer).bind(VarId), this);
+  auto CastDestinationIsFunction =
+      hasDestinationType(pointsTo(ParenFunctionType));
+  Finder->addMatcher(
+      cStyleCastExpr(CastDestinationIsFunction).bind(CStyleCastId), this);
+  Finder->addMatcher(
+      cxxStaticCastExpr(CastDestinationIsFunction).bind(NamedCastId), this);
+  Finder->addMatcher(
+      cxxReinterpretCastExpr(CastDestinationIsFunction).bind(NamedCastId),
+      this);
+  Finder->addMatcher(
+      cxxConstCastExpr(CastDestinationIsFunction).bind(NamedCastId), this);
+  Finder->addMatcher(lambdaExpr().bind(LambdaId), this);
+}
+
+void RedundantVoidArgCheck::check(const MatchFinder::MatchResult &Result) {
+  const BoundNodes &Nodes = Result.Nodes;
+  if (const auto *Function = Nodes.getNodeAs<FunctionDecl>(FunctionId)) {
+    processFunctionDecl(Result, Function);
+  } else if (const auto *TypedefName =
+                 Nodes.getNodeAs<TypedefNameDecl>(TypedefId)) {
+    processTypedefNameDecl(Result, TypedefName);
+  } else if (const auto *Member = Nodes.getNodeAs<FieldDecl>(FieldId)) {
+    processFieldDecl(Result, Member);
+  } else if (const auto *Var = Nodes.getNodeAs<VarDecl>(VarId)) {
+    processVarDecl(Result, Var);
+  } else if (const auto *NamedCast =
+                 Nodes.getNodeAs<CXXNamedCastExpr>(NamedCastId)) {
+    processNamedCastExpr(Result, NamedCast);
+  } else if (const auto *CStyleCast =
+                 Nodes.getNodeAs<CStyleCastExpr>(CStyleCastId)) {
+    processExplicitCastExpr(Result, CStyleCast);
+  } else if (const auto *ExplicitCast =
+                 Nodes.getNodeAs<ExplicitCastExpr>(ExplicitCastId)) {
+    processExplicitCastExpr(Result, ExplicitCast);
+  } else if (const auto *Lambda = Nodes.getNodeAs<LambdaExpr>(LambdaId)) {
+    processLambdaExpr(Result, Lambda);
+  }
+}
+
+void RedundantVoidArgCheck::processFunctionDecl(
+    const MatchFinder::MatchResult &Result, const FunctionDecl *Function) {
+  if (Function->isThisDeclarationADefinition()) {
+    const Stmt *Body = Function->getBody();
+    SourceLocation Start = Function->getLocStart();
+    SourceLocation End =
+        Body ? Body->getLocStart().getLocWithOffset(-1) : Function->getLocEnd();
+    removeVoidArgumentTokens(Result, SourceRange(Start, End),
+                             "function definition");
+  } else {
+    removeVoidArgumentTokens(Result, Function->getSourceRange(),
+                             "function declaration");
+  }
+}
+
+void RedundantVoidArgCheck::removeVoidArgumentTokens(
+    const ast_matchers::MatchFinder::MatchResult &Result, SourceRange Range,
+    StringRef GrammarLocation) {
+  CharSourceRange CharRange =
+      Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Range),
+                               *Result.SourceManager, getLangOpts());
+
+  std::string DeclText =
+      Lexer::getSourceText(CharRange, *Result.SourceManager, getLangOpts())
+          .str();
+  Lexer PrototypeLexer(CharRange.getBegin(), getLangOpts(), DeclText.data(),
+                       DeclText.data(), DeclText.data() + DeclText.size());
+  enum TokenState {
+    NothingYet,
+    SawLeftParen,
+    SawVoid,
+  };
+  TokenState State = NothingYet;
+  Token VoidToken;
+  Token ProtoToken;
+  std::string Diagnostic =
+      ("redundant void argument list in " + GrammarLocation).str();
+
+  while (!PrototypeLexer.LexFromRawLexer(ProtoToken)) {
+    switch (State) {
+    case NothingYet:
+      if (ProtoToken.is(tok::TokenKind::l_paren)) {
+        State = SawLeftParen;
+      }
+      break;
+    case SawLeftParen:
+      if (ProtoToken.is(tok::TokenKind::raw_identifier) &&
+          ProtoToken.getRawIdentifier() == "void") {
+        State = SawVoid;
+        VoidToken = ProtoToken;
+      } else {
+        State = NothingYet;
+      }
+      break;
+    case SawVoid:
+      State = NothingYet;
+      if (ProtoToken.is(tok::TokenKind::r_paren)) {
+        removeVoidToken(VoidToken, Diagnostic);
+      } else if (ProtoToken.is(tok::TokenKind::l_paren)) {
+        State = SawLeftParen;
+      }
+      break;
+    }
+  }
+
+  if (State == SawVoid && ProtoToken.is(tok::TokenKind::r_paren)) {
+    removeVoidToken(VoidToken, Diagnostic);
+  }
+}
+
+void RedundantVoidArgCheck::removeVoidToken(Token VoidToken,
+                                            StringRef Diagnostic) {
+  SourceLocation VoidLoc(VoidToken.getLocation());
+  auto VoidRange =
+      CharSourceRange::getTokenRange(VoidLoc, VoidLoc.getLocWithOffset(3));
+  diag(VoidLoc, Diagnostic) << FixItHint::CreateRemoval(VoidRange);
+}
+
+void RedundantVoidArgCheck::processTypedefNameDecl(
+    const MatchFinder::MatchResult &Result,
+    const TypedefNameDecl *TypedefName) {
+  if (protoTypeHasNoParms(TypedefName->getUnderlyingType())) {
+    removeVoidArgumentTokens(Result, TypedefName->getSourceRange(),
+                             isa<TypedefDecl>(TypedefName) ? "typedef"
+                                                           : "type alias");
+  }
+}
+
+void RedundantVoidArgCheck::processFieldDecl(
+    const MatchFinder::MatchResult &Result, const FieldDecl *Member) {
+  if (protoTypeHasNoParms(Member->getType())) {
+    removeVoidArgumentTokens(Result, Member->getSourceRange(),
+                             "field declaration");
+  }
+}
+
+void RedundantVoidArgCheck::processVarDecl(
+    const MatchFinder::MatchResult &Result, const VarDecl *Var) {
+  if (protoTypeHasNoParms(Var->getType())) {
+    SourceLocation Begin = Var->getLocStart();
+    if (Var->hasInit()) {
+      SourceLocation InitStart =
+          Result.SourceManager->getExpansionLoc(Var->getInit()->getLocStart())
+              .getLocWithOffset(-1);
+      removeVoidArgumentTokens(Result, SourceRange(Begin, InitStart),
+                               "variable declaration with initializer");
+    } else {
+      removeVoidArgumentTokens(Result, Var->getSourceRange(),
+                               "variable declaration");
+    }
+  }
+}
+
+void RedundantVoidArgCheck::processNamedCastExpr(
+    const MatchFinder::MatchResult &Result, const CXXNamedCastExpr *NamedCast) {
+  if (protoTypeHasNoParms(NamedCast->getTypeAsWritten())) {
+    removeVoidArgumentTokens(
+        Result,
+        NamedCast->getTypeInfoAsWritten()->getTypeLoc().getSourceRange(),
+        "named cast");
+  }
+}
+
+void RedundantVoidArgCheck::processExplicitCastExpr(
+    const MatchFinder::MatchResult &Result,
+    const ExplicitCastExpr *ExplicitCast) {
+  if (protoTypeHasNoParms(ExplicitCast->getTypeAsWritten())) {
+    removeVoidArgumentTokens(Result, ExplicitCast->getSourceRange(),
+                             "cast expression");
+  }
+}
+
+void RedundantVoidArgCheck::processLambdaExpr(
+    const MatchFinder::MatchResult &Result, const LambdaExpr *Lambda) {
+  if (Lambda->getLambdaClass()->getLambdaCallOperator()->getNumParams() == 0 &&
+      Lambda->hasExplicitParameters()) {
+    SourceLocation Begin =
+        Lambda->getIntroducerRange().getEnd().getLocWithOffset(1);
+    SourceLocation End = Lambda->getBody()->getLocStart().getLocWithOffset(-1);
+    removeVoidArgumentTokens(Result, SourceRange(Begin, End),
+                             "lambda expression");
+  }
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/RedundantVoidArgCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/RedundantVoidArgCheck.h
new file mode 100644
index 0000000..c990ef4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/RedundantVoidArgCheck.h
@@ -0,0 +1,77 @@
+//===--- RedundantVoidArgCheck.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_REDUNDANT_VOID_ARG_CHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REDUNDANT_VOID_ARG_CHECK_H
+
+#include "../ClangTidy.h"
+#include "clang/Lex/Token.h"
+
+#include <string>
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// \brief Find and remove redundant void argument lists.
+///
+/// Examples:
+///   `int f(void);`                    becomes `int f();`
+///   `int (*f(void))(void);`           becomes `int (*f())();`
+///   `typedef int (*f_t(void))(void);` becomes `typedef int (*f_t())();`
+///   `void (C::*p)(void);`             becomes `void (C::*p)();`
+///   `C::C(void) {}`                   becomes `C::C() {}`
+///   `C::~C(void) {}`                  becomes `C::~C() {}`
+///
+class RedundantVoidArgCheck : public ClangTidyCheck {
+public:
+  RedundantVoidArgCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void processFunctionDecl(const ast_matchers::MatchFinder::MatchResult &Result,
+                           const FunctionDecl *Function);
+
+  void
+  processTypedefNameDecl(const ast_matchers::MatchFinder::MatchResult &Result,
+                         const TypedefNameDecl *Typedef);
+
+  void processFieldDecl(const ast_matchers::MatchFinder::MatchResult &Result,
+                        const FieldDecl *Member);
+
+  void processVarDecl(const ast_matchers::MatchFinder::MatchResult &Result,
+                      const VarDecl *Var);
+
+  void
+  processNamedCastExpr(const ast_matchers::MatchFinder::MatchResult &Result,
+                       const CXXNamedCastExpr *NamedCast);
+
+  void
+  processExplicitCastExpr(const ast_matchers::MatchFinder::MatchResult &Result,
+                          const ExplicitCastExpr *ExplicitCast);
+
+  void processLambdaExpr(const ast_matchers::MatchFinder::MatchResult &Result,
+                         const LambdaExpr *Lambda);
+
+  void
+  removeVoidArgumentTokens(const ast_matchers::MatchFinder::MatchResult &Result,
+                           SourceRange Range, StringRef GrammarLocation);
+
+  void removeVoidToken(Token VoidToken, StringRef Diagnostic);
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REDUNDANT_VOID_ARG_CHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
new file mode 100644
index 0000000..04ecf21
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
@@ -0,0 +1,202 @@
+//===--- ReplaceAutoPtrCheck.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 "ReplaceAutoPtrCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang;
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+namespace {
+static const char AutoPtrTokenId[] = "AutoPrTokenId";
+static const char AutoPtrOwnershipTransferId[] = "AutoPtrOwnershipTransferId";
+
+/// \brief Matches expressions that are lvalues.
+///
+/// In the following example, a[0] matches expr(isLValue()):
+/// \code
+///   std::string a[2];
+///   std::string b;
+///   b = a[0];
+///   b = "this string won't match";
+/// \endcode
+AST_MATCHER(Expr, isLValue) { return Node.getValueKind() == VK_LValue; }
+
+/// Matches declarations whose declaration context is the C++ standard library
+/// namespace std.
+///
+/// Note that inline namespaces are silently ignored during the lookup since
+/// both libstdc++ and libc++ are known to use them for versioning purposes.
+///
+/// Given:
+/// \code
+///   namespace ns {
+///     struct my_type {};
+///     using namespace std;
+///   }
+///
+///   using std::vector;
+///   using ns:my_type;
+///   using ns::list;
+/// \code
+///
+/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(isFromStdNamespace())))
+/// matches "using std::vector" and "using ns::list".
+AST_MATCHER(Decl, isFromStdNamespace) {
+  const DeclContext *D = Node.getDeclContext();
+
+  while (D->isInlineNamespace())
+    D = D->getParent();
+
+  if (!D->isNamespace() || !D->getParent()->isTranslationUnit())
+    return false;
+
+  const IdentifierInfo *Info = cast<NamespaceDecl>(D)->getIdentifier();
+
+  return (Info && Info->isStr("std"));
+}
+
+} // namespace
+
+ReplaceAutoPtrCheck::ReplaceAutoPtrCheck(StringRef Name,
+                                         ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
+          Options.getLocalOrGlobal("IncludeStyle", "llvm"))) {}
+
+void ReplaceAutoPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle",
+                utils::IncludeSorter::toString(IncludeStyle));
+}
+
+void ReplaceAutoPtrCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  auto AutoPtrDecl = recordDecl(hasName("auto_ptr"), isFromStdNamespace());
+  auto AutoPtrType = qualType(hasDeclaration(AutoPtrDecl));
+
+  //   std::auto_ptr<int> a;
+  //        ^~~~~~~~~~~~~
+  //
+  //   typedef std::auto_ptr<int> int_ptr_t;
+  //                ^~~~~~~~~~~~~
+  //
+  //   std::auto_ptr<int> fn(std::auto_ptr<int>);
+  //        ^~~~~~~~~~~~~         ^~~~~~~~~~~~~
+  Finder->addMatcher(typeLoc(loc(qualType(AutoPtrType,
+                                          // Skip elaboratedType() as the named
+                                          // type will match soon thereafter.
+                                          unless(elaboratedType()))))
+                         .bind(AutoPtrTokenId),
+                     this);
+
+  //   using std::auto_ptr;
+  //   ^~~~~~~~~~~~~~~~~~~
+  Finder->addMatcher(usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(allOf(
+                                   hasName("auto_ptr"), isFromStdNamespace()))))
+                         .bind(AutoPtrTokenId),
+                     this);
+
+  // Find ownership transfers via copy construction and assignment.
+  // AutoPtrOwnershipTransferId is bound to the the part that has to be wrapped
+  // into std::move().
+  //   std::auto_ptr<int> i, j;
+  //   i = j;
+  //   ~~~~^
+  auto MovableArgumentMatcher =
+      expr(isLValue(), hasType(AutoPtrType)).bind(AutoPtrOwnershipTransferId);
+
+  Finder->addMatcher(
+      cxxOperatorCallExpr(hasOverloadedOperatorName("="),
+                          callee(cxxMethodDecl(ofClass(AutoPtrDecl))),
+                          hasArgument(1, MovableArgumentMatcher)),
+      this);
+  Finder->addMatcher(cxxConstructExpr(hasType(AutoPtrType), argumentCountIs(1),
+                                      hasArgument(0, MovableArgumentMatcher)),
+                     this);
+}
+
+void ReplaceAutoPtrCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  // Only register the preprocessor callbacks for C++; the functionality
+  // currently does not provide any benefit to other languages, despite being
+  // benign.
+  if (!getLangOpts().CPlusPlus)
+    return;
+  Inserter.reset(new utils::IncludeInserter(
+      Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle));
+  Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+}
+
+void ReplaceAutoPtrCheck::check(const MatchFinder::MatchResult &Result) {
+  SourceManager &SM = *Result.SourceManager;
+  if (const auto *E =
+          Result.Nodes.getNodeAs<Expr>(AutoPtrOwnershipTransferId)) {
+    CharSourceRange Range = Lexer::makeFileCharRange(
+        CharSourceRange::getTokenRange(E->getSourceRange()), SM, LangOptions());
+
+    if (Range.isInvalid())
+      return;
+
+    auto Diag = diag(Range.getBegin(), "use std::move to transfer ownership")
+                << FixItHint::CreateInsertion(Range.getBegin(), "std::move(")
+                << FixItHint::CreateInsertion(Range.getEnd(), ")");
+
+    if (auto Fix =
+            Inserter->CreateIncludeInsertion(SM.getMainFileID(), "utility",
+                                             /*IsAngled=*/true))
+      Diag << *Fix;
+
+    return;
+  }
+
+  SourceLocation AutoPtrLoc;
+  if (const auto *TL = Result.Nodes.getNodeAs<TypeLoc>(AutoPtrTokenId)) {
+    //   std::auto_ptr<int> i;
+    //        ^
+    if (auto Loc = TL->getAs<TemplateSpecializationTypeLoc>())
+      AutoPtrLoc = Loc.getTemplateNameLoc();
+  } else if (const auto *D =
+                 Result.Nodes.getNodeAs<UsingDecl>(AutoPtrTokenId)) {
+    // using std::auto_ptr;
+    //            ^
+    AutoPtrLoc = D->getNameInfo().getBeginLoc();
+  } else {
+    llvm_unreachable("Bad Callback. No node provided.");
+  }
+
+  if (AutoPtrLoc.isMacroID())
+    AutoPtrLoc = SM.getSpellingLoc(AutoPtrLoc);
+
+  // Ensure that only the 'auto_ptr' token is replaced and not the template
+  // aliases.
+  if (StringRef(SM.getCharacterData(AutoPtrLoc), strlen("auto_ptr")) !=
+      "auto_ptr")
+    return;
+
+  SourceLocation EndLoc =
+      AutoPtrLoc.getLocWithOffset(strlen("auto_ptr") - 1);
+  diag(AutoPtrLoc, "auto_ptr is deprecated, use unique_ptr instead")
+      << FixItHint::CreateReplacement(SourceRange(AutoPtrLoc, EndLoc),
+                                      "unique_ptr");
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.h
new file mode 100644
index 0000000..5b73d51
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.h
@@ -0,0 +1,61 @@
+//===--- ReplaceAutoPtrCheck.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_REPLACE_AUTO_PTR_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REPLACE_AUTO_PTR_H
+
+#include "../ClangTidy.h"
+#include "../utils/IncludeInserter.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Transforms the deprecated `std::auto_ptr` into the C++11 `std::unique_ptr`.
+///
+/// Note that both the `std::auto_ptr` type and the transfer of ownership are
+/// transformed. `std::auto_ptr` provides two ways to transfer the ownership,
+/// the copy-constructor and the assignment operator. Unlike most classes these
+/// operations do not 'copy' the resource but they 'steal' it.
+/// `std::unique_ptr` uses move semantics instead, which makes the intent of
+/// transferring the resource explicit. This difference between the two smart
+/// pointers requeres to wrap the copy-ctor and assign-operator with
+/// `std::move()`.
+///
+/// For example, given:
+///
+/// \code
+///   std::auto_ptr<int> i, j;
+///   i = j;
+/// \endcode
+///
+/// This code is transformed to:
+///
+/// \code
+///   std::unique_ptr<in> i, j;
+///   i = std::move(j);
+/// \endcode
+class ReplaceAutoPtrCheck : public ClangTidyCheck {
+public:
+  ReplaceAutoPtrCheck(StringRef Name, ClangTidyContext *Context);
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  std::unique_ptr<utils::IncludeInserter> Inserter;
+  const utils::IncludeSorter::IncludeStyle IncludeStyle;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REPLACE_AUTO_PTR_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp
new file mode 100644
index 0000000..cd9aa11
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp
@@ -0,0 +1,109 @@
+//===--- ReplaceRandomShuffleCheck.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 "ReplaceRandomShuffleCheck.h"
+#include "../utils/FixItHintUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+ReplaceRandomShuffleCheck::ReplaceRandomShuffleCheck(StringRef Name,
+                                                     ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
+          Options.getLocalOrGlobal("IncludeStyle", "llvm"))) {}
+
+void ReplaceRandomShuffleCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  const auto Begin = hasArgument(0, expr());
+  const auto End = hasArgument(1, expr());
+  const auto RandomFunc = hasArgument(2, expr().bind("randomFunc"));
+  Finder->addMatcher(
+      callExpr(anyOf(allOf(Begin, End, argumentCountIs(2)),
+                     allOf(Begin, End, RandomFunc, argumentCountIs(3))),
+               hasDeclaration(functionDecl(hasName("::std::random_shuffle"))),
+               has(implicitCastExpr(has(declRefExpr().bind("name")))))
+          .bind("match"),
+      this);
+}
+
+void ReplaceRandomShuffleCheck::registerPPCallbacks(
+    CompilerInstance &Compiler) {
+  IncludeInserter = llvm::make_unique<utils::IncludeInserter>(
+      Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle);
+  Compiler.getPreprocessor().addPPCallbacks(
+      IncludeInserter->CreatePPCallbacks());
+}
+
+void ReplaceRandomShuffleCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle",
+                utils::IncludeSorter::toString(IncludeStyle));
+}
+
+void ReplaceRandomShuffleCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<DeclRefExpr>("name");
+  const auto *MatchedArgumentThree = Result.Nodes.getNodeAs<Expr>("randomFunc");
+  const auto *MatchedCallExpr = Result.Nodes.getNodeAs<CallExpr>("match");
+
+  if (MatchedCallExpr->getLocStart().isMacroID())
+    return;
+
+  auto Diag = [&] {
+    if (MatchedCallExpr->getNumArgs() == 3) {
+      auto DiagL =
+          diag(MatchedCallExpr->getLocStart(),
+               "'std::random_shuffle' has been removed in C++17; use "
+               "'std::shuffle' and an alternative random mechanism instead");
+      DiagL << FixItHint::CreateReplacement(
+          MatchedArgumentThree->getSourceRange(),
+          "std::mt19937(std::random_device()())");
+      return DiagL;
+    } else {
+      auto DiagL = diag(MatchedCallExpr->getLocStart(),
+                        "'std::random_shuffle' has been removed in C++17; use "
+                        "'std::shuffle' instead");
+      DiagL << FixItHint::CreateInsertion(
+          MatchedCallExpr->getRParenLoc(),
+          ", std::mt19937(std::random_device()())");
+      return DiagL;
+    }
+  }();
+
+  std::string NewName = "shuffle";
+  StringRef ContainerText = Lexer::getSourceText(
+      CharSourceRange::getTokenRange(MatchedDecl->getSourceRange()),
+      *Result.SourceManager, getLangOpts());
+  if (ContainerText.startswith("std::"))
+    NewName = "std::" + NewName;
+
+  Diag << FixItHint::CreateRemoval(MatchedDecl->getSourceRange());
+  Diag << FixItHint::CreateInsertion(MatchedDecl->getLocStart(), NewName);
+
+  if (Optional<FixItHint> IncludeFixit =
+          IncludeInserter->CreateIncludeInsertion(
+              Result.Context->getSourceManager().getFileID(
+                  MatchedCallExpr->getLocStart()),
+              "random", /*IsAngled=*/true))
+    Diag << IncludeFixit.getValue();
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.h
new file mode 100644
index 0000000..050d740
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.h
@@ -0,0 +1,42 @@
+//===--- ReplaceRandomShuffleCheck.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_REPLACE_RANDOM_SHUFFLE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REPLACE_RANDOM_SHUFFLE_H
+
+#include "../ClangTidy.h"
+#include "../utils/IncludeInserter.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// std::random_shuffle will be removed as of C++17. This check will find and
+/// replace all occurrences of std::random_shuffle with std::shuffle.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-replace-random-shuffle.html
+class ReplaceRandomShuffleCheck : public ClangTidyCheck {
+public:
+  ReplaceRandomShuffleCheck(StringRef Name, ClangTidyContext *Context);
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  std::unique_ptr<utils::IncludeInserter> IncludeInserter;
+  const utils::IncludeSorter::IncludeStyle IncludeStyle;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REPLACE_RANDOM_SHUFFLE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReturnBracedInitListCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReturnBracedInitListCheck.cpp
new file mode 100644
index 0000000..e5857f7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReturnBracedInitListCheck.cpp
@@ -0,0 +1,97 @@
+//===--- ReturnBracedInitListCheck.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 "ReturnBracedInitListCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+void ReturnBracedInitListCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++.
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  // Skip list initialization and constructors with an initializer list.
+  auto ConstructExpr =
+      cxxConstructExpr(
+          unless(anyOf(hasDeclaration(cxxConstructorDecl(isExplicit())),
+                       isListInitialization(), hasDescendant(initListExpr()),
+                       isInTemplateInstantiation())))
+          .bind("ctor");
+
+  auto CtorAsArgument = materializeTemporaryExpr(anyOf(
+      has(ConstructExpr), has(cxxFunctionalCastExpr(has(ConstructExpr)))));
+
+  Finder->addMatcher(
+      functionDecl(isDefinition(), // Declarations don't have return statements.
+                   returns(unless(anyOf(builtinType(), autoType()))),
+                   hasDescendant(returnStmt(hasReturnValue(
+                       has(cxxConstructExpr(has(CtorAsArgument)))))))
+          .bind("fn"),
+      this);
+}
+
+void ReturnBracedInitListCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunctionDecl = Result.Nodes.getNodeAs<FunctionDecl>("fn");
+  const auto *MatchedConstructExpr =
+      Result.Nodes.getNodeAs<CXXConstructExpr>("ctor");
+
+  // Don't make replacements in macro.
+  SourceLocation Loc = MatchedConstructExpr->getExprLoc();
+  if (Loc.isMacroID())
+    return;
+
+  // Make sure that the return type matches the constructed type.
+  const QualType ReturnType =
+      MatchedFunctionDecl->getReturnType().getCanonicalType();
+  const QualType ConstructType =
+      MatchedConstructExpr->getType().getCanonicalType();
+  if (ReturnType != ConstructType)
+    return;
+
+  auto Diag = diag(Loc, "avoid repeating the return type from the "
+                        "declaration; use a braced initializer list instead");
+
+  const SourceRange CallParensRange =
+      MatchedConstructExpr->getParenOrBraceRange();
+
+  // Make sure there is an explicit constructor call.
+  if (CallParensRange.isInvalid())
+    return;
+
+  // Make sure that the ctor arguments match the declaration.
+  for (unsigned I = 0, NumParams = MatchedConstructExpr->getNumArgs();
+       I < NumParams; ++I) {
+    if (const auto *VD = dyn_cast<VarDecl>(
+            MatchedConstructExpr->getConstructor()->getParamDecl(I))) {
+      if (MatchedConstructExpr->getArg(I)->getType().getCanonicalType() !=
+          VD->getType().getCanonicalType())
+        return;
+    }
+  }
+
+  // Range for constructor name and opening brace.
+  CharSourceRange CtorCallSourceRange = CharSourceRange::getTokenRange(
+      Loc, CallParensRange.getBegin().getLocWithOffset(-1));
+
+  Diag << FixItHint::CreateRemoval(CtorCallSourceRange)
+       << FixItHint::CreateReplacement(CallParensRange.getBegin(), "{")
+       << FixItHint::CreateReplacement(CallParensRange.getEnd(), "}");
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReturnBracedInitListCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReturnBracedInitListCheck.h
new file mode 100644
index 0000000..eda982a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ReturnBracedInitListCheck.h
@@ -0,0 +1,36 @@
+//===--- ReturnBracedInitListCheck.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_RETURN_BRACED_INIT_LIST_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_RETURN_BRACED_INIT_LIST_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Use a braced init list for return statements rather than unnecessary
+/// repeating the return type name.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-return-braced-init-list.html
+class ReturnBracedInitListCheck : public ClangTidyCheck {
+public:
+  ReturnBracedInitListCheck(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_RETURN_BRACED_INIT_LIST_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ShrinkToFitCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ShrinkToFitCheck.cpp
new file mode 100644
index 0000000..f197399
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ShrinkToFitCheck.cpp
@@ -0,0 +1,90 @@
+//===--- ShrinkToFitCheck.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 "ShrinkToFitCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/StringRef.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+void ShrinkToFitCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  // Swap as a function need not to be considered, because rvalue can not
+  // be bound to a non-const reference.
+  const auto ShrinkableAsMember =
+      memberExpr(member(valueDecl().bind("ContainerDecl")));
+  const auto ShrinkableAsDecl =
+      declRefExpr(hasDeclaration(valueDecl().bind("ContainerDecl")));
+  const auto CopyCtorCall = cxxConstructExpr(hasArgument(
+      0, anyOf(ShrinkableAsMember, ShrinkableAsDecl,
+               unaryOperator(has(ignoringParenImpCasts(ShrinkableAsMember))),
+               unaryOperator(has(ignoringParenImpCasts(ShrinkableAsDecl))))));
+  const auto SwapParam =
+      expr(anyOf(memberExpr(member(equalsBoundNode("ContainerDecl"))),
+                 declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl"))),
+                 unaryOperator(has(ignoringParenImpCasts(
+                     memberExpr(member(equalsBoundNode("ContainerDecl")))))),
+                 unaryOperator(has(ignoringParenImpCasts(declRefExpr(
+                     hasDeclaration(equalsBoundNode("ContainerDecl"))))))));
+
+  Finder->addMatcher(
+      cxxMemberCallExpr(
+          on(hasType(hasCanonicalType(hasDeclaration(namedDecl(
+              hasAnyName("std::basic_string", "std::deque", "std::vector")))))),
+          callee(cxxMethodDecl(hasName("swap"))),
+          has(ignoringParenImpCasts(memberExpr(hasDescendant(CopyCtorCall)))),
+          hasArgument(0, SwapParam.bind("ContainerToShrink")),
+          unless(isInTemplateInstantiation()))
+          .bind("CopyAndSwapTrick"),
+      this);
+}
+
+void ShrinkToFitCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MemberCall =
+      Result.Nodes.getNodeAs<CXXMemberCallExpr>("CopyAndSwapTrick");
+  const auto *Container = Result.Nodes.getNodeAs<Expr>("ContainerToShrink");
+  FixItHint Hint;
+
+  if (!MemberCall->getLocStart().isMacroID()) {
+    const LangOptions &Opts = getLangOpts();
+    std::string ReplacementText;
+    if (const auto *UnaryOp = llvm::dyn_cast<UnaryOperator>(Container)) {
+      ReplacementText =
+          Lexer::getSourceText(CharSourceRange::getTokenRange(
+                                   UnaryOp->getSubExpr()->getSourceRange()),
+                               *Result.SourceManager, Opts);
+      ReplacementText += "->shrink_to_fit()";
+    } else {
+      ReplacementText = Lexer::getSourceText(
+          CharSourceRange::getTokenRange(Container->getSourceRange()),
+          *Result.SourceManager, Opts);
+      ReplacementText += ".shrink_to_fit()";
+    }
+
+    Hint = FixItHint::CreateReplacement(MemberCall->getSourceRange(),
+                                        ReplacementText);
+  }
+
+  diag(MemberCall->getLocStart(), "the shrink_to_fit method should be used "
+                                  "to reduce the capacity of a shrinkable "
+                                  "container")
+      << Hint;
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ShrinkToFitCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ShrinkToFitCheck.h
new file mode 100644
index 0000000..1e3745c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/ShrinkToFitCheck.h
@@ -0,0 +1,37 @@
+//===--- ShrinkToFitCheck.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_SHRINKTOFITCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_SHRINKTOFITCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Replace copy and swap tricks on shrinkable containers with the
+/// `shrink_to_fit()` method call.
+///
+/// The `shrink_to_fit()` method is more readable and more effective than
+/// the copy and swap trick to reduce the capacity of a shrinkable container.
+/// Note that, the `shrink_to_fit()` method is only available in C++11 and up.
+class ShrinkToFitCheck : public ClangTidyCheck {
+public:
+  ShrinkToFitCheck(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_SHRINKTOFITCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UnaryStaticAssertCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UnaryStaticAssertCheck.cpp
new file mode 100644
index 0000000..67c0063
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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().CPlusPlus17)
+    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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UnaryStaticAssertCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UnaryStaticAssertCheck.h
new file mode 100644
index 0000000..b83c2c4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp
new file mode 100644
index 0000000..8687162
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp
@@ -0,0 +1,503 @@
+//===--- UseAutoCheck.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 "UseAutoCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang;
+using namespace clang::ast_matchers;
+using namespace clang::ast_matchers::internal;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+namespace {
+
+const char IteratorDeclStmtId[] = "iterator_decl";
+const char DeclWithNewId[] = "decl_new";
+const char DeclWithCastId[] = "decl_cast";
+const char DeclWithTemplateCastId[] = "decl_template";
+
+size_t GetTypeNameLength(bool RemoveStars, StringRef Text) {
+  enum CharType { Space, Alpha, Punctuation };
+  CharType LastChar = Space, BeforeSpace = Punctuation;
+  size_t NumChars = 0;
+  int TemplateTypenameCntr = 0;
+  for (const unsigned char C : Text) {
+    if (C == '<')
+      ++TemplateTypenameCntr;
+    else if (C == '>')
+      --TemplateTypenameCntr;
+    const CharType NextChar =
+        isAlphanumeric(C)
+            ? Alpha
+            : (isWhitespace(C) ||
+               (!RemoveStars && TemplateTypenameCntr == 0 && C == '*'))
+                  ? Space
+                  : Punctuation;
+    if (NextChar != Space) {
+      ++NumChars; // Count the non-space character.
+      if (LastChar == Space && NextChar == Alpha && BeforeSpace == Alpha)
+        ++NumChars; // Count a single space character between two words.
+      BeforeSpace = NextChar;
+    }
+    LastChar = NextChar;
+  }
+  return NumChars;
+}
+
+/// \brief Matches variable declarations that have explicit initializers that
+/// are not initializer lists.
+///
+/// Given
+/// \code
+///   iterator I = Container.begin();
+///   MyType A(42);
+///   MyType B{2};
+///   MyType C;
+/// \endcode
+///
+/// varDecl(hasWrittenNonListInitializer()) maches \c I and \c A but not \c B
+/// or \c C.
+AST_MATCHER(VarDecl, hasWrittenNonListInitializer) {
+  const Expr *Init = Node.getAnyInitializer();
+  if (!Init)
+    return false;
+
+  Init = Init->IgnoreImplicit();
+
+  // The following test is based on DeclPrinter::VisitVarDecl() to find if an
+  // initializer is implicit or not.
+  if (const auto *Construct = dyn_cast<CXXConstructExpr>(Init)) {
+    return !Construct->isListInitialization() && Construct->getNumArgs() > 0 &&
+           !Construct->getArg(0)->isDefaultArgument();
+  }
+  return Node.getInitStyle() != VarDecl::ListInit;
+}
+
+/// \brief Matches QualTypes that are type sugar for QualTypes that match \c
+/// SugarMatcher.
+///
+/// Given
+/// \code
+///   class C {};
+///   typedef C my_type;
+///   typedef my_type my_other_type;
+/// \endcode
+///
+/// qualType(isSugarFor(recordType(hasDeclaration(namedDecl(hasName("C"))))))
+/// matches \c my_type and \c my_other_type.
+AST_MATCHER_P(QualType, isSugarFor, Matcher<QualType>, SugarMatcher) {
+  QualType QT = Node;
+  while (true) {
+    if (SugarMatcher.matches(QT, Finder, Builder))
+      return true;
+
+    QualType NewQT = QT.getSingleStepDesugaredType(Finder->getASTContext());
+    if (NewQT == QT)
+      return false;
+    QT = NewQT;
+  }
+}
+
+/// \brief Matches named declarations that have one of the standard iterator
+/// names: iterator, reverse_iterator, const_iterator, const_reverse_iterator.
+///
+/// Given
+/// \code
+///   iterator I;
+///   const_iterator CI;
+/// \endcode
+///
+/// namedDecl(hasStdIteratorName()) matches \c I and \c CI.
+AST_MATCHER(NamedDecl, hasStdIteratorName) {
+  static const char *const IteratorNames[] = {"iterator", "reverse_iterator",
+                                              "const_iterator",
+                                              "const_reverse_iterator"};
+
+  for (const char *Name : IteratorNames) {
+    if (hasName(Name).matches(Node, Finder, Builder))
+      return true;
+  }
+  return false;
+}
+
+/// \brief Matches named declarations that have one of the standard container
+/// names.
+///
+/// Given
+/// \code
+///   class vector {};
+///   class forward_list {};
+///   class my_ver{};
+/// \endcode
+///
+/// recordDecl(hasStdContainerName()) matches \c vector and \c forward_list
+/// but not \c my_vec.
+AST_MATCHER(NamedDecl, hasStdContainerName) {
+  static const char *const ContainerNames[] = {
+      "array",         "deque",
+      "forward_list",  "list",
+      "vector",
+
+      "map",           "multimap",
+      "set",           "multiset",
+
+      "unordered_map", "unordered_multimap",
+      "unordered_set", "unordered_multiset",
+
+      "queue",         "priority_queue",
+      "stack"};
+
+  for (const char *Name : ContainerNames) {
+    if (hasName(Name).matches(Node, Finder, Builder))
+      return true;
+  }
+  return false;
+}
+
+/// Matches declarations whose declaration context is the C++ standard library
+/// namespace std.
+///
+/// Note that inline namespaces are silently ignored during the lookup since
+/// both libstdc++ and libc++ are known to use them for versioning purposes.
+///
+/// Given:
+/// \code
+///   namespace ns {
+///     struct my_type {};
+///     using namespace std;
+///   }
+///
+///   using std::vector;
+///   using ns:my_type;
+///   using ns::list;
+/// \code
+///
+/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(isFromStdNamespace())))
+/// matches "using std::vector" and "using ns::list".
+AST_MATCHER(Decl, isFromStdNamespace) {
+  const DeclContext *D = Node.getDeclContext();
+
+  while (D->isInlineNamespace())
+    D = D->getParent();
+
+  if (!D->isNamespace() || !D->getParent()->isTranslationUnit())
+    return false;
+
+  const IdentifierInfo *Info = cast<NamespaceDecl>(D)->getIdentifier();
+
+  return (Info && Info->isStr("std"));
+}
+
+/// Matches declaration reference or member expressions with explicit template
+/// arguments.
+AST_POLYMORPHIC_MATCHER(hasExplicitTemplateArgs,
+                        AST_POLYMORPHIC_SUPPORTED_TYPES(DeclRefExpr,
+                                                        MemberExpr)) {
+  return Node.hasExplicitTemplateArgs();
+}
+
+/// \brief Returns a DeclarationMatcher that matches standard iterators nested
+/// inside records with a standard container name.
+DeclarationMatcher standardIterator() {
+  return allOf(
+      namedDecl(hasStdIteratorName()),
+      hasDeclContext(recordDecl(hasStdContainerName(), isFromStdNamespace())));
+}
+
+/// \brief Returns a TypeMatcher that matches typedefs for standard iterators
+/// inside records with a standard container name.
+TypeMatcher typedefIterator() {
+  return typedefType(hasDeclaration(standardIterator()));
+}
+
+/// \brief Returns a TypeMatcher that matches records named for standard
+/// iterators nested inside records named for standard containers.
+TypeMatcher nestedIterator() {
+  return recordType(hasDeclaration(standardIterator()));
+}
+
+/// \brief Returns a TypeMatcher that matches types declared with using
+/// declarations and which name standard iterators for standard containers.
+TypeMatcher iteratorFromUsingDeclaration() {
+  auto HasIteratorDecl = hasDeclaration(namedDecl(hasStdIteratorName()));
+  // Types resulting from using declarations are represented by elaboratedType.
+  return elaboratedType(allOf(
+      // Unwrap the nested name specifier to test for one of the standard
+      // containers.
+      hasQualifier(specifiesType(templateSpecializationType(hasDeclaration(
+          namedDecl(hasStdContainerName(), isFromStdNamespace()))))),
+      // the named type is what comes after the final '::' in the type. It
+      // should name one of the standard iterator names.
+      namesType(
+          anyOf(typedefType(HasIteratorDecl), recordType(HasIteratorDecl)))));
+}
+
+/// \brief This matcher returns declaration statements that contain variable
+/// declarations with written non-list initializer for standard iterators.
+StatementMatcher makeIteratorDeclMatcher() {
+  return declStmt(unless(has(
+                      varDecl(anyOf(unless(hasWrittenNonListInitializer()),
+                                    unless(hasType(isSugarFor(anyOf(
+                                        typedefIterator(), nestedIterator(),
+                                        iteratorFromUsingDeclaration())))))))))
+      .bind(IteratorDeclStmtId);
+}
+
+StatementMatcher makeDeclWithNewMatcher() {
+  return declStmt(
+             unless(has(varDecl(anyOf(
+                 unless(hasInitializer(ignoringParenImpCasts(cxxNewExpr()))),
+                 // FIXME: TypeLoc information is not reliable where CV
+                 // qualifiers are concerned so these types can't be
+                 // handled for now.
+                 hasType(pointerType(
+                     pointee(hasCanonicalType(hasLocalQualifiers())))),
+
+                 // FIXME: Handle function pointers. For now we ignore them
+                 // because the replacement replaces the entire type
+                 // specifier source range which includes the identifier.
+                 hasType(pointsTo(
+                     pointsTo(parenType(innerType(functionType()))))))))))
+      .bind(DeclWithNewId);
+}
+
+StatementMatcher makeDeclWithCastMatcher() {
+  return declStmt(
+             unless(has(varDecl(unless(hasInitializer(explicitCastExpr()))))))
+      .bind(DeclWithCastId);
+}
+
+StatementMatcher makeDeclWithTemplateCastMatcher() {
+  auto ST =
+      substTemplateTypeParmType(hasReplacementType(equalsBoundNode("arg")));
+
+  auto ExplicitCall =
+      anyOf(has(memberExpr(hasExplicitTemplateArgs())),
+            has(ignoringImpCasts(declRefExpr(hasExplicitTemplateArgs()))));
+
+  auto TemplateArg =
+      hasTemplateArgument(0, refersToType(qualType().bind("arg")));
+
+  auto TemplateCall = callExpr(
+      ExplicitCall,
+      callee(functionDecl(TemplateArg,
+                          returns(anyOf(ST, pointsTo(ST), references(ST))))));
+
+  return declStmt(unless(has(varDecl(
+                      unless(hasInitializer(ignoringImplicit(TemplateCall)))))))
+      .bind(DeclWithTemplateCastId);
+}
+
+StatementMatcher makeCombinedMatcher() {
+  return declStmt(
+      // At least one varDecl should be a child of the declStmt to ensure
+      // it's a declaration list and avoid matching other declarations,
+      // e.g. using directives.
+      has(varDecl(unless(isImplicit()))),
+      // Skip declarations that are already using auto.
+      unless(has(varDecl(anyOf(hasType(autoType()),
+                               hasType(qualType(hasDescendant(autoType()))))))),
+      anyOf(makeIteratorDeclMatcher(), makeDeclWithNewMatcher(),
+            makeDeclWithCastMatcher(), makeDeclWithTemplateCastMatcher()));
+}
+
+} // namespace
+
+UseAutoCheck::UseAutoCheck(StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      MinTypeNameLength(Options.get("MinTypeNameLength", 5)),
+      RemoveStars(Options.get("RemoveStars", 0)) {}
+
+void UseAutoCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "MinTypeNameLength", MinTypeNameLength);
+  Options.store(Opts, "RemoveStars", RemoveStars ? 1 : 0);
+}
+
+void UseAutoCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (getLangOpts().CPlusPlus) {
+    Finder->addMatcher(makeCombinedMatcher(), this);
+  }
+}
+
+void UseAutoCheck::replaceIterators(const DeclStmt *D, ASTContext *Context) {
+  for (const auto *Dec : D->decls()) {
+    const auto *V = cast<VarDecl>(Dec);
+    const Expr *ExprInit = V->getInit();
+
+    // Skip expressions with cleanups from the intializer expression.
+    if (const auto *E = dyn_cast<ExprWithCleanups>(ExprInit))
+      ExprInit = E->getSubExpr();
+
+    const auto *Construct = dyn_cast<CXXConstructExpr>(ExprInit);
+    if (!Construct)
+      continue;
+
+    // Ensure that the constructor receives a single argument.
+    if (Construct->getNumArgs() != 1)
+      return;
+
+    // Drill down to the as-written initializer.
+    const Expr *E = (*Construct->arg_begin())->IgnoreParenImpCasts();
+    if (E != E->IgnoreConversionOperator()) {
+      // We hit a conversion operator. Early-out now as they imply an implicit
+      // conversion from a different type. Could also mean an explicit
+      // conversion from the same type but that's pretty rare.
+      return;
+    }
+
+    if (const auto *NestedConstruct = dyn_cast<CXXConstructExpr>(E)) {
+      // If we ran into an implicit conversion contructor, can't convert.
+      //
+      // FIXME: The following only checks if the constructor can be used
+      // implicitly, not if it actually was. Cases where the converting
+      // constructor was used explicitly won't get converted.
+      if (NestedConstruct->getConstructor()->isConvertingConstructor(false))
+        return;
+    }
+    if (!Context->hasSameType(V->getType(), E->getType()))
+      return;
+  }
+
+  // Get the type location using the first declaration.
+  const auto *V = cast<VarDecl>(*D->decl_begin());
+
+  // WARNING: TypeLoc::getSourceRange() will include the identifier for things
+  // like function pointers. Not a concern since this action only works with
+  // iterators but something to keep in mind in the future.
+
+  SourceRange Range(V->getTypeSourceInfo()->getTypeLoc().getSourceRange());
+  diag(Range.getBegin(), "use auto when declaring iterators")
+      << FixItHint::CreateReplacement(Range, "auto");
+}
+
+void UseAutoCheck::replaceExpr(
+    const DeclStmt *D, ASTContext *Context,
+    llvm::function_ref<QualType(const Expr *)> GetType, StringRef Message) {
+  const auto *FirstDecl = dyn_cast<VarDecl>(*D->decl_begin());
+  // Ensure that there is at least one VarDecl within the DeclStmt.
+  if (!FirstDecl)
+    return;
+
+  const QualType FirstDeclType = FirstDecl->getType().getCanonicalType();
+
+  std::vector<FixItHint> StarRemovals;
+  for (const auto *Dec : D->decls()) {
+    const auto *V = cast<VarDecl>(Dec);
+    // Ensure that every DeclStmt child is a VarDecl.
+    if (!V)
+      return;
+
+    const auto *Expr = V->getInit()->IgnoreParenImpCasts();
+    // Ensure that every VarDecl has an initializer.
+    if (!Expr)
+      return;
+
+    // If VarDecl and Initializer have mismatching unqualified types.
+    if (!Context->hasSameUnqualifiedType(V->getType(), GetType(Expr)))
+      return;
+
+    // All subsequent variables in this declaration should have the same
+    // canonical type.  For example, we don't want to use `auto` in
+    // `T *p = new T, **pp = new T*;`.
+    if (FirstDeclType != V->getType().getCanonicalType())
+      return;
+
+    if (RemoveStars) {
+      // Remove explicitly written '*' from declarations where there's more than
+      // one declaration in the declaration list.
+      if (Dec == *D->decl_begin())
+        continue;
+
+      auto Q = V->getTypeSourceInfo()->getTypeLoc().getAs<PointerTypeLoc>();
+      while (!Q.isNull()) {
+        StarRemovals.push_back(FixItHint::CreateRemoval(Q.getStarLoc()));
+        Q = Q.getNextTypeLoc().getAs<PointerTypeLoc>();
+      }
+    }
+  }
+
+  // FIXME: There is, however, one case we can address: when the VarDecl pointee
+  // is the same as the initializer, just more CV-qualified. However, TypeLoc
+  // information is not reliable where CV qualifiers are concerned so we can't
+  // do anything about this case for now.
+  TypeLoc Loc = FirstDecl->getTypeSourceInfo()->getTypeLoc();
+  if (!RemoveStars) {
+    while (Loc.getTypeLocClass() == TypeLoc::Pointer ||
+           Loc.getTypeLocClass() == TypeLoc::Qualified)
+      Loc = Loc.getNextTypeLoc();
+  }
+  while (Loc.getTypeLocClass() == TypeLoc::LValueReference ||
+         Loc.getTypeLocClass() == TypeLoc::RValueReference ||
+         Loc.getTypeLocClass() == TypeLoc::Qualified) {
+    Loc = Loc.getNextTypeLoc();
+  }
+  SourceRange Range(Loc.getSourceRange());
+
+  if (MinTypeNameLength != 0 &&
+      GetTypeNameLength(RemoveStars,
+                        tooling::fixit::getText(Loc.getSourceRange(),
+                                                FirstDecl->getASTContext())) <
+          MinTypeNameLength)
+    return;
+
+  auto Diag = diag(Range.getBegin(), Message);
+
+  // Space after 'auto' to handle cases where the '*' in the pointer type is
+  // next to the identifier. This avoids changing 'int *p' into 'autop'.
+  // FIXME: This doesn't work for function pointers because the variable name
+  // is inside the type.
+  Diag << FixItHint::CreateReplacement(Range, RemoveStars ? "auto " : "auto")
+       << StarRemovals;
+}
+
+void UseAutoCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *Decl = Result.Nodes.getNodeAs<DeclStmt>(IteratorDeclStmtId)) {
+    replaceIterators(Decl, Result.Context);
+  } else if (const auto *Decl =
+                 Result.Nodes.getNodeAs<DeclStmt>(DeclWithNewId)) {
+    replaceExpr(Decl, Result.Context,
+                [](const Expr *Expr) { return Expr->getType(); },
+                "use auto when initializing with new to avoid "
+                "duplicating the type name");
+  } else if (const auto *Decl =
+                 Result.Nodes.getNodeAs<DeclStmt>(DeclWithCastId)) {
+    replaceExpr(
+        Decl, Result.Context,
+        [](const Expr *Expr) {
+          return cast<ExplicitCastExpr>(Expr)->getTypeAsWritten();
+        },
+        "use auto when initializing with a cast to avoid duplicating the type "
+        "name");
+  } else if (const auto *Decl =
+                 Result.Nodes.getNodeAs<DeclStmt>(DeclWithTemplateCastId)) {
+    replaceExpr(
+        Decl, Result.Context,
+        [](const Expr *Expr) {
+          return cast<CallExpr>(Expr->IgnoreImplicit())
+              ->getDirectCallee()
+              ->getReturnType();
+        },
+        "use auto when initializing with a template cast to avoid duplicating "
+        "the type name");
+  } else {
+    llvm_unreachable("Bad Callback. No node provided.");
+  }
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.h
new file mode 100644
index 0000000..a061c5f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.h
@@ -0,0 +1,40 @@
+//===--- UseAutoCheck.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_USE_AUTO_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_AUTO_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+class UseAutoCheck : public ClangTidyCheck {
+public:
+  UseAutoCheck(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:
+  void replaceIterators(const DeclStmt *D, ASTContext *Context);
+  void replaceExpr(const DeclStmt *D, ASTContext *Context,
+                   llvm::function_ref<QualType(const Expr *)> GetType,
+                   StringRef Message);
+
+  const unsigned int MinTypeNameLength;
+  const bool RemoveStars;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_AUTO_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp
new file mode 100644
index 0000000..ece8cd5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp
@@ -0,0 +1,76 @@
+//===--- UseBoolLiteralsCheck.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 "UseBoolLiteralsCheck.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 modernize {
+
+UseBoolLiteralsCheck::UseBoolLiteralsCheck(StringRef Name,
+                                           ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {}
+
+void UseBoolLiteralsCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(
+      implicitCastExpr(
+          has(ignoringParenImpCasts(integerLiteral().bind("literal"))),
+          hasImplicitDestinationType(qualType(booleanType())),
+          unless(isInTemplateInstantiation()),
+          anyOf(hasParent(explicitCastExpr().bind("cast")), anything())),
+      this);
+
+  Finder->addMatcher(
+      conditionalOperator(
+          hasParent(implicitCastExpr(
+              hasImplicitDestinationType(qualType(booleanType())),
+              unless(isInTemplateInstantiation()))),
+          eachOf(hasTrueExpression(
+                     ignoringParenImpCasts(integerLiteral().bind("literal"))),
+                 hasFalseExpression(
+                     ignoringParenImpCasts(integerLiteral().bind("literal"))))),
+      this);
+}
+
+void UseBoolLiteralsCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Literal = Result.Nodes.getNodeAs<IntegerLiteral>("literal");
+  const auto *Cast = Result.Nodes.getNodeAs<Expr>("cast");
+  bool LiteralBooleanValue = Literal->getValue().getBoolValue();
+
+  if (Literal->isInstantiationDependent())
+    return;
+
+  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 (!InMacro)
+    Diag << FixItHint::CreateReplacement(
+        Expression->getSourceRange(), LiteralBooleanValue ? "true" : "false");
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.h
new file mode 100644
index 0000000..c9c7363
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.h
@@ -0,0 +1,37 @@
+//===--- UseBoolLiteralsCheck.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_USE_BOOL_LITERALS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_BOOL_LITERALS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Finds integer literals which are cast to bool.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-bool-literals.html
+class UseBoolLiteralsCheck : public ClangTidyCheck {
+public:
+  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
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_BOOL_LITERALS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
new file mode 100644
index 0000000..c14c685
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
@@ -0,0 +1,247 @@
+//===--- UseDefaultMemberInitCheck.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 "UseDefaultMemberInitCheck.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 modernize {
+
+static StringRef getValueOfValueInit(const QualType InitType) {
+  switch (InitType->getScalarTypeKind()) {
+  case Type::STK_CPointer:
+  case Type::STK_BlockPointer:
+  case Type::STK_ObjCObjectPointer:
+  case Type::STK_MemberPointer:
+    return "nullptr";
+
+  case Type::STK_Bool:
+    return "false";
+
+  case Type::STK_Integral:
+    switch (InitType->getAs<BuiltinType>()->getKind()) {
+    case BuiltinType::Char_U:
+    case BuiltinType::UChar:
+    case BuiltinType::Char_S:
+    case BuiltinType::SChar:
+      return "'\\0'";
+    case BuiltinType::WChar_U:
+    case BuiltinType::WChar_S:
+      return "L'\\0'";
+    case BuiltinType::Char16:
+      return "u'\\0'";
+    case BuiltinType::Char32:
+      return "U'\\0'";
+    default:
+      return "0";
+    }
+
+  case Type::STK_Floating:
+    switch (InitType->getAs<BuiltinType>()->getKind()) {
+    case BuiltinType::Half:
+    case BuiltinType::Float:
+      return "0.0f";
+    default:
+      return "0.0";
+    }
+
+  case Type::STK_FloatingComplex:
+  case Type::STK_IntegralComplex:
+    return getValueOfValueInit(
+        InitType->getAs<ComplexType>()->getElementType());
+  }
+  llvm_unreachable("Invalid scalar type kind");
+}
+
+static bool isZero(const Expr *E) {
+  switch (E->getStmtClass()) {
+  case Stmt::CXXNullPtrLiteralExprClass:
+  case Stmt::ImplicitValueInitExprClass:
+    return true;
+  case Stmt::InitListExprClass:
+    return cast<InitListExpr>(E)->getNumInits() == 0;
+  case Stmt::CharacterLiteralClass:
+    return !cast<CharacterLiteral>(E)->getValue();
+  case Stmt::CXXBoolLiteralExprClass:
+    return !cast<CXXBoolLiteralExpr>(E)->getValue();
+  case Stmt::IntegerLiteralClass:
+    return !cast<IntegerLiteral>(E)->getValue();
+  case Stmt::FloatingLiteralClass: {
+    llvm::APFloat Value = cast<FloatingLiteral>(E)->getValue();
+    return Value.isZero() && !Value.isNegative();
+  }
+  default:
+    return false;
+  }
+}
+
+static const Expr *ignoreUnaryPlus(const Expr *E) {
+  auto *UnaryOp = dyn_cast<UnaryOperator>(E);
+  if (UnaryOp && UnaryOp->getOpcode() == UO_Plus)
+    return UnaryOp->getSubExpr();
+  return E;
+}
+
+static const Expr *getInitializer(const Expr *E) {
+  auto *InitList = dyn_cast<InitListExpr>(E);
+  if (InitList && InitList->getNumInits() == 1)
+    return InitList->getInit(0);
+  return E;
+}
+
+static bool sameValue(const Expr *E1, const Expr *E2) {
+  E1 = ignoreUnaryPlus(getInitializer(E1->IgnoreParenImpCasts()));
+  E2 = ignoreUnaryPlus(getInitializer(E2->IgnoreParenImpCasts()));
+
+  if (isZero(E1) && isZero(E2))
+    return true;
+
+  if (E1->getStmtClass() != E2->getStmtClass())
+    return false;
+
+  switch (E1->getStmtClass()) {
+  case Stmt::UnaryOperatorClass:
+    return sameValue(cast<UnaryOperator>(E1)->getSubExpr(),
+                     cast<UnaryOperator>(E2)->getSubExpr());
+  case Stmt::CharacterLiteralClass:
+    return cast<CharacterLiteral>(E1)->getValue() ==
+           cast<CharacterLiteral>(E2)->getValue();
+  case Stmt::CXXBoolLiteralExprClass:
+    return cast<CXXBoolLiteralExpr>(E1)->getValue() ==
+           cast<CXXBoolLiteralExpr>(E2)->getValue();
+  case Stmt::IntegerLiteralClass:
+    return cast<IntegerLiteral>(E1)->getValue() ==
+           cast<IntegerLiteral>(E2)->getValue();
+  case Stmt::FloatingLiteralClass:
+    return cast<FloatingLiteral>(E1)->getValue().bitwiseIsEqual(
+        cast<FloatingLiteral>(E2)->getValue());
+  case Stmt::StringLiteralClass:
+    return cast<StringLiteral>(E1)->getString() ==
+           cast<StringLiteral>(E2)->getString();
+  case Stmt::DeclRefExprClass:
+    return cast<DeclRefExpr>(E1)->getDecl() == cast<DeclRefExpr>(E2)->getDecl();
+  default:
+    return false;
+  }
+}
+
+UseDefaultMemberInitCheck::UseDefaultMemberInitCheck(StringRef Name,
+                                                     ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      UseAssignment(Options.get("UseAssignment", 0) != 0),
+      IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true) != 0) {}
+
+void UseDefaultMemberInitCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "UseAssignment", UseAssignment);
+  Options.store(Opts, "IgnoreMacros", IgnoreMacros);
+}
+
+void UseDefaultMemberInitCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  auto Init =
+      anyOf(stringLiteral(), characterLiteral(), integerLiteral(),
+            unaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("-")),
+                          hasUnaryOperand(integerLiteral())),
+            floatLiteral(),
+            unaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("-")),
+                          hasUnaryOperand(floatLiteral())),
+            cxxBoolLiteral(), cxxNullPtrLiteralExpr(), implicitValueInitExpr(),
+            declRefExpr(to(enumConstantDecl())));
+
+  Finder->addMatcher(
+      cxxConstructorDecl(
+          isDefaultConstructor(), unless(isInstantiated()),
+          forEachConstructorInitializer(
+              cxxCtorInitializer(
+                  forField(unless(anyOf(getLangOpts().CPlusPlus2a
+                                            ? unless(anything())
+                                            : isBitField(),
+                                        hasInClassInitializer(anything()),
+                                        hasParent(recordDecl(isUnion()))))),
+                  isWritten(), withInitializer(ignoringImplicit(Init)))
+                  .bind("default"))),
+      this);
+
+  Finder->addMatcher(
+      cxxConstructorDecl(
+          unless(ast_matchers::isTemplateInstantiation()),
+          forEachConstructorInitializer(
+              cxxCtorInitializer(forField(hasInClassInitializer(anything())),
+                                 isWritten(),
+                                 withInitializer(ignoringImplicit(Init)))
+                  .bind("existing"))),
+      this);
+}
+
+void UseDefaultMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *Default =
+          Result.Nodes.getNodeAs<CXXCtorInitializer>("default"))
+    checkDefaultInit(Result, Default);
+  else if (const auto *Existing =
+               Result.Nodes.getNodeAs<CXXCtorInitializer>("existing"))
+    checkExistingInit(Result, Existing);
+  else
+    llvm_unreachable("Bad Callback. No node provided.");
+}
+
+void UseDefaultMemberInitCheck::checkDefaultInit(
+    const MatchFinder::MatchResult &Result, const CXXCtorInitializer *Init) {
+  const FieldDecl *Field = Init->getAnyMember();
+
+  SourceLocation StartLoc = Field->getLocStart();
+  if (StartLoc.isMacroID() && IgnoreMacros)
+    return;
+
+  SourceLocation FieldEnd =
+      Lexer::getLocForEndOfToken(Field->getSourceRange().getEnd(), 0,
+                                 *Result.SourceManager, getLangOpts());
+  SourceLocation LParenEnd = Lexer::getLocForEndOfToken(
+      Init->getLParenLoc(), 0, *Result.SourceManager, getLangOpts());
+  CharSourceRange InitRange =
+      CharSourceRange::getCharRange(LParenEnd, Init->getRParenLoc());
+
+  auto Diag =
+      diag(Field->getLocation(), "use default member initializer for %0")
+      << Field
+      << FixItHint::CreateInsertion(FieldEnd, UseAssignment ? " = " : "{")
+      << FixItHint::CreateInsertionFromRange(FieldEnd, InitRange);
+
+  if (UseAssignment && isa<ImplicitValueInitExpr>(Init->getInit()))
+    Diag << FixItHint::CreateInsertion(
+        FieldEnd, getValueOfValueInit(Init->getInit()->getType()));
+
+  if (!UseAssignment)
+    Diag << FixItHint::CreateInsertion(FieldEnd, "}");
+
+  Diag << FixItHint::CreateRemoval(Init->getSourceRange());
+}
+
+void UseDefaultMemberInitCheck::checkExistingInit(
+    const MatchFinder::MatchResult &Result, const CXXCtorInitializer *Init) {
+  const FieldDecl *Field = Init->getMember();
+
+  if (!sameValue(Field->getInClassInitializer(), Init->getInit()))
+    return;
+
+  diag(Init->getSourceLocation(), "member initializer for %0 is redundant")
+      << Field
+      << FixItHint::CreateRemoval(Init->getSourceRange());
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.h
new file mode 100644
index 0000000..d8887a0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.h
@@ -0,0 +1,46 @@
+//===--- UseDefaultMemberInitCheck.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_USE_DEFAULT_MEMBER_INIT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_DEFAULT_MEMBER_INIT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Convert a default constructor's member initializers into default member
+/// initializers.  Remove member initializers that are the same as a default
+/// member initializer.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-default-member-init.html
+class UseDefaultMemberInitCheck : public ClangTidyCheck {
+public:
+  UseDefaultMemberInitCheck(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:
+  void checkDefaultInit(const ast_matchers::MatchFinder::MatchResult &Result,
+                        const CXXCtorInitializer *Init);
+  void checkExistingInit(const ast_matchers::MatchFinder::MatchResult &Result,
+                         const CXXCtorInitializer *Init);
+
+  const bool UseAssignment;
+  const bool IgnoreMacros;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_DEFAULT_MEMBER_INIT_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp
new file mode 100644
index 0000000..4d5d801
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp
@@ -0,0 +1,177 @@
+//===--- UseEmplaceCheck.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 "UseEmplaceCheck.h"
+#include "../utils/OptionsUtils.h"
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+namespace {
+AST_MATCHER(DeclRefExpr, hasExplicitTemplateArgs) {
+  return Node.hasExplicitTemplateArgs();
+}
+
+const auto DefaultContainersWithPushBack =
+    "::std::vector; ::std::list; ::std::deque";
+const auto DefaultSmartPointers =
+    "::std::shared_ptr; ::std::unique_ptr; ::std::auto_ptr; ::std::weak_ptr";
+const auto DefaultTupleTypes = "::std::pair; ::std::tuple";
+const auto DefaultTupleMakeFunctions = "::std::make_pair; ::std::make_tuple";
+} // namespace
+
+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(
+          Options.get("SmartPointers", DefaultSmartPointers))),
+      TupleTypes(utils::options::parseStringList(
+          Options.get("TupleTypes", DefaultTupleTypes))),
+      TupleMakeFunctions(utils::options::parseStringList(
+          Options.get("TupleMakeFunctions", DefaultTupleMakeFunctions))) {}
+
+void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  // FIXME: Bunch of functionality that could be easily added:
+  // + add handling of `push_front` for std::forward_list, std::list
+  // and std::deque.
+  // + add handling of `push` for std::stack, std::queue, std::priority_queue
+  // + add handling of `insert` for stl associative container, but be careful
+  // because this requires special treatment (it could cause performance
+  // regression)
+  // + match for emplace calls that should be replaced with insertion
+  auto CallPushBack = cxxMemberCallExpr(
+      hasDeclaration(functionDecl(hasName("push_back"))),
+      on(hasType(cxxRecordDecl(hasAnyName(SmallVector<StringRef, 5>(
+          ContainersWithPushBack.begin(), ContainersWithPushBack.end()))))));
+
+  // We can't replace push_backs of smart pointer because
+  // if emplacement fails (f.e. bad_alloc in vector) we will have leak of
+  // passed pointer because smart pointer won't be constructed
+  // (and destructed) as in push_back case.
+  auto IsCtorOfSmartPtr = hasDeclaration(cxxConstructorDecl(ofClass(hasAnyName(
+      SmallVector<StringRef, 5>(SmartPointers.begin(), SmartPointers.end())))));
+
+  // Bitfields binds only to consts and emplace_back take it by universal ref.
+  auto BitFieldAsArgument = hasAnyArgument(
+      ignoringImplicit(memberExpr(hasDeclaration(fieldDecl(isBitField())))));
+
+  // Initializer list can't be passed to universal reference.
+  auto InitializerListAsArgument = hasAnyArgument(
+      ignoringImplicit(cxxConstructExpr(isListInitialization())));
+
+  // We could have leak of resource.
+  auto NewExprAsArgument = hasAnyArgument(ignoringImplicit(cxxNewExpr()));
+  // We would call another constructor.
+  auto ConstructingDerived =
+      hasParent(implicitCastExpr(hasCastKind(CastKind::CK_DerivedToBase)));
+
+  // emplace_back can't access private constructor.
+  auto IsPrivateCtor = hasDeclaration(cxxConstructorDecl(isPrivate()));
+
+  auto HasInitList = anyOf(has(ignoringImplicit(initListExpr())),
+                           has(cxxStdInitializerListExpr()));
+
+  // FIXME: Discard 0/NULL (as nullptr), static inline const data members,
+  // overloaded functions and template names.
+  auto SoughtConstructExpr =
+      cxxConstructExpr(
+          unless(anyOf(IsCtorOfSmartPtr, HasInitList, BitFieldAsArgument,
+                       InitializerListAsArgument, NewExprAsArgument,
+                       ConstructingDerived, IsPrivateCtor)))
+          .bind("ctor");
+  auto HasConstructExpr = has(ignoringImplicit(SoughtConstructExpr));
+
+  auto MakeTuple = ignoringImplicit(
+      callExpr(
+          callee(expr(ignoringImplicit(declRefExpr(
+              unless(hasExplicitTemplateArgs()),
+              to(functionDecl(hasAnyName(SmallVector<StringRef, 2>(
+                  TupleMakeFunctions.begin(), TupleMakeFunctions.end())))))))))
+          .bind("make"));
+
+  // make_something can return type convertible to container's element type.
+  // Allow the conversion only on containers of pairs.
+  auto MakeTupleCtor = ignoringImplicit(cxxConstructExpr(
+      has(materializeTemporaryExpr(MakeTuple)),
+      hasDeclaration(cxxConstructorDecl(ofClass(hasAnyName(
+          SmallVector<StringRef, 2>(TupleTypes.begin(), TupleTypes.end())))))));
+
+  auto SoughtParam = materializeTemporaryExpr(
+      anyOf(has(MakeTuple), has(MakeTupleCtor),
+            HasConstructExpr, has(cxxFunctionalCastExpr(HasConstructExpr))));
+
+  Finder->addMatcher(cxxMemberCallExpr(CallPushBack, has(SoughtParam),
+                                       unless(isInTemplateInstantiation()))
+                         .bind("call"),
+                     this);
+}
+
+void UseEmplaceCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Call = Result.Nodes.getNodeAs<CXXMemberCallExpr>("call");
+  const auto *CtorCall = Result.Nodes.getNodeAs<CXXConstructExpr>("ctor");
+  const auto *MakeCall = Result.Nodes.getNodeAs<CallExpr>("make");
+  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());
+
+  auto Diag = diag(Call->getExprLoc(), "use emplace_back instead of push_back");
+
+  if (FunctionNameSourceRange.getBegin().isMacroID())
+    return;
+
+  const auto *EmplacePrefix = MakeCall ? "emplace_back" : "emplace_back(";
+  Diag << FixItHint::CreateReplacement(FunctionNameSourceRange, EmplacePrefix);
+
+  const SourceRange CallParensRange =
+      MakeCall ? SourceRange(MakeCall->getCallee()->getLocEnd(),
+                             MakeCall->getRParenLoc())
+               : CtorCall->getParenOrBraceRange();
+
+  // Finish if there is no explicit constructor call.
+  if (CallParensRange.getBegin().isInvalid())
+    return;
+
+  const SourceLocation ExprBegin =
+      MakeCall ? MakeCall->getExprLoc() : CtorCall->getExprLoc();
+
+  // Range for constructor name and opening brace.
+  const auto ParamCallSourceRange =
+      CharSourceRange::getTokenRange(ExprBegin, CallParensRange.getBegin());
+
+  Diag << FixItHint::CreateRemoval(ParamCallSourceRange)
+       << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
+           CallParensRange.getEnd(), CallParensRange.getEnd()));
+}
+
+void UseEmplaceCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "ContainersWithPushBack",
+                utils::options::serializeStringList(ContainersWithPushBack));
+  Options.store(Opts, "SmartPointers",
+                utils::options::serializeStringList(SmartPointers));
+  Options.store(Opts, "TupleTypes",
+                utils::options::serializeStringList(TupleTypes));
+  Options.store(Opts, "TupleMakeFunctions",
+                utils::options::serializeStringList(TupleMakeFunctions));
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.h
new file mode 100644
index 0000000..2efb212
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.h
@@ -0,0 +1,47 @@
+//===--- UseEmplaceCheck.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_USE_EMPLACE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_EMPLACE_H
+
+#include "../ClangTidy.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// This check looks for cases when inserting new element into std::vector but
+/// the element is constructed temporarily.
+/// It replaces those calls for emplace_back of arguments passed to
+/// constructor of temporary object.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-emplace.html
+class UseEmplaceCheck : public ClangTidyCheck {
+public:
+  UseEmplaceCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  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
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_EMPLACE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
new file mode 100644
index 0000000..88f4485
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
@@ -0,0 +1,313 @@
+//===--- UseEqualsDefaultCheck.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 "UseEqualsDefaultCheck.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 modernize {
+
+static const char SpecialFunction[] = "SpecialFunction";
+
+/// \brief Finds all the named non-static fields of \p Record.
+static std::set<const FieldDecl *>
+getAllNamedFields(const CXXRecordDecl *Record) {
+  std::set<const FieldDecl *> Result;
+  for (const auto *Field : Record->fields()) {
+    // Static data members are not in this range.
+    if (Field->isUnnamedBitfield())
+      continue;
+    Result.insert(Field);
+  }
+  return Result;
+}
+
+/// \brief Returns the names of the direct bases of \p Record, both virtual and
+/// non-virtual.
+static std::set<const Type *> getAllDirectBases(const CXXRecordDecl *Record) {
+  std::set<const Type *> Result;
+  for (auto Base : Record->bases()) {
+    // CXXBaseSpecifier.
+    const auto *BaseType = Base.getTypeSourceInfo()->getType().getTypePtr();
+    Result.insert(BaseType);
+  }
+  return Result;
+}
+
+/// \brief Returns a matcher that matches member expressions where the base is
+/// the variable declared as \p Var and the accessed member is the one declared
+/// as \p Field.
+internal::Matcher<Expr> accessToFieldInVar(const FieldDecl *Field,
+                                           const ValueDecl *Var) {
+  return ignoringImpCasts(
+      memberExpr(hasObjectExpression(declRefExpr(to(varDecl(equalsNode(Var))))),
+                 member(fieldDecl(equalsNode(Field)))));
+}
+
+/// \brief Check that the given constructor has copy signature and that it
+/// copy-initializes all its bases and members.
+static bool isCopyConstructorAndCanBeDefaulted(ASTContext *Context,
+                                               const CXXConstructorDecl *Ctor) {
+  // An explicitly-defaulted constructor cannot have default arguments.
+  if (Ctor->getMinRequiredArguments() != 1)
+    return false;
+
+  const auto *Record = Ctor->getParent();
+  const auto *Param = Ctor->getParamDecl(0);
+
+  // Base classes and members that have to be copied.
+  auto BasesToInit = getAllDirectBases(Record);
+  auto FieldsToInit = getAllNamedFields(Record);
+
+  // Ensure that all the bases are copied.
+  for (const auto *Base : BasesToInit) {
+    // The initialization of a base class should be a call to a copy
+    // constructor of the base.
+    if (match(
+            cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer(
+                isBaseInitializer(),
+                withInitializer(cxxConstructExpr(allOf(
+                    hasType(equalsNode(Base)),
+                    hasDeclaration(cxxConstructorDecl(isCopyConstructor())),
+                    argumentCountIs(1),
+                    hasArgument(
+                        0, declRefExpr(to(varDecl(equalsNode(Param))))))))))),
+            *Ctor, *Context)
+            .empty())
+      return false;
+  }
+
+  // Ensure that all the members are copied.
+  for (const auto *Field : FieldsToInit) {
+    auto AccessToFieldInParam = accessToFieldInVar(Field, Param);
+    // The initialization is a CXXConstructExpr for class types.
+    if (match(
+            cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer(
+                isMemberInitializer(), forField(equalsNode(Field)),
+                withInitializer(anyOf(
+                    AccessToFieldInParam,
+                    initListExpr(has(AccessToFieldInParam)),
+                    cxxConstructExpr(allOf(
+                        hasDeclaration(cxxConstructorDecl(isCopyConstructor())),
+                        argumentCountIs(1),
+                        hasArgument(0, AccessToFieldInParam)))))))),
+            *Ctor, *Context)
+            .empty())
+      return false;
+  }
+
+  // Ensure that we don't do anything else, like initializing an indirect base.
+  return Ctor->getNumCtorInitializers() ==
+         BasesToInit.size() + FieldsToInit.size();
+}
+
+/// \brief Checks that the given method is an overloading of the assignment
+/// operator, has copy signature, returns a reference to "*this" and copies
+/// all its members and subobjects.
+static bool isCopyAssignmentAndCanBeDefaulted(ASTContext *Context,
+                                              const CXXMethodDecl *Operator) {
+  const auto *Record = Operator->getParent();
+  const auto *Param = Operator->getParamDecl(0);
+
+  // Base classes and members that have to be copied.
+  auto BasesToInit = getAllDirectBases(Record);
+  auto FieldsToInit = getAllNamedFields(Record);
+
+  const auto *Compound = cast<CompoundStmt>(Operator->getBody());
+
+  // The assignment operator definition has to end with the following return
+  // statement:
+  //   return *this;
+  if (Compound->body_empty() ||
+      match(returnStmt(has(ignoringParenImpCasts(unaryOperator(
+                hasOperatorName("*"), hasUnaryOperand(cxxThisExpr()))))),
+            *Compound->body_back(), *Context)
+          .empty())
+    return false;
+
+  // Ensure that all the bases are copied.
+  for (const auto *Base : BasesToInit) {
+    // Assignment operator of a base class:
+    //   Base::operator=(Other);
+    //
+    // Clang translates this into:
+    //   ((Base*)this)->operator=((Base)Other);
+    //
+    // So we are looking for a member call that fulfills:
+    if (match(compoundStmt(has(ignoringParenImpCasts(cxxMemberCallExpr(allOf(
+                  // - The object is an implicit cast of 'this' to a pointer to
+                  //   a base class.
+                  onImplicitObjectArgument(
+                      implicitCastExpr(hasImplicitDestinationType(
+                                           pointsTo(type(equalsNode(Base)))),
+                                       hasSourceExpression(cxxThisExpr()))),
+                  // - The called method is the operator=.
+                  callee(cxxMethodDecl(isCopyAssignmentOperator())),
+                  // - The argument is (an implicit cast to a Base of) the
+                  // argument taken by "Operator".
+                  argumentCountIs(1),
+                  hasArgument(0,
+                              declRefExpr(to(varDecl(equalsNode(Param)))))))))),
+              *Compound, *Context)
+            .empty())
+      return false;
+  }
+
+  // Ensure that all the members are copied.
+  for (const auto *Field : FieldsToInit) {
+    // The assignment of data members:
+    //   Field = Other.Field;
+    // Is a BinaryOperator in non-class types, and a CXXOperatorCallExpr
+    // otherwise.
+    auto LHS = memberExpr(hasObjectExpression(cxxThisExpr()),
+                          member(fieldDecl(equalsNode(Field))));
+    auto RHS = accessToFieldInVar(Field, Param);
+    if (match(
+            compoundStmt(has(ignoringParenImpCasts(stmt(anyOf(
+                binaryOperator(hasOperatorName("="), hasLHS(LHS), hasRHS(RHS)),
+                cxxOperatorCallExpr(hasOverloadedOperatorName("="),
+                                    argumentCountIs(2), hasArgument(0, LHS),
+                                    hasArgument(1, RHS))))))),
+            *Compound, *Context)
+            .empty())
+      return false;
+  }
+
+  // Ensure that we don't do anything else.
+  return Compound->size() == BasesToInit.size() + FieldsToInit.size() + 1;
+}
+
+/// \brief Returns false if the body has any non-whitespace character.
+static bool bodyEmpty(const ASTContext *Context, const CompoundStmt *Body) {
+  bool Invalid = false;
+  StringRef Text = Lexer::getSourceText(
+      CharSourceRange::getCharRange(Body->getLBracLoc().getLocWithOffset(1),
+                                    Body->getRBracLoc()),
+      Context->getSourceManager(), Context->getLangOpts(), &Invalid);
+  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)
+    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) {
+  std::string SpecialFunctionName;
+
+  // Both CXXConstructorDecl and CXXDestructorDecl inherit from CXXMethodDecl.
+  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() ||
+      SpecialFunctionDecl->isExplicitlyDefaulted() ||
+      SpecialFunctionDecl->isLateTemplateParsed() ||
+      SpecialFunctionDecl->isTemplateInstantiation() ||
+      !SpecialFunctionDecl->isUserProvided() || !SpecialFunctionDecl->hasBody())
+    return;
+
+  const auto *Body = dyn_cast<CompoundStmt>(SpecialFunctionDecl->getBody());
+  if (!Body)
+    return;
+
+  // If there is code inside the body, don't warn.
+  if (!SpecialFunctionDecl->isCopyAssignmentOperator() && !Body->body_empty())
+    return;
+
+  // If there are comments inside the body, don't do the change.
+  bool ApplyFix = SpecialFunctionDecl->isCopyAssignmentOperator() ||
+                  bodyEmpty(Result.Context, Body);
+
+  std::vector<FixItHint> RemoveInitializers;
+
+  if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(SpecialFunctionDecl)) {
+    if (Ctor->getNumParams() == 0) {
+      SpecialFunctionName = "default constructor";
+    } else {
+      if (!isCopyConstructorAndCanBeDefaulted(Result.Context, Ctor))
+        return;
+      SpecialFunctionName = "copy constructor";
+      // If there are constructor initializers, they must be removed.
+      for (const auto *Init : Ctor->inits()) {
+        RemoveInitializers.emplace_back(
+            FixItHint::CreateRemoval(Init->getSourceRange()));
+      }
+    }
+  } else if (isa<CXXDestructorDecl>(SpecialFunctionDecl)) {
+    SpecialFunctionName = "destructor";
+  } else {
+    if (!isCopyAssignmentAndCanBeDefaulted(Result.Context, SpecialFunctionDecl))
+      return;
+    SpecialFunctionName = "copy-assignment operator";
+  }
+
+  // The location of the body is more useful inside a macro as spelling and
+  // expansion locations are reported.
+  SourceLocation Location = SpecialFunctionDecl->getLocation();
+  if (Location.isMacroID())
+    Location = Body->getLocStart();
+
+  auto Diag = diag(Location, "use '= default' to define a trivial " +
+                                 SpecialFunctionName);
+
+  if (ApplyFix)
+    Diag << FixItHint::CreateReplacement(Body->getSourceRange(), "= default;")
+         << RemoveInitializers;
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.h
new file mode 100644
index 0000000..a55c222
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.h
@@ -0,0 +1,53 @@
+//===--- UseEqualsDefaultCheck.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_USE_EQUALS_DEFAULT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_EQUALS_DEFAULT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// \brief Replace default bodies of special member functions with '= default;'.
+/// \code
+///   struct A {
+///     A() {}
+///     ~A();
+///   };
+///   A::~A() {}
+/// \endcode
+/// Is converted to:
+/// \code
+///   struct A {
+///     A() = default;
+///     ~A();
+///   };
+///   A::~A() = default;
+/// \endcode
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-equals-default.html
+class UseEqualsDefaultCheck : public ClangTidyCheck {
+public:
+  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
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_EQUALS_DEFAULT_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEqualsDeleteCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEqualsDeleteCheck.cpp
new file mode 100644
index 0000000..18190b1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEqualsDeleteCheck.cpp
@@ -0,0 +1,78 @@
+//===--- UseEqualsDeleteCheck.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 "UseEqualsDeleteCheck.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 modernize {
+
+static const char SpecialFunction[] = "SpecialFunction";
+static const char DeletedNotPublic[] = "DeletedNotPublic";
+
+void UseEqualsDeleteCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  auto PrivateSpecialFn = cxxMethodDecl(
+      isPrivate(),
+      anyOf(cxxConstructorDecl(anyOf(isDefaultConstructor(),
+                                     isCopyConstructor(), isMoveConstructor())),
+            cxxMethodDecl(
+                anyOf(isCopyAssignmentOperator(), isMoveAssignmentOperator())),
+            cxxDestructorDecl()));
+
+  Finder->addMatcher(
+      cxxMethodDecl(
+          PrivateSpecialFn,
+          unless(anyOf(hasBody(stmt()), isDefaulted(), isDeleted(),
+                       ast_matchers::isTemplateInstantiation(),
+                       // Ensure that all methods except private special member
+                       // functions are defined.
+                       hasParent(cxxRecordDecl(hasMethod(unless(
+                           anyOf(PrivateSpecialFn, hasBody(stmt()), isPure(),
+                                 isDefaulted(), isDeleted()))))))))
+          .bind(SpecialFunction),
+      this);
+
+  Finder->addMatcher(
+      cxxMethodDecl(isDeleted(), unless(isPublic())).bind(DeletedNotPublic),
+      this);
+}
+
+void UseEqualsDeleteCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *Func =
+          Result.Nodes.getNodeAs<CXXMethodDecl>(SpecialFunction)) {
+    SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+        Func->getLocEnd(), 0, *Result.SourceManager, getLangOpts());
+
+    // FIXME: Improve FixItHint to make the method public.
+    diag(Func->getLocation(),
+         "use '= delete' to prohibit calling of a special member function")
+        << FixItHint::CreateInsertion(EndLoc, " = delete");
+  } else if (const auto *Func =
+                 Result.Nodes.getNodeAs<CXXMethodDecl>(DeletedNotPublic)) {
+    // Ignore this warning in macros, since it's extremely noisy in code using
+    // DISALLOW_COPY_AND_ASSIGN-style macros and there's no easy way to
+    // automatically fix the warning when macros are in play.
+    if (Func->getLocation().isMacroID())
+      return;
+    // FIXME: Add FixItHint to make the method public.
+    diag(Func->getLocation(), "deleted member function should be public");
+  }
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEqualsDeleteCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEqualsDeleteCheck.h
new file mode 100644
index 0000000..1daa1a85
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseEqualsDeleteCheck.h
@@ -0,0 +1,50 @@
+//===--- UseEqualsDeleteCheck.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_USE_EQUALS_DELETE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_EQUALS_DELETE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// \brief Mark unimplemented private special member functions with '= delete'.
+/// \code
+///   struct A {
+///   private:
+///     A(const A&);
+///     A& operator=(const A&);
+///   };
+/// \endcode
+/// Is converted to:
+/// \code
+///   struct A {
+///   private:
+///     A(const A&) = delete;
+///     A& operator=(const A&) = delete;
+///   };
+/// \endcode
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-equals-delete.html
+class UseEqualsDeleteCheck : public ClangTidyCheck {
+public:
+  UseEqualsDeleteCheck(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_USE_EQUALS_DELETE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.cpp
new file mode 100644
index 0000000..869381a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.cpp
@@ -0,0 +1,114 @@
+//===--- UseNoexceptCheck.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 "UseNoexceptCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+UseNoexceptCheck::UseNoexceptCheck(StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      NoexceptMacro(Options.get("ReplacementString", "")),
+      UseNoexceptFalse(Options.get("UseNoexceptFalse", true)) {}
+
+void UseNoexceptCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "ReplacementString", NoexceptMacro);
+  Options.store(Opts, "UseNoexceptFalse", UseNoexceptFalse);
+}
+
+void UseNoexceptCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  Finder->addMatcher(
+      functionDecl(
+          cxxMethodDecl(
+              hasTypeLoc(loc(functionProtoType(hasDynamicExceptionSpec()))),
+              anyOf(hasOverloadedOperatorName("delete[]"),
+                    hasOverloadedOperatorName("delete"), cxxDestructorDecl()))
+              .bind("del-dtor"))
+          .bind("funcDecl"),
+      this);
+
+  Finder->addMatcher(
+      functionDecl(
+          hasTypeLoc(loc(functionProtoType(hasDynamicExceptionSpec()))),
+          unless(anyOf(hasOverloadedOperatorName("delete[]"),
+                       hasOverloadedOperatorName("delete"),
+                       cxxDestructorDecl())))
+          .bind("funcDecl"),
+      this);
+
+  Finder->addMatcher(
+      parmVarDecl(anyOf(hasType(pointerType(pointee(parenType(innerType(
+                            functionProtoType(hasDynamicExceptionSpec())))))),
+                        hasType(memberPointerType(pointee(parenType(innerType(
+                            functionProtoType(hasDynamicExceptionSpec()))))))))
+          .bind("parmVarDecl"),
+      this);
+}
+
+void UseNoexceptCheck::check(const MatchFinder::MatchResult &Result) {
+  const FunctionProtoType *FnTy = nullptr;
+  bool DtorOrOperatorDel = false;
+  SourceRange Range;
+
+  if (const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("funcDecl")) {
+    DtorOrOperatorDel = Result.Nodes.getNodeAs<FunctionDecl>("del-dtor");
+    FnTy = FuncDecl->getType()->getAs<FunctionProtoType>();
+    if (const auto *TSI = FuncDecl->getTypeSourceInfo())
+      Range =
+          TSI->getTypeLoc().castAs<FunctionTypeLoc>().getExceptionSpecRange();
+  } else if (const auto *ParmDecl =
+                 Result.Nodes.getNodeAs<ParmVarDecl>("parmVarDecl")) {
+    FnTy = ParmDecl->getType()
+               ->getAs<Type>()
+               ->getPointeeType()
+               ->getAs<FunctionProtoType>();
+
+    if (const auto *TSI = ParmDecl->getTypeSourceInfo())
+      Range = TSI->getTypeLoc()
+                  .getNextTypeLoc()
+                  .IgnoreParens()
+                  .castAs<FunctionProtoTypeLoc>()
+                  .getExceptionSpecRange();
+  }
+  CharSourceRange CRange = Lexer::makeFileCharRange(
+      CharSourceRange::getTokenRange(Range), *Result.SourceManager,
+      Result.Context->getLangOpts());
+
+  assert(FnTy && "FunctionProtoType is null.");
+  bool IsNoThrow = FnTy->isNothrow();
+  StringRef ReplacementStr =
+      IsNoThrow
+          ? NoexceptMacro.empty() ? "noexcept" : NoexceptMacro.c_str()
+          : NoexceptMacro.empty()
+                ? (DtorOrOperatorDel || UseNoexceptFalse) ? "noexcept(false)"
+                                                          : ""
+                : "";
+
+  FixItHint FixIt;
+  if ((IsNoThrow || NoexceptMacro.empty()) && CRange.isValid())
+    FixIt = FixItHint::CreateReplacement(CRange, ReplacementStr);
+
+  diag(Range.getBegin(), "dynamic exception specification '%0' is deprecated; "
+                         "consider %select{using '%2'|removing it}1 instead")
+      << Lexer::getSourceText(CRange, *Result.SourceManager,
+                              Result.Context->getLangOpts())
+      << ReplacementStr.empty() << ReplacementStr << FixIt;
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.h
new file mode 100644
index 0000000..a15867b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.h
@@ -0,0 +1,49 @@
+//===--- UseNoexceptCheck.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_USE_NOEXCEPT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_NOEXCEPT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// \brief Replace dynamic exception specifications, with
+/// `noexcept` (or user-defined macro) or `noexcept(false)`.
+/// \code
+///   void foo() throw();
+///   void bar() throw(int);
+/// \endcode
+/// Is converted to:
+/// \code
+///   void foo() ;
+///   void bar() noexcept(false);
+/// \endcode
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-noexcept.html
+class UseNoexceptCheck : public ClangTidyCheck {
+public:
+  UseNoexceptCheck(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 std::string NoexceptMacro;
+  bool UseNoexceptFalse;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_NOEXCEPT_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
new file mode 100644
index 0000000..476c549
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -0,0 +1,500 @@
+//===--- UseNullptrCheck.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 "UseNullptrCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang;
+using namespace clang::ast_matchers;
+using namespace llvm;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+namespace {
+
+const char CastSequence[] = "sequence";
+
+AST_MATCHER(Type, sugaredNullptrType) {
+  const Type *DesugaredType = Node.getUnqualifiedDesugaredType();
+  if (const auto *BT = dyn_cast<BuiltinType>(DesugaredType))
+    return BT->getKind() == BuiltinType::NullPtr;
+  return false;
+}
+
+/// \brief Create a matcher that finds implicit casts as well as the head of a
+/// sequence of zero or more nested explicit casts that have an implicit cast
+/// to null within.
+/// Finding sequences of explict casts is necessary so that an entire sequence
+/// can be replaced instead of just the inner-most implicit cast.
+StatementMatcher makeCastSequenceMatcher() {
+  StatementMatcher ImplicitCastToNull = implicitCastExpr(
+      anyOf(hasCastKind(CK_NullToPointer), hasCastKind(CK_NullToMemberPointer)),
+      unless(hasImplicitDestinationType(qualType(substTemplateTypeParmType()))),
+      unless(hasSourceExpression(hasType(sugaredNullptrType()))));
+
+  return castExpr(anyOf(ImplicitCastToNull,
+                        explicitCastExpr(hasDescendant(ImplicitCastToNull))),
+                  unless(hasAncestor(explicitCastExpr())))
+      .bind(CastSequence);
+}
+
+bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc,
+                        const SourceManager &SM) {
+  return SM.isWrittenInSameFile(StartLoc, EndLoc);
+}
+
+/// \brief Replaces the provided range with the text "nullptr", but only if
+/// the start and end location are both in main file.
+/// Returns true if and only if a replacement was made.
+void replaceWithNullptr(ClangTidyCheck &Check, SourceManager &SM,
+                        SourceLocation StartLoc, SourceLocation EndLoc) {
+  CharSourceRange Range(SourceRange(StartLoc, EndLoc), true);
+  // Add a space if nullptr follows an alphanumeric character. This happens
+  // whenever there is an c-style explicit cast to nullptr not surrounded by
+  // parentheses and right beside a return statement.
+  SourceLocation PreviousLocation = StartLoc.getLocWithOffset(-1);
+  bool NeedsSpace = isAlphanumeric(*SM.getCharacterData(PreviousLocation));
+  Check.diag(Range.getBegin(), "use nullptr") << FixItHint::CreateReplacement(
+      Range, NeedsSpace ? " nullptr" : "nullptr");
+}
+
+/// \brief Returns the name of the outermost macro.
+///
+/// Given
+/// \code
+/// #define MY_NULL NULL
+/// \endcode
+/// If \p Loc points to NULL, this function will return the name MY_NULL.
+StringRef getOutermostMacroName(SourceLocation Loc, const SourceManager &SM,
+                                const LangOptions &LO) {
+  assert(Loc.isMacroID());
+  SourceLocation OutermostMacroLoc;
+
+  while (Loc.isMacroID()) {
+    OutermostMacroLoc = Loc;
+    Loc = SM.getImmediateMacroCallerLoc(Loc);
+  }
+
+  return Lexer::getImmediateMacroName(OutermostMacroLoc, SM, LO);
+}
+
+/// \brief RecursiveASTVisitor for ensuring all nodes rooted at a given AST
+/// subtree that have file-level source locations corresponding to a macro
+/// argument have implicit NullTo(Member)Pointer nodes as ancestors.
+class MacroArgUsageVisitor : public RecursiveASTVisitor<MacroArgUsageVisitor> {
+public:
+  MacroArgUsageVisitor(SourceLocation CastLoc, const SourceManager &SM)
+      : CastLoc(CastLoc), SM(SM), Visited(false), CastFound(false),
+        InvalidFound(false) {
+    assert(CastLoc.isFileID());
+  }
+
+  bool TraverseStmt(Stmt *S) {
+    bool VisitedPreviously = Visited;
+
+    if (!RecursiveASTVisitor<MacroArgUsageVisitor>::TraverseStmt(S))
+      return false;
+
+    // The point at which VisitedPreviously is false and Visited is true is the
+    // root of a subtree containing nodes whose locations match CastLoc. It's
+    // at this point we test that the Implicit NullTo(Member)Pointer cast was
+    // found or not.
+    if (!VisitedPreviously) {
+      if (Visited && !CastFound) {
+        // Found nodes with matching SourceLocations but didn't come across a
+        // cast. This is an invalid macro arg use. Can stop traversal
+        // completely now.
+        InvalidFound = true;
+        return false;
+      }
+      // Reset state as we unwind back up the tree.
+      CastFound = false;
+      Visited = false;
+    }
+    return true;
+  }
+
+  bool VisitStmt(Stmt *S) {
+    if (SM.getFileLoc(S->getLocStart()) != CastLoc)
+      return true;
+    Visited = true;
+
+    const ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(S);
+    if (Cast && (Cast->getCastKind() == CK_NullToPointer ||
+                 Cast->getCastKind() == CK_NullToMemberPointer))
+      CastFound = true;
+
+    return true;
+  }
+
+  bool TraverseInitListExpr(InitListExpr *S) {
+    // Only go through the semantic form of the InitListExpr, because
+    // ImplicitCast might not appear in the syntactic form, and this results in
+    // finding usages of the macro argument that don't have a ImplicitCast as an
+    // ancestor (thus invalidating the replacement) when they actually have.
+    return RecursiveASTVisitor<MacroArgUsageVisitor>::
+        TraverseSynOrSemInitListExpr(
+            S->isSemanticForm() ? S : S->getSemanticForm());
+  }
+
+  bool foundInvalid() const { return InvalidFound; }
+
+private:
+  SourceLocation CastLoc;
+  const SourceManager &SM;
+
+  bool Visited;
+  bool CastFound;
+  bool InvalidFound;
+};
+
+/// \brief Looks for implicit casts as well as sequences of 0 or more explicit
+/// casts with an implicit null-to-pointer cast within.
+///
+/// The matcher this visitor is used with will find a single implicit cast or a
+/// top-most explicit cast (i.e. it has no explicit casts as an ancestor) where
+/// an implicit cast is nested within. However, there is no guarantee that only
+/// explicit casts exist between the found top-most explicit cast and the
+/// possibly more than one nested implicit cast. This visitor finds all cast
+/// sequences with an implicit cast to null within and creates a replacement
+/// leaving the outermost explicit cast unchanged to avoid introducing
+/// ambiguities.
+class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> {
+public:
+  CastSequenceVisitor(ASTContext &Context, ArrayRef<StringRef> NullMacros,
+                      ClangTidyCheck &check)
+      : SM(Context.getSourceManager()), Context(Context),
+        NullMacros(NullMacros), Check(check), FirstSubExpr(nullptr),
+        PruneSubtree(false) {}
+
+  bool TraverseStmt(Stmt *S) {
+    // Stop traversing down the tree if requested.
+    if (PruneSubtree) {
+      PruneSubtree = false;
+      return true;
+    }
+    return RecursiveASTVisitor<CastSequenceVisitor>::TraverseStmt(S);
+  }
+
+  // Only VisitStmt is overridden as we shouldn't find other base AST types
+  // within a cast expression.
+  bool VisitStmt(Stmt *S) {
+    auto *C = dyn_cast<CastExpr>(S);
+    // Catch the castExpr inside cxxDefaultArgExpr.
+    if (auto *E = dyn_cast<CXXDefaultArgExpr>(S)) {
+      C = dyn_cast<CastExpr>(E->getExpr());
+      FirstSubExpr = nullptr;
+    }
+    if (!C) {
+      FirstSubExpr = nullptr;
+      return true;
+    }
+
+    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) {
+      return true;
+    }
+
+    SourceLocation StartLoc = FirstSubExpr->getLocStart();
+    SourceLocation EndLoc = FirstSubExpr->getLocEnd();
+
+    // If the location comes from a macro arg expansion, *all* uses of that
+    // arg must be checked to result in NullTo(Member)Pointer casts.
+    //
+    // If the location comes from a macro body expansion, check to see if its
+    // coming from one of the allowed 'NULL' macros.
+    if (SM.isMacroArgExpansion(StartLoc) && SM.isMacroArgExpansion(EndLoc)) {
+      SourceLocation FileLocStart = SM.getFileLoc(StartLoc),
+                     FileLocEnd = SM.getFileLoc(EndLoc);
+      SourceLocation ImmediateMacroArgLoc, MacroLoc;
+      // Skip NULL macros used in macro.
+      if (!getMacroAndArgLocations(StartLoc, ImmediateMacroArgLoc, MacroLoc) ||
+          ImmediateMacroArgLoc != FileLocStart)
+        return skipSubTree();
+
+      if (isReplaceableRange(FileLocStart, FileLocEnd, SM) &&
+          allArgUsesValid(C)) {
+        replaceWithNullptr(Check, SM, FileLocStart, FileLocEnd);
+      }
+      return true;
+    }
+
+    if (SM.isMacroBodyExpansion(StartLoc) && SM.isMacroBodyExpansion(EndLoc)) {
+      StringRef OutermostMacroName =
+          getOutermostMacroName(StartLoc, SM, Context.getLangOpts());
+
+      // Check to see if the user wants to replace the macro being expanded.
+      if (std::find(NullMacros.begin(), NullMacros.end(), OutermostMacroName) ==
+          NullMacros.end()) {
+        return skipSubTree();
+      }
+
+      StartLoc = SM.getFileLoc(StartLoc);
+      EndLoc = SM.getFileLoc(EndLoc);
+    }
+
+    if (!isReplaceableRange(StartLoc, EndLoc, SM)) {
+      return skipSubTree();
+    }
+    replaceWithNullptr(Check, SM, StartLoc, EndLoc);
+
+    return true;
+  }
+
+private:
+  bool skipSubTree() {
+    PruneSubtree = true;
+    return true;
+  }
+
+  /// \brief Tests that all expansions of a macro arg, one of which expands to
+  /// result in \p CE, yield NullTo(Member)Pointer casts.
+  bool allArgUsesValid(const CastExpr *CE) {
+    SourceLocation CastLoc = CE->getLocStart();
+
+    // Step 1: Get location of macro arg and location of the macro the arg was
+    // provided to.
+    SourceLocation ArgLoc, MacroLoc;
+    if (!getMacroAndArgLocations(CastLoc, ArgLoc, MacroLoc))
+      return false;
+
+    // Step 2: Find the first ancestor that doesn't expand from this macro.
+    ast_type_traits::DynTypedNode ContainingAncestor;
+    if (!findContainingAncestor(
+            ast_type_traits::DynTypedNode::create<Stmt>(*CE), MacroLoc,
+            ContainingAncestor))
+      return false;
+
+    // Step 3:
+    // Visit children of this containing parent looking for the least-descended
+    // nodes of the containing parent which are macro arg expansions that expand
+    // from the given arg location.
+    // Visitor needs: arg loc.
+    MacroArgUsageVisitor ArgUsageVisitor(SM.getFileLoc(CastLoc), SM);
+    if (const auto *D = ContainingAncestor.get<Decl>())
+      ArgUsageVisitor.TraverseDecl(const_cast<Decl *>(D));
+    else if (const auto *S = ContainingAncestor.get<Stmt>())
+      ArgUsageVisitor.TraverseStmt(const_cast<Stmt *>(S));
+    else
+      llvm_unreachable("Unhandled ContainingAncestor node type");
+
+    return !ArgUsageVisitor.foundInvalid();
+  }
+
+  /// \brief Given the SourceLocation for a macro arg expansion, finds the
+  /// non-macro SourceLocation of the macro the arg was passed to and the
+  /// non-macro SourceLocation of the argument in the arg list to that macro.
+  /// These results are returned via \c MacroLoc and \c ArgLoc respectively.
+  /// These values are undefined if the return value is false.
+  ///
+  /// \returns false if one of the returned SourceLocations would be a
+  /// SourceLocation pointing within the definition of another macro.
+  bool getMacroAndArgLocations(SourceLocation Loc, SourceLocation &ArgLoc,
+                               SourceLocation &MacroLoc) {
+    assert(Loc.isMacroID() && "Only reasonble to call this on macros");
+
+    ArgLoc = Loc;
+
+    // Find the location of the immediate macro expansion.
+    while (true) {
+      std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(ArgLoc);
+      const SrcMgr::SLocEntry *E = &SM.getSLocEntry(LocInfo.first);
+      const SrcMgr::ExpansionInfo &Expansion = E->getExpansion();
+
+      SourceLocation OldArgLoc = ArgLoc;
+      ArgLoc = Expansion.getExpansionLocStart();
+      if (!Expansion.isMacroArgExpansion()) {
+        if (!MacroLoc.isFileID())
+          return false;
+
+        StringRef Name =
+            Lexer::getImmediateMacroName(OldArgLoc, SM, Context.getLangOpts());
+        return std::find(NullMacros.begin(), NullMacros.end(), Name) !=
+               NullMacros.end();
+      }
+
+      MacroLoc = SM.getExpansionRange(ArgLoc).getBegin();
+
+      ArgLoc = Expansion.getSpellingLoc().getLocWithOffset(LocInfo.second);
+      if (ArgLoc.isFileID())
+        return true;
+
+      // If spelling location resides in the same FileID as macro expansion
+      // location, it means there is no inner macro.
+      FileID MacroFID = SM.getFileID(MacroLoc);
+      if (SM.isInFileID(ArgLoc, MacroFID)) {
+        // Don't transform this case. If the characters that caused the
+        // null-conversion come from within a macro, they can't be changed.
+        return false;
+      }
+    }
+
+    llvm_unreachable("getMacroAndArgLocations");
+  }
+
+  /// \brief Tests if TestMacroLoc is found while recursively unravelling
+  /// expansions starting at TestLoc. TestMacroLoc.isFileID() must be true.
+  /// Implementation is very similar to getMacroAndArgLocations() except in this
+  /// case, it's not assumed that TestLoc is expanded from a macro argument.
+  /// While unravelling expansions macro arguments are handled as with
+  /// getMacroAndArgLocations() but in this function macro body expansions are
+  /// also handled.
+  ///
+  /// False means either:
+  /// - TestLoc is not from a macro expansion.
+  /// - TestLoc is from a different macro expansion.
+  bool expandsFrom(SourceLocation TestLoc, SourceLocation TestMacroLoc) {
+    if (TestLoc.isFileID()) {
+      return false;
+    }
+
+    SourceLocation Loc = TestLoc, MacroLoc;
+
+    while (true) {
+      std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+      const SrcMgr::SLocEntry *E = &SM.getSLocEntry(LocInfo.first);
+      const SrcMgr::ExpansionInfo &Expansion = E->getExpansion();
+
+      Loc = Expansion.getExpansionLocStart();
+
+      if (!Expansion.isMacroArgExpansion()) {
+        if (Loc.isFileID()) {
+          return Loc == TestMacroLoc;
+        }
+        // Since Loc is still a macro ID and it's not an argument expansion, we
+        // don't need to do the work of handling an argument expansion. Simply
+        // keep recursively expanding until we hit a FileID or a macro arg
+        // expansion or a macro arg expansion.
+        continue;
+      }
+
+      MacroLoc = SM.getImmediateExpansionRange(Loc).getBegin();
+      if (MacroLoc.isFileID() && MacroLoc == TestMacroLoc) {
+        // Match made.
+        return true;
+      }
+
+      Loc = Expansion.getSpellingLoc().getLocWithOffset(LocInfo.second);
+      if (Loc.isFileID()) {
+        // If we made it this far without finding a match, there is no match to
+        // be made.
+        return false;
+      }
+    }
+
+    llvm_unreachable("expandsFrom");
+  }
+
+  /// \brief Given a starting point \c Start in the AST, find an ancestor that
+  /// doesn't expand from the macro called at file location \c MacroLoc.
+  ///
+  /// \pre MacroLoc.isFileID()
+  /// \returns true if such an ancestor was found, false otherwise.
+  bool findContainingAncestor(ast_type_traits::DynTypedNode Start,
+                              SourceLocation MacroLoc,
+                              ast_type_traits::DynTypedNode &Result) {
+    // Below we're only following the first parent back up the AST. This should
+    // be fine since for the statements we care about there should only be one
+    // parent, except for the case specified below.
+
+    assert(MacroLoc.isFileID());
+
+    while (true) {
+      const auto &Parents = Context.getParents(Start);
+      if (Parents.empty())
+        return false;
+      if (Parents.size() > 1) {
+        // If there are more than one parents, don't do the replacement unless
+        // they are InitListsExpr (semantic and syntactic form). In this case we
+        // can choose any one here, and the ASTVisitor will take care of
+        // traversing the right one.
+        for (const auto &Parent : Parents) {
+          if (!Parent.get<InitListExpr>())
+            return false;
+        }
+      }
+
+      const ast_type_traits::DynTypedNode &Parent = Parents[0];
+
+      SourceLocation Loc;
+      if (const auto *D = Parent.get<Decl>())
+        Loc = D->getLocStart();
+      else if (const auto *S = Parent.get<Stmt>())
+        Loc = S->getLocStart();
+
+      // TypeLoc and NestedNameSpecifierLoc are members of the parent map. Skip
+      // them and keep going up.
+      if (Loc.isValid()) {
+        if (!expandsFrom(Loc, MacroLoc)) {
+          Result = Parent;
+          return true;
+        }
+      }
+      Start = Parent;
+    }
+
+    llvm_unreachable("findContainingAncestor");
+  }
+
+private:
+  SourceManager &SM;
+  ASTContext &Context;
+  ArrayRef<StringRef> NullMacros;
+  ClangTidyCheck &Check;
+  Expr *FirstSubExpr;
+  bool PruneSubtree;
+};
+
+} // namespace
+
+UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      NullMacrosStr(Options.get("NullMacros", "")) {
+  StringRef(NullMacrosStr).split(NullMacros, ",");
+}
+
+void UseNullptrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "NullMacros", NullMacrosStr);
+}
+
+void UseNullptrCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matcher for C++. Because this checker is used for
+  // modernization, it is reasonable to run it on any C++ standard with the
+  // assumption the user is trying to modernize their codebase.
+  if (getLangOpts().CPlusPlus)
+    Finder->addMatcher(makeCastSequenceMatcher(), this);
+}
+
+void UseNullptrCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *NullCast = Result.Nodes.getNodeAs<CastExpr>(CastSequence);
+  assert(NullCast && "Bad Callback. No node provided");
+
+  // Given an implicit null-ptr cast or an explicit cast with an implicit
+  // null-to-pointer cast within use CastSequenceVisitor to identify sequences
+  // of explicit casts that can be converted into 'nullptr'.
+  CastSequenceVisitor(*Result.Context, NullMacros, *this)
+      .TraverseStmt(const_cast<CastExpr *>(NullCast));
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h
new file mode 100644
index 0000000..4b33f1e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h
@@ -0,0 +1,35 @@
+//===--- UseNullptrCheck.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_USE_NULLPTR_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_NULLPTR_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+class UseNullptrCheck : public ClangTidyCheck {
+public:
+  UseNullptrCheck(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 std::string NullMacrosStr;
+  SmallVector<StringRef, 1> NullMacros;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_NULLPTR_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp
new file mode 100644
index 0000000..9429eb2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp
@@ -0,0 +1,207 @@
+//===--- UseOverrideCheck.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 "UseOverrideCheck.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 modernize {
+
+void UseOverrideCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matcher for C++11.
+  if (getLangOpts().CPlusPlus11)
+    Finder->addMatcher(cxxMethodDecl(isOverride()).bind("method"), this);
+}
+
+// Re-lex the tokens to get precise locations to insert 'override' and remove
+// 'virtual'.
+static SmallVector<Token, 16>
+ParseTokens(CharSourceRange Range, const MatchFinder::MatchResult &Result) {
+  const SourceManager &Sources = *Result.SourceManager;
+  std::pair<FileID, unsigned> LocInfo =
+      Sources.getDecomposedLoc(Range.getBegin());
+  StringRef File = Sources.getBufferData(LocInfo.first);
+  const char *TokenBegin = File.data() + LocInfo.second;
+  Lexer RawLexer(Sources.getLocForStartOfFile(LocInfo.first),
+                 Result.Context->getLangOpts(), File.begin(), TokenBegin,
+                 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)) && 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()));
+      Tok.setIdentifierInfo(&Info);
+      Tok.setKind(Info.getTokenID());
+    }
+    Tokens.push_back(Tok);
+  }
+  return Tokens;
+}
+
+static StringRef GetText(const Token &Tok, const SourceManager &Sources) {
+  return StringRef(Sources.getCharacterData(Tok.getLocation()),
+                   Tok.getLength());
+}
+
+void UseOverrideCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Method = Result.Nodes.getNodeAs<FunctionDecl>("method");
+  const SourceManager &Sources = *Result.SourceManager;
+
+  assert(Method != nullptr);
+  if (Method->getInstantiatedFromMemberFunction() != nullptr)
+    Method = Method->getInstantiatedFromMemberFunction();
+
+  if (Method->isImplicit() || Method->getLocation().isMacroID() ||
+      Method->isOutOfLine())
+    return;
+
+  bool HasVirtual = Method->isVirtualAsWritten();
+  bool HasOverride = Method->getAttr<OverrideAttr>();
+  bool HasFinal = Method->getAttr<FinalAttr>();
+
+  bool OnlyVirtualSpecified = HasVirtual && !HasOverride && !HasFinal;
+  unsigned KeywordCount = HasVirtual + HasOverride + HasFinal;
+
+  if (!OnlyVirtualSpecified && KeywordCount == 1)
+    return; // Nothing to do.
+
+  std::string Message;
+
+  if (OnlyVirtualSpecified) {
+    Message =
+        "prefer using 'override' or (rarely) 'final' instead of 'virtual'";
+  } else if (KeywordCount == 0) {
+    Message = "annotate this function with 'override' or (rarely) 'final'";
+  } else {
+    StringRef Redundant =
+        HasVirtual ? (HasOverride && HasFinal ? "'virtual' and 'override' are"
+                                              : "'virtual' is")
+                   : "'override' is";
+    StringRef Correct = HasFinal ? "'final'" : "'override'";
+
+    Message = (llvm::Twine(Redundant) +
+               " redundant since the function is already declared " + Correct)
+                  .str();
+  }
+
+  DiagnosticBuilder Diag = diag(Method->getLocation(), Message);
+
+  CharSourceRange FileRange = Lexer::makeFileCharRange(
+      CharSourceRange::getTokenRange(Method->getSourceRange()), Sources,
+      getLangOpts());
+
+  if (!FileRange.isValid())
+    return;
+
+  // FIXME: Instead of re-lexing and looking for specific macros such as
+  // 'ABSTRACT', properly store the location of 'virtual' and '= 0' in each
+  // FunctionDecl.
+  SmallVector<Token, 16> Tokens = ParseTokens(FileRange, Result);
+
+  // Add 'override' on inline declarations that don't already have it.
+  if (!HasFinal && !HasOverride) {
+    SourceLocation InsertLoc;
+    StringRef ReplacementText = "override ";
+    SourceLocation MethodLoc = Method->getLocation();
+
+    for (Token T : Tokens) {
+      if (T.is(tok::kw___attribute) &&
+          !Sources.isBeforeInTranslationUnit(T.getLocation(), MethodLoc)) {
+        InsertLoc = T.getLocation();
+        break;
+      }
+    }
+
+    if (Method->hasAttrs()) {
+      for (const clang::Attr *A : Method->getAttrs()) {
+        if (!A->isImplicit() && !A->isInherited()) {
+          SourceLocation Loc =
+              Sources.getExpansionLoc(A->getRange().getBegin());
+          if ((!InsertLoc.isValid() ||
+               Sources.isBeforeInTranslationUnit(Loc, InsertLoc)) &&
+              !Sources.isBeforeInTranslationUnit(Loc, MethodLoc))
+            InsertLoc = Loc;
+        }
+      }
+    }
+
+    if (InsertLoc.isInvalid() && Method->doesThisDeclarationHaveABody() &&
+        Method->getBody() && !Method->isDefaulted()) {
+      // For methods with inline definition, add the override keyword at the
+      // end of the declaration of the function, but prefer to put it on the
+      // same line as the declaration if the beginning brace for the start of
+      // the body falls on the next line.
+      ReplacementText = " override";
+      auto LastTokenIter = std::prev(Tokens.end());
+      // When try statement is used instead of compound statement as
+      // method body - insert override keyword before it.
+      if (LastTokenIter->is(tok::kw_try))
+        LastTokenIter = std::prev(LastTokenIter);
+      InsertLoc = LastTokenIter->getEndLoc();
+    }
+
+    if (!InsertLoc.isValid()) {
+      // For declarations marked with "= 0" or "= [default|delete]", the end
+      // location will point until after those markings. Therefore, the override
+      // keyword shouldn't be inserted at the end, but before the '='.
+      if (Tokens.size() > 2 && (GetText(Tokens.back(), Sources) == "0" ||
+                                Tokens.back().is(tok::kw_default) ||
+                                Tokens.back().is(tok::kw_delete)) &&
+          GetText(Tokens[Tokens.size() - 2], Sources) == "=") {
+        InsertLoc = Tokens[Tokens.size() - 2].getLocation();
+        // Check if we need to insert a space.
+        if ((Tokens[Tokens.size() - 2].getFlags() & Token::LeadingSpace) == 0)
+          ReplacementText = " override ";
+      } else if (GetText(Tokens.back(), Sources) == "ABSTRACT") {
+        InsertLoc = Tokens.back().getLocation();
+      }
+    }
+
+    if (!InsertLoc.isValid()) {
+      InsertLoc = FileRange.getEnd();
+      ReplacementText = " override";
+    }
+    Diag << FixItHint::CreateInsertion(InsertLoc, ReplacementText);
+  }
+
+  if (HasFinal && HasOverride) {
+    SourceLocation OverrideLoc = Method->getAttr<OverrideAttr>()->getLocation();
+    Diag << FixItHint::CreateRemoval(
+        CharSourceRange::getTokenRange(OverrideLoc, OverrideLoc));
+  }
+
+  if (HasVirtual) {
+    for (Token Tok : Tokens) {
+      if (Tok.is(tok::kw_virtual)) {
+        Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
+            Tok.getLocation(), Tok.getLocation()));
+        break;
+      }
+    }
+  }
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.h
new file mode 100644
index 0000000..83ce7da
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.h
@@ -0,0 +1,32 @@
+//===--- UseOverrideCheck.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_USEOVERRIDECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USEOVERRIDECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Use C++11's `override` and remove `virtual` where applicable.
+class UseOverrideCheck : public ClangTidyCheck {
+public:
+  UseOverrideCheck(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_USEOVERRIDECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp
new file mode 100644
index 0000000..7f59200
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp
@@ -0,0 +1,131 @@
+//===--- UseTransparentFunctorsCheck.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 "UseTransparentFunctorsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+UseTransparentFunctorsCheck::UseTransparentFunctorsCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context), SafeMode(Options.get("SafeMode", 0)) {}
+
+void UseTransparentFunctorsCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "SafeMode", SafeMode ? 1 : 0);
+}
+
+void UseTransparentFunctorsCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus14)
+    return;
+
+  const auto TransparentFunctors =
+      classTemplateSpecializationDecl(
+          unless(hasAnyTemplateArgument(refersToType(voidType()))),
+          hasAnyName("::std::plus", "::std::minus", "::std::multiplies",
+                     "::std::divides", "::std::modulus", "::std::negate",
+                     "::std::equal_to", "::std::not_equal_to", "::std::greater",
+                     "::std::less", "::std::greater_equal", "::std::less_equal",
+                     "::std::logical_and", "::std::logical_or",
+                     "::std::logical_not", "::std::bit_and", "::std::bit_or",
+                     "::std::bit_xor", "::std::bit_not"))
+          .bind("FunctorClass");
+
+  // Non-transparent functor mentioned as a template parameter. FIXIT.
+  Finder->addMatcher(
+      loc(qualType(
+              unless(elaboratedType()),
+              hasDeclaration(classTemplateSpecializationDecl(
+                  unless(hasAnyTemplateArgument(templateArgument(refersToType(
+                      qualType(pointsTo(qualType(isAnyCharacter()))))))),
+                  hasAnyTemplateArgument(
+                      templateArgument(refersToType(qualType(hasDeclaration(
+                                           TransparentFunctors))))
+                          .bind("Functor"))))))
+          .bind("FunctorParentLoc"),
+      this);
+
+  if (SafeMode)
+    return;
+
+  // Non-transparent functor constructed. No FIXIT. There is no easy way
+  // to rule out the problematic char* vs string case.
+  Finder->addMatcher(cxxConstructExpr(hasDeclaration(cxxMethodDecl(
+                                          ofClass(TransparentFunctors))),
+                                      unless(isInTemplateInstantiation()))
+                         .bind("FuncInst"),
+                     this);
+}
+
+static const StringRef Message = "prefer transparent functors '%0'";
+
+template <typename T> static T getInnerTypeLocAs(TypeLoc Loc) {
+  T Result;
+  while (Result.isNull() && !Loc.isNull()) {
+    Result = Loc.getAs<T>();
+    Loc = Loc.getNextTypeLoc();
+  }
+  return Result;
+}
+
+void UseTransparentFunctorsCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *FuncClass =
+      Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("FunctorClass");
+  if (const auto *FuncInst =
+          Result.Nodes.getNodeAs<CXXConstructExpr>("FuncInst")) {
+    diag(FuncInst->getLocStart(), Message)
+          << (FuncClass->getName() + "<>").str();
+    return;
+  }
+
+  const auto *Functor = Result.Nodes.getNodeAs<TemplateArgument>("Functor");
+  const auto FunctorParentLoc =
+      Result.Nodes.getNodeAs<TypeLoc>("FunctorParentLoc")
+          ->getAs<TemplateSpecializationTypeLoc>();
+
+  if (!FunctorParentLoc)
+    return;
+
+  unsigned ArgNum = 0;
+  const auto *FunctorParentType =
+      FunctorParentLoc.getType()->castAs<TemplateSpecializationType>();
+  for (; ArgNum < FunctorParentType->getNumArgs(); ++ArgNum) {
+    const TemplateArgument &Arg = FunctorParentType->getArg(ArgNum);
+    if (Arg.getKind() != TemplateArgument::Type)
+      continue;
+    QualType ParentArgType = Arg.getAsType();
+    if (ParentArgType->isRecordType() &&
+        ParentArgType->getAsCXXRecordDecl() ==
+            Functor->getAsType()->getAsCXXRecordDecl())
+      break;
+  }
+  // Functor is a default template argument.
+  if (ArgNum == FunctorParentType->getNumArgs())
+    return;
+  TemplateArgumentLoc FunctorLoc = FunctorParentLoc.getArgLoc(ArgNum);
+  auto FunctorTypeLoc = getInnerTypeLocAs<TemplateSpecializationTypeLoc>(
+      FunctorLoc.getTypeSourceInfo()->getTypeLoc());
+  if (FunctorTypeLoc.isNull())
+    return;
+
+  SourceLocation ReportLoc = FunctorLoc.getLocation();
+  diag(ReportLoc, Message) << (FuncClass->getName() + "<>").str()
+                           << FixItHint::CreateRemoval(
+                                  FunctorTypeLoc.getArgLoc(0).getSourceRange());
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.h
new file mode 100644
index 0000000..4bdce76
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.h
@@ -0,0 +1,37 @@
+//===--- UseTransparentFunctorsCheck.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_USE_TRANSPARENT_FUNCTORS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_TRANSPARENT_FUNCTORS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Prefer using transparent functors to non-transparent ones.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-transparent-functors.html
+class UseTransparentFunctorsCheck : public ClangTidyCheck {
+public:
+  UseTransparentFunctorsCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+private:
+  const bool SafeMode;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_TRANSPARENT_FUNCTORS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
new file mode 100644
index 0000000..9ac6e1d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
@@ -0,0 +1,104 @@
+//===--- UseUncaughtExceptionsCheck.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 "UseUncaughtExceptionsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+void UseUncaughtExceptionsCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus17)
+    return;
+
+  std::string MatchText = "::std::uncaught_exception";
+
+  // Using declaration: warning and fix-it.
+  Finder->addMatcher(
+      usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(hasName(MatchText))))
+          .bind("using_decl"),
+      this);
+
+  // DeclRefExpr: warning, no fix-it.
+  Finder->addMatcher(declRefExpr(allOf(to(functionDecl(hasName(MatchText))),
+                                       unless(callExpr())))
+                         .bind("decl_ref_expr"),
+                     this);
+
+  // CallExpr: warning, fix-it.
+  Finder->addMatcher(
+      callExpr(allOf(hasDeclaration(functionDecl(hasName(MatchText))),
+                     unless(hasAncestor(initListExpr()))))
+          .bind("call_expr"),
+      this);
+  // CallExpr in initialisation list: warning, fix-it with avoiding narrowing
+  // conversions.
+  Finder->addMatcher(
+      callExpr(allOf(hasAncestor(initListExpr()),
+                     hasDeclaration(functionDecl(hasName(MatchText)))))
+          .bind("init_call_expr"),
+      this);
+}
+
+void UseUncaughtExceptionsCheck::check(const MatchFinder::MatchResult &Result) {
+  SourceLocation BeginLoc;
+  SourceLocation EndLoc;
+  const CallExpr *C = Result.Nodes.getNodeAs<CallExpr>("init_call_expr");
+  bool WarnOnly = false;
+
+  if (C) {
+    BeginLoc = C->getLocStart();
+    EndLoc = C->getLocEnd();
+  } else if (const auto *E = Result.Nodes.getNodeAs<CallExpr>("call_expr")) {
+    BeginLoc = E->getLocStart();
+    EndLoc = E->getLocEnd();
+  } else if (const auto *D =
+                 Result.Nodes.getNodeAs<DeclRefExpr>("decl_ref_expr")) {
+    BeginLoc = D->getLocStart();
+    EndLoc = D->getLocEnd();
+    WarnOnly = true;
+  } else {
+    const auto *U = Result.Nodes.getNodeAs<UsingDecl>("using_decl");
+    assert(U && "Null pointer, no node provided");
+    BeginLoc = U->getNameInfo().getBeginLoc();
+    EndLoc = U->getNameInfo().getEndLoc();
+  }
+
+  auto Diag = diag(BeginLoc, "'std::uncaught_exception' is deprecated, use "
+                             "'std::uncaught_exceptions' instead");
+
+  if (!BeginLoc.isMacroID()) {
+    StringRef Text =
+        Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
+                             *Result.SourceManager, getLangOpts());
+
+    Text.consume_back("()");
+    int TextLength = Text.size();
+
+    if (WarnOnly) {
+      return;
+    }
+
+    if (!C) {
+      Diag << FixItHint::CreateInsertion(BeginLoc.getLocWithOffset(TextLength),
+                                         "s");
+    } else {
+      Diag << FixItHint::CreateReplacement(C->getSourceRange(),
+                                           "std::uncaught_exceptions() > 0");
+    }
+  }
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseUncaughtExceptionsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseUncaughtExceptionsCheck.h
new file mode 100644
index 0000000..2b9660c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseUncaughtExceptionsCheck.h
@@ -0,0 +1,37 @@
+//===--- UseUncaughtExceptionsCheck.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_USE_UNCAUGHT_EXCEPTIONS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_UNCAUGHT_EXCEPTIONS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// This check will warn on calls to std::uncaught_exception and replace them with calls to
+/// std::uncaught_exceptions, since std::uncaught_exception was deprecated in C++17. In case of
+/// macro ID there will be only a warning without fixits.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-uncaught-exceptions.html
+class UseUncaughtExceptionsCheck : public ClangTidyCheck {
+public:
+  UseUncaughtExceptionsCheck(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_USE_UNCAUGHT_EXCEPTIONS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
new file mode 100644
index 0000000..cc6d77d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
@@ -0,0 +1,113 @@
+//===--- UseUsingCheck.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 "UseUsingCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+UseUsingCheck::UseUsingCheck(StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {}
+
+void UseUsingCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus11)
+    return;
+  Finder->addMatcher(typedefDecl().bind("typedef"), this);
+}
+
+// Checks if 'typedef' keyword can be removed - we do it only if
+// it is the only declaration in a declaration chain.
+static bool CheckRemoval(SourceManager &SM, SourceLocation StartLoc,
+                         ASTContext &Context) {
+  assert(StartLoc.isFileID() && "StartLoc must not be in a macro");
+  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(StartLoc);
+  StringRef File = SM.getBufferData(LocInfo.first);
+  const char *TokenBegin = File.data() + LocInfo.second;
+  Lexer DeclLexer(SM.getLocForStartOfFile(LocInfo.first), Context.getLangOpts(),
+                  File.begin(), TokenBegin, File.end());
+
+  Token Tok;
+  int ParenLevel = 0;
+  bool FoundTypedef = false;
+
+  while (!DeclLexer.LexFromRawLexer(Tok) && !Tok.is(tok::semi)) {
+    switch (Tok.getKind()) {
+    case tok::l_brace:
+    case tok::r_brace:
+      // This might be the `typedef struct {...} T;` case.
+      return false;
+    case tok::l_paren:
+      ParenLevel++;
+      break;
+    case tok::r_paren:
+      ParenLevel--;
+      break;
+    case tok::comma:
+      if (ParenLevel == 0) {
+        // If there is comma and we are not between open parenthesis then it is
+        // two or more declarations in this chain.
+        return false;
+      }
+      break;
+    case tok::raw_identifier:
+      if (Tok.getRawIdentifier() == "typedef") {
+        FoundTypedef = true;
+      }
+      break;
+    default:
+      break;
+    }
+  }
+
+  // Sanity check against weird macro cases.
+  return FoundTypedef;
+}
+
+void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<TypedefDecl>("typedef");
+  if (MatchedDecl->getLocation().isInvalid())
+    return;
+
+  auto &Context = *Result.Context;
+  auto &SM = *Result.SourceManager;
+
+  SourceLocation StartLoc = MatchedDecl->getLocStart();
+
+  if (StartLoc.isMacroID() && IgnoreMacros)
+    return;
+
+  auto Diag =
+      diag(StartLoc, "use 'using' instead of 'typedef'");
+
+  // do not fix if there is macro or array
+  if (MatchedDecl->getUnderlyingType()->isArrayType() || StartLoc.isMacroID())
+    return;
+
+  if (CheckRemoval(SM, StartLoc, Context)) {
+    auto printPolicy = PrintingPolicy(getLangOpts());
+    printPolicy.SuppressScope = true;
+    printPolicy.ConstantArraySizeAsWritten = true;
+    printPolicy.UseVoidForZeroParams = false;
+
+    Diag << FixItHint::CreateReplacement(
+        MatchedDecl->getSourceRange(),
+        "using " + MatchedDecl->getNameAsString() + " = " +
+            MatchedDecl->getUnderlyingType().getAsString(printPolicy));
+  }
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h
new file mode 100644
index 0000000..022eef0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h
@@ -0,0 +1,40 @@
+//===--- UseUsingCheck.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_USE_USING_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_USING_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Check finds typedefs and replaces it with usings.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-using.html
+class UseUsingCheck : public ClangTidyCheck {
+
+  const bool IgnoreMacros;
+
+public:
+  UseUsingCheck(StringRef Name, ClangTidyContext *Context);
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override {
+    Options.store(Opts, "IgnoreMacros", IgnoreMacros);
+  }
+  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_USE_USING_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/BufferDerefCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/BufferDerefCheck.cpp
new file mode 100644
index 0000000..8e2c0e3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/BufferDerefCheck.cpp
@@ -0,0 +1,132 @@
+//===--- BufferDerefCheck.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 "BufferDerefCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace mpi {
+
+void BufferDerefCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(callExpr().bind("CE"), this);
+}
+
+void BufferDerefCheck::check(const MatchFinder::MatchResult &Result) {
+  static ento::mpi::MPIFunctionClassifier FuncClassifier(*Result.Context);
+  const auto *CE = Result.Nodes.getNodeAs<CallExpr>("CE");
+  if (!CE->getDirectCallee())
+    return;
+
+  const IdentifierInfo *Identifier = CE->getDirectCallee()->getIdentifier();
+  if (!Identifier || !FuncClassifier.isMPIType(Identifier))
+    return;
+
+  // These containers are used, to capture the type and expression of a buffer.
+  SmallVector<const Type *, 1> BufferTypes;
+  SmallVector<const Expr *, 1> BufferExprs;
+
+  // Adds the type and expression of a buffer that is used in the MPI call
+  // expression to the captured containers.
+  auto addBuffer = [&CE, &Result, &BufferTypes,
+                    &BufferExprs](const size_t BufferIdx) {
+    // Skip null pointer constants and in place 'operators'.
+    if (CE->getArg(BufferIdx)->isNullPointerConstant(
+            *Result.Context, Expr::NPC_ValueDependentIsNull) ||
+        tooling::fixit::getText(*CE->getArg(BufferIdx), *Result.Context) ==
+            "MPI_IN_PLACE")
+      return;
+
+    const Expr *ArgExpr = CE->getArg(BufferIdx);
+    if (!ArgExpr)
+      return;
+    const Type *ArgType = ArgExpr->IgnoreImpCasts()->getType().getTypePtr();
+    if (!ArgType)
+      return;
+    BufferExprs.push_back(ArgExpr);
+    BufferTypes.push_back(ArgType);
+  };
+
+  // Collect buffer types and argument expressions for all buffers used in the
+  // MPI call expression. The number passed to the lambda corresponds to the
+  // argument index of the currently verified MPI function call.
+  if (FuncClassifier.isPointToPointType(Identifier)) {
+    addBuffer(0);
+  } else if (FuncClassifier.isCollectiveType(Identifier)) {
+    if (FuncClassifier.isReduceType(Identifier)) {
+      addBuffer(0);
+      addBuffer(1);
+    } else if (FuncClassifier.isScatterType(Identifier) ||
+               FuncClassifier.isGatherType(Identifier) ||
+               FuncClassifier.isAlltoallType(Identifier)) {
+      addBuffer(0);
+      addBuffer(3);
+    } else if (FuncClassifier.isBcastType(Identifier)) {
+      addBuffer(0);
+    }
+  }
+
+  checkBuffers(BufferTypes, BufferExprs);
+}
+
+void BufferDerefCheck::checkBuffers(ArrayRef<const Type *> BufferTypes,
+                                    ArrayRef<const Expr *> BufferExprs) {
+  for (size_t i = 0; i < BufferTypes.size(); ++i) {
+    unsigned IndirectionCount = 0;
+    const Type *BufferType = BufferTypes[i];
+    llvm::SmallVector<IndirectionType, 1> Indirections;
+
+    // Capture the depth and types of indirections for the passed buffer.
+    while (true) {
+      if (BufferType->isPointerType()) {
+        BufferType = BufferType->getPointeeType().getTypePtr();
+        Indirections.push_back(IndirectionType::Pointer);
+      } else if (BufferType->isArrayType()) {
+        BufferType = BufferType->getArrayElementTypeNoTypeQual();
+        Indirections.push_back(IndirectionType::Array);
+      } else {
+        break;
+      }
+      ++IndirectionCount;
+    }
+
+    if (IndirectionCount > 1) {
+      // Referencing an array with '&' is valid, as this also points to the
+      // beginning of the array.
+      if (IndirectionCount == 2 &&
+          Indirections[0] == IndirectionType::Pointer &&
+          Indirections[1] == IndirectionType::Array)
+        return;
+
+      // Build the indirection description in reverse order of discovery.
+      std::string IndirectionDesc;
+      for (auto It = Indirections.rbegin(); It != Indirections.rend(); ++It) {
+        if (!IndirectionDesc.empty())
+          IndirectionDesc += "->";
+        if (*It == IndirectionType::Pointer) {
+          IndirectionDesc += "pointer";
+        } else {
+          IndirectionDesc += "array";
+        }
+      }
+
+      const auto Loc = BufferExprs[i]->getSourceRange().getBegin();
+      diag(Loc, "buffer is insufficiently dereferenced: %0") << IndirectionDesc;
+    }
+  }
+}
+
+} // namespace mpi
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/BufferDerefCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/BufferDerefCheck.h
new file mode 100644
index 0000000..8490fa1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/BufferDerefCheck.h
@@ -0,0 +1,51 @@
+//===--- BufferDerefCheck.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_MPI_BUFFER_DEREF_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MPI_BUFFER_DEREF_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace mpi {
+
+/// This check verifies if a buffer passed to an MPI (Message Passing Interface)
+/// function is sufficiently dereferenced. Buffers should be passed as a single
+/// pointer or array. As MPI function signatures specify void * for their buffer
+/// types, insufficiently dereferenced buffers can be passed, like for example
+/// as double pointers or multidimensional arrays, without a compiler warning
+/// emitted.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/mpi-buffer-deref.html
+class BufferDerefCheck : public ClangTidyCheck {
+public:
+  BufferDerefCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  /// Checks for all buffers in an MPI call if they are sufficiently
+  /// dereferenced.
+  ///
+  /// \param BufferTypes buffer types
+  /// \param BufferExprs buffer arguments as expressions
+  void checkBuffers(ArrayRef<const Type *> BufferTypes,
+                    ArrayRef<const Expr *> BufferExprs);
+
+  enum class IndirectionType : unsigned char { Pointer, Array };
+};
+
+} // namespace mpi
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MPI_BUFFER_DEREF_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/CMakeLists.txt
new file mode 100644
index 0000000..3658434
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/CMakeLists.txt
@@ -0,0 +1,17 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyMPIModule
+  BufferDerefCheck.cpp
+  MPITidyModule.cpp
+  TypeMismatchCheck.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyUtils
+  clangTooling
+  clangStaticAnalyzerCheckers
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/MPITidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/MPITidyModule.cpp
new file mode 100644
index 0000000..55e187d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/MPITidyModule.cpp
@@ -0,0 +1,39 @@
+//===--- MPITidyModule.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 "BufferDerefCheck.h"
+#include "TypeMismatchCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace mpi {
+
+class MPIModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<BufferDerefCheck>("mpi-buffer-deref");
+    CheckFactories.registerCheck<TypeMismatchCheck>("mpi-type-mismatch");
+  }
+};
+
+} // namespace mpi
+
+// Register the MPITidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<mpi::MPIModule>
+    X("mpi-module", "Adds MPI clang-tidy checks.");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the MPIModule.
+volatile int MPIModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/TypeMismatchCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/TypeMismatchCheck.cpp
new file mode 100644
index 0000000..a1f92b8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/TypeMismatchCheck.cpp
@@ -0,0 +1,335 @@
+//===--- TypeMismatchCheck.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 "TypeMismatchCheck.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h"
+#include "clang/Tooling/FixIt.h"
+#include <map>
+#include <unordered_set>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace mpi {
+
+/// Check if a BuiltinType::Kind matches the MPI datatype.
+///
+/// \param MultiMap datatype group
+/// \param Kind buffer type kind
+/// \param MPIDatatype name of the MPI datatype
+///
+/// \returns true if the pair matches
+static bool
+isMPITypeMatching(const std::multimap<BuiltinType::Kind, std::string> &MultiMap,
+                  const BuiltinType::Kind Kind,
+                  const std::string &MPIDatatype) {
+  auto ItPair = MultiMap.equal_range(Kind);
+  while (ItPair.first != ItPair.second) {
+    if (ItPair.first->second == MPIDatatype)
+      return true;
+    ++ItPair.first;
+  }
+  return false;
+}
+
+/// Check if the MPI datatype is a standard type.
+///
+/// \param MPIDatatype name of the MPI datatype
+///
+/// \returns true if the type is a standard type
+static bool isStandardMPIDatatype(const std::string &MPIDatatype) {
+  static std::unordered_set<std::string> AllTypes = {
+      "MPI_C_BOOL",
+      "MPI_CHAR",
+      "MPI_SIGNED_CHAR",
+      "MPI_UNSIGNED_CHAR",
+      "MPI_WCHAR",
+      "MPI_INT",
+      "MPI_LONG",
+      "MPI_SHORT",
+      "MPI_LONG_LONG",
+      "MPI_LONG_LONG_INT",
+      "MPI_UNSIGNED",
+      "MPI_UNSIGNED_SHORT",
+      "MPI_UNSIGNED_LONG",
+      "MPI_UNSIGNED_LONG_LONG",
+      "MPI_FLOAT",
+      "MPI_DOUBLE",
+      "MPI_LONG_DOUBLE",
+      "MPI_C_COMPLEX",
+      "MPI_C_FLOAT_COMPLEX",
+      "MPI_C_DOUBLE_COMPLEX",
+      "MPI_C_LONG_DOUBLE_COMPLEX",
+      "MPI_INT8_T",
+      "MPI_INT16_T",
+      "MPI_INT32_T",
+      "MPI_INT64_T",
+      "MPI_UINT8_T",
+      "MPI_UINT16_T",
+      "MPI_UINT32_T",
+      "MPI_UINT64_T",
+      "MPI_CXX_BOOL",
+      "MPI_CXX_FLOAT_COMPLEX",
+      "MPI_CXX_DOUBLE_COMPLEX",
+      "MPI_CXX_LONG_DOUBLE_COMPLEX"};
+
+  return AllTypes.find(MPIDatatype) != AllTypes.end();
+}
+
+/// Check if a BuiltinType matches the MPI datatype.
+///
+/// \param Builtin the builtin type
+/// \param BufferTypeName buffer type name, gets assigned
+/// \param MPIDatatype name of the MPI datatype
+/// \param LO language options
+///
+/// \returns true if the type matches
+static bool isBuiltinTypeMatching(const BuiltinType *Builtin,
+                                  std::string &BufferTypeName,
+                                  const std::string &MPIDatatype,
+                                  const LangOptions &LO) {
+  static std::multimap<BuiltinType::Kind, std::string> BuiltinMatches = {
+      // On some systems like PPC or ARM, 'char' is unsigned by default which is
+      // why distinct signedness for the buffer and MPI type is tolerated.
+      {BuiltinType::SChar, "MPI_CHAR"},
+      {BuiltinType::SChar, "MPI_SIGNED_CHAR"},
+      {BuiltinType::SChar, "MPI_UNSIGNED_CHAR"},
+      {BuiltinType::Char_S, "MPI_CHAR"},
+      {BuiltinType::Char_S, "MPI_SIGNED_CHAR"},
+      {BuiltinType::Char_S, "MPI_UNSIGNED_CHAR"},
+      {BuiltinType::UChar, "MPI_CHAR"},
+      {BuiltinType::UChar, "MPI_SIGNED_CHAR"},
+      {BuiltinType::UChar, "MPI_UNSIGNED_CHAR"},
+      {BuiltinType::Char_U, "MPI_CHAR"},
+      {BuiltinType::Char_U, "MPI_SIGNED_CHAR"},
+      {BuiltinType::Char_U, "MPI_UNSIGNED_CHAR"},
+      {BuiltinType::WChar_S, "MPI_WCHAR"},
+      {BuiltinType::WChar_U, "MPI_WCHAR"},
+      {BuiltinType::Bool, "MPI_C_BOOL"},
+      {BuiltinType::Bool, "MPI_CXX_BOOL"},
+      {BuiltinType::Short, "MPI_SHORT"},
+      {BuiltinType::Int, "MPI_INT"},
+      {BuiltinType::Long, "MPI_LONG"},
+      {BuiltinType::LongLong, "MPI_LONG_LONG"},
+      {BuiltinType::LongLong, "MPI_LONG_LONG_INT"},
+      {BuiltinType::UShort, "MPI_UNSIGNED_SHORT"},
+      {BuiltinType::UInt, "MPI_UNSIGNED"},
+      {BuiltinType::ULong, "MPI_UNSIGNED_LONG"},
+      {BuiltinType::ULongLong, "MPI_UNSIGNED_LONG_LONG"},
+      {BuiltinType::Float, "MPI_FLOAT"},
+      {BuiltinType::Double, "MPI_DOUBLE"},
+      {BuiltinType::LongDouble, "MPI_LONG_DOUBLE"}};
+
+  if (!isMPITypeMatching(BuiltinMatches, Builtin->getKind(), MPIDatatype)) {
+    BufferTypeName = Builtin->getName(LO);
+    return false;
+  }
+
+  return true;
+}
+
+/// Check if a complex float/double/long double buffer type matches
+/// the MPI datatype.
+///
+/// \param Complex buffer type
+/// \param BufferTypeName buffer type name, gets assigned
+/// \param MPIDatatype name of the MPI datatype
+/// \param LO language options
+///
+/// \returns true if the type matches or the buffer type is unknown
+static bool isCComplexTypeMatching(const ComplexType *const Complex,
+                                   std::string &BufferTypeName,
+                                   const std::string &MPIDatatype,
+                                   const LangOptions &LO) {
+  static std::multimap<BuiltinType::Kind, std::string> ComplexCMatches = {
+      {BuiltinType::Float, "MPI_C_COMPLEX"},
+      {BuiltinType::Float, "MPI_C_FLOAT_COMPLEX"},
+      {BuiltinType::Double, "MPI_C_DOUBLE_COMPLEX"},
+      {BuiltinType::LongDouble, "MPI_C_LONG_DOUBLE_COMPLEX"}};
+
+  const auto *Builtin =
+      Complex->getElementType().getTypePtr()->getAs<BuiltinType>();
+
+  if (Builtin &&
+      !isMPITypeMatching(ComplexCMatches, Builtin->getKind(), MPIDatatype)) {
+    BufferTypeName = (llvm::Twine(Builtin->getName(LO)) + " _Complex").str();
+    return false;
+  }
+  return true;
+}
+
+/// Check if a complex<float/double/long double> templated buffer type matches
+/// the MPI datatype.
+///
+/// \param Template buffer type
+/// \param BufferTypeName buffer type name, gets assigned
+/// \param MPIDatatype name of the MPI datatype
+/// \param LO language options
+///
+/// \returns true if the type matches or the buffer type is unknown
+static bool
+isCXXComplexTypeMatching(const TemplateSpecializationType *const Template,
+                         std::string &BufferTypeName,
+                         const std::string &MPIDatatype,
+                         const LangOptions &LO) {
+  static std::multimap<BuiltinType::Kind, std::string> ComplexCXXMatches = {
+      {BuiltinType::Float, "MPI_CXX_FLOAT_COMPLEX"},
+      {BuiltinType::Double, "MPI_CXX_DOUBLE_COMPLEX"},
+      {BuiltinType::LongDouble, "MPI_CXX_LONG_DOUBLE_COMPLEX"}};
+
+  if (Template->getAsCXXRecordDecl()->getName() != "complex")
+    return true;
+
+  const auto *Builtin =
+      Template->getArg(0).getAsType().getTypePtr()->getAs<BuiltinType>();
+
+  if (Builtin &&
+      !isMPITypeMatching(ComplexCXXMatches, Builtin->getKind(), MPIDatatype)) {
+    BufferTypeName =
+        (llvm::Twine("complex<") + Builtin->getName(LO) + ">").str();
+    return false;
+  }
+
+  return true;
+}
+
+/// Check if a fixed size width buffer type matches the MPI datatype.
+///
+/// \param Typedef buffer type
+/// \param BufferTypeName buffer type name, gets assigned
+/// \param MPIDatatype name of the MPI datatype
+///
+/// \returns true if the type matches or the buffer type is unknown
+static bool isTypedefTypeMatching(const TypedefType *const Typedef,
+                                  std::string &BufferTypeName,
+                                  const std::string &MPIDatatype) {
+  static llvm::StringMap<std::string> FixedWidthMatches = {
+      {"int8_t", "MPI_INT8_T"},     {"int16_t", "MPI_INT16_T"},
+      {"int32_t", "MPI_INT32_T"},   {"int64_t", "MPI_INT64_T"},
+      {"uint8_t", "MPI_UINT8_T"},   {"uint16_t", "MPI_UINT16_T"},
+      {"uint32_t", "MPI_UINT32_T"}, {"uint64_t", "MPI_UINT64_T"}};
+
+  const auto it = FixedWidthMatches.find(Typedef->getDecl()->getName());
+  // Check if the typedef is known and not matching the MPI datatype.
+  if (it != FixedWidthMatches.end() && it->getValue() != MPIDatatype) {
+    BufferTypeName = Typedef->getDecl()->getName();
+    return false;
+  }
+  return true;
+}
+
+/// Get the unqualified, dereferenced type of an argument.
+///
+/// \param CE call expression
+/// \param idx argument index
+///
+/// \returns type of the argument
+static const Type *argumentType(const CallExpr *const CE, const size_t idx) {
+  const QualType QT = CE->getArg(idx)->IgnoreImpCasts()->getType();
+  return QT.getTypePtr()->getPointeeOrArrayElementType();
+}
+
+void TypeMismatchCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(callExpr().bind("CE"), this);
+}
+
+void TypeMismatchCheck::check(const MatchFinder::MatchResult &Result) {
+  static ento::mpi::MPIFunctionClassifier FuncClassifier(*Result.Context);
+  const auto *const CE = Result.Nodes.getNodeAs<CallExpr>("CE");
+  if (!CE->getDirectCallee())
+    return;
+
+  const IdentifierInfo *Identifier = CE->getDirectCallee()->getIdentifier();
+  if (!Identifier || !FuncClassifier.isMPIType(Identifier))
+    return;
+
+  // These containers are used, to capture buffer, MPI datatype pairs.
+  SmallVector<const Type *, 1> BufferTypes;
+  SmallVector<const Expr *, 1> BufferExprs;
+  SmallVector<StringRef, 1> MPIDatatypes;
+
+  // Adds a buffer, MPI datatype pair of an MPI call expression to the
+  // containers. For buffers, the type and expression is captured.
+  auto addPair = [&CE, &Result, &BufferTypes, &BufferExprs, &MPIDatatypes](
+      const size_t BufferIdx, const size_t DatatypeIdx) {
+    // Skip null pointer constants and in place 'operators'.
+    if (CE->getArg(BufferIdx)->isNullPointerConstant(
+            *Result.Context, Expr::NPC_ValueDependentIsNull) ||
+        tooling::fixit::getText(*CE->getArg(BufferIdx), *Result.Context) ==
+            "MPI_IN_PLACE")
+      return;
+
+    StringRef MPIDatatype =
+        tooling::fixit::getText(*CE->getArg(DatatypeIdx), *Result.Context);
+
+    const Type *ArgType = argumentType(CE, BufferIdx);
+    // Skip unknown MPI datatypes and void pointers.
+    if (!isStandardMPIDatatype(MPIDatatype) || ArgType->isVoidType())
+      return;
+
+    BufferTypes.push_back(ArgType);
+    BufferExprs.push_back(CE->getArg(BufferIdx));
+    MPIDatatypes.push_back(MPIDatatype);
+  };
+
+  // Collect all buffer, MPI datatype pairs for the inspected call expression.
+  if (FuncClassifier.isPointToPointType(Identifier)) {
+    addPair(0, 2);
+  } else if (FuncClassifier.isCollectiveType(Identifier)) {
+    if (FuncClassifier.isReduceType(Identifier)) {
+      addPair(0, 3);
+      addPair(1, 3);
+    } else if (FuncClassifier.isScatterType(Identifier) ||
+               FuncClassifier.isGatherType(Identifier) ||
+               FuncClassifier.isAlltoallType(Identifier)) {
+      addPair(0, 2);
+      addPair(3, 5);
+    } else if (FuncClassifier.isBcastType(Identifier)) {
+      addPair(0, 2);
+    }
+  }
+  checkArguments(BufferTypes, BufferExprs, MPIDatatypes, getLangOpts());
+}
+
+void TypeMismatchCheck::checkArguments(ArrayRef<const Type *> BufferTypes,
+                                       ArrayRef<const Expr *> BufferExprs,
+                                       ArrayRef<StringRef> MPIDatatypes,
+                                       const LangOptions &LO) {
+  std::string BufferTypeName;
+
+  for (size_t i = 0; i < MPIDatatypes.size(); ++i) {
+    const Type *const BT = BufferTypes[i];
+    bool Error = false;
+
+    if (const auto *Typedef = BT->getAs<TypedefType>()) {
+      Error = !isTypedefTypeMatching(Typedef, BufferTypeName, MPIDatatypes[i]);
+    } else if (const auto *Complex = BT->getAs<ComplexType>()) {
+      Error =
+          !isCComplexTypeMatching(Complex, BufferTypeName, MPIDatatypes[i], LO);
+    } else if (const auto *Template = BT->getAs<TemplateSpecializationType>()) {
+      Error = !isCXXComplexTypeMatching(Template, BufferTypeName,
+                                        MPIDatatypes[i], LO);
+    } else if (const auto *Builtin = BT->getAs<BuiltinType>()) {
+      Error =
+          !isBuiltinTypeMatching(Builtin, BufferTypeName, MPIDatatypes[i], LO);
+    }
+
+    if (Error) {
+      const auto Loc = BufferExprs[i]->getSourceRange().getBegin();
+      diag(Loc, "buffer type '%0' does not match the MPI datatype '%1'")
+          << BufferTypeName << MPIDatatypes[i];
+    }
+  }
+}
+
+} // namespace mpi
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/TypeMismatchCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/TypeMismatchCheck.h
new file mode 100644
index 0000000..dd56c46
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/mpi/TypeMismatchCheck.h
@@ -0,0 +1,51 @@
+//===--- TypeMismatchCheck.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_MPI_TYPE_MISMATCH_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MPI_TYPE_MISMATCH_H
+
+#include "../ClangTidy.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+namespace clang {
+namespace tidy {
+namespace mpi {
+
+/// This check verifies if buffer type and MPI (Message Passing Interface)
+/// datatype pairs match. All MPI datatypes defined by the MPI standard (3.1)
+/// are verified by this check. User defined typedefs, custom MPI datatypes and
+/// null pointer constants are skipped, in the course of verification.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/mpi-type-mismatch.html
+class TypeMismatchCheck : public ClangTidyCheck {
+public:
+  TypeMismatchCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  /// Check if the buffer type MPI datatype pairs match.
+  ///
+  /// \param BufferTypes buffer types
+  /// \param BufferExprs buffer arguments as expressions
+  /// \param MPIDatatypes MPI datatype
+  /// \param LO language options
+  void checkArguments(ArrayRef<const Type *> BufferTypes,
+                      ArrayRef<const Expr *> BufferExprs,
+                      ArrayRef<StringRef> MPIDatatypes, const LangOptions &LO);
+};
+
+} // namespace mpi
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MPI_TYPE_MISMATCH_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/AvoidNSErrorInitCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/AvoidNSErrorInitCheck.cpp
new file mode 100644
index 0000000..86c4656
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/AvoidNSErrorInitCheck.cpp
@@ -0,0 +1,41 @@
+//===--- AvoidNSErrorInitCheck.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 "AvoidNSErrorInitCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace objc {
+
+void AvoidNSErrorInitCheck::registerMatchers(MatchFinder *Finder) {
+  // this check should only be applied to ObjC sources.
+  if (!getLangOpts().ObjC1 && !getLangOpts().ObjC2) {
+    return;
+  }
+  Finder->addMatcher(objcMessageExpr(hasSelector("init"),
+                                     hasReceiverType(asString("NSError *")))
+                         .bind("nserrorInit"),
+                     this);
+}
+
+void AvoidNSErrorInitCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedExpr =
+      Result.Nodes.getNodeAs<ObjCMessageExpr>("nserrorInit");
+  diag(MatchedExpr->getLocStart(),
+       "use errorWithDomain:code:userInfo: or initWithDomain:code:userInfo: to "
+       "create a new NSError");
+}
+
+}  // namespace objc
+}  // namespace tidy
+}  // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/AvoidNSErrorInitCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/AvoidNSErrorInitCheck.h
new file mode 100644
index 0000000..bec19b2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/AvoidNSErrorInitCheck.h
@@ -0,0 +1,36 @@
+//===--- AvoidNSErrorInitCheck.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_OBJC_AVOIDNSERRORINITCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_AVOIDNSERRORINITCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace objc {
+
+/// Finds usages of [NSSError init]. It is not the proper way of creating
+/// NSError. errorWithDomain:code:userInfo: should be used instead.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/objc-avoid-nserror-init.html
+class AvoidNSErrorInitCheck : public ClangTidyCheck {
+ public:
+  AvoidNSErrorInitCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+}  // namespace objc
+}  // namespace tidy
+}  // namespace clang
+
+#endif  // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_AVOIDNSERRORINITCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/AvoidSpinlockCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/AvoidSpinlockCheck.cpp
new file mode 100644
index 0000000..21ec364
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/AvoidSpinlockCheck.cpp
@@ -0,0 +1,37 @@
+//===--- AvoidSpinlockCheck.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 "AvoidSpinlockCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace objc {
+
+void AvoidSpinlockCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      callExpr(callee((functionDecl(hasAnyName(
+                   "OSSpinlockLock", "OSSpinlockUnlock", "OSSpinlockTry")))))
+          .bind("spinlock"),
+      this);
+}
+
+void AvoidSpinlockCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("spinlock");
+  diag(MatchedExpr->getLocStart(),
+       "use os_unfair_lock_lock() or dispatch queue APIs instead of the "
+       "deprecated OSSpinLock");
+}
+
+}  // namespace objc
+}  // namespace tidy
+}  // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/AvoidSpinlockCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/AvoidSpinlockCheck.h
new file mode 100644
index 0000000..d9dbf8c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/AvoidSpinlockCheck.h
@@ -0,0 +1,36 @@
+//===--- AvoidSpinlockCheck.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_OBJC_AVOID_SPINLOCK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_AVOID_SPINLOCK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace objc {
+
+/// Finds usages of OSSpinlock, which is deprecated due to potential livelock
+/// problems.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/objc-avoid-spinlock.html
+class AvoidSpinlockCheck : public ClangTidyCheck {
+ public:
+  AvoidSpinlockCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+}  // namespace objc
+}  // namespace tidy
+}  // namespace clang
+
+#endif  // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_AVOID_SPINLOCK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/CMakeLists.txt
new file mode 100644
index 0000000..4063bba
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/CMakeLists.txt
@@ -0,0 +1,17 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyObjCModule
+  AvoidNSErrorInitCheck.cpp
+  AvoidSpinlockCheck.cpp
+  ForbiddenSubclassingCheck.cpp
+  ObjCTidyModule.cpp
+  PropertyDeclarationCheck.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyUtils
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/ForbiddenSubclassingCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/ForbiddenSubclassingCheck.cpp
new file mode 100644
index 0000000..e78cb99
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/ForbiddenSubclassingCheck.cpp
@@ -0,0 +1,122 @@
+//===--- ForbiddenSubclassingCheck.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 "ForbiddenSubclassingCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SmallVector.h"
+#include "../utils/OptionsUtils.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace objc {
+
+namespace {
+
+constexpr char DefaultForbiddenSuperClassNames[] =
+    "ABNewPersonViewController;"
+    "ABPeoplePickerNavigationController;"
+    "ABPersonViewController;"
+    "ABUnknownPersonViewController;"
+    "NSHashTable;"
+    "NSMapTable;"
+    "NSPointerArray;"
+    "NSPointerFunctions;"
+    "NSTimer;"
+    "UIActionSheet;"
+    "UIAlertView;"
+    "UIImagePickerController;"
+    "UITextInputMode;"
+    "UIWebView";
+
+/// \brief Matches Objective-C classes that directly or indirectly
+/// have a superclass matching \c Base.
+///
+/// Note that a class is not considered to be a subclass of itself.
+///
+/// Example matches Y, Z
+/// (matcher = objcInterfaceDecl(hasName("X")))
+/// \code
+///   @interface X
+///   @end
+///   @interface Y : X  // directly derived
+///   @end
+///   @interface Z : Y  // indirectly derived
+///   @end
+/// \endcode
+AST_MATCHER_P(ObjCInterfaceDecl, isSubclassOf,
+              ast_matchers::internal::Matcher<ObjCInterfaceDecl>, Base) {
+  for (const auto *SuperClass = Node.getSuperClass();
+       SuperClass != nullptr;
+       SuperClass = SuperClass->getSuperClass()) {
+    if (Base.matches(*SuperClass, Finder, Builder)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+} // namespace
+
+ForbiddenSubclassingCheck::ForbiddenSubclassingCheck(
+    StringRef Name,
+    ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      ForbiddenSuperClassNames(
+          utils::options::parseStringList(
+              Options.get("ClassNames", DefaultForbiddenSuperClassNames))) {
+}
+
+void ForbiddenSubclassingCheck::registerMatchers(MatchFinder *Finder) {
+  // this check should only be applied to ObjC sources.
+  if (!getLangOpts().ObjC1 && !getLangOpts().ObjC2) {
+    return;
+  }
+  Finder->addMatcher(
+      objcInterfaceDecl(
+          isSubclassOf(
+              objcInterfaceDecl(
+                  hasAnyName(
+                      std::vector<StringRef>(
+                          ForbiddenSuperClassNames.begin(),
+                          ForbiddenSuperClassNames.end())))
+              .bind("superclass")))
+      .bind("subclass"),
+      this);
+}
+
+void ForbiddenSubclassingCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *SubClass = Result.Nodes.getNodeAs<ObjCInterfaceDecl>(
+      "subclass");
+  assert(SubClass != nullptr);
+  const auto *SuperClass = Result.Nodes.getNodeAs<ObjCInterfaceDecl>(
+      "superclass");
+  assert(SuperClass != nullptr);
+  diag(SubClass->getLocation(),
+       "Objective-C interface %0 subclasses %1, which is not "
+       "intended to be subclassed")
+      << SubClass
+      << SuperClass;
+}
+
+void ForbiddenSubclassingCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(
+      Opts,
+      "ForbiddenSuperClassNames",
+      utils::options::serializeStringList(ForbiddenSuperClassNames));
+}
+
+} // namespace objc
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/ForbiddenSubclassingCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/ForbiddenSubclassingCheck.h
new file mode 100644
index 0000000..6c7e08b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/ForbiddenSubclassingCheck.h
@@ -0,0 +1,42 @@
+//===--- ForbiddenSubclassingCheck.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_OBJC_FORBIDDEN_SUBCLASSING_CHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_FORBIDDEN_SUBCLASSING_CHECK_H
+
+#include "../ClangTidy.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tidy {
+namespace objc {
+
+/// Finds Objective-C classes which have a superclass which is
+/// documented to not support subclassing.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/objc-forbidden-subclassing.html
+class ForbiddenSubclassingCheck : public ClangTidyCheck {
+public:
+  ForbiddenSubclassingCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Options) override;
+
+private:
+  const std::vector<std::string> ForbiddenSuperClassNames;
+};
+
+} // namespace objc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_FORBIDDEN_SUBCLASSING_CHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
new file mode 100644
index 0000000..19152c2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
@@ -0,0 +1,50 @@
+//===--- ObjCTidyModule.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 "AvoidNSErrorInitCheck.h"
+#include "AvoidSpinlockCheck.h"
+#include "ForbiddenSubclassingCheck.h"
+#include "PropertyDeclarationCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace objc {
+
+class ObjCModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<AvoidNSErrorInitCheck>(
+        "objc-avoid-nserror-init");
+    CheckFactories.registerCheck<AvoidSpinlockCheck>(
+        "objc-avoid-spinlock");
+    CheckFactories.registerCheck<ForbiddenSubclassingCheck>(
+        "objc-forbidden-subclassing");
+    CheckFactories.registerCheck<PropertyDeclarationCheck>(
+        "objc-property-declaration");
+  }
+};
+
+// Register the ObjCTidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<ObjCModule> X(
+    "objc-module",
+    "Adds Objective-C lint checks.");
+
+} // namespace objc
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the ObjCModule.
+volatile int ObjCModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/PropertyDeclarationCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/PropertyDeclarationCheck.cpp
new file mode 100644
index 0000000..d7715fa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/PropertyDeclarationCheck.cpp
@@ -0,0 +1,263 @@
+//===--- PropertyDeclarationCheck.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 "PropertyDeclarationCheck.h"
+#include <algorithm>
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/CharInfo.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Regex.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace objc {
+
+namespace {
+
+// For StandardProperty the naming style is 'lowerCamelCase'.
+// For CategoryProperty especially in categories of system class,
+// to avoid naming conflict, the suggested naming style is
+// 'abc_lowerCamelCase' (adding lowercase prefix followed by '_').
+enum NamingStyle {
+  StandardProperty = 1,
+  CategoryProperty = 2,
+};
+
+/// The acronyms are aggregated from multiple sources including
+/// https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/APIAbbreviations.html#//apple_ref/doc/uid/20001285-BCIHCGAE
+///
+/// Keep this list sorted.
+constexpr llvm::StringLiteral DefaultSpecialAcronyms[] = {
+    "[2-9]G",
+    "ACL",
+    "API",
+    "AR",
+    "ARGB",
+    "ASCII",
+    "AV",
+    "BGRA",
+    "CA",
+    "CF",
+    "CG",
+    "CI",
+    "CRC",
+    "CV",
+    "CMYK",
+    "DNS",
+    "FPS",
+    "FTP",
+    "GIF",
+    "GL",
+    "GPS",
+    "GUID",
+    "HD",
+    "HDR",
+    "HMAC",
+    "HTML",
+    "HTTP",
+    "HTTPS",
+    "HUD",
+    "ID",
+    "JPG",
+    "JS",
+    "LAN",
+    "LZW",
+    "MAC",
+    "MD",
+    "MDNS",
+    "MIDI",
+    "NS",
+    "OS",
+    "PDF",
+    "PIN",
+    "PNG",
+    "POI",
+    "PSTN",
+    "PTR",
+    "QA",
+    "QOS",
+    "RGB",
+    "RGBA",
+    "RGBX",
+    "RIPEMD",
+    "ROM",
+    "RPC",
+    "RTF",
+    "RTL",
+    "SC",
+    "SDK",
+    "SHA",
+    "SQL",
+    "SSO",
+    "TCP",
+    "TIFF",
+    "TTS",
+    "UI",
+    "URI",
+    "URL",
+    "UUID",
+    "VC",
+    "VOIP",
+    "VPN",
+    "VR",
+    "W",
+    "WAN",
+    "X",
+    "XML",
+    "Y",
+    "Z",
+};
+
+/// For now we will only fix 'CamelCase' or 'abc_CamelCase' property to
+/// 'camelCase' or 'abc_camelCase'. For other cases the users need to
+/// come up with a proper name by their own.
+/// FIXME: provide fix for snake_case to snakeCase
+FixItHint generateFixItHint(const ObjCPropertyDecl *Decl, NamingStyle Style) {
+  auto Name = Decl->getName();
+  auto NewName = Decl->getName().str();
+  size_t Index = 0;
+  if (Style == CategoryProperty) {
+    Index = Name.find_first_of('_') + 1;
+    NewName.replace(0, Index - 1, Name.substr(0, Index - 1).lower());
+  }
+  if (Index < Name.size()) {
+    NewName[Index] = tolower(NewName[Index]);
+    if (NewName != Name) {
+      return FixItHint::CreateReplacement(
+          CharSourceRange::getTokenRange(SourceRange(Decl->getLocation())),
+          llvm::StringRef(NewName));
+    }
+  }
+  return FixItHint();
+}
+
+std::string AcronymsGroupRegex(llvm::ArrayRef<std::string> EscapedAcronyms) {
+  return "(" +
+         llvm::join(EscapedAcronyms.begin(), EscapedAcronyms.end(), "s?|") +
+         "s?)";
+}
+
+std::string validPropertyNameRegex(llvm::ArrayRef<std::string> EscapedAcronyms,
+                                   bool UsedInMatcher) {
+  // Allow any of these names:
+  // foo
+  // fooBar
+  // url
+  // urlString
+  // URL
+  // URLString
+  // bundleID
+  std::string StartMatcher = UsedInMatcher ? "::" : "^";
+  std::string AcronymsMatcher = AcronymsGroupRegex(EscapedAcronyms);
+  return StartMatcher + "(" + AcronymsMatcher + "[A-Z]?)?[a-z]+[a-z0-9]*(" +
+         AcronymsMatcher + "|([A-Z][a-z0-9]+)|A|I)*$";
+}
+
+bool hasCategoryPropertyPrefix(llvm::StringRef PropertyName) {
+  auto RegexExp = llvm::Regex("^[a-zA-Z]+_[a-zA-Z0-9][a-zA-Z0-9_]+$");
+  return RegexExp.match(PropertyName);
+}
+
+bool prefixedPropertyNameValid(llvm::StringRef PropertyName,
+                               llvm::ArrayRef<std::string> Acronyms) {
+  size_t Start = PropertyName.find_first_of('_');
+  assert(Start != llvm::StringRef::npos && Start + 1 < PropertyName.size());
+  auto Prefix = PropertyName.substr(0, Start);
+  if (Prefix.lower() != Prefix) {
+    return false;
+  }
+  auto RegexExp =
+      llvm::Regex(llvm::StringRef(validPropertyNameRegex(Acronyms, false)));
+  return RegexExp.match(PropertyName.substr(Start + 1));
+}
+}  // namespace
+
+PropertyDeclarationCheck::PropertyDeclarationCheck(StringRef Name,
+                                                   ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      SpecialAcronyms(
+          utils::options::parseStringList(Options.get("Acronyms", ""))),
+      IncludeDefaultAcronyms(Options.get("IncludeDefaultAcronyms", true)),
+      EscapedAcronyms() {}
+
+void PropertyDeclarationCheck::registerMatchers(MatchFinder *Finder) {
+  // this check should only be applied to ObjC sources.
+  if (!getLangOpts().ObjC1 && !getLangOpts().ObjC2) {
+    return;
+  }
+  if (IncludeDefaultAcronyms) {
+    EscapedAcronyms.reserve(llvm::array_lengthof(DefaultSpecialAcronyms) +
+                            SpecialAcronyms.size());
+    // No need to regex-escape the default acronyms.
+    EscapedAcronyms.insert(EscapedAcronyms.end(),
+                           std::begin(DefaultSpecialAcronyms),
+                           std::end(DefaultSpecialAcronyms));
+  } else {
+    EscapedAcronyms.reserve(SpecialAcronyms.size());
+  }
+  // In case someone defines a prefix which includes a regex
+  // special character, regex-escape all the user-defined prefixes.
+  std::transform(SpecialAcronyms.begin(), SpecialAcronyms.end(),
+                 std::back_inserter(EscapedAcronyms),
+                 [](const std::string &s) { return llvm::Regex::escape(s); });
+  Finder->addMatcher(
+      objcPropertyDecl(
+          // the property name should be in Lower Camel Case like
+          // 'lowerCamelCase'
+          unless(matchesName(validPropertyNameRegex(EscapedAcronyms, true))))
+          .bind("property"),
+      this);
+}
+
+void PropertyDeclarationCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl =
+      Result.Nodes.getNodeAs<ObjCPropertyDecl>("property");
+  assert(MatchedDecl->getName().size() > 0);
+  auto *DeclContext = MatchedDecl->getDeclContext();
+  auto *CategoryDecl = llvm::dyn_cast<ObjCCategoryDecl>(DeclContext);
+
+  auto AcronymsRegex =
+      llvm::Regex("^" + AcronymsGroupRegex(EscapedAcronyms) + "$");
+  if (AcronymsRegex.match(MatchedDecl->getName())) {
+    return;
+  }
+  if (CategoryDecl != nullptr &&
+      hasCategoryPropertyPrefix(MatchedDecl->getName())) {
+    if (!prefixedPropertyNameValid(MatchedDecl->getName(), EscapedAcronyms) ||
+        CategoryDecl->IsClassExtension()) {
+      NamingStyle Style = CategoryDecl->IsClassExtension() ? StandardProperty
+                                                           : CategoryProperty;
+      diag(MatchedDecl->getLocation(),
+           "property name '%0' not using lowerCamelCase style or not prefixed "
+           "in a category, according to the Apple Coding Guidelines")
+          << MatchedDecl->getName() << generateFixItHint(MatchedDecl, Style);
+    }
+    return;
+  }
+  diag(MatchedDecl->getLocation(),
+       "property name '%0' not using lowerCamelCase style or not prefixed in "
+       "a category, according to the Apple Coding Guidelines")
+      << MatchedDecl->getName()
+      << generateFixItHint(MatchedDecl, StandardProperty);
+}
+
+void PropertyDeclarationCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "Acronyms",
+                utils::options::serializeStringList(SpecialAcronyms));
+  Options.store(Opts, "IncludeDefaultAcronyms", IncludeDefaultAcronyms);
+}
+
+}  // namespace objc
+}  // namespace tidy
+}  // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/PropertyDeclarationCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/PropertyDeclarationCheck.h
new file mode 100644
index 0000000..b2683ba
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/objc/PropertyDeclarationCheck.h
@@ -0,0 +1,46 @@
+//===--- PropertyDeclarationCheck.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_OBJC_PROPERTY_DECLARATION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_PROPERTY_DECLARATION_H
+
+#include "../ClangTidy.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tidy {
+namespace objc {
+
+/// Finds Objective-C property declarations which
+/// are not in Lower Camel Case.
+///
+/// The format of property should look like:
+/// @property(nonatomic) NSString *lowerCamelCase;
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/objc-property-declaration.html
+class PropertyDeclarationCheck : public ClangTidyCheck {
+public:
+  PropertyDeclarationCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Options) override;
+
+private:
+  const std::vector<std::string> SpecialAcronyms;
+  const bool IncludeDefaultAcronyms;
+  std::vector<std::string> EscapedAcronyms;
+};
+
+} // namespace objc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_PROPERTY_DECLARATION_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
new file mode 100644
index 0000000..ac417bc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -0,0 +1,25 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyPerformanceModule
+  FasterStringFindCheck.cpp
+  ForRangeCopyCheck.cpp
+  ImplicitConversionInLoopCheck.cpp
+  InefficientAlgorithmCheck.cpp
+  InefficientStringConcatenationCheck.cpp
+  InefficientVectorOperationCheck.cpp
+  MoveConstArgCheck.cpp
+  MoveConstructorInitCheck.cpp
+  NoexceptMoveConstructorCheck.cpp
+  PerformanceTidyModule.cpp
+  TypePromotionInMathFnCheck.cpp
+  UnnecessaryCopyInitialization.cpp
+  UnnecessaryValueParamCheck.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyUtils
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp
new file mode 100644
index 0000000..eddc52b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp
@@ -0,0 +1,104 @@
+//===--- FasterStringFindCheck.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 "FasterStringFindCheck.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+namespace {
+
+llvm::Optional<std::string> MakeCharacterLiteral(const StringLiteral *Literal) {
+  std::string Result;
+  {
+    llvm::raw_string_ostream OS(Result);
+    Literal->outputString(OS);
+  }
+  // Now replace the " with '.
+  auto pos = Result.find_first_of('"');
+  if (pos == Result.npos)
+    return llvm::None;
+  Result[pos] = '\'';
+  pos = Result.find_last_of('"');
+  if (pos == Result.npos)
+    return llvm::None;
+  Result[pos] = '\'';
+  return Result;
+}
+
+AST_MATCHER_FUNCTION(ast_matchers::internal::Matcher<Expr>,
+                     hasSubstitutedType) {
+  return hasType(qualType(anyOf(substTemplateTypeParmType(),
+                                hasDescendant(substTemplateTypeParmType()))));
+}
+
+} // namespace
+
+FasterStringFindCheck::FasterStringFindCheck(StringRef Name,
+                                             ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      StringLikeClasses(utils::options::parseStringList(
+          Options.get("StringLikeClasses", "std::basic_string"))) {}
+
+void FasterStringFindCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "StringLikeClasses",
+                utils::options::serializeStringList(StringLikeClasses));
+}
+
+void FasterStringFindCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  const auto SingleChar =
+      expr(ignoringParenCasts(stringLiteral(hasSize(1)).bind("literal")));
+  const auto StringFindFunctions =
+      hasAnyName("find", "rfind", "find_first_of", "find_first_not_of",
+                 "find_last_of", "find_last_not_of");
+
+  Finder->addMatcher(
+      cxxMemberCallExpr(
+          callee(functionDecl(StringFindFunctions).bind("func")),
+          anyOf(argumentCountIs(1), argumentCountIs(2)),
+          hasArgument(0, SingleChar),
+          on(expr(
+              hasType(hasUnqualifiedDesugaredType(recordType(hasDeclaration(
+                  recordDecl(hasAnyName(SmallVector<StringRef, 4>(
+                      StringLikeClasses.begin(), StringLikeClasses.end()))))))),
+              unless(hasSubstitutedType())))),
+      this);
+}
+
+void FasterStringFindCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Literal = Result.Nodes.getNodeAs<StringLiteral>("literal");
+  const auto *FindFunc = Result.Nodes.getNodeAs<FunctionDecl>("func");
+
+  auto Replacement = MakeCharacterLiteral(Literal);
+  if (!Replacement)
+    return;
+
+  diag(Literal->getLocStart(), "%0 called with a string literal consisting of "
+                               "a single character; consider using the more "
+                               "effective overload accepting a character")
+      << FindFunc << FixItHint::CreateReplacement(
+                         CharSourceRange::getTokenRange(Literal->getLocStart(),
+                                                        Literal->getLocEnd()),
+                         *Replacement);
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.h
new file mode 100644
index 0000000..ff666f2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.h
@@ -0,0 +1,43 @@
+//===--- FasterStringFindCheck.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_PERFORMANCE_FASTER_STRING_FIND_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_FASTER_STRING_FIND_H
+
+#include "../ClangTidy.h"
+
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+/// Optimize calls to std::string::find() and friends when the needle passed is
+/// a single character string literal.
+/// The character literal overload is more efficient.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/performance-faster-string-find.html
+class FasterStringFindCheck : public ClangTidyCheck {
+public:
+  FasterStringFindCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  const std::vector<std::string> StringLikeClasses;
+};
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_FASTER_STRING_FIND_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp
new file mode 100644
index 0000000..2358aac
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp
@@ -0,0 +1,95 @@
+//===--- ForRangeCopyCheck.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 "ForRangeCopyCheck.h"
+#include "../utils/ExprMutationAnalyzer.h"
+#include "../utils/FixItHintUtils.h"
+#include "../utils/TypeTraits.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+ForRangeCopyCheck::ForRangeCopyCheck(StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      WarnOnAllAutoCopies(Options.get("WarnOnAllAutoCopies", 0)) {}
+
+void ForRangeCopyCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "WarnOnAllAutoCopies", WarnOnAllAutoCopies);
+}
+
+void ForRangeCopyCheck::registerMatchers(MatchFinder *Finder) {
+  // Match loop variables that are not references or pointers or are already
+  // initialized through MaterializeTemporaryExpr which indicates a type
+  // conversion.
+  auto LoopVar = varDecl(
+      hasType(hasCanonicalType(unless(anyOf(referenceType(), pointerType())))),
+      unless(hasInitializer(expr(hasDescendant(materializeTemporaryExpr())))));
+  Finder->addMatcher(cxxForRangeStmt(hasLoopVariable(LoopVar.bind("loopVar")))
+                         .bind("forRange"),
+                     this);
+}
+
+void ForRangeCopyCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Var = Result.Nodes.getNodeAs<VarDecl>("loopVar");
+  // Ignore code in macros since we can't place the fixes correctly.
+  if (Var->getLocStart().isMacroID())
+    return;
+  if (handleConstValueCopy(*Var, *Result.Context))
+    return;
+  const auto *ForRange = Result.Nodes.getNodeAs<CXXForRangeStmt>("forRange");
+  handleCopyIsOnlyConstReferenced(*Var, *ForRange, *Result.Context);
+}
+
+bool ForRangeCopyCheck::handleConstValueCopy(const VarDecl &LoopVar,
+                                             ASTContext &Context) {
+  if (WarnOnAllAutoCopies) {
+    // For aggressive check just test that loop variable has auto type.
+    if (!isa<AutoType>(LoopVar.getType()))
+      return false;
+  } else if (!LoopVar.getType().isConstQualified()) {
+    return false;
+  }
+  llvm::Optional<bool> Expensive =
+      utils::type_traits::isExpensiveToCopy(LoopVar.getType(), Context);
+  if (!Expensive || !*Expensive)
+    return false;
+  auto Diagnostic =
+      diag(LoopVar.getLocation(),
+           "the loop variable's type is not a reference type; this creates a "
+           "copy in each iteration; consider making this a reference")
+      << utils::fixit::changeVarDeclToReference(LoopVar, Context);
+  if (!LoopVar.getType().isConstQualified())
+    Diagnostic << utils::fixit::changeVarDeclToConst(LoopVar);
+  return true;
+}
+
+bool ForRangeCopyCheck::handleCopyIsOnlyConstReferenced(
+    const VarDecl &LoopVar, const CXXForRangeStmt &ForRange,
+    ASTContext &Context) {
+  llvm::Optional<bool> Expensive =
+      utils::type_traits::isExpensiveToCopy(LoopVar.getType(), Context);
+  if (LoopVar.getType().isConstQualified() || !Expensive || !*Expensive)
+    return false;
+  if (utils::ExprMutationAnalyzer(ForRange.getBody(), &Context)
+          .isMutated(&LoopVar))
+    return false;
+  diag(LoopVar.getLocation(),
+       "loop variable is copied but only used as const reference; consider "
+       "making it a const reference")
+      << utils::fixit::changeVarDeclToConst(LoopVar)
+      << utils::fixit::changeVarDeclToReference(LoopVar, Context);
+  return true;
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.h
new file mode 100644
index 0000000..f88a126
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.h
@@ -0,0 +1,49 @@
+//===--- ForRangeCopyCheck.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_PERFORMANCE_FORRANGECOPYCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_FORRANGECOPYCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+/// A check that detects copied loop variables and suggests using const
+/// references.
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/performance-for-range-copy.html
+class ForRangeCopyCheck : public ClangTidyCheck {
+public:
+  ForRangeCopyCheck(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:
+  // Checks if the loop variable is a const value and expensive to copy. If so
+  // suggests it be converted to a const reference.
+  bool handleConstValueCopy(const VarDecl &LoopVar, ASTContext &Context);
+
+  // Checks if the loop variable is a non-const value and whether only
+  // const methods are invoked on it or whether it is only used as a const
+  // reference argument. If so it suggests it be made a const reference.
+  bool handleCopyIsOnlyConstReferenced(const VarDecl &LoopVar,
+                                       const CXXForRangeStmt &ForRange,
+                                       ASTContext &Context);
+
+  const bool WarnOnAllAutoCopies;
+};
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_FORRANGECOPYCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp
new file mode 100644
index 0000000..1a5605f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp
@@ -0,0 +1,104 @@
+//===--- ImplicitConversionInLoopCheck.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 "ImplicitConversionInLoopCheck.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.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 performance {
+
+// 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.
+static bool IsNonTrivialImplicitCast(const Stmt *ST) {
+  if (const auto *ICE = dyn_cast<ImplicitCastExpr>(ST)) {
+    return (ICE->getCastKind() != CK_NoOp) ||
+            IsNonTrivialImplicitCast(ICE->getSubExpr());
+  }
+  return false;
+}
+
+void ImplicitConversionInLoopCheck::registerMatchers(MatchFinder *Finder) {
+  // We look for const ref loop variables that (optionally inside an
+  // 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. We use both cxxOperatorCallExpr for user
+  // defined operator and unaryOperator when the iterator is a pointer, like
+  // for arrays or std::array.
+  //
+  // 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())))),
+              hasInitializer(
+                  expr(anyOf(hasDescendant(
+                                 cxxOperatorCallExpr().bind("operator-call")),
+                             hasDescendant(unaryOperator(hasOperatorName("*"))
+                                               .bind("operator-call"))))
+                      .bind("init")))
+              .bind("faulty-var"))),
+      this);
+}
+
+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 =
+      Result.Nodes.getNodeAs<Expr>("operator-call");
+
+  if (const auto *Cleanup = dyn_cast<ExprWithCleanups>(Init))
+    Init = Cleanup->getSubExpr();
+
+  const auto *Materialized = dyn_cast<MaterializeTemporaryExpr>(Init);
+  if (!Materialized)
+    return;
+
+  // We ignore NoOp casts. Those are generated if the * operator on the
+  // iterator returns a value instead of a reference, and the loop variable
+  // is a reference. This situation is fine (it probably produces the same
+  // code at the end).
+  if (IsNonTrivialImplicitCast(Materialized->getTemporary()))
+    ReportAndFix(Result.Context, VD, OperatorCall);
+}
+
+void ImplicitConversionInLoopCheck::ReportAndFix(
+    const ASTContext *Context, const VarDecl *VD,
+    const Expr *OperatorCall) {
+  // We only match on const ref, so we should print a const ref version of the
+  // type.
+  QualType ConstType = OperatorCall->getType().withConst();
+  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 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;
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.h
new file mode 100644
index 0000000..55cb84c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.h
@@ -0,0 +1,38 @@
+//===--- ImplicitConversionInLoopCheck.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_PERFORMANCE_IMPLICIT_CONVERSION_IN_LOOP_CHECK_H_
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CONVERSION_IN_LOOP_CHECK_H_
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+// 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 ImplicitConversionInLoopCheck : public ClangTidyCheck {
+public:
+  ImplicitConversionInLoopCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void ReportAndFix(const ASTContext *Context, const VarDecl *VD,
+                    const Expr *OperatorCall);
+};
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CONVERSION_IN_LOOP_CHECK_H_
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientAlgorithmCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientAlgorithmCheck.cpp
new file mode 100644
index 0000000..4471d07
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientAlgorithmCheck.cpp
@@ -0,0 +1,163 @@
+//===--- InefficientAlgorithmCheck.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 "InefficientAlgorithmCheck.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 performance {
+
+static bool areTypesCompatible(QualType Left, QualType Right) {
+  if (const auto *LeftRefType = Left->getAs<ReferenceType>())
+    Left = LeftRefType->getPointeeType();
+  if (const auto *RightRefType = Right->getAs<ReferenceType>())
+    Right = RightRefType->getPointeeType();
+  return Left->getCanonicalTypeUnqualified() ==
+         Right->getCanonicalTypeUnqualified();
+}
+
+void InefficientAlgorithmCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  const auto Algorithms =
+      hasAnyName("::std::find", "::std::count", "::std::equal_range",
+                 "::std::lower_bound", "::std::upper_bound");
+  const auto ContainerMatcher = classTemplateSpecializationDecl(hasAnyName(
+      "::std::set", "::std::map", "::std::multiset", "::std::multimap",
+      "::std::unordered_set", "::std::unordered_map",
+      "::std::unordered_multiset", "::std::unordered_multimap"));
+
+  const auto Matcher =
+      callExpr(
+          callee(functionDecl(Algorithms)),
+          hasArgument(
+              0, cxxConstructExpr(has(ignoringParenImpCasts(cxxMemberCallExpr(
+                     callee(cxxMethodDecl(hasName("begin"))),
+                     on(declRefExpr(
+                            hasDeclaration(decl().bind("IneffContObj")),
+                            anyOf(hasType(ContainerMatcher.bind("IneffCont")),
+                                  hasType(pointsTo(
+                                      ContainerMatcher.bind("IneffContPtr")))))
+                            .bind("IneffContExpr"))))))),
+          hasArgument(
+              1, cxxConstructExpr(has(ignoringParenImpCasts(cxxMemberCallExpr(
+                     callee(cxxMethodDecl(hasName("end"))),
+                     on(declRefExpr(
+                         hasDeclaration(equalsBoundNode("IneffContObj"))))))))),
+          hasArgument(2, expr().bind("AlgParam")),
+          unless(isInTemplateInstantiation()))
+          .bind("IneffAlg");
+
+  Finder->addMatcher(Matcher, this);
+}
+
+void InefficientAlgorithmCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *AlgCall = Result.Nodes.getNodeAs<CallExpr>("IneffAlg");
+  const auto *IneffCont =
+      Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("IneffCont");
+  bool PtrToContainer = false;
+  if (!IneffCont) {
+    IneffCont =
+        Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("IneffContPtr");
+    PtrToContainer = true;
+  }
+  const llvm::StringRef IneffContName = IneffCont->getName();
+  const bool Unordered =
+      IneffContName.find("unordered") != llvm::StringRef::npos;
+  const bool Maplike = IneffContName.find("map") != llvm::StringRef::npos;
+
+  // Store if the key type of the container is compatible with the value
+  // that is searched for.
+  QualType ValueType = AlgCall->getArg(2)->getType();
+  QualType KeyType =
+      IneffCont->getTemplateArgs()[0].getAsType().getCanonicalType();
+  const bool CompatibleTypes = areTypesCompatible(KeyType, ValueType);
+
+  // Check if the comparison type for the algorithm and the container matches.
+  if (AlgCall->getNumArgs() == 4 && !Unordered) {
+    const Expr *Arg = AlgCall->getArg(3);
+    const QualType AlgCmp =
+        Arg->getType().getUnqualifiedType().getCanonicalType();
+    const unsigned CmpPosition =
+        (IneffContName.find("map") == llvm::StringRef::npos) ? 1 : 2;
+    const QualType ContainerCmp = IneffCont->getTemplateArgs()[CmpPosition]
+                                      .getAsType()
+                                      .getUnqualifiedType()
+                                      .getCanonicalType();
+    if (AlgCmp != ContainerCmp) {
+      diag(Arg->getLocStart(),
+           "different comparers used in the algorithm and the container");
+      return;
+    }
+  }
+
+  const auto *AlgDecl = AlgCall->getDirectCallee();
+  if (!AlgDecl)
+    return;
+
+  if (Unordered && AlgDecl->getName().find("bound") != llvm::StringRef::npos)
+    return;
+
+  const auto *AlgParam = Result.Nodes.getNodeAs<Expr>("AlgParam");
+  const auto *IneffContExpr = Result.Nodes.getNodeAs<Expr>("IneffContExpr");
+  FixItHint Hint;
+
+  SourceManager &SM = *Result.SourceManager;
+  LangOptions LangOpts = getLangOpts();
+
+  CharSourceRange CallRange =
+      CharSourceRange::getTokenRange(AlgCall->getSourceRange());
+
+  // FIXME: Create a common utility to extract a file range that the given token
+  // sequence is exactly spelled at (without macro argument expansions etc.).
+  // We can't use Lexer::makeFileCharRange here, because for
+  //
+  //   #define F(x) x
+  //   x(a b c);
+  //
+  // it will return "x(a b c)", when given the range "a"-"c". It makes sense for
+  // removals, but not for replacements.
+  //
+  // This code is over-simplified, but works for many real cases.
+  if (SM.isMacroArgExpansion(CallRange.getBegin()) &&
+      SM.isMacroArgExpansion(CallRange.getEnd())) {
+    CallRange.setBegin(SM.getSpellingLoc(CallRange.getBegin()));
+    CallRange.setEnd(SM.getSpellingLoc(CallRange.getEnd()));
+  }
+
+  if (!CallRange.getBegin().isMacroID() && !Maplike && CompatibleTypes) {
+    StringRef ContainerText = Lexer::getSourceText(
+        CharSourceRange::getTokenRange(IneffContExpr->getSourceRange()), SM,
+        LangOpts);
+    StringRef ParamText = Lexer::getSourceText(
+        CharSourceRange::getTokenRange(AlgParam->getSourceRange()), SM,
+        LangOpts);
+    std::string ReplacementText =
+        (llvm::Twine(ContainerText) + (PtrToContainer ? "->" : ".") +
+         AlgDecl->getName() + "(" + ParamText + ")")
+            .str();
+    Hint = FixItHint::CreateReplacement(CallRange, ReplacementText);
+  }
+
+  diag(AlgCall->getLocStart(),
+       "this STL algorithm call should be replaced with a container method")
+      << Hint;
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientAlgorithmCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientAlgorithmCheck.h
new file mode 100644
index 0000000..72506cf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientAlgorithmCheck.h
@@ -0,0 +1,36 @@
+//===--- InefficientAlgorithmCheck.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_PERFORMANCE_INEFFICIENTALGORITHMCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_INEFFICIENTALGORITHMCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+/// Warns on inefficient use of STL algorithms on associative containers.
+///
+/// Associative containers implements some of the algorithms as methods which
+/// should be preferred to the algorithms in the algorithm header. The methods
+/// can take advanatage of the order of the elements.
+class InefficientAlgorithmCheck : public ClangTidyCheck {
+public:
+  InefficientAlgorithmCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_INEFFICIENTALGORITHMCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientStringConcatenationCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientStringConcatenationCheck.cpp
new file mode 100644
index 0000000..a17916d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientStringConcatenationCheck.cpp
@@ -0,0 +1,88 @@
+//===--- InefficientStringConcatenationCheck.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 "InefficientStringConcatenationCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+void InefficientStringConcatenationCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "StrictMode", StrictMode);
+}
+
+InefficientStringConcatenationCheck::InefficientStringConcatenationCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      StrictMode(Options.getLocalOrGlobal("StrictMode", 0)) {}
+
+void InefficientStringConcatenationCheck::registerMatchers(
+    MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  const auto BasicStringType =
+      hasType(qualType(hasUnqualifiedDesugaredType(recordType(
+          hasDeclaration(cxxRecordDecl(hasName("::std::basic_string")))))));
+
+  const auto BasicStringPlusOperator = cxxOperatorCallExpr(
+      hasOverloadedOperatorName("+"),
+      hasAnyArgument(ignoringImpCasts(declRefExpr(BasicStringType))));
+
+  const auto PlusOperator =
+      cxxOperatorCallExpr(
+          hasOverloadedOperatorName("+"),
+          hasAnyArgument(ignoringImpCasts(declRefExpr(BasicStringType))),
+          hasDescendant(BasicStringPlusOperator))
+          .bind("plusOperator");
+
+  const auto AssignOperator = cxxOperatorCallExpr(
+      hasOverloadedOperatorName("="),
+      hasArgument(0, declRefExpr(BasicStringType,
+                                 hasDeclaration(decl().bind("lhsStrT")))
+                         .bind("lhsStr")),
+      hasArgument(1, stmt(hasDescendant(declRefExpr(
+                         hasDeclaration(decl(equalsBoundNode("lhsStrT"))))))),
+      hasDescendant(BasicStringPlusOperator));
+
+  if (StrictMode) {
+    Finder->addMatcher(cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator)),
+                       this);
+  } else {
+    Finder->addMatcher(
+        cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator),
+                            hasAncestor(stmt(anyOf(cxxForRangeStmt(),
+                                                   whileStmt(), forStmt())))),
+        this);
+  }
+}
+
+void InefficientStringConcatenationCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *LhsStr = Result.Nodes.getNodeAs<DeclRefExpr>("lhsStr");
+  const auto *PlusOperator =
+      Result.Nodes.getNodeAs<CXXOperatorCallExpr>("plusOperator");
+  const auto DiagMsg =
+      "string concatenation results in allocation of unnecessary temporary "
+      "strings; consider using 'operator+=' or 'string::append()' instead";
+
+  if (LhsStr)
+    diag(LhsStr->getExprLoc(), DiagMsg);
+  else if (PlusOperator)
+    diag(PlusOperator->getExprLoc(), DiagMsg);
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientStringConcatenationCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientStringConcatenationCheck.h
new file mode 100644
index 0000000..12a154c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientStringConcatenationCheck.h
@@ -0,0 +1,41 @@
+//===--- InefficientStringConcatenationCheck.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_PERFORMANCE_INEFFICIENTSTRINGCONCATENATION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_INEFFICIENTSTRINGCONCATENATION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+/// This check is to warn about the performance overhead arising from
+/// concatenating strings, using the operator+, instead of operator+=.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/performance-inefficient-string-concatenation.html
+class InefficientStringConcatenationCheck : public ClangTidyCheck {
+public:
+  InefficientStringConcatenationCheck(StringRef Name,
+                                      ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  const bool StrictMode;
+};
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_INEFFICIENTSTRINGCONCATENATION_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientVectorOperationCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientVectorOperationCheck.cpp
new file mode 100644
index 0000000..33c68f0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientVectorOperationCheck.cpp
@@ -0,0 +1,214 @@
+//===--- InefficientVectorOperationCheck.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 "InefficientVectorOperationCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+#include "../utils/DeclRefExprUtils.h"
+#include "../utils/OptionsUtils.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+namespace {
+
+// Matcher names. Given the code:
+//
+// \code
+// void f() {
+//   vector<T> v;
+//   for (int i = 0; i < 10 + 1; ++i) {
+//     v.push_back(i);
+//   }
+// }
+// \endcode
+//
+// The matcher names are bound to following parts of the AST:
+//   - LoopCounterName: The entire for loop (as ForStmt).
+//   - LoopParentName: The body of function f (as CompoundStmt).
+//   - VectorVarDeclName: 'v' in  (as VarDecl).
+//   - VectorVarDeclStmatName: The entire 'std::vector<T> v;' statement (as
+//     DeclStmt).
+//   - PushBackOrEmplaceBackCallName: 'v.push_back(i)' (as cxxMemberCallExpr).
+//   - LoopInitVarName: 'i' (as VarDecl).
+//   - LoopEndExpr: '10+1' (as Expr).
+static const char LoopCounterName[] = "for_loop_counter";
+static const char LoopParentName[] = "loop_parent";
+static const char VectorVarDeclName[] = "vector_var_decl";
+static const char VectorVarDeclStmtName[] = "vector_var_decl_stmt";
+static const char PushBackOrEmplaceBackCallName[] = "append_call";
+static const char LoopInitVarName[] = "loop_init_var";
+static const char LoopEndExprName[] = "loop_end_expr";
+
+static const char RangeLoopName[] = "for_range_loop";
+
+ast_matchers::internal::Matcher<Expr> supportedContainerTypesMatcher() {
+  return hasType(cxxRecordDecl(hasAnyName(
+      "::std::vector", "::std::set", "::std::unordered_set", "::std::map",
+      "::std::unordered_map", "::std::array", "::std::deque")));
+}
+
+} // namespace
+
+InefficientVectorOperationCheck::InefficientVectorOperationCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      VectorLikeClasses(utils::options::parseStringList(
+          Options.get("VectorLikeClasses", "::std::vector"))) {}
+
+void InefficientVectorOperationCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "VectorLikeClasses",
+                utils::options::serializeStringList(VectorLikeClasses));
+}
+
+void InefficientVectorOperationCheck::registerMatchers(MatchFinder *Finder) {
+  const auto VectorDecl = cxxRecordDecl(hasAnyName(SmallVector<StringRef, 5>(
+      VectorLikeClasses.begin(), VectorLikeClasses.end())));
+  const auto VectorDefaultConstructorCall = cxxConstructExpr(
+      hasType(VectorDecl),
+      hasDeclaration(cxxConstructorDecl(isDefaultConstructor())));
+  const auto VectorVarDecl =
+      varDecl(hasInitializer(VectorDefaultConstructorCall))
+          .bind(VectorVarDeclName);
+  const auto VectorAppendCallExpr =
+      cxxMemberCallExpr(
+          callee(cxxMethodDecl(hasAnyName("push_back", "emplace_back"))),
+          on(hasType(VectorDecl)),
+          onImplicitObjectArgument(declRefExpr(to(VectorVarDecl))))
+          .bind(PushBackOrEmplaceBackCallName);
+  const auto VectorAppendCall = expr(ignoringImplicit(VectorAppendCallExpr));
+  const auto VectorVarDefStmt =
+      declStmt(hasSingleDecl(equalsBoundNode(VectorVarDeclName)))
+          .bind(VectorVarDeclStmtName);
+
+  const auto LoopVarInit =
+      declStmt(hasSingleDecl(varDecl(hasInitializer(integerLiteral(equals(0))))
+                                 .bind(LoopInitVarName)));
+  const auto RefersToLoopVar = ignoringParenImpCasts(
+      declRefExpr(to(varDecl(equalsBoundNode(LoopInitVarName)))));
+
+  // Matchers for the loop whose body has only 1 push_back/emplace_back calling
+  // statement.
+  const auto HasInterestingLoopBody =
+      hasBody(anyOf(compoundStmt(statementCountIs(1), has(VectorAppendCall)),
+                    VectorAppendCall));
+  const auto InInterestingCompoundStmt =
+      hasParent(compoundStmt(has(VectorVarDefStmt)).bind(LoopParentName));
+
+  // Match counter-based for loops:
+  //  for (int i = 0; i < n; ++i) { v.push_back(...); }
+  //
+  // FIXME: Support more types of counter-based loops like decrement loops.
+  Finder->addMatcher(
+      forStmt(
+          hasLoopInit(LoopVarInit),
+          hasCondition(binaryOperator(
+              hasOperatorName("<"), hasLHS(RefersToLoopVar),
+              hasRHS(expr(unless(hasDescendant(expr(RefersToLoopVar))))
+                         .bind(LoopEndExprName)))),
+          hasIncrement(unaryOperator(hasOperatorName("++"),
+                                     hasUnaryOperand(RefersToLoopVar))),
+          HasInterestingLoopBody, InInterestingCompoundStmt)
+          .bind(LoopCounterName),
+      this);
+
+  // Match for-range loops:
+  //   for (const auto& E : data) { v.push_back(...); }
+  //
+  // FIXME: Support more complex range-expressions.
+  Finder->addMatcher(
+      cxxForRangeStmt(
+          hasRangeInit(declRefExpr(supportedContainerTypesMatcher())),
+          HasInterestingLoopBody, InInterestingCompoundStmt)
+          .bind(RangeLoopName),
+      this);
+}
+
+void InefficientVectorOperationCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  auto* Context = Result.Context;
+  if (Context->getDiagnostics().hasUncompilableErrorOccurred())
+    return;
+
+  const SourceManager &SM = *Result.SourceManager;
+  const auto *VectorVarDecl =
+      Result.Nodes.getNodeAs<VarDecl>(VectorVarDeclName);
+  const auto *ForLoop = Result.Nodes.getNodeAs<ForStmt>(LoopCounterName);
+  const auto *RangeLoop =
+      Result.Nodes.getNodeAs<CXXForRangeStmt>(RangeLoopName);
+  const auto *VectorAppendCall =
+      Result.Nodes.getNodeAs<CXXMemberCallExpr>(PushBackOrEmplaceBackCallName);
+  const auto *LoopEndExpr = Result.Nodes.getNodeAs<Expr>(LoopEndExprName);
+  const auto *LoopParent = Result.Nodes.getNodeAs<CompoundStmt>(LoopParentName);
+
+  const Stmt *LoopStmt = ForLoop;
+  if (!LoopStmt)
+    LoopStmt = RangeLoop;
+
+  llvm::SmallPtrSet<const DeclRefExpr *, 16> AllVectorVarRefs =
+      utils::decl_ref_expr::allDeclRefExprs(*VectorVarDecl, *LoopParent,
+                                            *Context);
+  for (const auto *Ref : AllVectorVarRefs) {
+    // Skip cases where there are usages (defined as DeclRefExpr that refers to
+    // "v") of vector variable `v` before the for loop. We consider these usages
+    // are operations causing memory preallocation (e.g. "v.resize(n)",
+    // "v.reserve(n)").
+    //
+    // FIXME: make it more intelligent to identify the pre-allocating operations
+    // before the for loop.
+    if (SM.isBeforeInTranslationUnit(Ref->getLocation(),
+                                     LoopStmt->getLocStart())) {
+      return;
+    }
+  }
+
+  llvm::StringRef VectorVarName = Lexer::getSourceText(
+      CharSourceRange::getTokenRange(
+          VectorAppendCall->getImplicitObjectArgument()->getSourceRange()),
+      SM, Context->getLangOpts());
+
+  std::string ReserveStmt;
+  // Handle for-range loop cases.
+  if (RangeLoop) {
+    // Get the range-expression in a for-range statement represented as
+    // `for (range-declarator: range-expression)`.
+    StringRef RangeInitExpName = Lexer::getSourceText(
+        CharSourceRange::getTokenRange(
+            RangeLoop->getRangeInit()->getSourceRange()),
+        SM, Context->getLangOpts());
+
+    ReserveStmt =
+        (VectorVarName + ".reserve(" + RangeInitExpName + ".size()" + ");\n")
+            .str();
+  } else if (ForLoop) {
+    // Handle counter-based loop cases.
+    StringRef LoopEndSource = Lexer::getSourceText(
+        CharSourceRange::getTokenRange(LoopEndExpr->getSourceRange()), SM,
+        Context->getLangOpts());
+    ReserveStmt = (VectorVarName + ".reserve(" + LoopEndSource + ");\n").str();
+  }
+
+  auto Diag =
+      diag(VectorAppendCall->getLocStart(),
+           "%0 is called inside a loop; "
+           "consider pre-allocating the vector capacity before the loop")
+      << VectorAppendCall->getMethodDecl()->getDeclName();
+
+  if (!ReserveStmt.empty())
+    Diag << FixItHint::CreateInsertion(LoopStmt->getLocStart(), ReserveStmt);
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientVectorOperationCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientVectorOperationCheck.h
new file mode 100644
index 0000000..1427ff1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/InefficientVectorOperationCheck.h
@@ -0,0 +1,39 @@
+//===--- InefficientVectorOperationCheck.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_PERFORMANCE_INEFFICIENT_VECTOR_OPERATION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_INEFFICIENT_VECTOR_OPERATION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+/// Finds possible inefficient `std::vector` operations (e.g. `push_back`) in
+/// for loops that may cause unnecessary memory reallocations.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/performance-inefficient-vector-operation.html
+class InefficientVectorOperationCheck : public ClangTidyCheck {
+public:
+  InefficientVectorOperationCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  const std::vector<std::string> VectorLikeClasses;
+};
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_INEFFICIENT_VECTOR_OPERATION_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp
new file mode 100644
index 0000000..8d49480
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp
@@ -0,0 +1,121 @@
+//===--- MoveConstArgCheck.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 "MoveConstArgCheck.h"
+
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+static void ReplaceCallWithArg(const CallExpr *Call, DiagnosticBuilder &Diag,
+                               const SourceManager &SM,
+                               const LangOptions &LangOpts) {
+  const Expr *Arg = Call->getArg(0);
+
+  CharSourceRange BeforeArgumentsRange = Lexer::makeFileCharRange(
+      CharSourceRange::getCharRange(Call->getLocStart(), Arg->getLocStart()),
+      SM, LangOpts);
+  CharSourceRange AfterArgumentsRange = Lexer::makeFileCharRange(
+      CharSourceRange::getCharRange(Call->getLocEnd(),
+                                    Call->getLocEnd().getLocWithOffset(1)),
+      SM, LangOpts);
+
+  if (BeforeArgumentsRange.isValid() && AfterArgumentsRange.isValid()) {
+    Diag << FixItHint::CreateRemoval(BeforeArgumentsRange)
+         << FixItHint::CreateRemoval(AfterArgumentsRange);
+  }
+}
+
+void MoveConstArgCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "CheckTriviallyCopyableMove", CheckTriviallyCopyableMove);
+}
+
+void MoveConstArgCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  auto MoveCallMatcher =
+      callExpr(callee(functionDecl(hasName("::std::move"))), argumentCountIs(1),
+               unless(isInTemplateInstantiation()))
+          .bind("call-move");
+
+  Finder->addMatcher(MoveCallMatcher, this);
+
+  auto ConstParamMatcher = forEachArgumentWithParam(
+      MoveCallMatcher, parmVarDecl(hasType(references(isConstQualified()))));
+
+  Finder->addMatcher(callExpr(ConstParamMatcher).bind("receiving-expr"), this);
+  Finder->addMatcher(cxxConstructExpr(ConstParamMatcher).bind("receiving-expr"),
+                     this);
+}
+
+void MoveConstArgCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *CallMove = Result.Nodes.getNodeAs<CallExpr>("call-move");
+  const auto *ReceivingExpr = Result.Nodes.getNodeAs<Expr>("receiving-expr");
+  const Expr *Arg = CallMove->getArg(0);
+  SourceManager &SM = Result.Context->getSourceManager();
+
+  CharSourceRange MoveRange =
+      CharSourceRange::getCharRange(CallMove->getSourceRange());
+  CharSourceRange FileMoveRange =
+      Lexer::makeFileCharRange(MoveRange, SM, getLangOpts());
+  if (!FileMoveRange.isValid())
+    return;
+
+  bool IsConstArg = Arg->getType().isConstQualified();
+  bool IsTriviallyCopyable =
+      Arg->getType().isTriviallyCopyableType(*Result.Context);
+
+  if (IsConstArg || IsTriviallyCopyable) {
+    if (const CXXRecordDecl *R = Arg->getType()->getAsCXXRecordDecl()) {
+      // According to [expr.prim.lambda]p3, "whether the closure type is
+      // trivially copyable" property can be changed by the implementation of
+      // the language, so we shouldn't rely on it when issuing diagnostics.
+      if (R->isLambda())
+        return;
+      // Don't warn when the type is not copyable.
+      for (const auto *Ctor : R->ctors()) {
+        if (Ctor->isCopyConstructor() && Ctor->isDeleted())
+          return;
+      }
+    }
+
+    if (!IsConstArg && IsTriviallyCopyable && !CheckTriviallyCopyableMove)
+      return;
+
+    bool IsVariable = isa<DeclRefExpr>(Arg);
+    const auto *Var =
+        IsVariable ? dyn_cast<DeclRefExpr>(Arg)->getDecl() : nullptr;
+    auto Diag = diag(FileMoveRange.getBegin(),
+                     "std::move of the %select{|const }0"
+                     "%select{expression|variable %4}1 "
+                     "%select{|of the trivially-copyable type %5 }2"
+                     "has no effect; remove std::move()"
+                     "%select{| or make the variable non-const}3")
+                << IsConstArg << IsVariable << IsTriviallyCopyable
+                << (IsConstArg && IsVariable && !IsTriviallyCopyable) << Var
+                << Arg->getType();
+
+    ReplaceCallWithArg(CallMove, Diag, SM, getLangOpts());
+  } else if (ReceivingExpr) {
+    auto Diag = diag(FileMoveRange.getBegin(),
+                     "passing result of std::move() as a const reference "
+                     "argument; no move will actually happen");
+
+    ReplaceCallWithArg(CallMove, Diag, SM, getLangOpts());
+  }
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.h
new file mode 100644
index 0000000..13ed9ae
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.h
@@ -0,0 +1,43 @@
+//===--- MoveConstArgCheck.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_MISC_MOVECONSTANTARGUMENTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MOVECONSTANTARGUMENTCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+/// Find casts of calculation results to bigger type. Typically from int to
+///
+/// There is one option:
+///
+///   - `CheckTriviallyCopyableMove`: Whether to check for trivially-copyable
+//      types as their objects are not moved but copied. Enabled by default.
+class MoveConstArgCheck : public ClangTidyCheck {
+public:
+  MoveConstArgCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context),
+        CheckTriviallyCopyableMove(
+            Options.get("CheckTriviallyCopyableMove", true)) {}
+  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 CheckTriviallyCopyableMove;
+};
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MOVECONSTANTARGUMENTCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp
new file mode 100644
index 0000000..055e4f0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp
@@ -0,0 +1,110 @@
+//===--- MoveConstructorInitCheck.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 "MoveConstructorInitCheck.h"
+#include "../utils/Matchers.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+MoveConstructorInitCheck::MoveConstructorInitCheck(StringRef Name,
+                                                   ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
+          Options.getLocalOrGlobal("IncludeStyle", "llvm"))) {}
+
+void MoveConstructorInitCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++11; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  Finder->addMatcher(
+      cxxConstructorDecl(
+          unless(isImplicit()),
+          allOf(isMoveConstructor(),
+                hasAnyConstructorInitializer(
+                    cxxCtorInitializer(
+                        withInitializer(cxxConstructExpr(hasDeclaration(
+                            cxxConstructorDecl(isCopyConstructor())
+                                .bind("ctor")))))
+                        .bind("move-init")))),
+      this);
+}
+
+void MoveConstructorInitCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *CopyCtor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
+  const auto *Initializer =
+      Result.Nodes.getNodeAs<CXXCtorInitializer>("move-init");
+
+  // Do not diagnose if the expression used to perform the initialization is a
+  // trivially-copyable type.
+  QualType QT = Initializer->getInit()->getType();
+  if (QT.isTriviallyCopyableType(*Result.Context))
+    return;
+
+  if (QT.isConstQualified())
+    return;
+
+  const auto *RD = QT->getAsCXXRecordDecl();
+  if (RD && RD->isTriviallyCopyable())
+    return;
+
+  // Diagnose when the class type has a move constructor available, but the
+  // ctor-initializer uses the copy constructor instead.
+  const CXXConstructorDecl *Candidate = nullptr;
+  for (const auto *Ctor : CopyCtor->getParent()->ctors()) {
+    if (Ctor->isMoveConstructor() && Ctor->getAccess() <= AS_protected &&
+        !Ctor->isDeleted()) {
+      // The type has a move constructor that is at least accessible to the
+      // initializer.
+      //
+      // FIXME: Determine whether the move constructor is a viable candidate
+      // for the ctor-initializer, perhaps provide a fixit that suggests
+      // using std::move().
+      Candidate = Ctor;
+      break;
+    }
+  }
+
+  if (Candidate) {
+    // There's a move constructor candidate that the caller probably intended
+    // to call instead.
+    diag(Initializer->getSourceLocation(),
+         "move constructor initializes %0 by calling a copy constructor")
+        << (Initializer->isBaseInitializer() ? "base class" : "class member");
+    diag(CopyCtor->getLocation(), "copy constructor being called",
+         DiagnosticIDs::Note);
+    diag(Candidate->getLocation(), "candidate move constructor here",
+         DiagnosticIDs::Note);
+  }
+}
+
+void MoveConstructorInitCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  Inserter.reset(new utils::IncludeInserter(
+      Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle));
+  Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+}
+
+void MoveConstructorInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle",
+                utils::IncludeSorter::toString(IncludeStyle));
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.h
new file mode 100644
index 0000000..3b7dda0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.h
@@ -0,0 +1,44 @@
+//===--- MoveConstructorInitCheck.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_PERFORMANCE_MOVECONSTRUCTORINITCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_MOVECONSTRUCTORINITCHECK_H
+
+#include "../ClangTidy.h"
+#include "../utils/IncludeInserter.h"
+
+#include <memory>
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+/// The check flags user-defined move constructors that have a ctor-initializer
+/// initializing a member or base class through a copy constructor instead of a
+/// move constructor.
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/performance-move-constructor-init.html
+class MoveConstructorInitCheck : public ClangTidyCheck {
+public:
+  MoveConstructorInitCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void registerPPCallbacks(clang::CompilerInstance &Compiler) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  std::unique_ptr<utils::IncludeInserter> Inserter;
+  const utils::IncludeSorter::IncludeStyle IncludeStyle;
+};
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_MOVECONSTRUCTORINITCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp
new file mode 100644
index 0000000..111f24d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp
@@ -0,0 +1,72 @@
+//===--- NoexceptMoveConstructorCheck.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 "NoexceptMoveConstructorCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+void NoexceptMoveConstructorCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++11; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  Finder->addMatcher(
+      cxxMethodDecl(anyOf(cxxConstructorDecl(), hasOverloadedOperatorName("=")),
+                    unless(isImplicit()), unless(isDeleted()))
+          .bind("decl"),
+      this);
+}
+
+void NoexceptMoveConstructorCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  if (const auto *Decl = Result.Nodes.getNodeAs<CXXMethodDecl>("decl")) {
+    StringRef MethodType = "assignment operator";
+    if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(Decl)) {
+      if (!Ctor->isMoveConstructor())
+        return;
+      MethodType = "constructor";
+    } else if (!Decl->isMoveAssignmentOperator()) {
+      return;
+    }
+
+    const auto *ProtoType = Decl->getType()->getAs<FunctionProtoType>();
+
+    if (isUnresolvedExceptionSpec(ProtoType->getExceptionSpecType()))
+      return;
+
+    if (!isNoexceptExceptionSpec(ProtoType->getExceptionSpecType())) {
+      diag(Decl->getLocation(), "move %0s should be marked noexcept")
+          << MethodType;
+      // FIXME: Add a fixit.
+      return;
+    }
+
+    // Don't complain about nothrow(false), but complain on nothrow(expr)
+    // where expr evaluates to false.
+    if (ProtoType->canThrow() == CT_Can) {
+      Expr *E = ProtoType->getNoexceptExpr();
+      if (!isa<CXXBoolLiteralExpr>(ProtoType->getNoexceptExpr())) {
+        diag(E->getExprLoc(),
+             "noexcept specifier on the move %0 evaluates to 'false'")
+            << MethodType;
+      }
+    }
+  }
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.h
new file mode 100644
index 0000000..9687ab1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.h
@@ -0,0 +1,38 @@
+//===--- NoexceptMoveConstructorCheck.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_PERFORMANCE_NOEXCEPTMOVECONSTRUCTORCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_NOEXCEPTMOVECONSTRUCTORCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+/// The check flags user-defined move constructors and assignment operators not
+/// marked with `noexcept` or marked with `noexcept(expr)` where `expr`
+/// evaluates to `false` (but is not a `false` literal itself).
+///
+/// Move constructors of all the types used with STL containers, for example,
+/// need to be declared `noexcept`. Otherwise STL will choose copy constructors
+/// instead. The same is valid for move assignment operations.
+class NoexceptMoveConstructorCheck : public ClangTidyCheck {
+public:
+  NoexceptMoveConstructorCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_NOEXCEPTMOVECONSTRUCTORCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
new file mode 100644
index 0000000..646c659
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -0,0 +1,71 @@
+//===--- PeformanceTidyModule.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 "FasterStringFindCheck.h"
+#include "ForRangeCopyCheck.h"
+#include "ImplicitConversionInLoopCheck.h"
+#include "InefficientAlgorithmCheck.h"
+#include "InefficientStringConcatenationCheck.h"
+#include "InefficientVectorOperationCheck.h"
+#include "MoveConstArgCheck.h"
+#include "MoveConstructorInitCheck.h"
+#include "NoexceptMoveConstructorCheck.h"
+#include "TypePromotionInMathFnCheck.h"
+#include "UnnecessaryCopyInitialization.h"
+#include "UnnecessaryValueParamCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+class PerformanceModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<FasterStringFindCheck>(
+        "performance-faster-string-find");
+    CheckFactories.registerCheck<ForRangeCopyCheck>(
+        "performance-for-range-copy");
+    CheckFactories.registerCheck<ImplicitConversionInLoopCheck>(
+        "performance-implicit-conversion-in-loop");
+    CheckFactories.registerCheck<InefficientAlgorithmCheck>(
+        "performance-inefficient-algorithm");
+    CheckFactories.registerCheck<InefficientStringConcatenationCheck>(
+        "performance-inefficient-string-concatenation");
+    CheckFactories.registerCheck<InefficientVectorOperationCheck>(
+        "performance-inefficient-vector-operation");
+    CheckFactories.registerCheck<MoveConstArgCheck>(
+        "performance-move-const-arg");
+    CheckFactories.registerCheck<MoveConstructorInitCheck>(
+        "performance-move-constructor-init");
+    CheckFactories.registerCheck<NoexceptMoveConstructorCheck>(
+        "performance-noexcept-move-constructor");
+    CheckFactories.registerCheck<TypePromotionInMathFnCheck>(
+        "performance-type-promotion-in-math-fn");
+    CheckFactories.registerCheck<UnnecessaryCopyInitialization>(
+        "performance-unnecessary-copy-initialization");
+    CheckFactories.registerCheck<UnnecessaryValueParamCheck>(
+        "performance-unnecessary-value-param");
+  }
+};
+
+// Register the PerformanceModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<PerformanceModule>
+    X("performance-module", "Adds performance checks.");
+
+} // namespace performance
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the PerformanceModule.
+volatile int PerformanceModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp
new file mode 100644
index 0000000..441bad3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp
@@ -0,0 +1,205 @@
+//===--- TypePromotionInMathFnCheck.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 "TypePromotionInMathFnCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/StringSet.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+namespace {
+AST_MATCHER_P(Type, isBuiltinType, BuiltinType::Kind, Kind) {
+  if (const auto *BT = dyn_cast<BuiltinType>(&Node)) {
+    return BT->getKind() == Kind;
+  }
+  return false;
+}
+} // anonymous namespace
+
+TypePromotionInMathFnCheck::TypePromotionInMathFnCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
+          Options.getLocalOrGlobal("IncludeStyle", "llvm"))) {}
+
+void TypePromotionInMathFnCheck::registerPPCallbacks(
+    CompilerInstance &Compiler) {
+  IncludeInserter = llvm::make_unique<utils::IncludeInserter>(
+      Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle);
+  Compiler.getPreprocessor().addPPCallbacks(
+      IncludeInserter->CreatePPCallbacks());
+}
+
+void TypePromotionInMathFnCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle",
+                utils::IncludeSorter::toString(IncludeStyle));
+}
+
+void TypePromotionInMathFnCheck::registerMatchers(MatchFinder *Finder) {
+  constexpr BuiltinType::Kind IntTy = BuiltinType::Int;
+  constexpr BuiltinType::Kind LongTy = BuiltinType::Long;
+  constexpr BuiltinType::Kind FloatTy = BuiltinType::Float;
+  constexpr BuiltinType::Kind DoubleTy = BuiltinType::Double;
+  constexpr BuiltinType::Kind LongDoubleTy = BuiltinType::LongDouble;
+
+  auto hasBuiltinTyParam = [](int Pos, BuiltinType::Kind Kind) {
+    return hasParameter(Pos, hasType(isBuiltinType(Kind)));
+  };
+  auto hasBuiltinTyArg = [](int Pos, BuiltinType::Kind Kind) {
+    return hasArgument(Pos, hasType(isBuiltinType(Kind)));
+  };
+
+  // Match calls to foo(double) with a float argument.
+  auto OneDoubleArgFns = hasAnyName(
+      "::acos", "::acosh", "::asin", "::asinh", "::atan", "::atanh", "::cbrt",
+      "::ceil", "::cos", "::cosh", "::erf", "::erfc", "::exp", "::exp2",
+      "::expm1", "::fabs", "::floor", "::ilogb", "::lgamma", "::llrint",
+      "::log", "::log10", "::log1p", "::log2", "::logb", "::lrint", "::modf",
+      "::nearbyint", "::rint", "::round", "::sin", "::sinh", "::sqrt", "::tan",
+      "::tanh", "::tgamma", "::trunc", "::llround", "::lround");
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(OneDoubleArgFns, parameterCountIs(1),
+                                   hasBuiltinTyParam(0, DoubleTy))),
+               hasBuiltinTyArg(0, FloatTy))
+          .bind("call"),
+      this);
+
+  // Match calls to foo(double, double) where both args are floats.
+  auto TwoDoubleArgFns = hasAnyName("::atan2", "::copysign", "::fdim", "::fmax",
+                                    "::fmin", "::fmod", "::hypot", "::ldexp",
+                                    "::nextafter", "::pow", "::remainder");
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(TwoDoubleArgFns, parameterCountIs(2),
+                                   hasBuiltinTyParam(0, DoubleTy),
+                                   hasBuiltinTyParam(1, DoubleTy))),
+               hasBuiltinTyArg(0, FloatTy), hasBuiltinTyArg(1, FloatTy))
+          .bind("call"),
+      this);
+
+  // Match calls to fma(double, double, double) where all args are floats.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasName("::fma"), parameterCountIs(3),
+                                   hasBuiltinTyParam(0, DoubleTy),
+                                   hasBuiltinTyParam(1, DoubleTy),
+                                   hasBuiltinTyParam(2, DoubleTy))),
+               hasBuiltinTyArg(0, FloatTy), hasBuiltinTyArg(1, FloatTy),
+               hasBuiltinTyArg(2, FloatTy))
+          .bind("call"),
+      this);
+
+  // Match calls to frexp(double, int*) where the first arg is a float.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(
+                   hasName("::frexp"), parameterCountIs(2),
+                   hasBuiltinTyParam(0, DoubleTy),
+                   hasParameter(1, parmVarDecl(hasType(pointerType(
+                                       pointee(isBuiltinType(IntTy)))))))),
+               hasBuiltinTyArg(0, FloatTy))
+          .bind("call"),
+      this);
+
+  // Match calls to nexttoward(double, long double) where the first arg is a
+  // float.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasName("::nexttoward"), parameterCountIs(2),
+                                   hasBuiltinTyParam(0, DoubleTy),
+                                   hasBuiltinTyParam(1, LongDoubleTy))),
+               hasBuiltinTyArg(0, FloatTy))
+          .bind("call"),
+      this);
+
+  // Match calls to remquo(double, double, int*) where the first two args are
+  // floats.
+  Finder->addMatcher(
+      callExpr(
+          callee(functionDecl(
+              hasName("::remquo"), parameterCountIs(3),
+              hasBuiltinTyParam(0, DoubleTy), hasBuiltinTyParam(1, DoubleTy),
+              hasParameter(2, parmVarDecl(hasType(pointerType(
+                                  pointee(isBuiltinType(IntTy)))))))),
+          hasBuiltinTyArg(0, FloatTy), hasBuiltinTyArg(1, FloatTy))
+          .bind("call"),
+      this);
+
+  // Match calls to scalbln(double, long) where the first arg is a float.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasName("::scalbln"), parameterCountIs(2),
+                                   hasBuiltinTyParam(0, DoubleTy),
+                                   hasBuiltinTyParam(1, LongTy))),
+               hasBuiltinTyArg(0, FloatTy))
+          .bind("call"),
+      this);
+
+  // Match calls to scalbn(double, int) where the first arg is a float.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasName("::scalbn"), parameterCountIs(2),
+                                   hasBuiltinTyParam(0, DoubleTy),
+                                   hasBuiltinTyParam(1, IntTy))),
+               hasBuiltinTyArg(0, FloatTy))
+          .bind("call"),
+      this);
+
+  // modf(double, double*) is omitted because the second parameter forces the
+  // type -- there's no conversion from float* to double*.
+}
+
+void TypePromotionInMathFnCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
+  assert(Call != nullptr);
+
+  StringRef OldFnName = Call->getDirectCallee()->getName();
+
+  // In C++ mode, we prefer std::foo to ::foof.  But some of these suggestions
+  // are only valid in C++11 and newer.
+  static llvm::StringSet<> Cpp11OnlyFns = {
+      "acosh",     "asinh",      "atanh",     "cbrt",   "copysign", "erf",
+      "erfc",      "exp2",       "expm1",     "fdim",   "fma",      "fmax",
+      "fmin",      "hypot",      "ilogb",     "lgamma", "llrint",   "llround",
+      "log1p",     "log2",       "logb",      "lrint",  "lround",   "nearbyint",
+      "nextafter", "nexttoward", "remainder", "remquo", "rint",     "round",
+      "scalbln",   "scalbn",     "tgamma",    "trunc"};
+  bool StdFnRequiresCpp11 = Cpp11OnlyFns.count(OldFnName);
+
+  std::string NewFnName;
+  bool FnInCmath = false;
+  if (getLangOpts().CPlusPlus &&
+      (!StdFnRequiresCpp11 || getLangOpts().CPlusPlus11)) {
+    NewFnName = ("std::" + OldFnName).str();
+    FnInCmath = true;
+  } else {
+    NewFnName = (OldFnName + "f").str();
+  }
+
+  auto Diag = diag(Call->getExprLoc(), "call to '%0' promotes float to double")
+              << OldFnName
+              << FixItHint::CreateReplacement(
+                     Call->getCallee()->getSourceRange(), NewFnName);
+
+  // Suggest including <cmath> if the function we're suggesting is declared in
+  // <cmath> and it's not already included.  We never have to suggest including
+  // <math.h>, because the functions we're suggesting moving away from are all
+  // declared in <math.h>.
+  if (FnInCmath)
+    if (auto IncludeFixit = IncludeInserter->CreateIncludeInsertion(
+            Result.Context->getSourceManager().getFileID(Call->getLocStart()),
+            "cmath", /*IsAngled=*/true))
+      Diag << *IncludeFixit;
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.h
new file mode 100644
index 0000000..2242957
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.h
@@ -0,0 +1,47 @@
+//===--- TypePromotionInMathFnCheck.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_PERFORMANCE_TYPE_PROMOTION_IN_MATH_FN_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_TYPE_PROMOTION_IN_MATH_FN_H
+
+#include "../ClangTidy.h"
+#include "../utils/IncludeInserter.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+/// Finds calls to C math library functions with implicit float to double
+/// promotions.
+///
+/// For example, warns on ::sin(0.f), because this funciton's parameter is a
+/// double.  You probably meant to call std::sin(0.f) (in C++), or sinf(0.f) (in
+/// C).
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/performance-type-promotion-in-math-fn.html
+class TypePromotionInMathFnCheck : public ClangTidyCheck {
+public:
+  TypePromotionInMathFnCheck(StringRef Name, ClangTidyContext *Context);
+
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  std::unique_ptr<utils::IncludeInserter> IncludeInserter;
+  const utils::IncludeSorter::IncludeStyle IncludeStyle;
+};
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_TYPE_PROMOTION_IN_MATH_FN_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
new file mode 100644
index 0000000..177497c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -0,0 +1,149 @@
+//===--- UnnecessaryCopyInitialization.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 "UnnecessaryCopyInitialization.h"
+
+#include "../utils/DeclRefExprUtils.h"
+#include "../utils/FixItHintUtils.h"
+#include "../utils/Matchers.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+namespace {
+
+void recordFixes(const VarDecl &Var, ASTContext &Context,
+                 DiagnosticBuilder &Diagnostic) {
+  Diagnostic << utils::fixit::changeVarDeclToReference(Var, Context);
+  if (!Var.getType().isLocalConstQualified())
+    Diagnostic << utils::fixit::changeVarDeclToConst(Var);
+}
+
+} // namespace
+
+using namespace ::clang::ast_matchers;
+using utils::decl_ref_expr::isOnlyUsedAsConst;
+
+void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) {
+  auto ConstReference = referenceType(pointee(qualType(isConstQualified())));
+  auto ConstOrConstReference =
+      allOf(anyOf(ConstReference, isConstQualified()),
+            unless(allOf(pointerType(), unless(pointerType(pointee(
+                                            qualType(isConstQualified())))))));
+
+  // Match method call expressions where the `this` argument is only used as
+  // const, this will be checked in `check()` part. This returned const
+  // reference is highly likely to outlive the local const reference of the
+  // variable being declared. The assumption is that the const reference being
+  // returned either points to a global static variable or to a member of the
+  // called object.
+  auto ConstRefReturningMethodCall =
+      cxxMemberCallExpr(callee(cxxMethodDecl(returns(ConstReference))),
+                        on(declRefExpr(to(varDecl().bind("objectArg")))));
+  auto ConstRefReturningFunctionCall =
+      callExpr(callee(functionDecl(returns(ConstReference))),
+               unless(callee(cxxMethodDecl())));
+
+  auto localVarCopiedFrom = [](const internal::Matcher<Expr> &CopyCtorArg) {
+    return compoundStmt(
+               forEachDescendant(
+                   declStmt(
+                       has(varDecl(hasLocalStorage(),
+                                   hasType(matchers::isExpensiveToCopy()),
+                                   unless(isImplicit()),
+                                   hasInitializer(
+                                       cxxConstructExpr(
+                                           hasDeclaration(cxxConstructorDecl(
+                                               isCopyConstructor())),
+                                           hasArgument(0, CopyCtorArg))
+                                           .bind("ctorCall")))
+                               .bind("newVarDecl")))
+                       .bind("declStmt")))
+        .bind("blockStmt");
+  };
+
+  Finder->addMatcher(localVarCopiedFrom(anyOf(ConstRefReturningFunctionCall,
+                                              ConstRefReturningMethodCall)),
+                     this);
+
+  Finder->addMatcher(localVarCopiedFrom(declRefExpr(
+                         to(varDecl(hasLocalStorage()).bind("oldVarDecl")))),
+                     this);
+}
+
+void UnnecessaryCopyInitialization::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *NewVar = Result.Nodes.getNodeAs<VarDecl>("newVarDecl");
+  const auto *OldVar = Result.Nodes.getNodeAs<VarDecl>("oldVarDecl");
+  const auto *ObjectArg = Result.Nodes.getNodeAs<VarDecl>("objectArg");
+  const auto *BlockStmt = Result.Nodes.getNodeAs<Stmt>("blockStmt");
+  const auto *CtorCall = Result.Nodes.getNodeAs<CXXConstructExpr>("ctorCall");
+  // Do not propose fixes if the DeclStmt has multiple VarDecls or in macros
+  // since we cannot place them correctly.
+  bool IssueFix =
+      Result.Nodes.getNodeAs<DeclStmt>("declStmt")->isSingleDecl() &&
+      !NewVar->getLocation().isMacroID();
+
+  // A constructor that looks like T(const T& t, bool arg = false) counts as a
+  // copy only when it is called with default arguments for the arguments after
+  // the first.
+  for (unsigned int i = 1; i < CtorCall->getNumArgs(); ++i)
+    if (!CtorCall->getArg(i)->isDefaultArgument())
+      return;
+
+  if (OldVar == nullptr) {
+    handleCopyFromMethodReturn(*NewVar, *BlockStmt, IssueFix, ObjectArg,
+                               *Result.Context);
+  } else {
+    handleCopyFromLocalVar(*NewVar, *OldVar, *BlockStmt, IssueFix,
+                           *Result.Context);
+  }
+}
+
+void UnnecessaryCopyInitialization::handleCopyFromMethodReturn(
+    const VarDecl &Var, const Stmt &BlockStmt, bool IssueFix,
+    const VarDecl *ObjectArg, ASTContext &Context) {
+  bool IsConstQualified = Var.getType().isConstQualified();
+  if (!IsConstQualified && !isOnlyUsedAsConst(Var, BlockStmt, Context))
+    return;
+  if (ObjectArg != nullptr &&
+      !isOnlyUsedAsConst(*ObjectArg, BlockStmt, Context))
+    return;
+
+  auto Diagnostic =
+      diag(Var.getLocation(),
+           IsConstQualified ? "the const qualified variable %0 is "
+                              "copy-constructed from a const reference; "
+                              "consider making it a const reference"
+                            : "the variable %0 is copy-constructed from a "
+                              "const reference but is only used as const "
+                              "reference; consider making it a const reference")
+      << &Var;
+  if (IssueFix)
+    recordFixes(Var, Context, Diagnostic);
+}
+
+void UnnecessaryCopyInitialization::handleCopyFromLocalVar(
+    const VarDecl &NewVar, const VarDecl &OldVar, const Stmt &BlockStmt,
+    bool IssueFix, ASTContext &Context) {
+  if (!isOnlyUsedAsConst(NewVar, BlockStmt, Context) ||
+      !isOnlyUsedAsConst(OldVar, BlockStmt, Context))
+    return;
+
+  auto Diagnostic = diag(NewVar.getLocation(),
+                         "local copy %0 of the variable %1 is never modified; "
+                         "consider avoiding the copy")
+                    << &NewVar << &OldVar;
+  if (IssueFix)
+    recordFixes(NewVar, Context, Diagnostic);
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h
new file mode 100644
index 0000000..8ed4142
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h
@@ -0,0 +1,47 @@
+//===--- UnnecessaryCopyInitialization.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_PERFORMANCE_UNNECESSARY_COPY_INITIALIZATION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_UNNECESSARY_COPY_INITIALIZATION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+// The check detects local variable declarations that are copy initialized with
+// the const reference of a function call or the const reference of a method
+// call whose object is guaranteed to outlive the variable's scope and suggests
+// to use a const reference.
+//
+// The check currently only understands a subset of variables that are
+// guaranteed to outlive the const reference returned, namely: const variables,
+// const references, and const pointers to const.
+class UnnecessaryCopyInitialization : public ClangTidyCheck {
+public:
+  UnnecessaryCopyInitialization(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void handleCopyFromMethodReturn(const VarDecl &Var, const Stmt &BlockStmt,
+                                  bool IssueFix, const VarDecl *ObjectArg,
+                                  ASTContext &Context);
+  void handleCopyFromLocalVar(const VarDecl &NewVar, const VarDecl &OldVar,
+                              const Stmt &BlockStmt, bool IssueFix,
+                              ASTContext &Context);
+};
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_UNNECESSARY_COPY_INITIALIZATION_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
new file mode 100644
index 0000000..e277ad3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -0,0 +1,207 @@
+//===--- UnnecessaryValueParamCheck.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 "UnnecessaryValueParamCheck.h"
+
+#include "../utils/DeclRefExprUtils.h"
+#include "../utils/FixItHintUtils.h"
+#include "../utils/Matchers.h"
+#include "../utils/TypeTraits.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+namespace {
+
+std::string paramNameOrIndex(StringRef Name, size_t Index) {
+  return (Name.empty() ? llvm::Twine('#') + llvm::Twine(Index + 1)
+                       : llvm::Twine('\'') + Name + llvm::Twine('\''))
+      .str();
+}
+
+template <typename S>
+bool isSubset(const S &SubsetCandidate, const S &SupersetCandidate) {
+  for (const auto &E : SubsetCandidate)
+    if (SupersetCandidate.count(E) == 0)
+      return false;
+  return true;
+}
+
+bool isReferencedOutsideOfCallExpr(const FunctionDecl &Function,
+                                   ASTContext &Context) {
+  auto Matches = match(declRefExpr(to(functionDecl(equalsNode(&Function))),
+                                   unless(hasAncestor(callExpr()))),
+                       Context);
+  return !Matches.empty();
+}
+
+bool hasLoopStmtAncestor(const DeclRefExpr &DeclRef, const Decl &Decl,
+                         ASTContext &Context) {
+  auto Matches =
+      match(decl(forEachDescendant(declRefExpr(
+                equalsNode(&DeclRef),
+                unless(hasAncestor(stmt(anyOf(forStmt(), cxxForRangeStmt(),
+                                              whileStmt(), doStmt()))))))),
+            Decl, Context);
+  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.getLocalOrGlobal("IncludeStyle", "llvm"))) {}
+
+void UnnecessaryValueParamCheck::registerMatchers(MatchFinder *Finder) {
+  // This check is specific to C++ and doesn't apply to languages like
+  // Objective-C.
+  if (!getLangOpts().CPlusPlus)
+    return;
+  const auto ExpensiveValueParamDecl =
+      parmVarDecl(hasType(hasCanonicalType(allOf(
+                      unless(referenceType()), matchers::isExpensiveToCopy()))),
+                  decl().bind("param"));
+  Finder->addMatcher(
+      functionDecl(hasBody(stmt()), isDefinition(), unless(isImplicit()),
+                   unless(cxxMethodDecl(anyOf(isOverride(), isFinal()))),
+                   has(typeLoc(forEach(ExpensiveValueParamDecl))),
+                   unless(isInstantiated()), decl().bind("functionDecl")),
+      this);
+}
+
+void UnnecessaryValueParamCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Param = Result.Nodes.getNodeAs<ParmVarDecl>("param");
+  const auto *Function = Result.Nodes.getNodeAs<FunctionDecl>("functionDecl");
+  const size_t Index = std::find(Function->parameters().begin(),
+                                 Function->parameters().end(), Param) -
+                       Function->parameters().begin();
+  bool IsConstQualified =
+      Param->getType().getCanonicalType().isConstQualified();
+
+  auto AllDeclRefExprs = utils::decl_ref_expr::allDeclRefExprs(
+      *Param, *Function, *Result.Context);
+  auto ConstDeclRefExprs = utils::decl_ref_expr::constReferenceDeclRefExprs(
+      *Param, *Function, *Result.Context);
+
+  // Do not trigger on non-const value parameters when they are not only used as
+  // const.
+  if (!isSubset(AllDeclRefExprs, ConstDeclRefExprs))
+    return;
+
+  // If the parameter is non-const, check if it has a move constructor and is
+  // only referenced once to copy-construct another object or whether it has a
+  // move assignment operator and is only referenced once when copy-assigned.
+  // In this case wrap DeclRefExpr with std::move() to avoid the unnecessary
+  // copy.
+  if (!IsConstQualified && AllDeclRefExprs.size() == 1) {
+    auto CanonicalType = Param->getType().getCanonicalType();
+    const auto &DeclRefExpr  = **AllDeclRefExprs.begin();
+
+    if (!hasLoopStmtAncestor(DeclRefExpr, *Function, *Result.Context) &&
+        ((utils::type_traits::hasNonTrivialMoveConstructor(CanonicalType) &&
+          utils::decl_ref_expr::isCopyConstructorArgument(
+              DeclRefExpr, *Function, *Result.Context)) ||
+         (utils::type_traits::hasNonTrivialMoveAssignment(CanonicalType) &&
+          utils::decl_ref_expr::isCopyAssignmentArgument(
+              DeclRefExpr, *Function, *Result.Context)))) {
+      handleMoveFix(*Param, DeclRefExpr, *Result.Context);
+      return;
+    }
+  }
+
+  auto Diag =
+      diag(Param->getLocation(),
+           IsConstQualified ? "the const qualified parameter %0 is "
+                              "copied for each invocation; consider "
+                              "making it a reference"
+                            : "the parameter %0 is copied for each "
+                              "invocation but only used as a const reference; "
+                              "consider making it a const reference")
+      << paramNameOrIndex(Param->getName(), Index);
+  // Do not propose fixes when:
+  // 1. the ParmVarDecl is in a macro, since we cannot place them correctly
+  // 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) ||
+      isExplicitTemplateSpecialization(*Function))
+    return;
+  for (const auto *FunctionDecl = Function; FunctionDecl != nullptr;
+       FunctionDecl = FunctionDecl->getPreviousDecl()) {
+    const auto &CurrentParam = *FunctionDecl->getParamDecl(Index);
+    Diag << utils::fixit::changeVarDeclToReference(CurrentParam,
+                                                   *Result.Context);
+    // The parameter of each declaration needs to be checked individually as to
+    // whether it is const or not as constness can differ between definition and
+    // declaration.
+    if (!CurrentParam.getType().getCanonicalType().isConstQualified())
+      Diag << utils::fixit::changeVarDeclToConst(CurrentParam);
+  }
+}
+
+void UnnecessaryValueParamCheck::registerPPCallbacks(
+    CompilerInstance &Compiler) {
+  Inserter.reset(new utils::IncludeInserter(
+      Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle));
+  Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+}
+
+void UnnecessaryValueParamCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle",
+                utils::IncludeSorter::toString(IncludeStyle));
+}
+
+void UnnecessaryValueParamCheck::handleMoveFix(const ParmVarDecl &Var,
+                                               const DeclRefExpr &CopyArgument,
+                                               const ASTContext &Context) {
+  auto Diag = diag(CopyArgument.getLocStart(),
+                   "parameter %0 is passed by value and only copied once; "
+                   "consider moving it to avoid unnecessary copies")
+              << &Var;
+  // Do not propose fixes in macros since we cannot place them correctly.
+  if (CopyArgument.getLocStart().isMacroID())
+    return;
+  const auto &SM = Context.getSourceManager();
+  auto EndLoc = Lexer::getLocForEndOfToken(CopyArgument.getLocation(), 0, SM,
+                                           Context.getLangOpts());
+  Diag << FixItHint::CreateInsertion(CopyArgument.getLocStart(), "std::move(")
+       << FixItHint::CreateInsertion(EndLoc, ")");
+  if (auto IncludeFixit = Inserter->CreateIncludeInsertion(
+          SM.getFileID(CopyArgument.getLocStart()), "utility",
+          /*IsAngled=*/true))
+    Diag << *IncludeFixit;
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.h
new file mode 100644
index 0000000..cbf0a3b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.h
@@ -0,0 +1,45 @@
+//===--- UnnecessaryValueParamCheck.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_PERFORMANCE_UNNECESSARY_VALUE_PARAM_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_UNNECESSARY_VALUE_PARAM_H
+
+#include "../ClangTidy.h"
+#include "../utils/IncludeInserter.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+/// \brief A check that flags value parameters of expensive to copy types that
+/// can safely be converted to const references.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/performance-unnecessary-value-param.html
+class UnnecessaryValueParamCheck : public ClangTidyCheck {
+public:
+  UnnecessaryValueParamCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  void handleMoveFix(const ParmVarDecl &Var, const DeclRefExpr &CopyArgument,
+                     const ASTContext &Context);
+
+  std::unique_ptr<utils::IncludeInserter> Inserter;
+  const utils::IncludeSorter::IncludeStyle IncludeStyle;
+};
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_UNNECESSARY_VALUE_PARAM_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/plugin/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/plugin/CMakeLists.txt
new file mode 100644
index 0000000..3540b2b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/plugin/CMakeLists.txt
@@ -0,0 +1,30 @@
+add_clang_library(clangTidyPlugin
+  ClangTidyPlugin.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFrontend
+  clangSema
+  clangTidy
+  clangTidyAbseilModule
+  clangTidyAndroidModule
+  clangTidyBoostModule
+  clangTidyBugproneModule
+  clangTidyCERTModule
+  clangTidyCppCoreGuidelinesModule
+  clangTidyFuchsiaModule
+  clangTidyGoogleModule
+  clangTidyHICPPModule
+  clangTidyLLVMModule
+  clangTidyMiscModule
+  clangTidyModernizeModule
+  clangTidyMPIModule
+  clangTidyObjCModule
+  clangTidyPerformanceModule
+  clangTidyPortabilityModule
+  clangTidyReadabilityModule
+  clangTidyZirconModule
+  clangTooling
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp
new file mode 100644
index 0000000..3455612
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp
@@ -0,0 +1,167 @@
+//===- ClangTidyPlugin.cpp - clang-tidy as a clang plugin -----------------===//
+//
+//                     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 "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendPluginRegistry.h"
+#include "clang/Frontend/MultiplexConsumer.h"
+
+namespace clang {
+namespace tidy {
+
+/// The core clang tidy plugin action. This just provides the AST consumer and
+/// command line flag parsing for using clang-tidy as a clang plugin.
+class ClangTidyPluginAction : public PluginASTAction {
+  /// Wrapper to grant the context the same lifetime as the action. We use
+  /// MultiplexConsumer to avoid writing out all the forwarding methods.
+  class WrapConsumer : public MultiplexConsumer {
+    std::unique_ptr<ClangTidyContext> Context;
+
+  public:
+    WrapConsumer(std::unique_ptr<ClangTidyContext> Context,
+                 std::vector<std::unique_ptr<ASTConsumer>> Consumer)
+        : MultiplexConsumer(std::move(Consumer)), Context(std::move(Context)) {}
+  };
+
+public:
+  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
+                                                 StringRef File) override {
+    // Insert the current diagnostics engine.
+    Context->setDiagnosticsEngine(&Compiler.getDiagnostics());
+
+    // Create the AST consumer.
+    ClangTidyASTConsumerFactory Factory(*Context);
+    std::vector<std::unique_ptr<ASTConsumer>> Vec;
+    Vec.push_back(Factory.CreateASTConsumer(Compiler, File));
+
+    return llvm::make_unique<WrapConsumer>(std::move(Context), std::move(Vec));
+  }
+
+  bool ParseArgs(const CompilerInstance &,
+                 const std::vector<std::string> &Args) override {
+    ClangTidyGlobalOptions GlobalOptions;
+    ClangTidyOptions DefaultOptions;
+    ClangTidyOptions OverrideOptions;
+
+    // Parse the extra command line args.
+    // FIXME: This is very limited at the moment.
+    for (StringRef Arg : Args)
+      if (Arg.startswith("-checks="))
+        OverrideOptions.Checks = Arg.substr(strlen("-checks="));
+
+    auto Options = llvm::make_unique<FileOptionsProvider>(
+        GlobalOptions, DefaultOptions, OverrideOptions);
+    Context = llvm::make_unique<ClangTidyContext>(std::move(Options));
+    return true;
+  }
+
+private:
+  std::unique_ptr<ClangTidyContext> Context;
+};
+} // namespace tidy
+} // namespace clang
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the clang-tidy plugin.
+volatile int ClangTidyPluginAnchorSource = 0;
+
+static clang::FrontendPluginRegistry::Add<clang::tidy::ClangTidyPluginAction>
+    X("clang-tidy", "clang-tidy");
+
+namespace clang {
+namespace tidy {
+
+// This anchor is used to force the linker to link the AbseilModule.
+extern volatile int AbseilModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED AbseilModuleAnchorDestination =
+    AbseilModuleAnchorSource;
+
+// 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 BoostModule.
+extern volatile int BoostModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED BoostModuleAnchorDestination =
+    BoostModuleAnchorSource;
+
+// This anchor is used to force the linker to link the CERTModule.
+extern volatile int CERTModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED CERTModuleAnchorDestination =
+    CERTModuleAnchorSource;
+
+// This anchor is used to force the linker to link the CppCoreGuidelinesModule.
+extern volatile int CppCoreGuidelinesModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED CppCoreGuidelinesModuleAnchorDestination =
+    CppCoreGuidelinesModuleAnchorSource;
+
+// This anchor is used to force the linker to link the FuchsiaModule.
+extern volatile int FuchsiaModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED FuchsiaModuleAnchorDestination =
+    FuchsiaModuleAnchorSource;
+
+// This anchor is used to force the linker to link the GoogleModule.
+extern volatile int GoogleModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED GoogleModuleAnchorDestination =
+    GoogleModuleAnchorSource;
+
+// This anchor is used to force the linker to link the HICPPModule.
+extern volatile int HICPPModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED HICPPModuleAnchorDestination =
+    HICPPModuleAnchorSource;
+
+// This anchor is used to force the linker to link the LLVMModule.
+extern volatile int LLVMModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED LLVMModuleAnchorDestination =
+    LLVMModuleAnchorSource;
+
+// This anchor is used to force the linker to link the MiscModule.
+extern volatile int MiscModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED MiscModuleAnchorDestination =
+    MiscModuleAnchorSource;
+
+// This anchor is used to force the linker to link the ModernizeModule.
+extern volatile int ModernizeModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination =
+    ModernizeModuleAnchorSource;
+
+// This anchor is used to force the linker to link the MPIModule.
+extern volatile int MPIModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED MPIModuleAnchorDestination =
+    MPIModuleAnchorSource;
+
+// This anchor is used to force the linker to link the ObjCModule.
+extern volatile int ObjCModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED ObjCModuleAnchorDestination =
+    ObjCModuleAnchorSource;
+
+// This anchor is used to force the linker to link the PerformanceModule.
+extern volatile int PerformanceModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED PerformanceModuleAnchorDestination =
+    PerformanceModuleAnchorSource;
+
+// This anchor is used to force the linker to link the PortabilityModule.
+extern volatile int PortabilityModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED PortabilityModuleAnchorDestination =
+    PortabilityModuleAnchorSource;
+
+// This anchor is used to force the linker to link the ReadabilityModule.
+extern volatile int ReadabilityModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED ReadabilityModuleAnchorDestination =
+    ReadabilityModuleAnchorSource;
+
+// This anchor is used to force the linker to link the ZirconModule.
+extern volatile int ZirconModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED ZirconModuleAnchorDestination =
+    ZirconModuleAnchorSource;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/portability/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/portability/CMakeLists.txt
new file mode 100644
index 0000000..0420a18
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/portability/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyPortabilityModule
+  PortabilityTidyModule.cpp
+  SIMDIntrinsicsCheck.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyUtils
+  clangTooling
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/portability/PortabilityTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/portability/PortabilityTidyModule.cpp
new file mode 100644
index 0000000..013cbcf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/portability/PortabilityTidyModule.cpp
@@ -0,0 +1,38 @@
+//===--- PortabilityTidyModule.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 "SIMDIntrinsicsCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace portability {
+
+class PortabilityModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<SIMDIntrinsicsCheck>(
+        "portability-simd-intrinsics");
+  }
+};
+
+// Register the PortabilityModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<PortabilityModule>
+    X("portability-module", "Adds portability-related checks.");
+
+} // namespace portability
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the PortabilityModule.
+volatile int PortabilityModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/portability/SIMDIntrinsicsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/portability/SIMDIntrinsicsCheck.cpp
new file mode 100644
index 0000000..d5434cc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/portability/SIMDIntrinsicsCheck.cpp
@@ -0,0 +1,160 @@
+//===--- SIMDIntrinsicsCheck.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 "SIMDIntrinsicsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Regex.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace portability {
+
+namespace {
+
+// If the callee has parameter of VectorType or pointer to VectorType,
+// or the return type is VectorType, we consider it a vector function
+// and a candidate for checking.
+AST_MATCHER(FunctionDecl, isVectorFunction) {
+  bool IsVector = Node.getReturnType()->isVectorType();
+  for (const ParmVarDecl *Parm : Node.parameters()) {
+    QualType Type = Parm->getType();
+    if (Type->isPointerType())
+      Type = Type->getPointeeType();
+    if (Type->isVectorType())
+      IsVector = true;
+  }
+  return IsVector;
+}
+
+} // namespace
+
+static StringRef TrySuggestPPC(StringRef Name) {
+  if (!Name.consume_front("vec_"))
+    return {};
+
+  static const llvm::StringMap<StringRef> Mapping{
+    // [simd.alg]
+    {"max", "$std::max"},
+    {"min", "$std::min"},
+
+    // [simd.binary]
+    {"add", "operator+ on $simd objects"},
+    {"sub", "operator- on $simd objects"},
+    {"mul", "operator* on $simd objects"},
+  };
+
+  auto It = Mapping.find(Name);
+  if (It != Mapping.end())
+    return It->second;
+  return {};
+}
+
+static StringRef TrySuggestX86(StringRef Name) {
+  if (!(Name.consume_front("_mm_") || Name.consume_front("_mm256_") ||
+        Name.consume_front("_mm512_")))
+    return {};
+
+  // [simd.alg]
+  if (Name.startswith("max_"))
+    return "$simd::max";
+  if (Name.startswith("min_"))
+    return "$simd::min";
+
+  // [simd.binary]
+  if (Name.startswith("add_"))
+    return "operator+ on $simd objects";
+  if (Name.startswith("sub_"))
+    return "operator- on $simd objects";
+  if (Name.startswith("mul_"))
+    return "operator* on $simd objects";
+
+  return {};
+}
+
+SIMDIntrinsicsCheck::SIMDIntrinsicsCheck(StringRef Name,
+                                         ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context), Std(Options.get("Std", "")),
+      Suggest(Options.get("Suggest", 0) != 0) {}
+
+void SIMDIntrinsicsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "Std", "");
+  Options.store(Opts, "Suggest", 0);
+}
+
+void SIMDIntrinsicsCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus11)
+    return;
+  // If Std is not specified, infer it from the language options.
+  // libcxx implementation backports it to C++11 std::experimental::simd.
+  if (Std.empty())
+    Std = getLangOpts().CPlusPlus2a ? "std" : "std::experimental";
+
+  Finder->addMatcher(callExpr(callee(functionDecl(allOf(
+                                  matchesName("^::(_mm_|_mm256_|_mm512_|vec_)"),
+                                  isVectorFunction()))),
+                              unless(isExpansionInSystemHeader()))
+                         .bind("call"),
+                     this);
+}
+
+void SIMDIntrinsicsCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
+  assert(Call != nullptr);
+  const FunctionDecl *Callee = Call->getDirectCallee();
+  if (!Callee)
+    return;
+
+  StringRef Old = Callee->getName();
+  StringRef New;
+  llvm::Triple::ArchType Arch =
+      Result.Context->getTargetInfo().getTriple().getArch();
+
+  // We warn or suggest if this SIMD intrinsic function has a std::simd
+  // replacement.
+  switch (Arch) {
+  default:
+    break;
+  case llvm::Triple::ppc:
+  case llvm::Triple::ppc64:
+  case llvm::Triple::ppc64le:
+    New = TrySuggestPPC(Old);
+    break;
+  case llvm::Triple::x86:
+  case llvm::Triple::x86_64:
+    New = TrySuggestX86(Old);
+    break;
+  }
+
+  // We have found a std::simd replacement.
+  if (!New.empty()) {
+    std::string Message;
+    // If Suggest is true, give a P0214 alternative, otherwise point it out it
+    // is non-portable.
+    if (Suggest) {
+      Message = (Twine("'") + Old + "' can be replaced by " + New).str();
+      Message = llvm::Regex("\\$std").sub(Std, Message);
+      Message =
+          llvm::Regex("\\$simd").sub((Std.str() + "::simd").str(), Message);
+    } else {
+      Message = (Twine("'") + Old + "' is a non-portable " +
+                 llvm::Triple::getArchTypeName(Arch) + " intrinsic function")
+                    .str();
+    }
+    diag(Call->getExprLoc(), Message);
+  }
+}
+
+} // namespace portability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/portability/SIMDIntrinsicsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/portability/SIMDIntrinsicsCheck.h
new file mode 100644
index 0000000..ebcc855
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/portability/SIMDIntrinsicsCheck.h
@@ -0,0 +1,42 @@
+//===--- SIMDIntrinsicsCheck.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_SIMD_INTRINSICS_CHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SIMD_INTRINSICS_CHECK_H
+
+#include "../ClangTidy.h"
+
+#include "llvm/ADT/SmallString.h"
+
+namespace clang {
+namespace tidy {
+namespace portability {
+
+/// Find SIMD intrinsics calls and suggest std::experimental::simd alternatives.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/portability-simd-intrinsics.html
+class SIMDIntrinsicsCheck : public ClangTidyCheck {
+public:
+  SIMDIntrinsicsCheck(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:
+  llvm::SmallString<32> Std;
+  const bool Suggest;
+};
+
+} // namespace portability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SIMD_INTRINSICS_CHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/AvoidConstParamsInDecls.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/AvoidConstParamsInDecls.cpp
new file mode 100644
index 0000000..70329e8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/AvoidConstParamsInDecls.cpp
@@ -0,0 +1,122 @@
+//===--- AvoidConstParamsInDecls.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 "AvoidConstParamsInDecls.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/Optional.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+namespace {
+
+SourceRange getTypeRange(const ParmVarDecl &Param) {
+  if (Param.getIdentifier() != nullptr)
+    return SourceRange(Param.getLocStart(),
+                       Param.getLocEnd().getLocWithOffset(-1));
+  return Param.getSourceRange();
+}
+
+} // namespace
+
+void AvoidConstParamsInDecls::registerMatchers(MatchFinder *Finder) {
+  const auto ConstParamDecl =
+      parmVarDecl(hasType(qualType(isConstQualified()))).bind("param");
+  Finder->addMatcher(
+      functionDecl(unless(isDefinition()),
+                   // Lambdas are always their own definition, but they
+                   // generate a non-definition FunctionDecl too. Ignore those.
+                   // Class template instantiations have a non-definition
+                   // CXXMethodDecl for methods that aren't used in this
+                   // translation unit. Ignore those, as the template will have
+                   // already been checked.
+                   unless(cxxMethodDecl(ofClass(cxxRecordDecl(anyOf(
+                       isLambda(), ast_matchers::isTemplateInstantiation()))))),
+                   has(typeLoc(forEach(ConstParamDecl))))
+          .bind("func"),
+      this);
+}
+
+// Re-lex the tokens to get precise location of last 'const'
+static llvm::Optional<Token> ConstTok(CharSourceRange Range,
+                                      const MatchFinder::MatchResult &Result) {
+  const SourceManager &Sources = *Result.SourceManager;
+  std::pair<FileID, unsigned> LocInfo =
+      Sources.getDecomposedLoc(Range.getBegin());
+  StringRef File = Sources.getBufferData(LocInfo.first);
+  const char *TokenBegin = File.data() + LocInfo.second;
+  Lexer RawLexer(Sources.getLocForStartOfFile(LocInfo.first),
+                 Result.Context->getLangOpts(), File.begin(), TokenBegin,
+                 File.end());
+  Token Tok;
+  llvm::Optional<Token> ConstTok;
+  while (!RawLexer.LexFromRawLexer(Tok)) {
+    if (Sources.isBeforeInTranslationUnit(Range.getEnd(), Tok.getLocation()))
+      break;
+    if (Tok.is(tok::raw_identifier)) {
+      IdentifierInfo &Info = Result.Context->Idents.get(StringRef(
+          Sources.getCharacterData(Tok.getLocation()), Tok.getLength()));
+      Tok.setIdentifierInfo(&Info);
+      Tok.setKind(Info.getTokenID());
+    }
+    if (Tok.is(tok::kw_const))
+      ConstTok = Tok;
+  }
+  return ConstTok;
+}
+
+void AvoidConstParamsInDecls::check(const MatchFinder::MatchResult &Result) {
+  const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func");
+  const auto *Param = Result.Nodes.getNodeAs<ParmVarDecl>("param");
+
+  if (!Param->getType().isLocalConstQualified())
+    return;
+
+  auto Diag = diag(Param->getLocStart(),
+                   "parameter %0 is const-qualified in the function "
+                   "declaration; const-qualification of parameters only has an "
+                   "effect in function definitions");
+  if (Param->getName().empty()) {
+    for (unsigned int i = 0; i < Func->getNumParams(); ++i) {
+      if (Param == Func->getParamDecl(i)) {
+        Diag << (i + 1);
+        break;
+      }
+    }
+  } else {
+    Diag << Param;
+  }
+
+  if (Param->getLocStart().isMacroID() != Param->getLocEnd().isMacroID()) {
+    // Do not offer a suggestion if the part of the variable declaration comes
+    // from a macro.
+    return;
+  }
+
+  CharSourceRange FileRange = Lexer::makeFileCharRange(
+      CharSourceRange::getTokenRange(getTypeRange(*Param)),
+      *Result.SourceManager, getLangOpts());
+
+  if (!FileRange.isValid())
+    return;
+
+  auto Tok = ConstTok(FileRange, Result);
+  if (!Tok)
+    return;
+  Diag << FixItHint::CreateRemoval(
+      CharSourceRange::getTokenRange(Tok->getLocation(), Tok->getLocation()));
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/AvoidConstParamsInDecls.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/AvoidConstParamsInDecls.h
new file mode 100644
index 0000000..f2d91e8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/AvoidConstParamsInDecls.h
@@ -0,0 +1,34 @@
+//===--- AvoidConstParamsInDecls.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_READABILITY_AVOID_CONST_PARAMS_IN_DECLS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_AVOID_CONST_PARAMS_IN_DECLS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+// Detect function declarations that have const value parameters and discourage
+// them.
+class AvoidConstParamsInDecls : public ClangTidyCheck {
+public:
+  AvoidConstParamsInDecls(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_AVOID_CONST_PARAMS_IN_DECLS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
new file mode 100644
index 0000000..1bff668
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
@@ -0,0 +1,278 @@
+//===--- BracesAroundStatementsCheck.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 "BracesAroundStatementsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+namespace {
+
+tok::TokenKind getTokenKind(SourceLocation Loc, const SourceManager &SM,
+                            const ASTContext *Context) {
+  Token Tok;
+  SourceLocation Beginning =
+      Lexer::GetBeginningOfToken(Loc, SM, Context->getLangOpts());
+  const bool Invalid =
+      Lexer::getRawToken(Beginning, Tok, SM, Context->getLangOpts());
+  assert(!Invalid && "Expected a valid token.");
+
+  if (Invalid)
+    return tok::NUM_TOKENS;
+
+  return Tok.getKind();
+}
+
+SourceLocation forwardSkipWhitespaceAndComments(SourceLocation Loc,
+                                                const SourceManager &SM,
+                                                const ASTContext *Context) {
+  assert(Loc.isValid());
+  for (;;) {
+    while (isWhitespace(*SM.getCharacterData(Loc)))
+      Loc = Loc.getLocWithOffset(1);
+
+    tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
+    if (TokKind == tok::NUM_TOKENS || TokKind != tok::comment)
+      return Loc;
+
+    // Fast-forward current token.
+    Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
+  }
+}
+
+SourceLocation findEndLocation(SourceLocation LastTokenLoc,
+                               const SourceManager &SM,
+                               const ASTContext *Context) {
+  SourceLocation Loc =
+      Lexer::GetBeginningOfToken(LastTokenLoc, SM, Context->getLangOpts());
+  // Loc points to the beginning of the last (non-comment non-ws) token
+  // before end or ';'.
+  assert(Loc.isValid());
+  bool SkipEndWhitespaceAndComments = true;
+  tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
+  if (TokKind == tok::NUM_TOKENS || TokKind == tok::semi ||
+      TokKind == tok::r_brace) {
+    // If we are at ";" or "}", we found the last token. We could use as well
+    // `if (isa<NullStmt>(S))`, but it wouldn't work for nested statements.
+    SkipEndWhitespaceAndComments = false;
+  }
+
+  Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
+  // Loc points past the last token before end or after ';'.
+  if (SkipEndWhitespaceAndComments) {
+    Loc = forwardSkipWhitespaceAndComments(Loc, SM, Context);
+    tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
+    if (TokKind == tok::semi)
+      Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
+  }
+
+  for (;;) {
+    assert(Loc.isValid());
+    while (isHorizontalWhitespace(*SM.getCharacterData(Loc))) {
+      Loc = Loc.getLocWithOffset(1);
+    }
+
+    if (isVerticalWhitespace(*SM.getCharacterData(Loc))) {
+      // EOL, insert brace before.
+      break;
+    }
+    tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
+    if (TokKind != tok::comment) {
+      // Non-comment token, insert brace before.
+      break;
+    }
+
+    SourceLocation TokEndLoc =
+        Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
+    SourceRange TokRange(Loc, TokEndLoc);
+    StringRef Comment = Lexer::getSourceText(
+        CharSourceRange::getTokenRange(TokRange), SM, Context->getLangOpts());
+    if (Comment.startswith("/*") && Comment.find('\n') != StringRef::npos) {
+      // Multi-line block comment, insert brace before.
+      break;
+    }
+    // else: Trailing comment, insert brace after the newline.
+
+    // Fast-forward current token.
+    Loc = TokEndLoc;
+  }
+  return Loc;
+}
+
+} // namespace
+
+BracesAroundStatementsCheck::BracesAroundStatementsCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      // Always add braces by default.
+      ShortStatementLines(Options.get("ShortStatementLines", 0U)) {}
+
+void BracesAroundStatementsCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "ShortStatementLines", ShortStatementLines);
+}
+
+void BracesAroundStatementsCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(ifStmt().bind("if"), this);
+  Finder->addMatcher(whileStmt().bind("while"), this);
+  Finder->addMatcher(doStmt().bind("do"), this);
+  Finder->addMatcher(forStmt().bind("for"), this);
+  Finder->addMatcher(cxxForRangeStmt().bind("for-range"), this);
+}
+
+void BracesAroundStatementsCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const SourceManager &SM = *Result.SourceManager;
+  const ASTContext *Context = Result.Context;
+
+  // Get location of closing parenthesis or 'do' to insert opening brace.
+  if (auto S = Result.Nodes.getNodeAs<ForStmt>("for")) {
+    checkStmt(Result, S->getBody(), S->getRParenLoc());
+  } else if (auto S = Result.Nodes.getNodeAs<CXXForRangeStmt>("for-range")) {
+    checkStmt(Result, S->getBody(), S->getRParenLoc());
+  } else if (auto S = Result.Nodes.getNodeAs<DoStmt>("do")) {
+    checkStmt(Result, S->getBody(), S->getDoLoc(), S->getWhileLoc());
+  } else if (auto S = Result.Nodes.getNodeAs<WhileStmt>("while")) {
+    SourceLocation StartLoc = findRParenLoc(S, SM, Context);
+    if (StartLoc.isInvalid())
+      return;
+    checkStmt(Result, S->getBody(), StartLoc);
+  } else if (auto S = Result.Nodes.getNodeAs<IfStmt>("if")) {
+    SourceLocation StartLoc = findRParenLoc(S, SM, Context);
+    if (StartLoc.isInvalid())
+      return;
+    if (ForceBracesStmts.erase(S))
+      ForceBracesStmts.insert(S->getThen());
+    bool BracedIf = checkStmt(Result, S->getThen(), StartLoc, S->getElseLoc());
+    const Stmt *Else = S->getElse();
+    if (Else && BracedIf)
+      ForceBracesStmts.insert(Else);
+    if (Else && !isa<IfStmt>(Else)) {
+      // Omit 'else if' statements here, they will be handled directly.
+      checkStmt(Result, Else, S->getElseLoc());
+    }
+  } else {
+    llvm_unreachable("Invalid match");
+  }
+}
+
+/// Find location of right parenthesis closing condition.
+template <typename IfOrWhileStmt>
+SourceLocation
+BracesAroundStatementsCheck::findRParenLoc(const IfOrWhileStmt *S,
+                                           const SourceManager &SM,
+                                           const ASTContext *Context) {
+  // Skip macros.
+  if (S->getLocStart().isMacroID())
+    return SourceLocation();
+
+  SourceLocation CondEndLoc = S->getCond()->getLocEnd();
+  if (const DeclStmt *CondVar = S->getConditionVariableDeclStmt())
+    CondEndLoc = CondVar->getLocEnd();
+
+  if (!CondEndLoc.isValid()) {
+    return SourceLocation();
+  }
+
+  SourceLocation PastCondEndLoc =
+      Lexer::getLocForEndOfToken(CondEndLoc, 0, SM, Context->getLangOpts());
+  if (PastCondEndLoc.isInvalid())
+    return SourceLocation();
+  SourceLocation RParenLoc =
+      forwardSkipWhitespaceAndComments(PastCondEndLoc, SM, Context);
+  if (RParenLoc.isInvalid())
+    return SourceLocation();
+  tok::TokenKind TokKind = getTokenKind(RParenLoc, SM, Context);
+  if (TokKind != tok::r_paren)
+    return SourceLocation();
+  return RParenLoc;
+}
+
+/// Determine if the statement needs braces around it, and add them if it does.
+/// Returns true if braces where added.
+bool BracesAroundStatementsCheck::checkStmt(
+    const MatchFinder::MatchResult &Result, const Stmt *S,
+    SourceLocation InitialLoc, SourceLocation EndLocHint) {
+  // 1) If there's a corresponding "else" or "while", the check inserts "} "
+  // right before that token.
+  // 2) If there's a multi-line block comment starting on the same line after
+  // the location we're inserting the closing brace at, or there's a non-comment
+  // token, the check inserts "\n}" right before that token.
+  // 3) Otherwise the check finds the end of line (possibly after some block or
+  // line comments) and inserts "\n}" right before that EOL.
+  if (!S || isa<CompoundStmt>(S)) {
+    // Already inside braces.
+    return false;
+  }
+
+  if (!InitialLoc.isValid())
+    return false;
+  const SourceManager &SM = *Result.SourceManager;
+  const ASTContext *Context = Result.Context;
+
+  // Treat macros.
+  CharSourceRange FileRange = Lexer::makeFileCharRange(
+      CharSourceRange::getTokenRange(S->getSourceRange()), SM,
+      Context->getLangOpts());
+  if (FileRange.isInvalid())
+    return false;
+
+  // Convert InitialLoc to file location, if it's on the same macro expansion
+  // level as the start of the statement. We also need file locations for
+  // Lexer::getLocForEndOfToken working properly.
+  InitialLoc = Lexer::makeFileCharRange(
+                   CharSourceRange::getCharRange(InitialLoc, S->getLocStart()),
+                   SM, Context->getLangOpts())
+                   .getBegin();
+  if (InitialLoc.isInvalid())
+    return false;
+  SourceLocation StartLoc =
+      Lexer::getLocForEndOfToken(InitialLoc, 0, SM, Context->getLangOpts());
+
+  // StartLoc points at the location of the opening brace to be inserted.
+  SourceLocation EndLoc;
+  std::string ClosingInsertion;
+  if (EndLocHint.isValid()) {
+    EndLoc = EndLocHint;
+    ClosingInsertion = "} ";
+  } else {
+    const auto FREnd = FileRange.getEnd().getLocWithOffset(-1);
+    EndLoc = findEndLocation(FREnd, SM, Context);
+    ClosingInsertion = "\n}";
+  }
+
+  assert(StartLoc.isValid());
+  assert(EndLoc.isValid());
+  // Don't require braces for statements spanning less than certain number of
+  // lines.
+  if (ShortStatementLines && !ForceBracesStmts.erase(S)) {
+    unsigned StartLine = SM.getSpellingLineNumber(StartLoc);
+    unsigned EndLine = SM.getSpellingLineNumber(EndLoc);
+    if (EndLine - StartLine < ShortStatementLines)
+      return false;
+  }
+
+  auto Diag = diag(StartLoc, "statement should be inside braces");
+  Diag << FixItHint::CreateInsertion(StartLoc, " {")
+       << FixItHint::CreateInsertion(EndLoc, ClosingInsertion);
+  return true;
+}
+
+void BracesAroundStatementsCheck::onEndOfTranslationUnit() {
+  ForceBracesStmts.clear();
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.h
new file mode 100644
index 0000000..919ca46
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.h
@@ -0,0 +1,69 @@
+//===--- BracesAroundStatementsCheck.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_BRACESAROUNDSTATEMENTSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_BRACESAROUNDSTATEMENTSCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Checks that bodies of `if` statements and loops (`for`, `range-for`,
+/// `do-while`, and `while`) are inside braces
+///
+/// Before:
+///
+/// \code
+///   if (condition)
+///     statement;
+/// \endcode
+///
+/// After:
+///
+/// \code
+///   if (condition) {
+///     statement;
+///   }
+/// \endcode
+///
+/// Additionally, one can define an option `ShortStatementLines` defining the
+/// minimal number of lines that the statement should have in order to trigger
+/// this check.
+///
+/// The number of lines is counted from the end of condition or initial keyword
+/// (`do`/`else`) until the last line of the inner statement.  Default value 0
+/// means that braces will be added to all statements (not having them already).
+class BracesAroundStatementsCheck : public ClangTidyCheck {
+public:
+  BracesAroundStatementsCheck(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;
+  void onEndOfTranslationUnit() override;
+
+private:
+  bool checkStmt(const ast_matchers::MatchFinder::MatchResult &Result,
+                 const Stmt *S, SourceLocation StartLoc,
+                 SourceLocation EndLocHint = SourceLocation());
+  template <typename IfOrWhileStmt>
+  SourceLocation findRParenLoc(const IfOrWhileStmt *S, const SourceManager &SM,
+                               const ASTContext *Context);
+
+private:
+  std::set<const Stmt *> ForceBracesStmts;
+  const unsigned ShortStatementLines;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_BRACESAROUNDSTATEMENTSCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
new file mode 100644
index 0000000..961ad88
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -0,0 +1,42 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyReadabilityModule
+  AvoidConstParamsInDecls.cpp
+  BracesAroundStatementsCheck.cpp
+  ContainerSizeEmptyCheck.cpp
+  DeleteNullPointerCheck.cpp
+  DeletedDefaultCheck.cpp
+  ElseAfterReturnCheck.cpp
+  FunctionSizeCheck.cpp
+  IdentifierNamingCheck.cpp
+  ImplicitBoolConversionCheck.cpp
+  InconsistentDeclarationParameterNameCheck.cpp
+  MisleadingIndentationCheck.cpp
+  MisplacedArrayIndexCheck.cpp
+  NamedParameterCheck.cpp
+  NamespaceCommentCheck.cpp
+  NonConstParameterCheck.cpp
+  ReadabilityTidyModule.cpp
+  RedundantControlFlowCheck.cpp
+  RedundantDeclarationCheck.cpp
+  RedundantFunctionPtrDereferenceCheck.cpp
+  RedundantMemberInitCheck.cpp
+  RedundantStringCStrCheck.cpp
+  RedundantSmartptrGetCheck.cpp
+  RedundantStringInitCheck.cpp
+  SimplifyBooleanExprCheck.cpp
+  SimplifySubscriptExprCheck.cpp
+  StaticAccessedThroughInstanceCheck.cpp
+  StaticDefinitionInAnonymousNamespaceCheck.cpp
+  StringCompareCheck.cpp
+  UniqueptrDeleteReleaseCheck.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyUtils
+  clangTooling
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
new file mode 100644
index 0000000..5604354
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
@@ -0,0 +1,225 @@
+//===--- ContainerSizeEmptyCheck.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 "ContainerSizeEmptyCheck.h"
+#include "../utils/ASTUtils.h"
+#include "../utils/Matchers.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/StringRef.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+using utils::IsBinaryOrTernary;
+
+ContainerSizeEmptyCheck::ContainerSizeEmptyCheck(StringRef Name,
+                                                 ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context) {}
+
+void ContainerSizeEmptyCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  const auto 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(
+                    matchers::isComparisonOperator(),
+                    hasEitherOperand(ignoringImpCasts(anyOf(
+                        integerLiteral(equals(1)), integerLiteral(equals(0))))))
+                    .bind("SizeBinaryOp")),
+      hasParent(implicitCastExpr(
+          hasImplicitDestinationType(booleanType()),
+          anyOf(
+              hasParent(unaryOperator(hasOperatorName("!")).bind("NegOnSize")),
+              anything()))),
+      hasParent(explicitCastExpr(hasDestinationType(booleanType()))));
+
+  Finder->addMatcher(
+      cxxMemberCallExpr(on(expr(anyOf(hasType(ValidContainer),
+                                      hasType(pointsTo(ValidContainer)),
+                                      hasType(references(ValidContainer))))),
+                        callee(cxxMethodDecl(hasName("size"))), WrongUse,
+                        unless(hasAncestor(cxxMethodDecl(
+                            ofClass(equalsBoundNode("container"))))))
+          .bind("SizeCallExpr"),
+      this);
+
+  // Empty constructor matcher.
+  const auto DefaultConstructor = cxxConstructExpr(
+          hasDeclaration(cxxConstructorDecl(isDefaultConstructor())));
+  // Comparison to empty string or empty constructor.
+  const auto WrongComparend = anyOf(
+      ignoringImpCasts(stringLiteral(hasSize(0))),
+      ignoringImpCasts(cxxBindTemporaryExpr(has(DefaultConstructor))),
+      ignoringImplicit(DefaultConstructor),
+      cxxConstructExpr(
+          hasDeclaration(cxxConstructorDecl(isCopyConstructor())),
+          has(expr(ignoringImpCasts(DefaultConstructor)))),
+      cxxConstructExpr(
+          hasDeclaration(cxxConstructorDecl(isMoveConstructor())),
+          has(expr(ignoringImpCasts(DefaultConstructor)))));
+  // Match the object being compared.
+  const auto STLArg =
+      anyOf(unaryOperator(
+                hasOperatorName("*"),
+                hasUnaryOperand(
+                    expr(hasType(pointsTo(ValidContainer))).bind("Pointee"))),
+            expr(hasType(ValidContainer)).bind("STLObject"));
+  Finder->addMatcher(
+      cxxOperatorCallExpr(
+          anyOf(hasOverloadedOperatorName("=="),
+                hasOverloadedOperatorName("!=")),
+          anyOf(allOf(hasArgument(0, WrongComparend), hasArgument(1, STLArg)),
+                allOf(hasArgument(0, STLArg), hasArgument(1, WrongComparend))),
+          unless(hasAncestor(
+              cxxMethodDecl(ofClass(equalsBoundNode("container"))))))
+          .bind("BinCmp"),
+      this);
+}
+
+void ContainerSizeEmptyCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MemberCall =
+      Result.Nodes.getNodeAs<CXXMemberCallExpr>("SizeCallExpr");
+  const auto *BinCmp = Result.Nodes.getNodeAs<CXXOperatorCallExpr>("BinCmp");
+  const auto *BinaryOp = Result.Nodes.getNodeAs<BinaryOperator>("SizeBinaryOp");
+  const auto *Pointee = Result.Nodes.getNodeAs<Expr>("Pointee");
+  const auto *E =
+      MemberCall
+          ? MemberCall->getImplicitObjectArgument()
+          : (Pointee ? Pointee : Result.Nodes.getNodeAs<Expr>("STLObject"));
+  FixItHint Hint;
+  std::string ReplacementText =
+      Lexer::getSourceText(CharSourceRange::getTokenRange(E->getSourceRange()),
+                           *Result.SourceManager, getLangOpts());
+  if (BinCmp && IsBinaryOrTernary(E)) {
+    // Not just a DeclRefExpr, so parenthesize to be on the safe side.
+    ReplacementText = "(" + ReplacementText + ")";
+  }
+  if (E->getType()->isPointerType())
+    ReplacementText += "->empty()";
+  else
+    ReplacementText += ".empty()";
+
+  if (BinCmp) {
+    if (BinCmp->getOperator() == OO_ExclaimEqual) {
+      ReplacementText = "!" + ReplacementText;
+    }
+    Hint =
+        FixItHint::CreateReplacement(BinCmp->getSourceRange(), ReplacementText);
+  } else if (BinaryOp) {  // Determine the correct transformation.
+    bool Negation = false;
+    const bool ContainerIsLHS =
+        !llvm::isa<IntegerLiteral>(BinaryOp->getLHS()->IgnoreImpCasts());
+    const auto OpCode = BinaryOp->getOpcode();
+    uint64_t Value = 0;
+    if (ContainerIsLHS) {
+      if (const auto *Literal = llvm::dyn_cast<IntegerLiteral>(
+              BinaryOp->getRHS()->IgnoreImpCasts()))
+        Value = Literal->getValue().getLimitedValue();
+      else
+        return;
+    } else {
+      Value =
+          llvm::dyn_cast<IntegerLiteral>(BinaryOp->getLHS()->IgnoreImpCasts())
+              ->getValue()
+              .getLimitedValue();
+    }
+
+    // Constant that is not handled.
+    if (Value > 1)
+      return;
+
+    if (Value == 1 && (OpCode == BinaryOperatorKind::BO_EQ ||
+                       OpCode == BinaryOperatorKind::BO_NE))
+      return;
+
+    // Always true, no warnings for that.
+    if ((OpCode == BinaryOperatorKind::BO_GE && Value == 0 && ContainerIsLHS) ||
+        (OpCode == BinaryOperatorKind::BO_LE && Value == 0 && !ContainerIsLHS))
+      return;
+
+    // Do not warn for size > 1, 1 < size, size <= 1, 1 >= size.
+    if (Value == 1) {
+      if ((OpCode == BinaryOperatorKind::BO_GT && ContainerIsLHS) ||
+          (OpCode == BinaryOperatorKind::BO_LT && !ContainerIsLHS))
+        return;
+      if ((OpCode == BinaryOperatorKind::BO_LE && ContainerIsLHS) ||
+          (OpCode == BinaryOperatorKind::BO_GE && !ContainerIsLHS))
+        return;
+    }
+
+    if (OpCode == BinaryOperatorKind::BO_NE && Value == 0)
+      Negation = true;
+    if ((OpCode == BinaryOperatorKind::BO_GT ||
+         OpCode == BinaryOperatorKind::BO_GE) &&
+        ContainerIsLHS)
+      Negation = true;
+    if ((OpCode == BinaryOperatorKind::BO_LT ||
+         OpCode == BinaryOperatorKind::BO_LE) &&
+        !ContainerIsLHS)
+      Negation = true;
+
+    if (Negation)
+      ReplacementText = "!" + ReplacementText;
+    Hint = FixItHint::CreateReplacement(BinaryOp->getSourceRange(),
+                                        ReplacementText);
+
+  } else {
+    // If there is a conversion above the size call to bool, it is safe to just
+    // replace size with empty.
+    if (const auto *UnaryOp =
+            Result.Nodes.getNodeAs<UnaryOperator>("NegOnSize"))
+      Hint = FixItHint::CreateReplacement(UnaryOp->getSourceRange(),
+                                          ReplacementText);
+    else
+      Hint = FixItHint::CreateReplacement(MemberCall->getSourceRange(),
+                                          "!" + ReplacementText);
+  }
+
+  if (MemberCall) {
+    diag(MemberCall->getLocStart(),
+         "the 'empty' method should be used to check "
+         "for emptiness instead of 'size'")
+        << Hint;
+  } else {
+    diag(BinCmp->getLocStart(),
+         "the 'empty' method should be used to check "
+         "for emptiness instead of comparing to an empty object")
+        << Hint;
+  }
+
+  const auto *Container = Result.Nodes.getNodeAs<NamedDecl>("container");
+  const auto *Empty = Result.Nodes.getNodeAs<FunctionDecl>("empty");
+
+  diag(Empty->getLocation(), "method %0::empty() defined here",
+       DiagnosticIDs::Note)
+      << Container;
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.h
new file mode 100644
index 0000000..bde83f8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.h
@@ -0,0 +1,40 @@
+//===--- ContainerSizeEmptyCheck.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_CONTAINERSIZEEMPTYCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_CONTAINERSIZEEMPTYCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Checks whether a call to the `size()` method can be replaced with a call to
+/// `empty()`.
+///
+/// The emptiness of a container should be checked using the `empty()` method
+/// instead of the `size()` method. It is not guaranteed that `size()` is a
+/// constant-time function, and it is generally more efficient and also shows
+/// clearer intent to use `empty()`. Furthermore some containers may implement
+/// the `empty()` method but not implement the `size()` method. Using `empty()`
+/// whenever possible makes it easier to switch to another container in the
+/// future.
+class ContainerSizeEmptyCheck : public ClangTidyCheck {
+public:
+  ContainerSizeEmptyCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_CONTAINERSIZEEMPTYCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp
new file mode 100644
index 0000000..766dfda
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp
@@ -0,0 +1,79 @@
+//===--- DeleteNullPointerCheck.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 "DeleteNullPointerCheck.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 readability {
+
+void DeleteNullPointerCheck::registerMatchers(MatchFinder *Finder) {
+  const auto DeleteExpr =
+      cxxDeleteExpr(has(castExpr(has(declRefExpr(
+                        to(decl(equalsBoundNode("deletedPointer"))))))))
+          .bind("deleteExpr");
+
+  const auto DeleteMemberExpr =
+      cxxDeleteExpr(has(castExpr(has(memberExpr(hasDeclaration(
+                        fieldDecl(equalsBoundNode("deletedMemberPointer"))))))))
+          .bind("deleteMemberExpr");
+
+  const auto PointerExpr = ignoringImpCasts(anyOf(
+      declRefExpr(to(decl().bind("deletedPointer"))),
+      memberExpr(hasDeclaration(fieldDecl().bind("deletedMemberPointer")))));
+
+  const auto PointerCondition = castExpr(hasCastKind(CK_PointerToBoolean),
+                                         hasSourceExpression(PointerExpr));
+  const auto BinaryPointerCheckCondition =
+      binaryOperator(hasEitherOperand(castExpr(hasCastKind(CK_NullToPointer))),
+                     hasEitherOperand(PointerExpr));
+
+  Finder->addMatcher(
+      ifStmt(hasCondition(anyOf(PointerCondition, BinaryPointerCheckCondition)),
+             hasThen(anyOf(
+                 DeleteExpr, DeleteMemberExpr,
+                 compoundStmt(anyOf(has(DeleteExpr), has(DeleteMemberExpr)),
+                              statementCountIs(1))
+                     .bind("compound"))))
+          .bind("ifWithDelete"),
+      this);
+}
+
+void DeleteNullPointerCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *IfWithDelete = Result.Nodes.getNodeAs<IfStmt>("ifWithDelete");
+  const auto *Compound = Result.Nodes.getNodeAs<CompoundStmt>("compound");
+
+  auto Diag = diag(
+      IfWithDelete->getLocStart(),
+      "'if' statement is unnecessary; deleting null pointer has no effect");
+  if (IfWithDelete->getElse())
+    return;
+  // FIXME: generate fixit for this case.
+
+  Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
+      IfWithDelete->getLocStart(),
+      Lexer::getLocForEndOfToken(IfWithDelete->getCond()->getLocEnd(), 0,
+                                 *Result.SourceManager,
+                                 Result.Context->getLangOpts())));
+  if (Compound) {
+    Diag << FixItHint::CreateRemoval(
+        CharSourceRange::getTokenRange(Compound->getLBracLoc()));
+    Diag << FixItHint::CreateRemoval(
+        CharSourceRange::getTokenRange(Compound->getRBracLoc()));
+  }
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.h
new file mode 100644
index 0000000..501f6f7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.h
@@ -0,0 +1,36 @@
+//===--- DeleteNullPointerCheck.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_DELETE_NULL_POINTER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DELETE_NULL_POINTER_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Check whether the 'if' statement is unnecessary before calling 'delete' on a
+/// pointer.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-delete-null-pointer.html
+class DeleteNullPointerCheck : public ClangTidyCheck {
+public:
+  DeleteNullPointerCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DELETE_NULL_POINTER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/DeletedDefaultCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/DeletedDefaultCheck.cpp
new file mode 100644
index 0000000..a197e8d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/DeletedDefaultCheck.cpp
@@ -0,0 +1,69 @@
+//===--- DeletedDefaultCheck.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 "DeletedDefaultCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void DeletedDefaultCheck::registerMatchers(MatchFinder *Finder) {
+  // We match constructors/assignment operators that are:
+  //   - explicitly marked '= default'
+  //   - actually deleted
+  //   - not in template instantiation.
+  // We bind the declaration to "method-decl" and also to "constructor" when
+  // it is a constructor.
+
+  Finder->addMatcher(
+      cxxMethodDecl(anyOf(cxxConstructorDecl().bind("constructor"),
+                          isCopyAssignmentOperator(),
+                          isMoveAssignmentOperator()),
+                    isDefaulted(), unless(isImplicit()), isDeleted(),
+                    unless(isInstantiated()))
+          .bind("method-decl"),
+      this);
+}
+
+void DeletedDefaultCheck::check(const MatchFinder::MatchResult &Result) {
+  const StringRef Message = "%0 is explicitly defaulted but implicitly "
+                            "deleted, probably because %1; definition can "
+                            "either be removed or explicitly deleted";
+  if (const auto *Constructor =
+          Result.Nodes.getNodeAs<CXXConstructorDecl>("constructor")) {
+    auto Diag = diag(Constructor->getLocStart(), Message);
+    if (Constructor->isDefaultConstructor()) {
+      Diag << "default constructor"
+           << "a non-static data member or a base class is lacking a default "
+              "constructor";
+    } else if (Constructor->isCopyConstructor()) {
+      Diag << "copy constructor"
+           << "a non-static data member or a base class is not copyable";
+    } else if (Constructor->isMoveConstructor()) {
+      Diag << "move constructor"
+           << "a non-static data member or a base class is neither copyable "
+              "nor movable";
+    }
+  } else if (const auto *Assignment =
+                 Result.Nodes.getNodeAs<CXXMethodDecl>("method-decl")) {
+    diag(Assignment->getLocStart(), Message)
+        << (Assignment->isCopyAssignmentOperator() ? "copy assignment operator"
+                                                   : "move assignment operator")
+        << "a base class or a non-static data member is not assignable, e.g. "
+           "because the latter is marked 'const'";
+  }
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/DeletedDefaultCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/DeletedDefaultCheck.h
new file mode 100644
index 0000000..0608b07
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/DeletedDefaultCheck.h
@@ -0,0 +1,36 @@
+//===--- DeletedDefaultCheck.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_DELETED_DEFAULT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DELETED_DEFAULT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Checks when a constructor or an assignment operator is marked as '= default'
+/// but is actually deleted by the compiler.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-deleted-default.html
+class DeletedDefaultCheck : public ClangTidyCheck {
+public:
+  DeletedDefaultCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DELETED_DEFAULT_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp
new file mode 100644
index 0000000..8b5526c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp
@@ -0,0 +1,57 @@
+//===--- ElseAfterReturnCheck.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 "ElseAfterReturnCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void ElseAfterReturnCheck::registerMatchers(MatchFinder *Finder) {
+  const auto ControlFlowInterruptorMatcher =
+      stmt(anyOf(returnStmt().bind("return"), continueStmt().bind("continue"),
+                 breakStmt().bind("break"),
+                 expr(ignoringImplicit(cxxThrowExpr().bind("throw")))));
+  Finder->addMatcher(
+      compoundStmt(forEach(
+          ifStmt(hasThen(stmt(
+                     anyOf(ControlFlowInterruptorMatcher,
+                           compoundStmt(has(ControlFlowInterruptorMatcher))))),
+                 hasElse(stmt().bind("else")))
+              .bind("if"))),
+      this);
+}
+
+void ElseAfterReturnCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
+  SourceLocation ElseLoc = If->getElseLoc();
+  std::string ControlFlowInterruptor;
+  for (const auto *BindingName : {"return", "continue", "break", "throw"})
+    if (Result.Nodes.getNodeAs<Stmt>(BindingName))
+      ControlFlowInterruptor = BindingName;
+
+  DiagnosticBuilder Diag = diag(ElseLoc, "do not use 'else' after '%0'")
+                           << ControlFlowInterruptor;
+  Diag << tooling::fixit::createRemoval(ElseLoc);
+
+  // FIXME: Removing the braces isn't always safe. Do a more careful analysis.
+  // FIXME: Change clang-format to correctly un-indent the code.
+  if (const auto *CS = Result.Nodes.getNodeAs<CompoundStmt>("else"))
+    Diag << tooling::fixit::createRemoval(CS->getLBracLoc())
+         << tooling::fixit::createRemoval(CS->getRBracLoc());
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.h
new file mode 100644
index 0000000..8479ab5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.h
@@ -0,0 +1,34 @@
+//===--- ElseAfterReturnCheck.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_ELSEAFTERRETURNCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_ELSEAFTERRETURNCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Flags the usages of `else` after `return`.
+///
+/// http://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return
+class ElseAfterReturnCheck : public ClangTidyCheck {
+public:
+  ElseAfterReturnCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_ELSEAFTERRETURNCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/FunctionSizeCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/FunctionSizeCheck.cpp
new file mode 100644
index 0000000..8ed6b90
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/FunctionSizeCheck.cpp
@@ -0,0 +1,221 @@
+//===--- FunctionSize.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 "FunctionSizeCheck.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+namespace {
+
+class FunctionASTVisitor : public RecursiveASTVisitor<FunctionASTVisitor> {
+  using Base = RecursiveASTVisitor<FunctionASTVisitor>;
+
+public:
+  bool VisitVarDecl(VarDecl *VD) {
+    // Do not count function params.
+    // Do not count decomposition declarations (C++17's structured bindings).
+    if (StructNesting == 0 &&
+        !(isa<ParmVarDecl>(VD) || isa<DecompositionDecl>(VD)))
+      ++Info.Variables;
+    return true;
+  }
+  bool VisitBindingDecl(BindingDecl *BD) {
+    // Do count each of the bindings (in the decomposition declaration).
+    if (StructNesting == 0)
+      ++Info.Variables;
+    return true;
+  }
+
+  bool TraverseStmt(Stmt *Node) {
+    if (!Node)
+      return Base::TraverseStmt(Node);
+
+    if (TrackedParent.back() && !isa<CompoundStmt>(Node))
+      ++Info.Statements;
+
+    switch (Node->getStmtClass()) {
+    case Stmt::IfStmtClass:
+    case Stmt::WhileStmtClass:
+    case Stmt::DoStmtClass:
+    case Stmt::CXXForRangeStmtClass:
+    case Stmt::ForStmtClass:
+    case Stmt::SwitchStmtClass:
+      ++Info.Branches;
+      LLVM_FALLTHROUGH;
+    case Stmt::CompoundStmtClass:
+      TrackedParent.push_back(true);
+      break;
+    default:
+      TrackedParent.push_back(false);
+      break;
+    }
+
+    Base::TraverseStmt(Node);
+
+    TrackedParent.pop_back();
+
+    return true;
+  }
+
+  bool TraverseCompoundStmt(CompoundStmt *Node) {
+    // If this new compound statement is located in a compound statement, which
+    // is already nested NestingThreshold levels deep, record the start location
+    // of this new compound statement.
+    if (CurrentNestingLevel == Info.NestingThreshold)
+      Info.NestingThresholders.push_back(Node->getLocStart());
+
+    ++CurrentNestingLevel;
+    Base::TraverseCompoundStmt(Node);
+    --CurrentNestingLevel;
+
+    return true;
+  }
+
+  bool TraverseDecl(Decl *Node) {
+    TrackedParent.push_back(false);
+    Base::TraverseDecl(Node);
+    TrackedParent.pop_back();
+    return true;
+  }
+
+  bool TraverseLambdaExpr(LambdaExpr *Node) {
+    ++StructNesting;
+    Base::TraverseLambdaExpr(Node);
+    --StructNesting;
+    return true;
+  }
+
+  bool TraverseCXXRecordDecl(CXXRecordDecl *Node) {
+    ++StructNesting;
+    Base::TraverseCXXRecordDecl(Node);
+    --StructNesting;
+    return true;
+  }
+
+  bool TraverseStmtExpr(StmtExpr *SE) {
+    ++StructNesting;
+    Base::TraverseStmtExpr(SE);
+    --StructNesting;
+    return true;
+  }
+
+  struct FunctionInfo {
+    unsigned Lines = 0;
+    unsigned Statements = 0;
+    unsigned Branches = 0;
+    unsigned NestingThreshold = 0;
+    unsigned Variables = 0;
+    std::vector<SourceLocation> NestingThresholders;
+  };
+  FunctionInfo Info;
+  std::vector<bool> TrackedParent;
+  unsigned StructNesting = 0;
+  unsigned CurrentNestingLevel = 0;
+};
+
+} // namespace
+
+FunctionSizeCheck::FunctionSizeCheck(StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      LineThreshold(Options.get("LineThreshold", -1U)),
+      StatementThreshold(Options.get("StatementThreshold", 800U)),
+      BranchThreshold(Options.get("BranchThreshold", -1U)),
+      ParameterThreshold(Options.get("ParameterThreshold", -1U)),
+      NestingThreshold(Options.get("NestingThreshold", -1U)),
+      VariableThreshold(Options.get("VariableThreshold", -1U)) {}
+
+void FunctionSizeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "LineThreshold", LineThreshold);
+  Options.store(Opts, "StatementThreshold", StatementThreshold);
+  Options.store(Opts, "BranchThreshold", BranchThreshold);
+  Options.store(Opts, "ParameterThreshold", ParameterThreshold);
+  Options.store(Opts, "NestingThreshold", NestingThreshold);
+  Options.store(Opts, "VariableThreshold", VariableThreshold);
+}
+
+void FunctionSizeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(functionDecl(unless(isInstantiated())).bind("func"), this);
+}
+
+void FunctionSizeCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func");
+
+  FunctionASTVisitor Visitor;
+  Visitor.Info.NestingThreshold = NestingThreshold;
+  Visitor.TraverseDecl(const_cast<FunctionDecl *>(Func));
+  auto &FI = Visitor.Info;
+
+  if (FI.Statements == 0)
+    return;
+
+  // Count the lines including whitespace and comments. Really simple.
+  if (const Stmt *Body = Func->getBody()) {
+    SourceManager *SM = Result.SourceManager;
+    if (SM->isWrittenInSameFile(Body->getLocStart(), Body->getLocEnd())) {
+      FI.Lines = SM->getSpellingLineNumber(Body->getLocEnd()) -
+                 SM->getSpellingLineNumber(Body->getLocStart());
+    }
+  }
+
+  unsigned ActualNumberParameters = Func->getNumParams();
+
+  if (FI.Lines > LineThreshold || FI.Statements > StatementThreshold ||
+      FI.Branches > BranchThreshold ||
+      ActualNumberParameters > ParameterThreshold ||
+      !FI.NestingThresholders.empty() || FI.Variables > VariableThreshold) {
+    diag(Func->getLocation(),
+         "function %0 exceeds recommended size/complexity thresholds")
+        << Func;
+  }
+
+  if (FI.Lines > LineThreshold) {
+    diag(Func->getLocation(),
+         "%0 lines including whitespace and comments (threshold %1)",
+         DiagnosticIDs::Note)
+        << FI.Lines << LineThreshold;
+  }
+
+  if (FI.Statements > StatementThreshold) {
+    diag(Func->getLocation(), "%0 statements (threshold %1)",
+         DiagnosticIDs::Note)
+        << FI.Statements << StatementThreshold;
+  }
+
+  if (FI.Branches > BranchThreshold) {
+    diag(Func->getLocation(), "%0 branches (threshold %1)", DiagnosticIDs::Note)
+        << FI.Branches << BranchThreshold;
+  }
+
+  if (ActualNumberParameters > ParameterThreshold) {
+    diag(Func->getLocation(), "%0 parameters (threshold %1)",
+         DiagnosticIDs::Note)
+        << ActualNumberParameters << ParameterThreshold;
+  }
+
+  for (const auto &CSPos : FI.NestingThresholders) {
+    diag(CSPos, "nesting level %0 starts here (threshold %1)",
+         DiagnosticIDs::Note)
+        << NestingThreshold + 1 << NestingThreshold;
+  }
+
+  if (FI.Variables > VariableThreshold) {
+    diag(Func->getLocation(), "%0 variables (threshold %1)",
+         DiagnosticIDs::Note)
+        << FI.Variables << VariableThreshold;
+  }
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/FunctionSizeCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/FunctionSizeCheck.h
new file mode 100644
index 0000000..7defccd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/FunctionSizeCheck.h
@@ -0,0 +1,59 @@
+//===--- FunctionSizeCheck.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_FUNCTIONSIZECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_FUNCTIONSIZECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Checks for large functions based on various metrics.
+///
+/// These options are supported:
+///
+///   * `LineThreshold` - flag functions exceeding this number of lines. The
+///     default is `-1` (ignore the number of lines).
+///   * `StatementThreshold` - flag functions exceeding this number of
+///     statements. This may differ significantly from the number of lines for
+///     macro-heavy code. The default is `800`.
+///   * `BranchThreshold` - flag functions exceeding this number of control
+///     statements. The default is `-1` (ignore the number of branches).
+///   * `ParameterThreshold` - flag functions having a high number of
+///     parameters. The default is `-1` (ignore the number of parameters).
+///   * `NestingThreshold` - flag compound statements which create next nesting
+///     level after `NestingThreshold`. This may differ significantly from the
+///     expected value for macro-heavy code. The default is `-1` (ignore the
+///     nesting level).
+///   * `VariableThreshold` - flag functions having a high number of variable
+///     declarations. The default is `-1` (ignore the number of variables).
+class FunctionSizeCheck : public ClangTidyCheck {
+public:
+  FunctionSizeCheck(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 unsigned LineThreshold;
+  const unsigned StatementThreshold;
+  const unsigned BranchThreshold;
+  const unsigned ParameterThreshold;
+  const unsigned NestingThreshold;
+  const unsigned VariableThreshold;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_FUNCTIONSIZECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp
new file mode 100644
index 0000000..46919d3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp
@@ -0,0 +1,942 @@
+//===--- IdentifierNamingCheck.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 "IdentifierNamingCheck.h"
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
+
+#define DEBUG_TYPE "clang-tidy"
+
+using namespace clang::ast_matchers;
+
+namespace llvm {
+/// Specialisation of DenseMapInfo to allow NamingCheckId objects in DenseMaps
+template <>
+struct DenseMapInfo<
+    clang::tidy::readability::IdentifierNamingCheck::NamingCheckId> {
+  using NamingCheckId =
+      clang::tidy::readability::IdentifierNamingCheck::NamingCheckId;
+
+  static inline NamingCheckId getEmptyKey() {
+    return NamingCheckId(
+        clang::SourceLocation::getFromRawEncoding(static_cast<unsigned>(-1)),
+        "EMPTY");
+  }
+
+  static inline NamingCheckId getTombstoneKey() {
+    return NamingCheckId(
+        clang::SourceLocation::getFromRawEncoding(static_cast<unsigned>(-2)),
+        "TOMBSTONE");
+  }
+
+  static unsigned getHashValue(NamingCheckId Val) {
+    assert(Val != getEmptyKey() && "Cannot hash the empty key!");
+    assert(Val != getTombstoneKey() && "Cannot hash the tombstone key!");
+
+    std::hash<NamingCheckId::second_type> SecondHash;
+    return Val.first.getRawEncoding() + SecondHash(Val.second);
+  }
+
+  static bool isEqual(const NamingCheckId &LHS, const NamingCheckId &RHS) {
+    if (RHS == getEmptyKey())
+      return LHS == getEmptyKey();
+    if (RHS == getTombstoneKey())
+      return LHS == getTombstoneKey();
+    return LHS == RHS;
+  }
+};
+} // namespace llvm
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+// clang-format off
+#define NAMING_KEYS(m) \
+    m(Namespace) \
+    m(InlineNamespace) \
+    m(EnumConstant) \
+    m(ConstexprVariable) \
+    m(ConstantMember) \
+    m(PrivateMember) \
+    m(ProtectedMember) \
+    m(PublicMember) \
+    m(Member) \
+    m(ClassConstant) \
+    m(ClassMember) \
+    m(GlobalConstant) \
+    m(GlobalVariable) \
+    m(LocalConstant) \
+    m(LocalVariable) \
+    m(StaticConstant) \
+    m(StaticVariable) \
+    m(Constant) \
+    m(Variable) \
+    m(ConstantParameter) \
+    m(ParameterPack) \
+    m(Parameter) \
+    m(AbstractClass) \
+    m(Struct) \
+    m(Class) \
+    m(Union) \
+    m(Enum) \
+    m(GlobalFunction) \
+    m(ConstexprFunction) \
+    m(Function) \
+    m(ConstexprMethod) \
+    m(VirtualMethod) \
+    m(ClassMethod) \
+    m(PrivateMethod) \
+    m(ProtectedMethod) \
+    m(PublicMethod) \
+    m(Method) \
+    m(Typedef) \
+    m(TypeTemplateParameter) \
+    m(ValueTemplateParameter) \
+    m(TemplateTemplateParameter) \
+    m(TemplateParameter) \
+    m(TypeAlias) \
+    m(MacroDefinition) \
+    m(ObjcIvar) \
+
+enum StyleKind {
+#define ENUMERATE(v) SK_ ## v,
+  NAMING_KEYS(ENUMERATE)
+#undef ENUMERATE
+  SK_Count,
+  SK_Invalid
+};
+
+static StringRef const StyleNames[] = {
+#define STRINGIZE(v) #v,
+  NAMING_KEYS(STRINGIZE)
+#undef STRINGIZE
+};
+
+#undef NAMING_KEYS
+// clang-format on
+
+namespace {
+/// Callback supplies macros to IdentifierNamingCheck::checkMacro
+class IdentifierNamingCheckPPCallbacks : public PPCallbacks {
+public:
+  IdentifierNamingCheckPPCallbacks(Preprocessor *PP,
+                                   IdentifierNamingCheck *Check)
+      : PP(PP), Check(Check) {}
+
+  /// MacroDefined calls checkMacro for macros in the main file
+  void MacroDefined(const Token &MacroNameTok,
+                    const MacroDirective *MD) override {
+    Check->checkMacro(PP->getSourceManager(), MacroNameTok, MD->getMacroInfo());
+  }
+
+  /// MacroExpands calls expandMacro for macros in the main file
+  void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
+                    SourceRange /*Range*/,
+                    const MacroArgs * /*Args*/) override {
+    Check->expandMacro(MacroNameTok, MD.getMacroInfo());
+  }
+
+private:
+  Preprocessor *PP;
+  IdentifierNamingCheck *Check;
+};
+} // namespace
+
+IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name,
+                                             ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context) {
+  auto const fromString = [](StringRef Str) {
+    return llvm::StringSwitch<llvm::Optional<CaseType>>(Str)
+        .Case("aNy_CasE", CT_AnyCase)
+        .Case("lower_case", CT_LowerCase)
+        .Case("UPPER_CASE", CT_UpperCase)
+        .Case("camelBack", CT_CamelBack)
+        .Case("CamelCase", CT_CamelCase)
+        .Case("Camel_Snake_Case", CT_CamelSnakeCase)
+        .Case("camel_Snake_Back", CT_CamelSnakeBack)
+        .Default(llvm::None);
+  };
+
+  for (auto const &Name : StyleNames) {
+    auto const caseOptional =
+        fromString(Options.get((Name + "Case").str(), ""));
+    auto prefix = Options.get((Name + "Prefix").str(), "");
+    auto postfix = Options.get((Name + "Suffix").str(), "");
+
+    if (caseOptional || !prefix.empty() || !postfix.empty()) {
+      NamingStyles.push_back(NamingStyle(caseOptional, prefix, postfix));
+    } else {
+      NamingStyles.push_back(llvm::None);
+    }
+  }
+
+  IgnoreFailedSplit = Options.get("IgnoreFailedSplit", 0);
+}
+
+void IdentifierNamingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  auto const toString = [](CaseType Type) {
+    switch (Type) {
+    case CT_AnyCase:
+      return "aNy_CasE";
+    case CT_LowerCase:
+      return "lower_case";
+    case CT_CamelBack:
+      return "camelBack";
+    case CT_UpperCase:
+      return "UPPER_CASE";
+    case CT_CamelCase:
+      return "CamelCase";
+    case CT_CamelSnakeCase:
+      return "Camel_Snake_Case";
+    case CT_CamelSnakeBack:
+      return "camel_Snake_Back";
+    }
+
+    llvm_unreachable("Unknown Case Type");
+  };
+
+  for (size_t i = 0; i < SK_Count; ++i) {
+    if (NamingStyles[i]) {
+      if (NamingStyles[i]->Case) {
+        Options.store(Opts, (StyleNames[i] + "Case").str(),
+                      toString(*NamingStyles[i]->Case));
+      }
+      Options.store(Opts, (StyleNames[i] + "Prefix").str(),
+                    NamingStyles[i]->Prefix);
+      Options.store(Opts, (StyleNames[i] + "Suffix").str(),
+                    NamingStyles[i]->Suffix);
+    }
+  }
+
+  Options.store(Opts, "IgnoreFailedSplit", IgnoreFailedSplit);
+}
+
+void IdentifierNamingCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(namedDecl().bind("decl"), this);
+  Finder->addMatcher(usingDecl().bind("using"), this);
+  Finder->addMatcher(declRefExpr().bind("declRef"), this);
+  Finder->addMatcher(cxxConstructorDecl().bind("classRef"), this);
+  Finder->addMatcher(cxxDestructorDecl().bind("classRef"), this);
+  Finder->addMatcher(typeLoc().bind("typeLoc"), this);
+  Finder->addMatcher(nestedNameSpecifierLoc().bind("nestedNameLoc"), this);
+}
+
+void IdentifierNamingCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  Compiler.getPreprocessor().addPPCallbacks(
+      llvm::make_unique<IdentifierNamingCheckPPCallbacks>(
+          &Compiler.getPreprocessor(), this));
+}
+
+static bool matchesStyle(StringRef Name,
+                         IdentifierNamingCheck::NamingStyle Style) {
+  static llvm::Regex Matchers[] = {
+      llvm::Regex("^.*$"),
+      llvm::Regex("^[a-z][a-z0-9_]*$"),
+      llvm::Regex("^[a-z][a-zA-Z0-9]*$"),
+      llvm::Regex("^[A-Z][A-Z0-9_]*$"),
+      llvm::Regex("^[A-Z][a-zA-Z0-9]*$"),
+      llvm::Regex("^[A-Z]([a-z0-9]*(_[A-Z])?)*"),
+      llvm::Regex("^[a-z]([a-z0-9]*(_[A-Z])?)*"),
+  };
+
+  bool Matches = true;
+  if (Name.startswith(Style.Prefix))
+    Name = Name.drop_front(Style.Prefix.size());
+  else
+    Matches = false;
+
+  if (Name.endswith(Style.Suffix))
+    Name = Name.drop_back(Style.Suffix.size());
+  else
+    Matches = false;
+
+  // Ensure the name doesn't have any extra underscores beyond those specified
+  // in the prefix and suffix.
+  if (Name.startswith("_") || Name.endswith("_"))
+    Matches = false;
+
+  if (Style.Case && !Matchers[static_cast<size_t>(*Style.Case)].match(Name))
+    Matches = false;
+
+  return Matches;
+}
+
+static std::string fixupWithCase(StringRef Name,
+                                 IdentifierNamingCheck::CaseType Case) {
+  static llvm::Regex Splitter(
+      "([a-z0-9A-Z]*)(_+)|([A-Z]?[a-z0-9]+)([A-Z]|$)|([A-Z]+)([A-Z]|$)");
+
+  SmallVector<StringRef, 8> Substrs;
+  Name.split(Substrs, "_", -1, false);
+
+  SmallVector<StringRef, 8> Words;
+  for (auto Substr : Substrs) {
+    while (!Substr.empty()) {
+      SmallVector<StringRef, 8> Groups;
+      if (!Splitter.match(Substr, &Groups))
+        break;
+
+      if (Groups[2].size() > 0) {
+        Words.push_back(Groups[1]);
+        Substr = Substr.substr(Groups[0].size());
+      } else if (Groups[3].size() > 0) {
+        Words.push_back(Groups[3]);
+        Substr = Substr.substr(Groups[0].size() - Groups[4].size());
+      } else if (Groups[5].size() > 0) {
+        Words.push_back(Groups[5]);
+        Substr = Substr.substr(Groups[0].size() - Groups[6].size());
+      }
+    }
+  }
+
+  if (Words.empty())
+    return Name;
+
+  std::string Fixup;
+  switch (Case) {
+  case IdentifierNamingCheck::CT_AnyCase:
+    Fixup += Name;
+    break;
+
+  case IdentifierNamingCheck::CT_LowerCase:
+    for (auto const &Word : Words) {
+      if (&Word != &Words.front())
+        Fixup += "_";
+      Fixup += Word.lower();
+    }
+    break;
+
+  case IdentifierNamingCheck::CT_UpperCase:
+    for (auto const &Word : Words) {
+      if (&Word != &Words.front())
+        Fixup += "_";
+      Fixup += Word.upper();
+    }
+    break;
+
+  case IdentifierNamingCheck::CT_CamelCase:
+    for (auto const &Word : Words) {
+      Fixup += Word.substr(0, 1).upper();
+      Fixup += Word.substr(1).lower();
+    }
+    break;
+
+  case IdentifierNamingCheck::CT_CamelBack:
+    for (auto const &Word : Words) {
+      if (&Word == &Words.front()) {
+        Fixup += Word.lower();
+      } else {
+        Fixup += Word.substr(0, 1).upper();
+        Fixup += Word.substr(1).lower();
+      }
+    }
+    break;
+
+  case IdentifierNamingCheck::CT_CamelSnakeCase:
+    for (auto const &Word : Words) {
+      if (&Word != &Words.front())
+        Fixup += "_";
+      Fixup += Word.substr(0, 1).upper();
+      Fixup += Word.substr(1).lower();
+    }
+    break;
+
+  case IdentifierNamingCheck::CT_CamelSnakeBack:
+    for (auto const &Word : Words) {
+      if (&Word != &Words.front()) {
+        Fixup += "_";
+        Fixup += Word.substr(0, 1).upper();
+      } else {
+        Fixup += Word.substr(0, 1).lower();
+      }
+      Fixup += Word.substr(1).lower();
+    }
+    break;
+  }
+
+  return Fixup;
+}
+
+static std::string
+fixupWithStyle(StringRef Name,
+               const IdentifierNamingCheck::NamingStyle &Style) {
+  const std::string Fixed = fixupWithCase(
+      Name, Style.Case.getValueOr(IdentifierNamingCheck::CaseType::CT_AnyCase));
+  StringRef Mid = StringRef(Fixed).trim("_");
+  if (Mid.empty())
+    Mid = "_";
+  return (Style.Prefix + Mid + Style.Suffix).str();
+}
+
+static StyleKind findStyleKind(
+    const NamedDecl *D,
+    const std::vector<llvm::Optional<IdentifierNamingCheck::NamingStyle>>
+        &NamingStyles) {
+  if (isa<ObjCIvarDecl>(D) && NamingStyles[SK_ObjcIvar])
+    return SK_ObjcIvar;
+  
+  if (isa<TypedefDecl>(D) && NamingStyles[SK_Typedef])
+    return SK_Typedef;
+
+  if (isa<TypeAliasDecl>(D) && NamingStyles[SK_TypeAlias])
+    return SK_TypeAlias;
+
+  if (const auto *Decl = dyn_cast<NamespaceDecl>(D)) {
+    if (Decl->isAnonymousNamespace())
+      return SK_Invalid;
+
+    if (Decl->isInline() && NamingStyles[SK_InlineNamespace])
+      return SK_InlineNamespace;
+
+    if (NamingStyles[SK_Namespace])
+      return SK_Namespace;
+  }
+
+  if (isa<EnumDecl>(D) && NamingStyles[SK_Enum])
+    return SK_Enum;
+
+  if (isa<EnumConstantDecl>(D)) {
+    if (NamingStyles[SK_EnumConstant])
+      return SK_EnumConstant;
+
+    if (NamingStyles[SK_Constant])
+      return SK_Constant;
+
+    return SK_Invalid;
+  }
+
+  if (const auto *Decl = dyn_cast<CXXRecordDecl>(D)) {
+    if (Decl->isAnonymousStructOrUnion())
+      return SK_Invalid;
+
+    if (!Decl->getCanonicalDecl()->isThisDeclarationADefinition())
+      return SK_Invalid;
+
+    if (Decl->hasDefinition() && Decl->isAbstract() &&
+        NamingStyles[SK_AbstractClass])
+      return SK_AbstractClass;
+
+    if (Decl->isStruct() && NamingStyles[SK_Struct])
+      return SK_Struct;
+
+    if (Decl->isStruct() && NamingStyles[SK_Class])
+      return SK_Class;
+
+    if (Decl->isClass() && NamingStyles[SK_Class])
+      return SK_Class;
+
+    if (Decl->isClass() && NamingStyles[SK_Struct])
+      return SK_Struct;
+
+    if (Decl->isUnion() && NamingStyles[SK_Union])
+      return SK_Union;
+
+    if (Decl->isEnum() && NamingStyles[SK_Enum])
+      return SK_Enum;
+
+    return SK_Invalid;
+  }
+
+  if (const auto *Decl = dyn_cast<FieldDecl>(D)) {
+    QualType Type = Decl->getType();
+
+    if (!Type.isNull() && Type.isConstQualified()) {
+      if (NamingStyles[SK_ConstantMember])
+        return SK_ConstantMember;
+
+      if (NamingStyles[SK_Constant])
+        return SK_Constant;
+    }
+
+    if (Decl->getAccess() == AS_private && NamingStyles[SK_PrivateMember])
+      return SK_PrivateMember;
+
+    if (Decl->getAccess() == AS_protected && NamingStyles[SK_ProtectedMember])
+      return SK_ProtectedMember;
+
+    if (Decl->getAccess() == AS_public && NamingStyles[SK_PublicMember])
+      return SK_PublicMember;
+
+    if (NamingStyles[SK_Member])
+      return SK_Member;
+
+    return SK_Invalid;
+  }
+
+  if (const auto *Decl = dyn_cast<ParmVarDecl>(D)) {
+    QualType Type = Decl->getType();
+
+    if (Decl->isConstexpr() && NamingStyles[SK_ConstexprVariable])
+      return SK_ConstexprVariable;
+
+    if (!Type.isNull() && Type.isConstQualified()) {
+      if (NamingStyles[SK_ConstantParameter])
+        return SK_ConstantParameter;
+
+      if (NamingStyles[SK_Constant])
+        return SK_Constant;
+    }
+
+    if (Decl->isParameterPack() && NamingStyles[SK_ParameterPack])
+      return SK_ParameterPack;
+
+    if (NamingStyles[SK_Parameter])
+      return SK_Parameter;
+
+    return SK_Invalid;
+  }
+
+  if (const auto *Decl = dyn_cast<VarDecl>(D)) {
+    QualType Type = Decl->getType();
+
+    if (Decl->isConstexpr() && NamingStyles[SK_ConstexprVariable])
+      return SK_ConstexprVariable;
+
+    if (!Type.isNull() && Type.isConstQualified()) {
+      if (Decl->isStaticDataMember() && NamingStyles[SK_ClassConstant])
+        return SK_ClassConstant;
+
+      if (Decl->isFileVarDecl() && NamingStyles[SK_GlobalConstant])
+        return SK_GlobalConstant;
+
+      if (Decl->isStaticLocal() && NamingStyles[SK_StaticConstant])
+        return SK_StaticConstant;
+
+      if (Decl->isLocalVarDecl() && NamingStyles[SK_LocalConstant])
+        return SK_LocalConstant;
+
+      if (Decl->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalConstant])
+        return SK_LocalConstant;
+
+      if (NamingStyles[SK_Constant])
+        return SK_Constant;
+    }
+
+    if (Decl->isStaticDataMember() && NamingStyles[SK_ClassMember])
+      return SK_ClassMember;
+
+    if (Decl->isFileVarDecl() && NamingStyles[SK_GlobalVariable])
+      return SK_GlobalVariable;
+
+    if (Decl->isStaticLocal() && NamingStyles[SK_StaticVariable])
+      return SK_StaticVariable;
+
+    if (Decl->isLocalVarDecl() && NamingStyles[SK_LocalVariable])
+      return SK_LocalVariable;
+
+    if (Decl->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalVariable])
+      return SK_LocalVariable;
+
+    if (NamingStyles[SK_Variable])
+      return SK_Variable;
+
+    return SK_Invalid;
+  }
+
+  if (const auto *Decl = dyn_cast<CXXMethodDecl>(D)) {
+    if (Decl->isMain() || !Decl->isUserProvided() ||
+        Decl->isUsualDeallocationFunction() ||
+        Decl->isCopyAssignmentOperator() || Decl->isMoveAssignmentOperator() ||
+        Decl->size_overridden_methods() > 0)
+      return SK_Invalid;
+
+    if (Decl->isConstexpr() && NamingStyles[SK_ConstexprMethod])
+      return SK_ConstexprMethod;
+
+    if (Decl->isConstexpr() && NamingStyles[SK_ConstexprFunction])
+      return SK_ConstexprFunction;
+
+    if (Decl->isStatic() && NamingStyles[SK_ClassMethod])
+      return SK_ClassMethod;
+
+    if (Decl->isVirtual() && NamingStyles[SK_VirtualMethod])
+      return SK_VirtualMethod;
+
+    if (Decl->getAccess() == AS_private && NamingStyles[SK_PrivateMethod])
+      return SK_PrivateMethod;
+
+    if (Decl->getAccess() == AS_protected && NamingStyles[SK_ProtectedMethod])
+      return SK_ProtectedMethod;
+
+    if (Decl->getAccess() == AS_public && NamingStyles[SK_PublicMethod])
+      return SK_PublicMethod;
+
+    if (NamingStyles[SK_Method])
+      return SK_Method;
+
+    if (NamingStyles[SK_Function])
+      return SK_Function;
+
+    return SK_Invalid;
+  }
+
+  if (const auto *Decl = dyn_cast<FunctionDecl>(D)) {
+    if (Decl->isMain())
+      return SK_Invalid;
+
+    if (Decl->isConstexpr() && NamingStyles[SK_ConstexprFunction])
+      return SK_ConstexprFunction;
+
+    if (Decl->isGlobal() && NamingStyles[SK_GlobalFunction])
+      return SK_GlobalFunction;
+
+    if (NamingStyles[SK_Function])
+      return SK_Function;
+  }
+
+  if (isa<TemplateTypeParmDecl>(D)) {
+    if (NamingStyles[SK_TypeTemplateParameter])
+      return SK_TypeTemplateParameter;
+
+    if (NamingStyles[SK_TemplateParameter])
+      return SK_TemplateParameter;
+
+    return SK_Invalid;
+  }
+
+  if (isa<NonTypeTemplateParmDecl>(D)) {
+    if (NamingStyles[SK_ValueTemplateParameter])
+      return SK_ValueTemplateParameter;
+
+    if (NamingStyles[SK_TemplateParameter])
+      return SK_TemplateParameter;
+
+    return SK_Invalid;
+  }
+
+  if (isa<TemplateTemplateParmDecl>(D)) {
+    if (NamingStyles[SK_TemplateTemplateParameter])
+      return SK_TemplateTemplateParameter;
+
+    if (NamingStyles[SK_TemplateParameter])
+      return SK_TemplateParameter;
+
+    return SK_Invalid;
+  }
+
+  return SK_Invalid;
+}
+
+static void addUsage(IdentifierNamingCheck::NamingCheckFailureMap &Failures,
+                     const IdentifierNamingCheck::NamingCheckId &Decl,
+                     SourceRange Range, SourceManager *SourceMgr = nullptr) {
+  // Do nothing if the provided range is invalid.
+  if (Range.getBegin().isInvalid() || Range.getEnd().isInvalid())
+    return;
+
+  // If we have a source manager, use it to convert to the spelling location for
+  // performing the fix. This is necessary because macros can map the same
+  // spelling location to different source locations, and we only want to fix
+  // the token once, before it is expanded by the macro.
+  SourceLocation FixLocation = Range.getBegin();
+  if (SourceMgr)
+    FixLocation = SourceMgr->getSpellingLoc(FixLocation);
+  if (FixLocation.isInvalid())
+    return;
+
+  // Try to insert the identifier location in the Usages map, and bail out if it
+  // is already in there
+  auto &Failure = Failures[Decl];
+  if (!Failure.RawUsageLocs.insert(FixLocation.getRawEncoding()).second)
+    return;
+
+  if (!Failure.ShouldFix)
+    return;
+
+  // Check if the range is entirely contained within a macro argument.
+  SourceLocation MacroArgExpansionStartForRangeBegin;
+  SourceLocation MacroArgExpansionStartForRangeEnd;
+  bool RangeIsEntirelyWithinMacroArgument =
+      SourceMgr &&
+      SourceMgr->isMacroArgExpansion(Range.getBegin(),
+                                     &MacroArgExpansionStartForRangeBegin) &&
+      SourceMgr->isMacroArgExpansion(Range.getEnd(),
+                                     &MacroArgExpansionStartForRangeEnd) &&
+      MacroArgExpansionStartForRangeBegin == MacroArgExpansionStartForRangeEnd;
+
+  // Check if the range contains any locations from a macro expansion.
+  bool RangeContainsMacroExpansion = RangeIsEntirelyWithinMacroArgument ||
+                                     Range.getBegin().isMacroID() ||
+                                     Range.getEnd().isMacroID();
+
+  bool RangeCanBeFixed =
+      RangeIsEntirelyWithinMacroArgument || !RangeContainsMacroExpansion;
+  Failure.ShouldFix = RangeCanBeFixed;
+}
+
+/// Convenience method when the usage to be added is a NamedDecl
+static void addUsage(IdentifierNamingCheck::NamingCheckFailureMap &Failures,
+                     const NamedDecl *Decl, SourceRange Range,
+                     SourceManager *SourceMgr = nullptr) {
+  return addUsage(Failures,
+                  IdentifierNamingCheck::NamingCheckId(Decl->getLocation(),
+                                                       Decl->getNameAsString()),
+                  Range, SourceMgr);
+}
+
+void IdentifierNamingCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *Decl =
+          Result.Nodes.getNodeAs<CXXConstructorDecl>("classRef")) {
+    if (Decl->isImplicit())
+      return;
+
+    addUsage(NamingCheckFailures, Decl->getParent(),
+             Decl->getNameInfo().getSourceRange());
+
+    for (const auto *Init : Decl->inits()) {
+      if (!Init->isWritten() || Init->isInClassMemberInitializer())
+        continue;
+      if (const auto *FD = Init->getAnyMember())
+        addUsage(NamingCheckFailures, FD,
+                 SourceRange(Init->getMemberLocation()));
+      // Note: delegating constructors and base class initializers are handled
+      // via the "typeLoc" matcher.
+    }
+    return;
+  }
+
+  if (const auto *Decl =
+          Result.Nodes.getNodeAs<CXXDestructorDecl>("classRef")) {
+    if (Decl->isImplicit())
+      return;
+
+    SourceRange Range = Decl->getNameInfo().getSourceRange();
+    if (Range.getBegin().isInvalid())
+      return;
+    // The first token that will be found is the ~ (or the equivalent trigraph),
+    // we want instead to replace the next token, that will be the identifier.
+    Range.setBegin(CharSourceRange::getTokenRange(Range).getEnd());
+
+    addUsage(NamingCheckFailures, Decl->getParent(), Range);
+    return;
+  }
+
+  if (const auto *Loc = Result.Nodes.getNodeAs<TypeLoc>("typeLoc")) {
+    NamedDecl *Decl = nullptr;
+    if (const auto &Ref = Loc->getAs<TagTypeLoc>()) {
+      Decl = Ref.getDecl();
+    } else if (const auto &Ref = Loc->getAs<InjectedClassNameTypeLoc>()) {
+      Decl = Ref.getDecl();
+    } else if (const auto &Ref = Loc->getAs<UnresolvedUsingTypeLoc>()) {
+      Decl = Ref.getDecl();
+    } else if (const auto &Ref = Loc->getAs<TemplateTypeParmTypeLoc>()) {
+      Decl = Ref.getDecl();
+    }
+
+    if (Decl) {
+      addUsage(NamingCheckFailures, Decl, Loc->getSourceRange());
+      return;
+    }
+
+    if (const auto &Ref = Loc->getAs<TemplateSpecializationTypeLoc>()) {
+      const auto *Decl =
+          Ref.getTypePtr()->getTemplateName().getAsTemplateDecl();
+
+      SourceRange Range(Ref.getTemplateNameLoc(), Ref.getTemplateNameLoc());
+      if (const auto *ClassDecl = dyn_cast<TemplateDecl>(Decl)) {
+        if (const auto *TemplDecl = ClassDecl->getTemplatedDecl())
+          addUsage(NamingCheckFailures, TemplDecl, Range);
+        return;
+      }
+    }
+
+    if (const auto &Ref =
+            Loc->getAs<DependentTemplateSpecializationTypeLoc>()) {
+      if (const auto *Decl = Ref.getTypePtr()->getAsTagDecl())
+        addUsage(NamingCheckFailures, Decl, Loc->getSourceRange());
+      return;
+    }
+  }
+
+  if (const auto *Loc =
+          Result.Nodes.getNodeAs<NestedNameSpecifierLoc>("nestedNameLoc")) {
+    if (NestedNameSpecifier *Spec = Loc->getNestedNameSpecifier()) {
+      if (NamespaceDecl *Decl = Spec->getAsNamespace()) {
+        addUsage(NamingCheckFailures, Decl, Loc->getLocalSourceRange());
+        return;
+      }
+    }
+  }
+
+  if (const auto *Decl = Result.Nodes.getNodeAs<UsingDecl>("using")) {
+    for (const auto &Shadow : Decl->shadows()) {
+      addUsage(NamingCheckFailures, Shadow->getTargetDecl(),
+               Decl->getNameInfo().getSourceRange());
+    }
+    return;
+  }
+
+  if (const auto *DeclRef = Result.Nodes.getNodeAs<DeclRefExpr>("declRef")) {
+    SourceRange Range = DeclRef->getNameInfo().getSourceRange();
+    addUsage(NamingCheckFailures, DeclRef->getDecl(), Range,
+             Result.SourceManager);
+    return;
+  }
+
+  if (const auto *Decl = Result.Nodes.getNodeAs<NamedDecl>("decl")) {
+    if (!Decl->getIdentifier() || Decl->getName().empty() || Decl->isImplicit())
+      return;
+
+    // Fix type aliases in value declarations
+    if (const auto *Value = Result.Nodes.getNodeAs<ValueDecl>("decl")) {
+      if (const auto *Typedef =
+              Value->getType().getTypePtr()->getAs<TypedefType>()) {
+        addUsage(NamingCheckFailures, Typedef->getDecl(),
+                 Value->getSourceRange());
+      }
+    }
+
+    // Fix type aliases in function declarations
+    if (const auto *Value = Result.Nodes.getNodeAs<FunctionDecl>("decl")) {
+      if (const auto *Typedef =
+              Value->getReturnType().getTypePtr()->getAs<TypedefType>()) {
+        addUsage(NamingCheckFailures, Typedef->getDecl(),
+                 Value->getSourceRange());
+      }
+      for (unsigned i = 0; i < Value->getNumParams(); ++i) {
+        if (const auto *Typedef = Value->parameters()[i]
+                                      ->getType()
+                                      .getTypePtr()
+                                      ->getAs<TypedefType>()) {
+          addUsage(NamingCheckFailures, Typedef->getDecl(),
+                   Value->getSourceRange());
+        }
+      }
+    }
+
+    // Ignore ClassTemplateSpecializationDecl which are creating duplicate
+    // replacements with CXXRecordDecl
+    if (isa<ClassTemplateSpecializationDecl>(Decl))
+      return;
+
+    StyleKind SK = findStyleKind(Decl, NamingStyles);
+    if (SK == SK_Invalid)
+      return;
+
+    if (!NamingStyles[SK])
+      return;
+
+    const NamingStyle &Style = *NamingStyles[SK];
+    StringRef Name = Decl->getName();
+    if (matchesStyle(Name, Style))
+      return;
+
+    std::string KindName = fixupWithCase(StyleNames[SK], CT_LowerCase);
+    std::replace(KindName.begin(), KindName.end(), '_', ' ');
+
+    std::string Fixup = fixupWithStyle(Name, Style);
+    if (StringRef(Fixup).equals(Name)) {
+      if (!IgnoreFailedSplit) {
+        LLVM_DEBUG(llvm::dbgs()
+                   << Decl->getLocStart().printToString(*Result.SourceManager)
+                   << llvm::format(": unable to split words for %s '%s'\n",
+                                   KindName.c_str(), Name.str().c_str()));
+      }
+    } else {
+      NamingCheckFailure &Failure = NamingCheckFailures[NamingCheckId(
+          Decl->getLocation(), Decl->getNameAsString())];
+      SourceRange Range =
+          DeclarationNameInfo(Decl->getDeclName(), Decl->getLocation())
+              .getSourceRange();
+
+      Failure.Fixup = std::move(Fixup);
+      Failure.KindName = std::move(KindName);
+      addUsage(NamingCheckFailures, Decl, Range);
+    }
+  }
+}
+
+void IdentifierNamingCheck::checkMacro(SourceManager &SourceMgr,
+                                       const Token &MacroNameTok,
+                                       const MacroInfo *MI) {
+  if (!NamingStyles[SK_MacroDefinition])
+    return;
+
+  StringRef Name = MacroNameTok.getIdentifierInfo()->getName();
+  const NamingStyle &Style = *NamingStyles[SK_MacroDefinition];
+  if (matchesStyle(Name, Style))
+    return;
+
+  std::string KindName =
+      fixupWithCase(StyleNames[SK_MacroDefinition], CT_LowerCase);
+  std::replace(KindName.begin(), KindName.end(), '_', ' ');
+
+  std::string Fixup = fixupWithStyle(Name, Style);
+  if (StringRef(Fixup).equals(Name)) {
+    if (!IgnoreFailedSplit) {
+      LLVM_DEBUG(llvm::dbgs()
+                 << MacroNameTok.getLocation().printToString(SourceMgr)
+                 << llvm::format(": unable to split words for %s '%s'\n",
+                                 KindName.c_str(), Name.str().c_str()));
+    }
+  } else {
+    NamingCheckId ID(MI->getDefinitionLoc(), Name);
+    NamingCheckFailure &Failure = NamingCheckFailures[ID];
+    SourceRange Range(MacroNameTok.getLocation(), MacroNameTok.getEndLoc());
+
+    Failure.Fixup = std::move(Fixup);
+    Failure.KindName = std::move(KindName);
+    addUsage(NamingCheckFailures, ID, Range);
+  }
+}
+
+void IdentifierNamingCheck::expandMacro(const Token &MacroNameTok,
+                                        const MacroInfo *MI) {
+  StringRef Name = MacroNameTok.getIdentifierInfo()->getName();
+  NamingCheckId ID(MI->getDefinitionLoc(), Name);
+
+  auto Failure = NamingCheckFailures.find(ID);
+  if (Failure == NamingCheckFailures.end())
+    return;
+
+  SourceRange Range(MacroNameTok.getLocation(), MacroNameTok.getEndLoc());
+  addUsage(NamingCheckFailures, ID, Range);
+}
+
+void IdentifierNamingCheck::onEndOfTranslationUnit() {
+  for (const auto &Pair : NamingCheckFailures) {
+    const NamingCheckId &Decl = Pair.first;
+    const NamingCheckFailure &Failure = Pair.second;
+
+    if (Failure.KindName.empty())
+      continue;
+
+    if (Failure.ShouldFix) {
+      auto Diag = diag(Decl.first, "invalid case style for %0 '%1'")
+                  << Failure.KindName << Decl.second;
+
+      for (const auto &Loc : Failure.RawUsageLocs) {
+        // We assume that the identifier name is made of one token only. This is
+        // always the case as we ignore usages in macros that could build
+        // identifier names by combining multiple tokens.
+        //
+        // For destructors, we alread take care of it by remembering the
+        // location of the start of the identifier and not the start of the
+        // tilde.
+        //
+        // Other multi-token identifiers, such as operators are not checked at
+        // all.
+        Diag << FixItHint::CreateReplacement(
+            SourceRange(SourceLocation::getFromRawEncoding(Loc)),
+            Failure.Fixup);
+      }
+    }
+  }
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h
new file mode 100644
index 0000000..c236ad5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h
@@ -0,0 +1,109 @@
+//===--- IdentifierNamingCheck.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_IDENTIFIERNAMINGCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERNAMINGCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+
+class MacroInfo;
+
+namespace tidy {
+namespace readability {
+
+/// Checks for identifiers naming style mismatch.
+///
+/// This check will try to enforce coding guidelines on the identifiers naming.
+/// It supports `lower_case`, `UPPER_CASE`, `camelBack` and `CamelCase` casing
+/// and tries to convert from one to another if a mismatch is detected.
+///
+/// It also supports a fixed prefix and suffix that will be prepended or
+/// appended to the identifiers, regardless of the casing.
+///
+/// Many configuration options are available, in order to be able to create
+/// different rules for different kind of identifier. In general, the
+/// rules are falling back to a more generic rule if the specific case is not
+/// configured.
+class IdentifierNamingCheck : public ClangTidyCheck {
+public:
+  IdentifierNamingCheck(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;
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+  void onEndOfTranslationUnit() override;
+
+  enum CaseType {
+    CT_AnyCase = 0,
+    CT_LowerCase,
+    CT_CamelBack,
+    CT_UpperCase,
+    CT_CamelCase,
+    CT_CamelSnakeCase,
+    CT_CamelSnakeBack
+  };
+
+  struct NamingStyle {
+    NamingStyle() = default;
+
+    NamingStyle(llvm::Optional<CaseType> Case, const std::string &Prefix,
+                const std::string &Suffix)
+        : Case(Case), Prefix(Prefix), Suffix(Suffix) {}
+
+    llvm::Optional<CaseType> Case;
+    std::string Prefix;
+    std::string Suffix;
+  };
+
+  /// \brief Holds an identifier name check failure, tracking the kind of the
+  /// identifer, its possible fixup and the starting locations of all the
+  /// identifier usages.
+  struct NamingCheckFailure {
+    std::string KindName;
+    std::string Fixup;
+
+    /// \brief Whether the failure should be fixed or not.
+    ///
+    /// ie: if the identifier was used or declared within a macro we won't offer
+    /// a fixup for safety reasons.
+    bool ShouldFix;
+
+    /// \brief A set of all the identifier usages starting SourceLocation, in
+    /// their encoded form.
+    llvm::DenseSet<unsigned> RawUsageLocs;
+
+    NamingCheckFailure() : ShouldFix(true) {}
+  };
+
+  typedef std::pair<SourceLocation, std::string> NamingCheckId;
+
+  typedef llvm::DenseMap<NamingCheckId, NamingCheckFailure>
+      NamingCheckFailureMap;
+
+  /// Check Macros for style violations.
+  void checkMacro(SourceManager &sourceMgr, const Token &MacroNameTok,
+                  const MacroInfo *MI);
+
+  /// Add a usage of a macro if it already has a violation.
+  void expandMacro(const Token &MacroNameTok, const MacroInfo *MI);
+
+private:
+  std::vector<llvm::Optional<NamingStyle>> NamingStyles;
+  bool IgnoreFailedSplit;
+  NamingCheckFailureMap NamingCheckFailures;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERNAMINGCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp
new file mode 100644
index 0000000..79022d4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp
@@ -0,0 +1,388 @@
+//===--- ImplicitBoolConversionCheck.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 "ImplicitBoolConversionCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/FixIt.h"
+#include <queue>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+namespace {
+
+AST_MATCHER(Stmt, isMacroExpansion) {
+  SourceManager &SM = Finder->getASTContext().getSourceManager();
+  SourceLocation Loc = Node.getLocStart();
+  return SM.isMacroBodyExpansion(Loc) || SM.isMacroArgExpansion(Loc);
+}
+
+bool isNULLMacroExpansion(const Stmt *Statement, ASTContext &Context) {
+  SourceManager &SM = Context.getSourceManager();
+  const LangOptions &LO = Context.getLangOpts();
+  SourceLocation Loc = Statement->getLocStart();
+  return SM.isMacroBodyExpansion(Loc) &&
+         Lexer::getImmediateMacroName(Loc, SM, LO) == "NULL";
+}
+
+AST_MATCHER(Stmt, isNULLMacroExpansion) {
+  return isNULLMacroExpansion(&Node, Finder->getASTContext());
+}
+
+StringRef getZeroLiteralToCompareWithForType(CastKind CastExprKind,
+                                             QualType Type,
+                                             ASTContext &Context) {
+  switch (CastExprKind) {
+  case CK_IntegralToBoolean:
+    return Type->isUnsignedIntegerType() ? "0u" : "0";
+
+  case CK_FloatingToBoolean:
+    return Context.hasSameType(Type, Context.FloatTy) ? "0.0f" : "0.0";
+
+  case CK_PointerToBoolean:
+  case CK_MemberPointerToBoolean: // Fall-through on purpose.
+    return Context.getLangOpts().CPlusPlus11 ? "nullptr" : "0";
+
+  default:
+    llvm_unreachable("Unexpected cast kind");
+  }
+}
+
+bool isUnaryLogicalNotOperator(const Stmt *Statement) {
+  const auto *UnaryOperatorExpr = dyn_cast<UnaryOperator>(Statement);
+  return UnaryOperatorExpr && UnaryOperatorExpr->getOpcode() == UO_LNot;
+}
+
+bool areParensNeededForOverloadedOperator(OverloadedOperatorKind OperatorKind) {
+  switch (OperatorKind) {
+  case OO_New:
+  case OO_Delete: // Fall-through on purpose.
+  case OO_Array_New:
+  case OO_Array_Delete:
+  case OO_ArrowStar:
+  case OO_Arrow:
+  case OO_Call:
+  case OO_Subscript:
+    return false;
+
+  default:
+    return true;
+  }
+}
+
+bool areParensNeededForStatement(const Stmt *Statement) {
+  if (const auto *OperatorCall = dyn_cast<CXXOperatorCallExpr>(Statement)) {
+    return areParensNeededForOverloadedOperator(OperatorCall->getOperator());
+  }
+
+  return isa<BinaryOperator>(Statement) || isa<UnaryOperator>(Statement);
+}
+
+void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
+                              const ImplicitCastExpr *Cast, const Stmt *Parent,
+                              ASTContext &Context) {
+  // In case of expressions like (! integer), we should remove the redundant not
+  // operator and use inverted comparison (integer == 0).
+  bool InvertComparison =
+      Parent != nullptr && isUnaryLogicalNotOperator(Parent);
+  if (InvertComparison) {
+    SourceLocation ParentStartLoc = Parent->getLocStart();
+    SourceLocation ParentEndLoc =
+        cast<UnaryOperator>(Parent)->getSubExpr()->getLocStart();
+    Diag << FixItHint::CreateRemoval(
+        CharSourceRange::getCharRange(ParentStartLoc, ParentEndLoc));
+
+    Parent = Context.getParents(*Parent)[0].get<Stmt>();
+  }
+
+  const Expr *SubExpr = Cast->getSubExpr();
+
+  bool NeedInnerParens = areParensNeededForStatement(SubExpr);
+  bool NeedOuterParens =
+      Parent != nullptr && areParensNeededForStatement(Parent);
+
+  std::string StartLocInsertion;
+
+  if (NeedOuterParens) {
+    StartLocInsertion += "(";
+  }
+  if (NeedInnerParens) {
+    StartLocInsertion += "(";
+  }
+
+  if (!StartLocInsertion.empty()) {
+    Diag << FixItHint::CreateInsertion(Cast->getLocStart(), StartLocInsertion);
+  }
+
+  std::string EndLocInsertion;
+
+  if (NeedInnerParens) {
+    EndLocInsertion += ")";
+  }
+
+  if (InvertComparison) {
+    EndLocInsertion += " == ";
+  } else {
+    EndLocInsertion += " != ";
+  }
+
+  EndLocInsertion += getZeroLiteralToCompareWithForType(
+      Cast->getCastKind(), SubExpr->getType(), Context);
+
+  if (NeedOuterParens) {
+    EndLocInsertion += ")";
+  }
+
+  SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+      Cast->getLocEnd(), 0, Context.getSourceManager(), Context.getLangOpts());
+  Diag << FixItHint::CreateInsertion(EndLoc, EndLocInsertion);
+}
+
+StringRef getEquivalentBoolLiteralForExpr(const Expr *Expression,
+                                          ASTContext &Context) {
+  if (isNULLMacroExpansion(Expression, Context)) {
+    return "false";
+  }
+
+  if (const auto *IntLit = dyn_cast<IntegerLiteral>(Expression)) {
+    return (IntLit->getValue() == 0) ? "false" : "true";
+  }
+
+  if (const auto *FloatLit = dyn_cast<FloatingLiteral>(Expression)) {
+    llvm::APFloat FloatLitAbsValue = FloatLit->getValue();
+    FloatLitAbsValue.clearSign();
+    return (FloatLitAbsValue.bitcastToAPInt() == 0) ? "false" : "true";
+  }
+
+  if (const auto *CharLit = dyn_cast<CharacterLiteral>(Expression)) {
+    return (CharLit->getValue() == 0) ? "false" : "true";
+  }
+
+  if (isa<StringLiteral>(Expression->IgnoreCasts())) {
+    return "true";
+  }
+
+  return StringRef();
+}
+
+void fixGenericExprCastFromBool(DiagnosticBuilder &Diag,
+                                const ImplicitCastExpr *Cast,
+                                ASTContext &Context, StringRef OtherType) {
+  const Expr *SubExpr = Cast->getSubExpr();
+  bool NeedParens = !isa<ParenExpr>(SubExpr);
+
+  Diag << FixItHint::CreateInsertion(
+      Cast->getLocStart(),
+      (Twine("static_cast<") + OtherType + ">" + (NeedParens ? "(" : ""))
+          .str());
+
+  if (NeedParens) {
+    SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+        Cast->getLocEnd(), 0, Context.getSourceManager(),
+        Context.getLangOpts());
+
+    Diag << FixItHint::CreateInsertion(EndLoc, ")");
+  }
+}
+
+StringRef getEquivalentForBoolLiteral(const CXXBoolLiteralExpr *BoolLiteral,
+                                      QualType DestType, ASTContext &Context) {
+  // Prior to C++11, false literal could be implicitly converted to pointer.
+  if (!Context.getLangOpts().CPlusPlus11 &&
+      (DestType->isPointerType() || DestType->isMemberPointerType()) &&
+      BoolLiteral->getValue() == false) {
+    return "0";
+  }
+
+  if (DestType->isFloatingType()) {
+    if (Context.hasSameType(DestType, Context.FloatTy)) {
+      return BoolLiteral->getValue() ? "1.0f" : "0.0f";
+    }
+    return BoolLiteral->getValue() ? "1.0" : "0.0";
+  }
+
+  if (DestType->isUnsignedIntegerType()) {
+    return BoolLiteral->getValue() ? "1u" : "0u";
+  }
+  return BoolLiteral->getValue() ? "1" : "0";
+}
+
+bool isCastAllowedInCondition(const ImplicitCastExpr *Cast,
+                              ASTContext &Context) {
+  std::queue<const Stmt *> Q;
+  Q.push(Cast);
+  while (!Q.empty()) {
+    for (const auto &N : Context.getParents(*Q.front())) {
+      const Stmt *S = N.get<Stmt>();
+      if (!S)
+        return false;
+      if (isa<IfStmt>(S) || isa<ConditionalOperator>(S) || isa<ForStmt>(S) ||
+          isa<WhileStmt>(S) || isa<BinaryConditionalOperator>(S))
+        return true;
+      if (isa<ParenExpr>(S) || isa<ImplicitCastExpr>(S) ||
+          isUnaryLogicalNotOperator(S) ||
+          (isa<BinaryOperator>(S) && cast<BinaryOperator>(S)->isLogicalOp())) {
+        Q.push(S);
+      } else {
+        return false;
+      }
+    }
+    Q.pop();
+  }
+  return false;
+}
+
+} // anonymous namespace
+
+ImplicitBoolConversionCheck::ImplicitBoolConversionCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      AllowIntegerConditions(Options.get("AllowIntegerConditions", false)),
+      AllowPointerConditions(Options.get("AllowPointerConditions", false)) {}
+
+void ImplicitBoolConversionCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "AllowIntegerConditions", AllowIntegerConditions);
+  Options.store(Opts, "AllowPointerConditions", AllowPointerConditions);
+}
+
+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) {
+    return;
+  }
+
+  auto exceptionCases =
+      expr(anyOf(allOf(isMacroExpansion(), unless(isNULLMacroExpansion())),
+                 hasParent(explicitCastExpr())));
+  auto implicitCastFromBool = implicitCastExpr(
+      anyOf(hasCastKind(CK_IntegralCast), hasCastKind(CK_IntegralToFloating),
+            // Prior to C++11 cast from bool literal to pointer was allowed.
+            allOf(anyOf(hasCastKind(CK_NullToPointer),
+                        hasCastKind(CK_NullToMemberPointer)),
+                  hasSourceExpression(cxxBoolLiteral()))),
+      hasSourceExpression(expr(hasType(booleanType()))),
+      unless(exceptionCases));
+  auto boolXor =
+      binaryOperator(hasOperatorName("^"), hasLHS(implicitCastFromBool),
+                     hasRHS(implicitCastFromBool));
+  Finder->addMatcher(
+      implicitCastExpr(
+          anyOf(hasCastKind(CK_IntegralToBoolean),
+                hasCastKind(CK_FloatingToBoolean),
+                hasCastKind(CK_PointerToBoolean),
+                hasCastKind(CK_MemberPointerToBoolean)),
+          // Exclude case of using if or while statements with variable
+          // declaration, e.g.:
+          //   if (int var = functionCall()) {}
+          unless(
+              hasParent(stmt(anyOf(ifStmt(), whileStmt()), has(declStmt())))),
+          // Exclude cases common to implicit cast to and from bool.
+          unless(exceptionCases), unless(has(boolXor)),
+          // Retrive also parent statement, to check if we need additional
+          // parens in replacement.
+          anyOf(hasParent(stmt().bind("parentStmt")), anything()),
+          unless(isInTemplateInstantiation()),
+          unless(hasAncestor(functionTemplateDecl())))
+          .bind("implicitCastToBool"),
+      this);
+
+  auto boolComparison = binaryOperator(
+      anyOf(hasOperatorName("=="), hasOperatorName("!=")),
+      hasLHS(implicitCastFromBool), hasRHS(implicitCastFromBool));
+  auto boolOpAssignment =
+      binaryOperator(anyOf(hasOperatorName("|="), hasOperatorName("&=")),
+                     hasLHS(expr(hasType(booleanType()))));
+  Finder->addMatcher(
+      implicitCastExpr(
+          implicitCastFromBool,
+          // Exclude comparisons of bools, as they are always cast to integers
+          // in such context:
+          //   bool_expr_a == bool_expr_b
+          //   bool_expr_a != bool_expr_b
+          unless(hasParent(binaryOperator(
+              anyOf(boolComparison, boolXor, boolOpAssignment)))),
+          // Check also for nested casts, for example: bool -> int -> float.
+          anyOf(hasParent(implicitCastExpr().bind("furtherImplicitCast")),
+                anything()),
+          unless(isInTemplateInstantiation()),
+          unless(hasAncestor(functionTemplateDecl())))
+          .bind("implicitCastFromBool"),
+      this);
+}
+
+void ImplicitBoolConversionCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  if (const auto *CastToBool =
+          Result.Nodes.getNodeAs<ImplicitCastExpr>("implicitCastToBool")) {
+    const auto *Parent = Result.Nodes.getNodeAs<Stmt>("parentStmt");
+    return handleCastToBool(CastToBool, Parent, *Result.Context);
+  }
+
+  if (const auto *CastFromBool =
+          Result.Nodes.getNodeAs<ImplicitCastExpr>("implicitCastFromBool")) {
+    const auto *NextImplicitCast =
+        Result.Nodes.getNodeAs<ImplicitCastExpr>("furtherImplicitCast");
+    return handleCastFromBool(CastFromBool, NextImplicitCast, *Result.Context);
+  }
+}
+
+void ImplicitBoolConversionCheck::handleCastToBool(const ImplicitCastExpr *Cast,
+                                                   const Stmt *Parent,
+                                                   ASTContext &Context) {
+  if (AllowPointerConditions &&
+      (Cast->getCastKind() == CK_PointerToBoolean ||
+       Cast->getCastKind() == CK_MemberPointerToBoolean) &&
+      isCastAllowedInCondition(Cast, Context)) {
+    return;
+  }
+
+  if (AllowIntegerConditions && Cast->getCastKind() == CK_IntegralToBoolean &&
+      isCastAllowedInCondition(Cast, Context)) {
+    return;
+  }
+
+  auto Diag = diag(Cast->getLocStart(), "implicit conversion %0 -> bool")
+              << Cast->getSubExpr()->getType();
+
+  StringRef EquivalentLiteral =
+      getEquivalentBoolLiteralForExpr(Cast->getSubExpr(), Context);
+  if (!EquivalentLiteral.empty()) {
+    Diag << tooling::fixit::createReplacement(*Cast, EquivalentLiteral);
+  } else {
+    fixGenericExprCastToBool(Diag, Cast, Parent, Context);
+  }
+}
+
+void ImplicitBoolConversionCheck::handleCastFromBool(
+    const ImplicitCastExpr *Cast, const ImplicitCastExpr *NextImplicitCast,
+    ASTContext &Context) {
+  QualType DestType =
+      NextImplicitCast ? NextImplicitCast->getType() : Cast->getType();
+  auto Diag = diag(Cast->getLocStart(), "implicit conversion bool -> %0")
+              << DestType;
+
+  if (const auto *BoolLiteral =
+          dyn_cast<CXXBoolLiteralExpr>(Cast->getSubExpr())) {
+    Diag << tooling::fixit::createReplacement(
+        *Cast, getEquivalentForBoolLiteral(BoolLiteral, DestType, Context));
+  } else {
+    fixGenericExprCastFromBool(Diag, Cast, Context, DestType.getAsString());
+  }
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.h
new file mode 100644
index 0000000..bb062e0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.h
@@ -0,0 +1,46 @@
+//===--- ImplicitBoolConversionCheck.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_IMPLICIT_BOOL_CONVERSION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CONVERSION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// \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-conversion.html
+class ImplicitBoolConversionCheck : public ClangTidyCheck {
+public:
+  ImplicitBoolConversionCheck(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:
+  void handleCastToBool(const ImplicitCastExpr *CastExpression,
+                        const Stmt *ParentStatement, ASTContext &Context);
+  void handleCastFromBool(const ImplicitCastExpr *CastExpression,
+                          const ImplicitCastExpr *FurtherImplicitCastExpression,
+                          ASTContext &Context);
+
+  const bool AllowIntegerConditions;
+  const bool AllowPointerConditions;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CONVERSION_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.cpp
new file mode 100644
index 0000000..f1d0036
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.cpp
@@ -0,0 +1,360 @@
+//===--- InconsistentDeclarationParameterNameCheck.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 "InconsistentDeclarationParameterNameCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+#include <algorithm>
+#include <functional>
+#include <sstream>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+namespace {
+
+AST_MATCHER(FunctionDecl, hasOtherDeclarations) {
+  auto It = Node.redecls_begin();
+  auto EndIt = Node.redecls_end();
+
+  if (It == EndIt)
+    return false;
+
+  ++It;
+  return It != EndIt;
+}
+
+struct DifferingParamInfo {
+  DifferingParamInfo(StringRef SourceName, StringRef OtherName,
+                     SourceRange OtherNameRange, bool GenerateFixItHint)
+      : SourceName(SourceName), OtherName(OtherName),
+        OtherNameRange(OtherNameRange), GenerateFixItHint(GenerateFixItHint) {}
+
+  StringRef SourceName;
+  StringRef OtherName;
+  SourceRange OtherNameRange;
+  bool GenerateFixItHint;
+};
+
+using DifferingParamsContainer = llvm::SmallVector<DifferingParamInfo, 10>;
+
+struct InconsistentDeclarationInfo {
+  InconsistentDeclarationInfo(SourceLocation DeclarationLocation,
+                              DifferingParamsContainer &&DifferingParams)
+      : DeclarationLocation(DeclarationLocation),
+        DifferingParams(std::move(DifferingParams)) {}
+
+  SourceLocation DeclarationLocation;
+  DifferingParamsContainer DifferingParams;
+};
+
+using InconsistentDeclarationsContainer =
+    llvm::SmallVector<InconsistentDeclarationInfo, 2>;
+
+bool checkIfFixItHintIsApplicable(
+    const FunctionDecl *ParameterSourceDeclaration,
+    const ParmVarDecl *SourceParam, const FunctionDecl *OriginalDeclaration) {
+  // Assumptions with regard to function declarations/definition:
+  //  * If both function declaration and definition are seen, assume that
+  //    definition is most up-to-date, and use it to generate replacements.
+  //  * If only function declarations are seen, there is no easy way to tell
+  //    which is up-to-date and which is not, so don't do anything.
+  // TODO: This may be changed later, but for now it seems the reasonable
+  // solution.
+  if (!ParameterSourceDeclaration->isThisDeclarationADefinition())
+    return false;
+
+  // Assumption: if parameter is not referenced in function defintion body, it
+  // may indicate that it's outdated, so don't touch it.
+  if (!SourceParam->isReferenced())
+    return false;
+
+  // In case there is the primary template definition and (possibly several)
+  // template specializations (and each with possibly several redeclarations),
+  // it is not at all clear what to change.
+  if (OriginalDeclaration->getTemplatedKind() ==
+      FunctionDecl::TK_FunctionTemplateSpecialization)
+    return false;
+
+  // Other cases seem OK to allow replacements.
+  return true;
+}
+
+bool nameMatch(StringRef L, StringRef R, bool Strict) {
+  if (Strict)
+    return L.empty() || R.empty() || L == R;
+  // We allow two names if one is a prefix/suffix of the other, ignoring case.
+  // Important special case: this is true if either parameter has no name!
+  return L.startswith_lower(R) || R.startswith_lower(L) ||
+         L.endswith_lower(R) || R.endswith_lower(L);
+}
+
+DifferingParamsContainer
+findDifferingParamsInDeclaration(const FunctionDecl *ParameterSourceDeclaration,
+                                 const FunctionDecl *OtherDeclaration,
+                                 const FunctionDecl *OriginalDeclaration,
+                                 bool Strict) {
+  DifferingParamsContainer DifferingParams;
+
+  auto SourceParamIt = ParameterSourceDeclaration->param_begin();
+  auto OtherParamIt = OtherDeclaration->param_begin();
+
+  while (SourceParamIt != ParameterSourceDeclaration->param_end() &&
+         OtherParamIt != OtherDeclaration->param_end()) {
+    auto SourceParamName = (*SourceParamIt)->getName();
+    auto OtherParamName = (*OtherParamIt)->getName();
+
+    // FIXME: Provide a way to extract commented out parameter name from comment
+    // next to it.
+    if (!nameMatch(SourceParamName, OtherParamName, Strict)) {
+      SourceRange OtherParamNameRange =
+          DeclarationNameInfo((*OtherParamIt)->getDeclName(),
+                              (*OtherParamIt)->getLocation())
+              .getSourceRange();
+
+      bool GenerateFixItHint = checkIfFixItHintIsApplicable(
+          ParameterSourceDeclaration, *SourceParamIt, OriginalDeclaration);
+
+      DifferingParams.emplace_back(SourceParamName, OtherParamName,
+                                   OtherParamNameRange, GenerateFixItHint);
+    }
+
+    ++SourceParamIt;
+    ++OtherParamIt;
+  }
+
+  return DifferingParams;
+}
+
+InconsistentDeclarationsContainer
+findInconsistentDeclarations(const FunctionDecl *OriginalDeclaration,
+                            const FunctionDecl *ParameterSourceDeclaration,
+                            SourceManager &SM, bool Strict) {
+  InconsistentDeclarationsContainer InconsistentDeclarations;
+  SourceLocation ParameterSourceLocation =
+      ParameterSourceDeclaration->getLocation();
+
+  for (const FunctionDecl *OtherDeclaration : OriginalDeclaration->redecls()) {
+    SourceLocation OtherLocation = OtherDeclaration->getLocation();
+    if (OtherLocation != ParameterSourceLocation) { // Skip self.
+      DifferingParamsContainer DifferingParams =
+          findDifferingParamsInDeclaration(ParameterSourceDeclaration,
+                                           OtherDeclaration,
+                                           OriginalDeclaration, Strict);
+      if (!DifferingParams.empty()) {
+        InconsistentDeclarations.emplace_back(OtherDeclaration->getLocation(),
+                                              std::move(DifferingParams));
+      }
+    }
+  }
+
+  // Sort in order of appearance in translation unit to generate clear
+  // diagnostics.
+  std::sort(InconsistentDeclarations.begin(), InconsistentDeclarations.end(),
+            [&SM](const InconsistentDeclarationInfo &Info1,
+                  const InconsistentDeclarationInfo &Info2) {
+              return SM.isBeforeInTranslationUnit(Info1.DeclarationLocation,
+                                                  Info2.DeclarationLocation);
+            });
+  return InconsistentDeclarations;
+}
+
+const FunctionDecl *
+getParameterSourceDeclaration(const FunctionDecl *OriginalDeclaration) {
+  const FunctionTemplateDecl *PrimaryTemplate =
+      OriginalDeclaration->getPrimaryTemplate();
+  if (PrimaryTemplate != nullptr) {
+    // In case of template specializations, use primary template declaration as
+    // the source of parameter names.
+    return PrimaryTemplate->getTemplatedDecl();
+  }
+
+  // In other cases, try to change to function definition, if available.
+
+  if (OriginalDeclaration->isThisDeclarationADefinition())
+    return OriginalDeclaration;
+
+  for (const FunctionDecl *OtherDeclaration : OriginalDeclaration->redecls()) {
+    if (OtherDeclaration->isThisDeclarationADefinition()) {
+      return OtherDeclaration;
+    }
+  }
+
+  // No definition found, so return original declaration.
+  return OriginalDeclaration;
+}
+
+std::string joinParameterNames(
+    const DifferingParamsContainer &DifferingParams,
+    llvm::function_ref<StringRef(const DifferingParamInfo &)> ChooseParamName) {
+  llvm::SmallVector<char, 40> Buffer;
+  llvm::raw_svector_ostream Str(Buffer);
+  bool First = true;
+  for (const DifferingParamInfo &ParamInfo : DifferingParams) {
+    if (First)
+      First = false;
+    else
+      Str << ", ";
+
+    Str << "'" << ChooseParamName(ParamInfo).str() << "'";
+  }
+  return Str.str().str();
+}
+
+void formatDifferingParamsDiagnostic(
+    InconsistentDeclarationParameterNameCheck *Check, SourceLocation Location,
+    StringRef OtherDeclarationDescription,
+    const DifferingParamsContainer &DifferingParams) {
+  auto ChooseOtherName = [](const DifferingParamInfo &ParamInfo) {
+    return ParamInfo.OtherName;
+  };
+  auto ChooseSourceName = [](const DifferingParamInfo &ParamInfo) {
+    return ParamInfo.SourceName;
+  };
+
+  auto ParamDiag =
+      Check->diag(Location,
+                  "differing parameters are named here: (%0), in %1: (%2)",
+                  DiagnosticIDs::Level::Note)
+      << joinParameterNames(DifferingParams, ChooseOtherName)
+      << OtherDeclarationDescription
+      << joinParameterNames(DifferingParams, ChooseSourceName);
+
+  for (const DifferingParamInfo &ParamInfo : DifferingParams) {
+    if (ParamInfo.GenerateFixItHint) {
+      ParamDiag << FixItHint::CreateReplacement(
+          CharSourceRange::getTokenRange(ParamInfo.OtherNameRange),
+          ParamInfo.SourceName);
+    }
+  }
+}
+
+void formatDiagnosticsForDeclarations(
+    InconsistentDeclarationParameterNameCheck *Check,
+    const FunctionDecl *ParameterSourceDeclaration,
+    const FunctionDecl *OriginalDeclaration,
+    const InconsistentDeclarationsContainer &InconsistentDeclarations) {
+  Check->diag(
+      OriginalDeclaration->getLocation(),
+      "function %q0 has %1 other declaration%s1 with different parameter names")
+      << OriginalDeclaration
+      << static_cast<int>(InconsistentDeclarations.size());
+  int Count = 1;
+  for (const InconsistentDeclarationInfo &InconsistentDeclaration :
+       InconsistentDeclarations) {
+    Check->diag(InconsistentDeclaration.DeclarationLocation,
+                "the %ordinal0 inconsistent declaration seen here",
+                DiagnosticIDs::Level::Note)
+        << Count;
+
+    formatDifferingParamsDiagnostic(
+        Check, InconsistentDeclaration.DeclarationLocation,
+        "the other declaration", InconsistentDeclaration.DifferingParams);
+
+    ++Count;
+  }
+}
+
+void formatDiagnostics(
+    InconsistentDeclarationParameterNameCheck *Check,
+    const FunctionDecl *ParameterSourceDeclaration,
+    const FunctionDecl *OriginalDeclaration,
+    const InconsistentDeclarationsContainer &InconsistentDeclarations,
+    StringRef FunctionDescription, StringRef ParameterSourceDescription) {
+  for (const InconsistentDeclarationInfo &InconsistentDeclaration :
+       InconsistentDeclarations) {
+    Check->diag(InconsistentDeclaration.DeclarationLocation,
+                "%0 %q1 has a %2 with different parameter names")
+        << FunctionDescription << OriginalDeclaration
+        << ParameterSourceDescription;
+
+    Check->diag(ParameterSourceDeclaration->getLocation(), "the %0 seen here",
+                DiagnosticIDs::Level::Note)
+        << ParameterSourceDescription;
+
+    formatDifferingParamsDiagnostic(
+        Check, InconsistentDeclaration.DeclarationLocation,
+        ParameterSourceDescription, InconsistentDeclaration.DifferingParams);
+  }
+}
+
+} // anonymous namespace
+
+void InconsistentDeclarationParameterNameCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IgnoreMacros", IgnoreMacros);
+  Options.store(Opts, "Strict", Strict);
+}
+
+void InconsistentDeclarationParameterNameCheck::registerMatchers(
+    MatchFinder *Finder) {
+  Finder->addMatcher(functionDecl(unless(isImplicit()), hasOtherDeclarations())
+                         .bind("functionDecl"),
+                     this);
+}
+
+void InconsistentDeclarationParameterNameCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *OriginalDeclaration =
+      Result.Nodes.getNodeAs<FunctionDecl>("functionDecl");
+
+  if (VisitedDeclarations.count(OriginalDeclaration) > 0)
+    return; // Avoid multiple warnings.
+
+  const FunctionDecl *ParameterSourceDeclaration =
+      getParameterSourceDeclaration(OriginalDeclaration);
+
+  InconsistentDeclarationsContainer InconsistentDeclarations =
+      findInconsistentDeclarations(OriginalDeclaration,
+                                   ParameterSourceDeclaration,
+                                   *Result.SourceManager, Strict);
+  if (InconsistentDeclarations.empty()) {
+    // Avoid unnecessary further visits.
+    markRedeclarationsAsVisited(OriginalDeclaration);
+    return;
+  }
+
+  SourceLocation StartLoc = OriginalDeclaration->getLocStart();
+  if (StartLoc.isMacroID() && IgnoreMacros) {
+    markRedeclarationsAsVisited(OriginalDeclaration);
+    return;
+  }
+
+  if (OriginalDeclaration->getTemplatedKind() ==
+      FunctionDecl::TK_FunctionTemplateSpecialization) {
+    formatDiagnostics(this, ParameterSourceDeclaration, OriginalDeclaration,
+                      InconsistentDeclarations,
+                      "function template specialization",
+                      "primary template declaration");
+  } else if (ParameterSourceDeclaration->isThisDeclarationADefinition()) {
+    formatDiagnostics(this, ParameterSourceDeclaration, OriginalDeclaration,
+                      InconsistentDeclarations, "function", "definition");
+  } else {
+    formatDiagnosticsForDeclarations(this, ParameterSourceDeclaration,
+                                     OriginalDeclaration,
+                                     InconsistentDeclarations);
+  }
+
+  markRedeclarationsAsVisited(OriginalDeclaration);
+}
+
+void InconsistentDeclarationParameterNameCheck::markRedeclarationsAsVisited(
+    const FunctionDecl *OriginalDeclaration) {
+  for (const FunctionDecl *Redecl : OriginalDeclaration->redecls()) {
+    VisitedDeclarations.insert(Redecl);
+  }
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.h
new file mode 100644
index 0000000..602856f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.h
@@ -0,0 +1,50 @@
+//===- InconsistentDeclarationParameterNameCheck.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_INCONSISTENT_DECLARATION_PARAMETER_NAME_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_INCONSISTENT_DECLARATION_PARAMETER_NAME_H
+
+#include "../ClangTidy.h"
+
+#include "llvm/ADT/DenseSet.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// \brief Checks for declarations of functions which differ in parameter names.
+///
+/// For detailed documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-inconsistent-declaration-parameter-name.html
+///
+class InconsistentDeclarationParameterNameCheck : public ClangTidyCheck {
+public:
+  InconsistentDeclarationParameterNameCheck(StringRef Name,
+                                            ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context),
+        IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", 1) != 0),
+        Strict(Options.getLocalOrGlobal("Strict", 0) != 0) {}
+
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void markRedeclarationsAsVisited(const FunctionDecl *FunctionDeclaration);
+
+  llvm::DenseSet<const FunctionDecl *> VisitedDeclarations;
+  const bool IgnoreMacros;
+  const bool Strict;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_INCONSISTENT_DECLARATION_PARAMETER_NAME_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/MisleadingIndentationCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/MisleadingIndentationCheck.cpp
new file mode 100644
index 0000000..8a6c8c4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/MisleadingIndentationCheck.cpp
@@ -0,0 +1,123 @@
+//===--- MisleadingIndentationCheck.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 "MisleadingIndentationCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+static const IfStmt *getPrecedingIf(const SourceManager &SM,
+                                    ASTContext *Context, const IfStmt *If) {
+  auto parents = Context->getParents(*If);
+  if (parents.size() != 1)
+    return nullptr;
+  if (const auto *PrecedingIf = parents[0].get<IfStmt>()) {
+    SourceLocation PreviousElseLoc = PrecedingIf->getElseLoc();
+    if (SM.getExpansionLineNumber(PreviousElseLoc) ==
+        SM.getExpansionLineNumber(If->getIfLoc()))
+      return PrecedingIf;
+  }
+  return nullptr;
+}
+
+void MisleadingIndentationCheck::danglingElseCheck(const SourceManager &SM,
+                                                   ASTContext *Context,
+                                                   const IfStmt *If) {
+  SourceLocation IfLoc = If->getIfLoc();
+  SourceLocation ElseLoc = If->getElseLoc();
+
+  if (IfLoc.isMacroID() || ElseLoc.isMacroID())
+    return;
+
+  if (SM.getExpansionLineNumber(If->getThen()->getLocEnd()) ==
+      SM.getExpansionLineNumber(ElseLoc))
+    return;
+
+  // Find location of first 'if' in a 'if else if' chain.
+  for (auto PrecedingIf = getPrecedingIf(SM, Context, If); PrecedingIf;
+       PrecedingIf = getPrecedingIf(SM, Context, PrecedingIf))
+    IfLoc = PrecedingIf->getIfLoc();
+
+  if (SM.getExpansionColumnNumber(IfLoc) !=
+      SM.getExpansionColumnNumber(ElseLoc))
+    diag(ElseLoc, "different indentation for 'if' and corresponding 'else'");
+}
+
+void MisleadingIndentationCheck::missingBracesCheck(const SourceManager &SM,
+                                                    const CompoundStmt *CStmt) {
+  const static StringRef StmtNames[] = {"if", "for", "while"};
+  for (unsigned int i = 0; i < CStmt->size() - 1; i++) {
+    const Stmt *CurrentStmt = CStmt->body_begin()[i];
+    const Stmt *Inner = nullptr;
+    int StmtKind = 0;
+
+    if (const auto *CurrentIf = dyn_cast<IfStmt>(CurrentStmt)) {
+      StmtKind = 0;
+      Inner =
+          CurrentIf->getElse() ? CurrentIf->getElse() : CurrentIf->getThen();
+    } else if (const auto *CurrentFor = dyn_cast<ForStmt>(CurrentStmt)) {
+      StmtKind = 1;
+      Inner = CurrentFor->getBody();
+    } else if (const auto *CurrentWhile = dyn_cast<WhileStmt>(CurrentStmt)) {
+      StmtKind = 2;
+      Inner = CurrentWhile->getBody();
+    } else {
+      continue;
+    }
+
+    if (isa<CompoundStmt>(Inner))
+      continue;
+
+    SourceLocation InnerLoc = Inner->getLocStart();
+    SourceLocation OuterLoc = CurrentStmt->getLocStart();
+
+    if (SM.getExpansionLineNumber(InnerLoc) ==
+        SM.getExpansionLineNumber(OuterLoc))
+      continue;
+
+    const Stmt *NextStmt = CStmt->body_begin()[i + 1];
+    SourceLocation NextLoc = NextStmt->getLocStart();
+
+    if (InnerLoc.isMacroID() || OuterLoc.isMacroID() || NextLoc.isMacroID())
+      continue;
+
+    if (SM.getExpansionColumnNumber(InnerLoc) ==
+        SM.getExpansionColumnNumber(NextLoc)) {
+      diag(NextLoc, "misleading indentation: statement is indented too deeply");
+      diag(OuterLoc, "did you mean this line to be inside this '%0'",
+           DiagnosticIDs::Note)
+          << StmtNames[StmtKind];
+    }
+  }
+}
+
+void MisleadingIndentationCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(ifStmt(hasElse(stmt())).bind("if"), this);
+  Finder->addMatcher(
+      compoundStmt(has(stmt(anyOf(ifStmt(), forStmt(), whileStmt()))))
+          .bind("compound"),
+      this);
+}
+
+void MisleadingIndentationCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *If = Result.Nodes.getNodeAs<IfStmt>("if"))
+    danglingElseCheck(*Result.SourceManager, Result.Context, If);
+
+  if (const auto *CStmt = Result.Nodes.getNodeAs<CompoundStmt>("compound"))
+    missingBracesCheck(*Result.SourceManager, CStmt);
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/MisleadingIndentationCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/MisleadingIndentationCheck.h
new file mode 100644
index 0000000..0ca50bb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/MisleadingIndentationCheck.h
@@ -0,0 +1,42 @@
+//===--- MisleadingIndentationCheck.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_MISLEADING_INDENTATION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MISLEADING_INDENTATION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Checks the code for dangling else, and possible misleading indentations due
+/// to missing braces. Note that this check only works as expected when the tabs
+/// or spaces are used consistently and not mixed.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-misleading-indentation.html
+class MisleadingIndentationCheck : public ClangTidyCheck {
+public:
+  MisleadingIndentationCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void danglingElseCheck(const SourceManager &SM, ASTContext *Context,
+                         const IfStmt *If);
+  void missingBracesCheck(const SourceManager &SM, const CompoundStmt *CStmt);
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MISLEADING_INDENTATION_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/MisplacedArrayIndexCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/MisplacedArrayIndexCheck.cpp
new file mode 100644
index 0000000..f5e09fa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/MisplacedArrayIndexCheck.cpp
@@ -0,0 +1,57 @@
+//===--- MisplacedArrayIndexCheck.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 "MisplacedArrayIndexCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void MisplacedArrayIndexCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(arraySubscriptExpr(hasLHS(hasType(isInteger())),
+                                        hasRHS(hasType(isAnyPointer())))
+                         .bind("expr"),
+                     this);
+}
+
+void MisplacedArrayIndexCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *ArraySubscriptE =
+      Result.Nodes.getNodeAs<ArraySubscriptExpr>("expr");
+
+  auto Diag = diag(ArraySubscriptE->getLocStart(), "confusing array subscript "
+                                                   "expression, usually the "
+                                                   "index is inside the []");
+
+  // Only try to fixit when LHS and RHS can be swapped directly without changing
+  // the logic.
+  const Expr *RHSE = ArraySubscriptE->getRHS()->IgnoreParenImpCasts();
+  if (!isa<StringLiteral>(RHSE) && !isa<DeclRefExpr>(RHSE) &&
+      !isa<MemberExpr>(RHSE))
+    return;
+
+  const StringRef LText = tooling::fixit::getText(
+      ArraySubscriptE->getLHS()->getSourceRange(), *Result.Context);
+  const StringRef RText = tooling::fixit::getText(
+      ArraySubscriptE->getRHS()->getSourceRange(), *Result.Context);
+
+  Diag << FixItHint::CreateReplacement(
+      ArraySubscriptE->getLHS()->getSourceRange(), RText);
+  Diag << FixItHint::CreateReplacement(
+      ArraySubscriptE->getRHS()->getSourceRange(), LText);
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/MisplacedArrayIndexCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/MisplacedArrayIndexCheck.h
new file mode 100644
index 0000000..e9a2231
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/MisplacedArrayIndexCheck.h
@@ -0,0 +1,36 @@
+//===--- MisplacedArrayIndexCheck.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_MISPLACED_ARRAY_INDEX_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MISPLACED_ARRAY_INDEX_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Warn about unusual array index syntax (`index[array]` instead of
+/// `array[index]`).
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-misplaced-array-index.html
+class MisplacedArrayIndexCheck : public ClangTidyCheck {
+public:
+  MisplacedArrayIndexCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MISPLACED_ARRAY_INDEX_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NamedParameterCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NamedParameterCheck.cpp
new file mode 100644
index 0000000..ffdc813
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NamedParameterCheck.cpp
@@ -0,0 +1,127 @@
+//===--- NamedParameterCheck.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 "NamedParameterCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void NamedParameterCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
+  Finder->addMatcher(functionDecl(unless(isInstantiated())).bind("decl"), this);
+}
+
+void NamedParameterCheck::check(const MatchFinder::MatchResult &Result) {
+  const SourceManager &SM = *Result.SourceManager;
+  const auto *Function = Result.Nodes.getNodeAs<FunctionDecl>("decl");
+  SmallVector<std::pair<const FunctionDecl *, unsigned>, 4> UnnamedParams;
+
+  // Ignore implicitly generated members.
+  if (Function->isImplicit())
+    return;
+
+  // Ignore declarations without a definition if we're not dealing with an
+  // overriden method.
+  const FunctionDecl *Definition = nullptr;
+  if ((!Function->isDefined(Definition) || Function->isDefaulted() ||
+       Function->isDeleted()) &&
+      (!isa<CXXMethodDecl>(Function) ||
+       cast<CXXMethodDecl>(Function)->size_overridden_methods() == 0))
+    return;
+
+  // TODO: Handle overloads.
+  // TODO: We could check that all redeclarations use the same name for
+  //       arguments in the same position.
+  for (unsigned I = 0, E = Function->getNumParams(); I != E; ++I) {
+    const ParmVarDecl *Parm = Function->getParamDecl(I);
+    if (Parm->isImplicit())
+      continue;
+    // Look for unnamed parameters.
+    if (!Parm->getName().empty())
+      continue;
+
+    // Don't warn on the dummy argument on post-inc and post-dec operators.
+    if ((Function->getOverloadedOperator() == OO_PlusPlus ||
+         Function->getOverloadedOperator() == OO_MinusMinus) &&
+        Parm->getType()->isSpecificBuiltinType(BuiltinType::Int))
+      continue;
+
+    // Sanity check the source locations.
+    if (!Parm->getLocation().isValid() || Parm->getLocation().isMacroID() ||
+        !SM.isWrittenInSameFile(Parm->getLocStart(), Parm->getLocation()))
+      continue;
+
+    // Skip gmock testing::Unused parameters.
+    if (auto Typedef = Parm->getType()->getAs<clang::TypedefType>())
+      if (Typedef->getDecl()->getQualifiedNameAsString() == "testing::Unused")
+        continue;
+
+    // Skip std::nullptr_t.
+    if (Parm->getType().getCanonicalType()->isNullPtrType())
+      continue;
+
+    // Look for comments. We explicitly want to allow idioms like
+    // void foo(int /*unused*/)
+    const char *Begin = SM.getCharacterData(Parm->getLocStart());
+    const char *End = SM.getCharacterData(Parm->getLocation());
+    StringRef Data(Begin, End - Begin);
+    if (Data.find("/*") != StringRef::npos)
+      continue;
+
+    UnnamedParams.push_back(std::make_pair(Function, I));
+  }
+
+  // Emit only one warning per function but fixits for all unnamed parameters.
+  if (!UnnamedParams.empty()) {
+    const ParmVarDecl *FirstParm =
+        UnnamedParams.front().first->getParamDecl(UnnamedParams.front().second);
+    auto D = diag(FirstParm->getLocation(),
+                  "all parameters should be named in a function");
+
+    for (auto P : UnnamedParams) {
+      // Fallback to an unused marker.
+      StringRef NewName = "unused";
+
+      // If the method is overridden, try to copy the name from the base method
+      // into the overrider.
+      const auto *M = dyn_cast<CXXMethodDecl>(P.first);
+      if (M && M->size_overridden_methods() > 0) {
+        const ParmVarDecl *OtherParm =
+            (*M->begin_overridden_methods())->getParamDecl(P.second);
+        StringRef Name = OtherParm->getName();
+        if (!Name.empty())
+          NewName = Name;
+      }
+
+      // If the definition has a named parameter use that name.
+      if (Definition) {
+        const ParmVarDecl *DefParm = Definition->getParamDecl(P.second);
+        StringRef Name = DefParm->getName();
+        if (!Name.empty())
+          NewName = Name;
+      }
+
+      // Now insert the comment. Note that getLocation() points to the place
+      // where the name would be, this allows us to also get complex cases like
+      // function pointers right.
+      const ParmVarDecl *Parm = P.first->getParamDecl(P.second);
+      D << FixItHint::CreateInsertion(Parm->getLocation(),
+                                      " /*" + NewName.str() + "*/");
+    }
+  }
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NamedParameterCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NamedParameterCheck.h
new file mode 100644
index 0000000..bd38ad2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NamedParameterCheck.h
@@ -0,0 +1,42 @@
+//===--- NamedParameterCheck.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_NAMEDPARAMETERCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NAMEDPARAMETERCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Find functions with unnamed arguments.
+///
+/// The check implements the following rule originating in the Google C++ Style
+/// Guide:
+///
+/// https://google.github.io/styleguide/cppguide.html#Function_Declarations_and_Definitions
+///
+/// All parameters should be named, with identical names in the declaration and
+/// implementation.
+///
+/// Corresponding cpplint.py check name: 'readability/function'.
+class NamedParameterCheck : public ClangTidyCheck {
+public:
+  NamedParameterCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NAMEDPARAMETERCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp
new file mode 100644
index 0000000..409aba9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp
@@ -0,0 +1,196 @@
+//===--- NamespaceCommentCheck.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 "NamespaceCommentCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+NamespaceCommentCheck::NamespaceCommentCheck(StringRef Name,
+                                             ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      NamespaceCommentPattern("^/[/*] *(end (of )?)? *(anonymous|unnamed)? *"
+                              "namespace( +([a-zA-Z0-9_:]+))?\\.? *(\\*/)?$",
+                              llvm::Regex::IgnoreCase),
+      ShortNamespaceLines(Options.get("ShortNamespaceLines", 1u)),
+      SpacesBeforeComments(Options.get("SpacesBeforeComments", 1u)) {}
+
+void NamespaceCommentCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "ShortNamespaceLines", ShortNamespaceLines);
+  Options.store(Opts, "SpacesBeforeComments", SpacesBeforeComments);
+}
+
+void NamespaceCommentCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (getLangOpts().CPlusPlus)
+    Finder->addMatcher(namespaceDecl().bind("namespace"), this);
+}
+
+static bool locationsInSameFile(const SourceManager &Sources,
+                                SourceLocation Loc1, SourceLocation Loc2) {
+  return Loc1.isFileID() && Loc2.isFileID() &&
+         Sources.getFileID(Loc1) == Sources.getFileID(Loc2);
+}
+
+static std::string getNamespaceComment(const NamespaceDecl *ND,
+                                       bool InsertLineBreak) {
+  std::string Fix = "// namespace";
+  if (!ND->isAnonymousNamespace())
+    Fix.append(" ").append(ND->getNameAsString());
+  if (InsertLineBreak)
+    Fix.append("\n");
+  return Fix;
+}
+
+static std::string getNamespaceComment(const std::string &NameSpaceName,
+                                       bool InsertLineBreak) {
+  std::string Fix = "// namespace ";
+  Fix.append(NameSpaceName);
+  if (InsertLineBreak)
+    Fix.append("\n");
+  return Fix;
+}
+
+void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *ND = Result.Nodes.getNodeAs<NamespaceDecl>("namespace");
+  const SourceManager &Sources = *Result.SourceManager;
+
+  if (!locationsInSameFile(Sources, ND->getLocStart(), ND->getRBraceLoc()))
+    return;
+
+  // Don't require closing comments for namespaces spanning less than certain
+  // number of lines.
+  unsigned StartLine = Sources.getSpellingLineNumber(ND->getLocStart());
+  unsigned EndLine = Sources.getSpellingLineNumber(ND->getRBraceLoc());
+  if (EndLine - StartLine + 1 <= ShortNamespaceLines)
+    return;
+
+  // Find next token after the namespace closing brace.
+  SourceLocation AfterRBrace = ND->getRBraceLoc().getLocWithOffset(1);
+  SourceLocation Loc = AfterRBrace;
+  Token Tok;
+  SourceLocation LBracketLocation = ND->getLocation();
+  SourceLocation NestedNamespaceBegin = LBracketLocation;
+
+  // Currently for nested namepsace (n1::n2::...) the AST matcher will match foo
+  // then bar instead of a single match. So if we got a nested namespace we have
+  // to skip the next ones.
+  for (const auto &EndOfNameLocation : Ends) {
+    if (Sources.isBeforeInTranslationUnit(NestedNamespaceBegin,
+                                          EndOfNameLocation))
+      return;
+  }
+
+  // Ignore macros
+  if (!ND->getLocation().isMacroID()) {
+    while (Lexer::getRawToken(LBracketLocation, Tok, Sources, getLangOpts()) ||
+           !Tok.is(tok::l_brace)) {
+      LBracketLocation = LBracketLocation.getLocWithOffset(1);
+    }
+  }
+
+  auto TextRange =
+      Lexer::getAsCharRange(SourceRange(NestedNamespaceBegin, LBracketLocation),
+                            Sources, getLangOpts());
+  StringRef NestedNamespaceName =
+      Lexer::getSourceText(TextRange, Sources, getLangOpts()).rtrim();
+  bool IsNested = NestedNamespaceName.contains(':');
+
+  if (IsNested)
+    Ends.push_back(LBracketLocation);
+  else
+    NestedNamespaceName = ND->getName();
+
+  // Skip whitespace until we find the next token.
+  while (Lexer::getRawToken(Loc, Tok, Sources, getLangOpts()) ||
+         Tok.is(tok::semi)) {
+    Loc = Loc.getLocWithOffset(1);
+  }
+
+  if (!locationsInSameFile(Sources, ND->getRBraceLoc(), Loc))
+    return;
+
+  bool NextTokenIsOnSameLine = Sources.getSpellingLineNumber(Loc) == EndLine;
+  // If we insert a line comment before the token in the same line, we need
+  // to insert a line break.
+  bool NeedLineBreak = NextTokenIsOnSameLine && Tok.isNot(tok::eof);
+
+  SourceRange OldCommentRange(AfterRBrace, AfterRBrace);
+  std::string Message = "%0 not terminated with a closing comment";
+
+  // Try to find existing namespace closing comment on the same line.
+  if (Tok.is(tok::comment) && NextTokenIsOnSameLine) {
+    StringRef Comment(Sources.getCharacterData(Loc), Tok.getLength());
+    SmallVector<StringRef, 7> Groups;
+    if (NamespaceCommentPattern.match(Comment, &Groups)) {
+      StringRef NamespaceNameInComment = Groups.size() > 5 ? Groups[5] : "";
+      StringRef Anonymous = Groups.size() > 3 ? Groups[3] : "";
+
+      if (IsNested && NestedNamespaceName == NamespaceNameInComment) {
+        // C++17 nested namespace.
+        return;
+      } else if ((ND->isAnonymousNamespace() &&
+                  NamespaceNameInComment.empty()) ||
+                 (ND->getNameAsString() == NamespaceNameInComment &&
+                  Anonymous.empty())) {
+        // Check if the namespace in the comment is the same.
+        // FIXME: Maybe we need a strict mode, where we always fix namespace
+        // comments with different format.
+        return;
+      }
+
+      // Otherwise we need to fix the comment.
+      NeedLineBreak = Comment.startswith("/*");
+      OldCommentRange =
+          SourceRange(AfterRBrace, Loc.getLocWithOffset(Tok.getLength()));
+      Message =
+          (llvm::Twine(
+               "%0 ends with a comment that refers to a wrong namespace '") +
+           NamespaceNameInComment + "'")
+              .str();
+    } else if (Comment.startswith("//")) {
+      // Assume that this is an unrecognized form of a namespace closing line
+      // comment. Replace it.
+      NeedLineBreak = false;
+      OldCommentRange =
+          SourceRange(AfterRBrace, Loc.getLocWithOffset(Tok.getLength()));
+      Message = "%0 ends with an unrecognized comment";
+    }
+    // If it's a block comment, just move it to the next line, as it can be
+    // multi-line or there may be other tokens behind it.
+  }
+
+  std::string NamespaceName =
+      ND->isAnonymousNamespace()
+          ? "anonymous namespace"
+          : ("namespace '" + NestedNamespaceName.str() + "'");
+
+  diag(AfterRBrace, Message)
+      << NamespaceName
+      << FixItHint::CreateReplacement(
+             CharSourceRange::getCharRange(OldCommentRange),
+             std::string(SpacesBeforeComments, ' ') +
+                 (IsNested
+                      ? getNamespaceComment(NestedNamespaceName, NeedLineBreak)
+                      : getNamespaceComment(ND, NeedLineBreak)));
+  diag(ND->getLocation(), "%0 starts here", DiagnosticIDs::Note)
+      << NamespaceName;
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.h
new file mode 100644
index 0000000..1b1a231
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.h
@@ -0,0 +1,44 @@
+//===--- NamespaceCommentCheck.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_NAMESPACECOMMENTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NAMESPACECOMMENTCHECK_H
+
+#include "../ClangTidy.h"
+#include "llvm/Support/Regex.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Checks that long namespaces have a closing comment.
+///
+/// http://llvm.org/docs/CodingStandards.html#namespace-indentation
+///
+/// https://google.github.io/styleguide/cppguide.html#Namespaces
+class NamespaceCommentCheck : public ClangTidyCheck {
+public:
+  NamespaceCommentCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void storeOptions(ClangTidyOptions::OptionMap &Options) override;
+
+  llvm::Regex NamespaceCommentPattern;
+  const unsigned ShortNamespaceLines;
+  const unsigned SpacesBeforeComments;
+  llvm::SmallVector<SourceLocation, 4> Ends;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NAMESPACECOMMENTCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
new file mode 100644
index 0000000..bc6507c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
@@ -0,0 +1,223 @@
+//===--- NonConstParameterCheck.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 "NonConstParameterCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void NonConstParameterCheck::registerMatchers(MatchFinder *Finder) {
+  // Add parameters to Parameters.
+  Finder->addMatcher(parmVarDecl(unless(isInstantiated())).bind("Parm"), this);
+
+  // C++ constructor.
+  Finder->addMatcher(cxxConstructorDecl().bind("Ctor"), this);
+
+  // Track unused parameters, there is Wunused-parameter about unused
+  // parameters.
+  Finder->addMatcher(declRefExpr().bind("Ref"), this);
+
+  // Analyse parameter usage in function.
+  Finder->addMatcher(stmt(anyOf(unaryOperator(anyOf(hasOperatorName("++"),
+                                                    hasOperatorName("--"))),
+                                binaryOperator(), callExpr(), returnStmt(),
+                                cxxConstructExpr()))
+                         .bind("Mark"),
+                     this);
+  Finder->addMatcher(varDecl(hasInitializer(anything())).bind("Mark"), this);
+}
+
+void NonConstParameterCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *Parm = Result.Nodes.getNodeAs<ParmVarDecl>("Parm")) {
+    if (const DeclContext *D = Parm->getParentFunctionOrMethod()) {
+      if (const auto *M = dyn_cast<CXXMethodDecl>(D)) {
+        if (M->isVirtual() || M->size_overridden_methods() != 0)
+          return;
+      }
+    }
+    addParm(Parm);
+  } else if (const auto *Ctor =
+                 Result.Nodes.getNodeAs<CXXConstructorDecl>("Ctor")) {
+    for (const auto *Parm : Ctor->parameters())
+      addParm(Parm);
+    for (const auto *Init : Ctor->inits())
+      markCanNotBeConst(Init->getInit(), true);
+  } else if (const auto *Ref = Result.Nodes.getNodeAs<DeclRefExpr>("Ref")) {
+    setReferenced(Ref);
+  } else if (const auto *S = Result.Nodes.getNodeAs<Stmt>("Mark")) {
+    if (const auto *B = dyn_cast<BinaryOperator>(S)) {
+      if (B->isAssignmentOp())
+        markCanNotBeConst(B, false);
+    } else if (const auto *CE = dyn_cast<CallExpr>(S)) {
+      // Typically, if a parameter is const then it is fine to make the data
+      // const. But sometimes the data is written even though the parameter
+      // is const. Mark all data passed by address to the function.
+      for (const auto *Arg : CE->arguments()) {
+        markCanNotBeConst(Arg->IgnoreParenCasts(), true);
+      }
+
+      // Data passed by nonconst reference should not be made const.
+      if (const FunctionDecl *FD = CE->getDirectCallee()) {
+        unsigned ArgNr = 0U;
+        for (const auto *Par : FD->parameters()) {
+          if (ArgNr >= CE->getNumArgs())
+            break;
+          const Expr *Arg = CE->getArg(ArgNr++);
+          // Is this a non constant reference parameter?
+          const Type *ParType = Par->getType().getTypePtr();
+          if (!ParType->isReferenceType() || Par->getType().isConstQualified())
+            continue;
+          markCanNotBeConst(Arg->IgnoreParenCasts(), false);
+        }
+      }
+    } else if (const auto *CE = dyn_cast<CXXConstructExpr>(S)) {
+      for (const auto *Arg : CE->arguments()) {
+        markCanNotBeConst(Arg->IgnoreParenCasts(), true);
+      }
+    } else if (const auto *R = dyn_cast<ReturnStmt>(S)) {
+      markCanNotBeConst(R->getRetValue(), true);
+    } else if (const auto *U = dyn_cast<UnaryOperator>(S)) {
+      markCanNotBeConst(U, true);
+    }
+  } else if (const auto *VD = Result.Nodes.getNodeAs<VarDecl>("Mark")) {
+    const QualType T = VD->getType();
+    if ((T->isPointerType() && !T->getPointeeType().isConstQualified()) ||
+        T->isArrayType())
+      markCanNotBeConst(VD->getInit(), true);
+  }
+}
+
+void NonConstParameterCheck::addParm(const ParmVarDecl *Parm) {
+  // Only add nonconst integer/float pointer parameters.
+  const QualType T = Parm->getType();
+  if (!T->isPointerType() || T->getPointeeType().isConstQualified() ||
+      !(T->getPointeeType()->isIntegerType() ||
+        T->getPointeeType()->isFloatingType()))
+    return;
+
+  if (Parameters.find(Parm) != Parameters.end())
+    return;
+
+  ParmInfo PI;
+  PI.IsReferenced = false;
+  PI.CanBeConst = true;
+  Parameters[Parm] = PI;
+}
+
+void NonConstParameterCheck::setReferenced(const DeclRefExpr *Ref) {
+  auto It = Parameters.find(dyn_cast<ParmVarDecl>(Ref->getDecl()));
+  if (It != Parameters.end())
+    It->second.IsReferenced = true;
+}
+
+void NonConstParameterCheck::onEndOfTranslationUnit() {
+  diagnoseNonConstParameters();
+}
+
+void NonConstParameterCheck::diagnoseNonConstParameters() {
+  for (const auto &It : Parameters) {
+    const ParmVarDecl *Par = It.first;
+    const ParmInfo &ParamInfo = It.second;
+
+    // Unused parameter => there are other warnings about this.
+    if (!ParamInfo.IsReferenced)
+      continue;
+
+    // Parameter can't be const.
+    if (!ParamInfo.CanBeConst)
+      continue;
+
+    SmallVector<FixItHint, 8> Fixes;
+    auto *Function =
+        dyn_cast_or_null<const FunctionDecl>(Par->getParentFunctionOrMethod());
+    if (!Function)
+      continue;
+    unsigned Index = Par->getFunctionScopeIndex();
+    for (FunctionDecl *FnDecl : Function->redecls())
+      Fixes.push_back(FixItHint::CreateInsertion(
+          FnDecl->getParamDecl(Index)->getLocStart(), "const "));
+
+    diag(Par->getLocation(), "pointer parameter '%0' can be pointer to const")
+        << Par->getName() << Fixes;
+  }
+}
+
+void NonConstParameterCheck::markCanNotBeConst(const Expr *E,
+                                               bool CanNotBeConst) {
+  if (!E)
+    return;
+
+  if (const auto *Cast = dyn_cast<ImplicitCastExpr>(E)) {
+    // If expression is const then ignore usage.
+    const QualType T = Cast->getType();
+    if (T->isPointerType() && T->getPointeeType().isConstQualified())
+      return;
+  }
+
+  E = E->IgnoreParenCasts();
+
+  if (const auto *B = dyn_cast<BinaryOperator>(E)) {
+    if (B->isAdditiveOp()) {
+      // p + 2
+      markCanNotBeConst(B->getLHS(), CanNotBeConst);
+      markCanNotBeConst(B->getRHS(), CanNotBeConst);
+    } else if (B->isAssignmentOp()) {
+      markCanNotBeConst(B->getLHS(), false);
+
+      // If LHS is not const then RHS can't be const.
+      const QualType T = B->getLHS()->getType();
+      if (T->isPointerType() && !T->getPointeeType().isConstQualified())
+        markCanNotBeConst(B->getRHS(), true);
+    }
+  } else if (const auto *C = dyn_cast<ConditionalOperator>(E)) {
+    markCanNotBeConst(C->getTrueExpr(), CanNotBeConst);
+    markCanNotBeConst(C->getFalseExpr(), CanNotBeConst);
+  } else if (const auto *U = dyn_cast<UnaryOperator>(E)) {
+    if (U->getOpcode() == UO_PreInc || U->getOpcode() == UO_PreDec ||
+        U->getOpcode() == UO_PostInc || U->getOpcode() == UO_PostDec) {
+      if (const auto *SubU =
+              dyn_cast<UnaryOperator>(U->getSubExpr()->IgnoreParenCasts()))
+        markCanNotBeConst(SubU->getSubExpr(), true);
+      markCanNotBeConst(U->getSubExpr(), CanNotBeConst);
+    } else if (U->getOpcode() == UO_Deref) {
+      if (!CanNotBeConst)
+        markCanNotBeConst(U->getSubExpr(), true);
+    } else {
+      markCanNotBeConst(U->getSubExpr(), CanNotBeConst);
+    }
+  } else if (const auto *A = dyn_cast<ArraySubscriptExpr>(E)) {
+    markCanNotBeConst(A->getBase(), true);
+  } else if (const auto *CLE = dyn_cast<CompoundLiteralExpr>(E)) {
+    markCanNotBeConst(CLE->getInitializer(), true);
+  } else if (const auto *Constr = dyn_cast<CXXConstructExpr>(E)) {
+    for (const auto *Arg : Constr->arguments()) {
+      if (const auto *M = dyn_cast<MaterializeTemporaryExpr>(Arg))
+        markCanNotBeConst(cast<Expr>(M->getTemporary()), CanNotBeConst);
+    }
+  } else if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
+    for (unsigned I = 0U; I < ILE->getNumInits(); ++I)
+      markCanNotBeConst(ILE->getInit(I), true);
+  } else if (CanNotBeConst) {
+    // Referencing parameter.
+    if (const auto *D = dyn_cast<DeclRefExpr>(E)) {
+      auto It = Parameters.find(dyn_cast<ParmVarDecl>(D->getDecl()));
+      if (It != Parameters.end())
+        It->second.CanBeConst = false;
+    }
+  }
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.h
new file mode 100644
index 0000000..3cc73e9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.h
@@ -0,0 +1,64 @@
+//===--- NonConstParameterCheck.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_NON_CONST_PARAMETER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NON_CONST_PARAMETER_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Warn when a pointer function parameter can be const.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-non-const-parameter.html
+class NonConstParameterCheck : public ClangTidyCheck {
+public:
+  NonConstParameterCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void onEndOfTranslationUnit() override;
+
+private:
+  /// Parameter info.
+  struct ParmInfo {
+    /// Is function parameter referenced?
+    bool IsReferenced;
+
+    /// Can function parameter be const?
+    bool CanBeConst;
+  };
+
+  /// Track all nonconst integer/float parameters.
+  std::map<const ParmVarDecl *, ParmInfo> Parameters;
+
+  /// Add function parameter.
+  void addParm(const ParmVarDecl *Parm);
+
+  /// Set IsReferenced.
+  void setReferenced(const DeclRefExpr *Ref);
+
+  /// Set CanNotBeConst.
+  /// Visits sub expressions recursively. If a DeclRefExpr is found
+  /// and CanNotBeConst is true the Parameter is marked as not-const.
+  /// The CanNotBeConst is updated as sub expressions are visited.
+  void markCanNotBeConst(const Expr *E, bool CanNotBeConst);
+
+  /// Diagnose non const parameters.
+  void diagnoseNonConstParameters();
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NON_CONST_PARAMETER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
new file mode 100644
index 0000000..be1ae43
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -0,0 +1,116 @@
+//===--- ReadabilityTidyModule.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 "AvoidConstParamsInDecls.h"
+#include "BracesAroundStatementsCheck.h"
+#include "ContainerSizeEmptyCheck.h"
+#include "DeleteNullPointerCheck.h"
+#include "DeletedDefaultCheck.h"
+#include "ElseAfterReturnCheck.h"
+#include "FunctionSizeCheck.h"
+#include "IdentifierNamingCheck.h"
+#include "ImplicitBoolConversionCheck.h"
+#include "InconsistentDeclarationParameterNameCheck.h"
+#include "MisleadingIndentationCheck.h"
+#include "MisplacedArrayIndexCheck.h"
+#include "NamedParameterCheck.h"
+#include "NonConstParameterCheck.h"
+#include "RedundantControlFlowCheck.h"
+#include "RedundantDeclarationCheck.h"
+#include "RedundantFunctionPtrDereferenceCheck.h"
+#include "RedundantMemberInitCheck.h"
+#include "RedundantSmartptrGetCheck.h"
+#include "RedundantStringCStrCheck.h"
+#include "RedundantStringInitCheck.h"
+#include "SimplifyBooleanExprCheck.h"
+#include "SimplifySubscriptExprCheck.h"
+#include "StaticAccessedThroughInstanceCheck.h"
+#include "StaticDefinitionInAnonymousNamespaceCheck.h"
+#include "StringCompareCheck.h"
+#include "UniqueptrDeleteReleaseCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+class ReadabilityModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<AvoidConstParamsInDecls>(
+        "readability-avoid-const-params-in-decls");
+    CheckFactories.registerCheck<BracesAroundStatementsCheck>(
+        "readability-braces-around-statements");
+    CheckFactories.registerCheck<ContainerSizeEmptyCheck>(
+        "readability-container-size-empty");
+    CheckFactories.registerCheck<DeleteNullPointerCheck>(
+        "readability-delete-null-pointer");
+    CheckFactories.registerCheck<DeletedDefaultCheck>(
+        "readability-deleted-default");
+    CheckFactories.registerCheck<ElseAfterReturnCheck>(
+        "readability-else-after-return");
+    CheckFactories.registerCheck<FunctionSizeCheck>(
+        "readability-function-size");
+    CheckFactories.registerCheck<IdentifierNamingCheck>(
+        "readability-identifier-naming");
+    CheckFactories.registerCheck<ImplicitBoolConversionCheck>(
+        "readability-implicit-bool-conversion");
+    CheckFactories.registerCheck<InconsistentDeclarationParameterNameCheck>(
+        "readability-inconsistent-declaration-parameter-name");
+    CheckFactories.registerCheck<MisleadingIndentationCheck>(
+        "readability-misleading-indentation");
+    CheckFactories.registerCheck<MisplacedArrayIndexCheck>(
+        "readability-misplaced-array-index");
+    CheckFactories.registerCheck<RedundantFunctionPtrDereferenceCheck>(
+        "readability-redundant-function-ptr-dereference");
+    CheckFactories.registerCheck<RedundantMemberInitCheck>(
+        "readability-redundant-member-init");
+    CheckFactories.registerCheck<SimplifySubscriptExprCheck>(
+        "readability-simplify-subscript-expr");
+    CheckFactories.registerCheck<StaticAccessedThroughInstanceCheck>(
+        "readability-static-accessed-through-instance");
+    CheckFactories.registerCheck<StaticDefinitionInAnonymousNamespaceCheck>(
+        "readability-static-definition-in-anonymous-namespace");
+    CheckFactories.registerCheck<StringCompareCheck>(
+        "readability-string-compare");
+    CheckFactories.registerCheck<readability::NamedParameterCheck>(
+        "readability-named-parameter");
+    CheckFactories.registerCheck<NonConstParameterCheck>(
+        "readability-non-const-parameter");
+    CheckFactories.registerCheck<RedundantControlFlowCheck>(
+        "readability-redundant-control-flow");
+    CheckFactories.registerCheck<RedundantDeclarationCheck>(
+        "readability-redundant-declaration");
+    CheckFactories.registerCheck<RedundantSmartptrGetCheck>(
+        "readability-redundant-smartptr-get");
+    CheckFactories.registerCheck<RedundantStringCStrCheck>(
+        "readability-redundant-string-cstr");
+    CheckFactories.registerCheck<RedundantStringInitCheck>(
+        "readability-redundant-string-init");
+    CheckFactories.registerCheck<SimplifyBooleanExprCheck>(
+        "readability-simplify-boolean-expr");
+    CheckFactories.registerCheck<UniqueptrDeleteReleaseCheck>(
+        "readability-uniqueptr-delete-release");
+  }
+};
+
+// Register the ReadabilityModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<ReadabilityModule>
+    X("readability-module", "Adds readability-related checks.");
+
+} // namespace readability
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the ReadabilityModule.
+volatile int ReadabilityModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
new file mode 100644
index 0000000..0788c42
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
@@ -0,0 +1,98 @@
+//===--- RedundantControlFlowCheck.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 "RedundantControlFlowCheck.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 readability {
+
+namespace {
+
+const char *const RedundantReturnDiag = "redundant return statement at the end "
+                                        "of a function with a void return type";
+const char *const RedundantContinueDiag = "redundant continue statement at the "
+                                          "end of loop statement";
+
+bool isLocationInMacroExpansion(const SourceManager &SM, SourceLocation Loc) {
+  return SM.isMacroBodyExpansion(Loc) || SM.isMacroArgExpansion(Loc);
+}
+
+} // namespace
+
+void RedundantControlFlowCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      functionDecl(
+          isDefinition(), returns(voidType()),
+          has(compoundStmt(hasAnySubstatement(returnStmt(unless(has(expr())))))
+                  .bind("return"))),
+      this);
+  auto CompoundContinue =
+      has(compoundStmt(hasAnySubstatement(continueStmt())).bind("continue"));
+  Finder->addMatcher(
+      stmt(anyOf(forStmt(), cxxForRangeStmt(), whileStmt(), doStmt()),
+           CompoundContinue),
+      this);
+}
+
+void RedundantControlFlowCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *Return = Result.Nodes.getNodeAs<CompoundStmt>("return"))
+    checkRedundantReturn(Result, Return);
+  else if (const auto *Continue =
+               Result.Nodes.getNodeAs<CompoundStmt>("continue"))
+    checkRedundantContinue(Result, Continue);
+}
+
+void RedundantControlFlowCheck::checkRedundantReturn(
+    const MatchFinder::MatchResult &Result, const CompoundStmt *Block) {
+  CompoundStmt::const_reverse_body_iterator last = Block->body_rbegin();
+  if (const auto *Return = dyn_cast<ReturnStmt>(*last))
+    issueDiagnostic(Result, Block, Return->getSourceRange(),
+                    RedundantReturnDiag);
+}
+
+void RedundantControlFlowCheck::checkRedundantContinue(
+    const MatchFinder::MatchResult &Result, const CompoundStmt *Block) {
+  CompoundStmt::const_reverse_body_iterator last = Block->body_rbegin();
+  if (const auto *Continue = dyn_cast<ContinueStmt>(*last))
+    issueDiagnostic(Result, Block, Continue->getSourceRange(),
+                    RedundantContinueDiag);
+}
+
+void RedundantControlFlowCheck::issueDiagnostic(
+    const MatchFinder::MatchResult &Result, const CompoundStmt *const Block,
+    const SourceRange &StmtRange, const char *const Diag) {
+  SourceManager &SM = *Result.SourceManager;
+  if (isLocationInMacroExpansion(SM, StmtRange.getBegin()))
+    return;
+
+  CompoundStmt::const_reverse_body_iterator Previous = ++Block->body_rbegin();
+  SourceLocation Start;
+  if (Previous != Block->body_rend())
+    Start = Lexer::findLocationAfterToken(
+        dyn_cast<Stmt>(*Previous)->getLocEnd(), tok::semi, SM, getLangOpts(),
+        /*SkipTrailingWhitespaceAndNewLine=*/true);
+  if (!Start.isValid())
+    Start = StmtRange.getBegin();
+  auto RemovedRange = CharSourceRange::getCharRange(
+      Start, Lexer::findLocationAfterToken(
+                 StmtRange.getEnd(), tok::semi, SM, getLangOpts(),
+                 /*SkipTrailingWhitespaceAndNewLine=*/true));
+
+  diag(StmtRange.getBegin(), Diag) << FixItHint::CreateRemoval(RemovedRange);
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.h
new file mode 100644
index 0000000..4b8b6fb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.h
@@ -0,0 +1,51 @@
+//===--- RedundantControlFlowCheck.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_REDUNDANT_CONTROL_FLOW_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_CONTROL_FLOW_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Eliminates redundant `return` statements at the end of a function that
+/// returns `void`.
+///
+/// Eliminates redundant `continue` statements at the end of a loop body.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-control-flow.html
+class RedundantControlFlowCheck : public ClangTidyCheck {
+public:
+  RedundantControlFlowCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void
+  checkRedundantReturn(const ast_matchers::MatchFinder::MatchResult &Result,
+                       const CompoundStmt *Block);
+
+  void
+  checkRedundantContinue(const ast_matchers::MatchFinder::MatchResult &Result,
+                         const CompoundStmt *Block);
+
+  void issueDiagnostic(const ast_matchers::MatchFinder::MatchResult &Result,
+                       const CompoundStmt *Block, const SourceRange &StmtRange,
+                       const char *Diag);
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_CONTROL_FLOW_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp
new file mode 100644
index 0000000..1df3f05
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp
@@ -0,0 +1,82 @@
+//===--- RedundantDeclarationCheck.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 "RedundantDeclarationCheck.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 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(),
+                                                hasParent(friendDecl()))))))
+          .bind("Decl"),
+      this);
+}
+
+void RedundantDeclarationCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *D = Result.Nodes.getNodeAs<NamedDecl>("Decl");
+  const auto *Prev = D->getPreviousDecl();
+  if (!Prev)
+    return;
+  if (!Prev->getLocation().isValid())
+    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;
+
+  const bool DifferentHeaders =
+      !SM.isInMainFile(D->getLocation()) &&
+      !SM.isWrittenInSameFile(Prev->getLocation(), D->getLocation());
+
+  bool MultiVar = false;
+  if (const auto *VD = dyn_cast<VarDecl>(D)) {
+    // Is this a multivariable declaration?
+    for (const auto Other : VD->getDeclContext()->decls()) {
+      if (Other != D && Other->getLocStart() == VD->getLocStart()) {
+        MultiVar = true;
+        break;
+      }
+    }
+  }
+
+  SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+      D->getSourceRange().getEnd(), 0, SM, Result.Context->getLangOpts());
+  {
+    auto Diag = diag(D->getLocation(), "redundant %0 declaration") << D;
+    if (!MultiVar && !DifferentHeaders)
+      Diag << FixItHint::CreateRemoval(
+          SourceRange(D->getSourceRange().getBegin(), EndLoc));
+  }
+  diag(Prev->getLocation(), "previously declared here", DiagnosticIDs::Note);
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.h
new file mode 100644
index 0000000..9be79b8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.h
@@ -0,0 +1,37 @@
+//===--- RedundantDeclarationCheck.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_REDUNDANT_DECLARATION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_DECLARATION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Find redundant variable declarations.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-declaration.html
+class RedundantDeclarationCheck : public ClangTidyCheck {
+public:
+  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
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_DECLARATION_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp
new file mode 100644
index 0000000..fa503c5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp
@@ -0,0 +1,37 @@
+//===--- RedundantFunctionPtrDereferenceCheck.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 "RedundantFunctionPtrDereferenceCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void RedundantFunctionPtrDereferenceCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(unaryOperator(hasOperatorName("*"),
+                                   has(implicitCastExpr(
+                                       hasCastKind(CK_FunctionToPointerDecay))))
+                         .bind("op"),
+                     this);
+}
+
+void RedundantFunctionPtrDereferenceCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Operator = Result.Nodes.getNodeAs<UnaryOperator>("op");
+  diag(Operator->getOperatorLoc(),
+       "redundant repeated dereference of function pointer")
+      << FixItHint::CreateRemoval(Operator->getOperatorLoc());
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.h
new file mode 100644
index 0000000..4cf6d11
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.h
@@ -0,0 +1,35 @@
+//===--- RedundantFunctionPtrDereferenceCheck.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_REDUNDANT_FUNCTION_PTR_DEREFERENCE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_FUNCTION_PTR_DEREFERENCE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Eliminate redundant dereferences of a function pointer.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-function-ptr-dereference.html
+class RedundantFunctionPtrDereferenceCheck : public ClangTidyCheck {
+public:
+  RedundantFunctionPtrDereferenceCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_FUNCTION_PTR_DEREFERENCE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
new file mode 100644
index 0000000..8409f9f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
@@ -0,0 +1,69 @@
+//===--- RedundantMemberInitCheck.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 "RedundantMemberInitCheck.h"
+#include "../utils/Matchers.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+#include <algorithm>
+
+using namespace clang::ast_matchers;
+using namespace clang::tidy::matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void RedundantMemberInitCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  auto Construct =
+      cxxConstructExpr(
+          hasDeclaration(cxxConstructorDecl(hasParent(
+              cxxRecordDecl(unless(isTriviallyDefaultConstructible()))))))
+          .bind("construct");
+
+  Finder->addMatcher(
+      cxxConstructorDecl(
+          unless(isDelegatingConstructor()),
+          ofClass(unless(
+              anyOf(isUnion(), ast_matchers::isTemplateInstantiation()))),
+          forEachConstructorInitializer(
+              cxxCtorInitializer(isWritten(),
+                                 withInitializer(ignoringImplicit(Construct)),
+                                 unless(forField(hasType(isConstQualified()))),
+                                 unless(forField(hasParent(recordDecl(isUnion())))))
+                  .bind("init"))),
+      this);
+}
+
+void RedundantMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Init = Result.Nodes.getNodeAs<CXXCtorInitializer>("init");
+  const auto *Construct = Result.Nodes.getNodeAs<CXXConstructExpr>("construct");
+
+  if (Construct->getNumArgs() == 0 ||
+      Construct->getArg(0)->isDefaultArgument()) {
+    if (Init->isAnyMemberInitializer()) {
+      diag(Init->getSourceLocation(), "initializer for member %0 is redundant")
+          << Init->getAnyMember()
+          << FixItHint::CreateRemoval(Init->getSourceRange());
+    } else {
+      diag(Init->getSourceLocation(),
+           "initializer for base class %0 is redundant")
+          << Construct->getType()
+          << FixItHint::CreateRemoval(Init->getSourceRange());
+    }
+  }
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
new file mode 100644
index 0000000..13cc9d3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
@@ -0,0 +1,36 @@
+//===--- RedundantMemberInitCheck.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_REDUNDANT_MEMBER_INIT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_MEMBER_INIT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Finds member initializations that are unnecessary because the same default
+/// constructor would be called if they were not present.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-member-init.html
+class RedundantMemberInitCheck : public ClangTidyCheck {
+public:
+  RedundantMemberInitCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_MEMBER_INIT_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantSmartptrGetCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantSmartptrGetCheck.cpp
new file mode 100644
index 0000000..1abd70b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantSmartptrGetCheck.cpp
@@ -0,0 +1,147 @@
+//===--- RedundantSmartptrGetCheck.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 "RedundantSmartptrGetCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+namespace {
+internal::Matcher<Expr> callToGet(const internal::Matcher<Decl> &OnClass) {
+  return cxxMemberCallExpr(
+             on(expr(anyOf(hasType(OnClass),
+                           hasType(qualType(
+                               pointsTo(decl(OnClass).bind("ptr_to_ptr"))))))
+                    .bind("smart_pointer")),
+             unless(callee(memberExpr(hasObjectExpression(cxxThisExpr())))),
+             callee(cxxMethodDecl(
+                 hasName("get"),
+                 returns(qualType(pointsTo(type().bind("getType")))))))
+      .bind("redundant_get");
+}
+
+void registerMatchersForGetArrowStart(MatchFinder *Finder,
+                                      MatchFinder::MatchCallback *Callback) {
+  const auto QuacksLikeASmartptr = recordDecl(
+      recordDecl().bind("duck_typing"),
+      has(cxxMethodDecl(hasName("operator->"),
+                        returns(qualType(pointsTo(type().bind("op->Type")))))),
+      has(cxxMethodDecl(hasName("operator*"), returns(qualType(references(
+                                                  type().bind("op*Type")))))));
+
+  // Catch 'ptr.get()->Foo()'
+  Finder->addMatcher(memberExpr(expr().bind("memberExpr"), isArrow(),
+                                hasObjectExpression(ignoringImpCasts(
+                                    callToGet(QuacksLikeASmartptr)))),
+                     Callback);
+
+  // Catch '*ptr.get()' or '*ptr->get()'
+  Finder->addMatcher(
+      unaryOperator(hasOperatorName("*"),
+                    hasUnaryOperand(callToGet(QuacksLikeASmartptr))),
+      Callback);
+
+  // Catch '!ptr.get()'
+  const auto CallToGetAsBool = ignoringParenImpCasts(callToGet(recordDecl(
+      QuacksLikeASmartptr, has(cxxConversionDecl(returns(booleanType()))))));
+  Finder->addMatcher(
+      unaryOperator(hasOperatorName("!"), hasUnaryOperand(CallToGetAsBool)),
+      Callback);
+
+  // Catch 'if(ptr.get())'
+  Finder->addMatcher(ifStmt(hasCondition(CallToGetAsBool)), Callback);
+
+  // Catch 'ptr.get() ? X : Y'
+  Finder->addMatcher(conditionalOperator(hasCondition(CallToGetAsBool)),
+                     Callback);
+}
+
+void registerMatchersForGetEquals(MatchFinder *Finder,
+                                  MatchFinder::MatchCallback *Callback) {
+  // This one is harder to do with duck typing.
+  // The operator==/!= that we are looking for might be member or non-member,
+  // might be on global namespace or found by ADL, might be a template, etc.
+  // For now, lets keep a list of known standard types.
+
+  const auto IsAKnownSmartptr =
+      recordDecl(hasAnyName("::std::unique_ptr", "::std::shared_ptr"));
+
+  // Matches against nullptr.
+  Finder->addMatcher(
+      binaryOperator(anyOf(hasOperatorName("=="), hasOperatorName("!=")),
+                     hasEitherOperand(ignoringImpCasts(
+                         anyOf(cxxNullPtrLiteralExpr(), gnuNullExpr(),
+                               integerLiteral(equals(0))))),
+                     hasEitherOperand(callToGet(IsAKnownSmartptr))),
+      Callback);
+
+  // FIXME: Match and fix if (l.get() == r.get()).
+}
+
+} // namespace
+
+void RedundantSmartptrGetCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  registerMatchersForGetArrowStart(Finder, this);
+  registerMatchersForGetEquals(Finder, this);
+}
+
+namespace {
+bool allReturnTypesMatch(const MatchFinder::MatchResult &Result) {
+  if (Result.Nodes.getNodeAs<Decl>("duck_typing") == nullptr)
+    return true;
+  // Verify that the types match.
+  // We can't do this on the matcher because the type nodes can be different,
+  // even though they represent the same type. This difference comes from how
+  // the type is referenced (eg. through a typedef, a type trait, etc).
+  const Type *OpArrowType =
+      Result.Nodes.getNodeAs<Type>("op->Type")->getUnqualifiedDesugaredType();
+  const Type *OpStarType =
+      Result.Nodes.getNodeAs<Type>("op*Type")->getUnqualifiedDesugaredType();
+  const Type *GetType =
+      Result.Nodes.getNodeAs<Type>("getType")->getUnqualifiedDesugaredType();
+  return OpArrowType == OpStarType && OpArrowType == GetType;
+}
+} // namespace
+
+void RedundantSmartptrGetCheck::check(const MatchFinder::MatchResult &Result) {
+  if (!allReturnTypesMatch(Result))
+    return;
+
+  bool IsPtrToPtr = Result.Nodes.getNodeAs<Decl>("ptr_to_ptr") != nullptr;
+  bool IsMemberExpr = Result.Nodes.getNodeAs<Expr>("memberExpr") != nullptr;
+  const auto *GetCall = Result.Nodes.getNodeAs<Expr>("redundant_get");
+  const auto *Smartptr = Result.Nodes.getNodeAs<Expr>("smart_pointer");
+
+  if (IsPtrToPtr && IsMemberExpr) {
+    // Ignore this case (eg. Foo->get()->DoSomething());
+    return;
+  }
+
+  StringRef SmartptrText = Lexer::getSourceText(
+      CharSourceRange::getTokenRange(Smartptr->getSourceRange()),
+      *Result.SourceManager, getLangOpts());
+  // Replace foo->get() with *foo, and foo.get() with foo.
+  std::string Replacement = Twine(IsPtrToPtr ? "*" : "", SmartptrText).str();
+  diag(GetCall->getLocStart(), "redundant get() call on smart pointer")
+      << FixItHint::CreateReplacement(GetCall->getSourceRange(), Replacement);
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantSmartptrGetCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantSmartptrGetCheck.h
new file mode 100644
index 0000000..1da6195
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantSmartptrGetCheck.h
@@ -0,0 +1,40 @@
+//===--- RedundantSmartptrGetCheck.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_REDUNDANTSMARTPTRGETCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTSMARTPTRGETCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Find and remove redundant calls to smart pointer's `.get()` method.
+///
+/// Examples:
+///
+/// \code
+///   ptr.get()->Foo()  ==>  ptr->Foo()
+///   *ptr.get()  ==>  *ptr
+///   *ptr->get()  ==>  **ptr
+/// \endcode
+class RedundantSmartptrGetCheck : public ClangTidyCheck {
+public:
+  RedundantSmartptrGetCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTSMARTPTRGETCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
new file mode 100644
index 0000000..21f4a8a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
@@ -0,0 +1,199 @@
+//===- RedundantStringCStrCheck.cpp - Check for redundant c_str calls -----===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements a check for redundant calls of c_str() on strings.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RedundantStringCStrCheck.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+namespace {
+
+template <typename T>
+StringRef getText(const ast_matchers::MatchFinder::MatchResult &Result,
+                  T const &Node) {
+  return Lexer::getSourceText(
+      CharSourceRange::getTokenRange(Node.getSourceRange()),
+      *Result.SourceManager, Result.Context->getLangOpts());
+}
+
+// Return true if expr needs to be put in parens when it is an argument of a
+// prefix unary operator, e.g. when it is a binary or ternary operator
+// syntactically.
+bool needParensAfterUnaryOperator(const Expr &ExprNode) {
+  if (isa<clang::BinaryOperator>(&ExprNode) ||
+      isa<clang::ConditionalOperator>(&ExprNode)) {
+    return true;
+  }
+  if (const auto *Op = dyn_cast<CXXOperatorCallExpr>(&ExprNode)) {
+    return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
+           Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
+           Op->getOperator() != OO_Subscript;
+  }
+  return false;
+}
+
+// Format a pointer to an expression: prefix with '*' but simplify
+// when it already begins with '&'.  Return empty string on failure.
+std::string
+formatDereference(const ast_matchers::MatchFinder::MatchResult &Result,
+                  const Expr &ExprNode) {
+  if (const auto *Op = dyn_cast<clang::UnaryOperator>(&ExprNode)) {
+    if (Op->getOpcode() == UO_AddrOf) {
+      // Strip leading '&'.
+      return getText(Result, *Op->getSubExpr()->IgnoreParens());
+    }
+  }
+  StringRef Text = getText(Result, ExprNode);
+  if (Text.empty())
+    return std::string();
+  // Add leading '*'.
+  if (needParensAfterUnaryOperator(ExprNode)) {
+    return (llvm::Twine("*(") + Text + ")").str();
+  }
+  return (llvm::Twine("*") + Text).str();
+}
+
+} // end namespace
+
+void RedundantStringCStrCheck::registerMatchers(
+    ast_matchers::MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // Match expressions of type 'string' or 'string*'.
+  const auto StringDecl = type(hasUnqualifiedDesugaredType(recordType(
+      hasDeclaration(cxxRecordDecl(hasName("::std::basic_string"))))));
+  const auto StringExpr =
+      expr(anyOf(hasType(StringDecl), hasType(qualType(pointsTo(StringDecl)))));
+
+  // Match string constructor.
+  const auto StringConstructorExpr = expr(anyOf(
+      cxxConstructExpr(argumentCountIs(1),
+                       hasDeclaration(cxxMethodDecl(hasName("basic_string")))),
+      cxxConstructExpr(
+          argumentCountIs(2),
+          hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
+          // If present, the second argument is the alloc object which must not
+          // be present explicitly.
+          hasArgument(1, cxxDefaultArgExpr()))));
+
+  // Match a call to the string 'c_str()' method.
+  const auto StringCStrCallExpr =
+      cxxMemberCallExpr(on(StringExpr.bind("arg")),
+                        callee(memberExpr().bind("member")),
+                        callee(cxxMethodDecl(hasAnyName("c_str", "data"))))
+          .bind("call");
+
+  // Detect redundant 'c_str()' calls through a string constructor.
+  Finder->addMatcher(cxxConstructExpr(StringConstructorExpr,
+                                      hasArgument(0, StringCStrCallExpr)),
+                     this);
+
+  // Detect: 's == str.c_str()'  ->  's == str'
+  Finder->addMatcher(
+      cxxOperatorCallExpr(
+          anyOf(
+              hasOverloadedOperatorName("<"), hasOverloadedOperatorName(">"),
+              hasOverloadedOperatorName(">="), hasOverloadedOperatorName("<="),
+              hasOverloadedOperatorName("!="), hasOverloadedOperatorName("=="),
+              hasOverloadedOperatorName("+")),
+          anyOf(allOf(hasArgument(0, StringExpr),
+                      hasArgument(1, StringCStrCallExpr)),
+                allOf(hasArgument(0, StringCStrCallExpr),
+                      hasArgument(1, StringExpr)))),
+      this);
+
+  // Detect: 'dst += str.c_str()'  ->  'dst += str'
+  // Detect: 's = str.c_str()'  ->  's = str'
+  Finder->addMatcher(cxxOperatorCallExpr(anyOf(hasOverloadedOperatorName("="),
+                                               hasOverloadedOperatorName("+=")),
+                                         hasArgument(0, StringExpr),
+                                         hasArgument(1, StringCStrCallExpr)),
+                     this);
+
+  // Detect: 'dst.append(str.c_str())'  ->  'dst.append(str)'
+  Finder->addMatcher(
+      cxxMemberCallExpr(on(StringExpr), callee(decl(cxxMethodDecl(hasAnyName(
+                                            "append", "assign", "compare")))),
+                        argumentCountIs(1), hasArgument(0, StringCStrCallExpr)),
+      this);
+
+  // Detect: 'dst.compare(p, n, str.c_str())'  ->  'dst.compare(p, n, str)'
+  Finder->addMatcher(
+      cxxMemberCallExpr(on(StringExpr),
+                        callee(decl(cxxMethodDecl(hasName("compare")))),
+                        argumentCountIs(3), hasArgument(2, StringCStrCallExpr)),
+      this);
+
+  // Detect: 'dst.find(str.c_str())'  ->  'dst.find(str)'
+  Finder->addMatcher(
+      cxxMemberCallExpr(on(StringExpr),
+                        callee(decl(cxxMethodDecl(hasAnyName(
+                            "find", "find_first_not_of", "find_first_of",
+                            "find_last_not_of", "find_last_of", "rfind")))),
+                        anyOf(argumentCountIs(1), argumentCountIs(2)),
+                        hasArgument(0, StringCStrCallExpr)),
+      this);
+
+  // Detect: 'dst.insert(pos, str.c_str())'  ->  'dst.insert(pos, str)'
+  Finder->addMatcher(
+      cxxMemberCallExpr(on(StringExpr),
+                        callee(decl(cxxMethodDecl(hasName("insert")))),
+                        argumentCountIs(2), hasArgument(1, StringCStrCallExpr)),
+      this);
+
+  // Detect redundant 'c_str()' calls through a StringRef constructor.
+  Finder->addMatcher(
+      cxxConstructExpr(
+          // Implicit constructors of these classes are overloaded
+          // wrt. string types and they internally make a StringRef
+          // referring to the argument.  Passing a string directly to
+          // them is preferred to passing a char pointer.
+          hasDeclaration(cxxMethodDecl(hasAnyName(
+              "::llvm::StringRef::StringRef", "::llvm::Twine::Twine"))),
+          argumentCountIs(1),
+          // The only argument must have the form x.c_str() or p->c_str()
+          // where the method is string::c_str().  StringRef also has
+          // a constructor from string which is more efficient (avoids
+          // strlen), so we can construct StringRef from the string
+          // directly.
+          hasArgument(0, StringCStrCallExpr)),
+      this);
+}
+
+void RedundantStringCStrCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
+  const auto *Arg = Result.Nodes.getNodeAs<Expr>("arg");
+  const auto *Member = Result.Nodes.getNodeAs<MemberExpr>("member");
+  bool Arrow = Member->isArrow();
+  // Replace the "call" node with the "arg" node, prefixed with '*'
+  // if the call was using '->' rather than '.'.
+  std::string ArgText =
+      Arrow ? formatDereference(Result, *Arg) : getText(Result, *Arg).str();
+  if (ArgText.empty())
+    return;
+
+  diag(Call->getLocStart(), "redundant call to %0")
+      << Member->getMemberDecl()
+      << FixItHint::CreateReplacement(Call->getSourceRange(), ArgText);
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.h
new file mode 100644
index 0000000..9406f8e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.h
@@ -0,0 +1,32 @@
+//===--- RedundantStringCStrCheck.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_REDUNDANTSTRINGCSTRCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTSTRINGCSTRCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Finds unnecessary calls to `std::string::c_str()`.
+class RedundantStringCStrCheck : public ClangTidyCheck {
+public:
+  RedundantStringCStrCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTSTRINGCSTRCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
new file mode 100644
index 0000000..46ce2a4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
@@ -0,0 +1,71 @@
+//===- RedundantStringInitCheck.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 "RedundantStringInitCheck.h"
+#include "../utils/Matchers.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+using namespace clang::tidy::matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void RedundantStringInitCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // Match string constructor.
+  const auto StringConstructorExpr = expr(anyOf(
+      cxxConstructExpr(argumentCountIs(1),
+                       hasDeclaration(cxxMethodDecl(hasName("basic_string")))),
+      // If present, the second argument is the alloc object which must not
+      // be present explicitly.
+      cxxConstructExpr(argumentCountIs(2),
+                       hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
+                       hasArgument(1, cxxDefaultArgExpr()))));
+
+  // Match a string constructor expression with an empty string literal.
+  const auto EmptyStringCtorExpr = cxxConstructExpr(
+      StringConstructorExpr,
+      hasArgument(0, ignoringParenImpCasts(stringLiteral(hasSize(0)))));
+
+  const auto EmptyStringCtorExprWithTemporaries =
+      cxxConstructExpr(StringConstructorExpr,
+                       hasArgument(0, ignoringImplicit(EmptyStringCtorExpr)));
+
+  // Match a variable declaration with an empty string literal as initializer.
+  // Examples:
+  //     string foo = "";
+  //     string bar("");
+  Finder->addMatcher(
+      namedDecl(
+          varDecl(hasType(hasUnqualifiedDesugaredType(recordType(
+                      hasDeclaration(cxxRecordDecl(hasName("basic_string")))))),
+                  hasInitializer(expr(ignoringImplicit(anyOf(
+                                          EmptyStringCtorExpr,
+                                          EmptyStringCtorExprWithTemporaries)))
+                                     .bind("expr"))),
+          unless(parmVarDecl()))
+          .bind("decl"),
+      this);
+}
+
+void RedundantStringInitCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *CtorExpr = Result.Nodes.getNodeAs<Expr>("expr");
+  const auto *Decl = Result.Nodes.getNodeAs<NamedDecl>("decl");
+  diag(CtorExpr->getExprLoc(), "redundant string initialization")
+      << FixItHint::CreateReplacement(CtorExpr->getSourceRange(),
+                                      Decl->getName());
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h
new file mode 100644
index 0000000..0a32eb6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h
@@ -0,0 +1,32 @@
+//===- RedundantStringInitCheck.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_REDUNDANT_STRING_INIT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_STRING_INIT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Finds unnecessary string initializations.
+class RedundantStringInitCheck : public ClangTidyCheck {
+public:
+  RedundantStringInitCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_STRING_INIT_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
new file mode 100644
index 0000000..ba8e5b4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
@@ -0,0 +1,676 @@
+//===--- SimplifyBooleanExpr.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 "SimplifyBooleanExprCheck.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Lex/Lexer.h"
+
+#include <cassert>
+#include <string>
+#include <utility>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+namespace {
+
+StringRef getText(const MatchFinder::MatchResult &Result, SourceRange Range) {
+  return Lexer::getSourceText(CharSourceRange::getTokenRange(Range),
+                              *Result.SourceManager,
+                              Result.Context->getLangOpts());
+}
+
+template <typename T>
+StringRef getText(const MatchFinder::MatchResult &Result, T &Node) {
+  return getText(Result, Node.getSourceRange());
+}
+
+const char ConditionThenStmtId[] = "if-bool-yields-then";
+const char ConditionElseStmtId[] = "if-bool-yields-else";
+const char TernaryId[] = "ternary-bool-yields-condition";
+const char TernaryNegatedId[] = "ternary-bool-yields-not-condition";
+const char IfReturnsBoolId[] = "if-return";
+const char IfReturnsNotBoolId[] = "if-not-return";
+const char ThenLiteralId[] = "then-literal";
+const char IfAssignVariableId[] = "if-assign-lvalue";
+const char IfAssignLocId[] = "if-assign-loc";
+const char IfAssignBoolId[] = "if-assign";
+const char IfAssignNotBoolId[] = "if-assign-not";
+const char IfAssignObjId[] = "if-assign-obj";
+const char CompoundReturnId[] = "compound-return";
+const char CompoundBoolId[] = "compound-bool";
+const char CompoundNotBoolId[] = "compound-bool-not";
+
+const char IfStmtId[] = "if";
+
+const char SimplifyOperatorDiagnostic[] =
+    "redundant boolean literal supplied to boolean operator";
+const char SimplifyConditionDiagnostic[] =
+    "redundant boolean literal in if statement condition";
+const char SimplifyConditionalReturnDiagnostic[] =
+    "redundant boolean literal in conditional return statement";
+
+const CXXBoolLiteralExpr *getBoolLiteral(const MatchFinder::MatchResult &Result,
+                                         StringRef Id) {
+  const auto *Literal = Result.Nodes.getNodeAs<CXXBoolLiteralExpr>(Id);
+  return (Literal && Literal->getLocStart().isMacroID()) ? nullptr : Literal;
+}
+
+internal::Matcher<Stmt> returnsBool(bool Value, StringRef Id = "ignored") {
+  auto SimpleReturnsBool =
+      returnStmt(has(cxxBoolLiteral(equals(Value)).bind(Id)))
+          .bind("returns-bool");
+  return anyOf(SimpleReturnsBool,
+               compoundStmt(statementCountIs(1), has(SimpleReturnsBool)));
+}
+
+bool needsParensAfterUnaryNegation(const Expr *E) {
+  E = E->IgnoreImpCasts();
+  if (isa<BinaryOperator>(E) || isa<ConditionalOperator>(E))
+    return true;
+
+  if (const auto *Op = dyn_cast<CXXOperatorCallExpr>(E))
+    return Op->getNumArgs() == 2 && Op->getOperator() != OO_Call &&
+           Op->getOperator() != OO_Subscript;
+
+  return false;
+}
+
+std::pair<BinaryOperatorKind, BinaryOperatorKind> Opposites[] = {
+    {BO_LT, BO_GE}, {BO_GT, BO_LE}, {BO_EQ, BO_NE}};
+
+StringRef negatedOperator(const BinaryOperator *BinOp) {
+  const BinaryOperatorKind Opcode = BinOp->getOpcode();
+  for (auto NegatableOp : Opposites) {
+    if (Opcode == NegatableOp.first)
+      return BinOp->getOpcodeStr(NegatableOp.second);
+    if (Opcode == NegatableOp.second)
+      return BinOp->getOpcodeStr(NegatableOp.first);
+  }
+  return StringRef();
+}
+
+std::pair<OverloadedOperatorKind, StringRef> OperatorNames[] = {
+    {OO_EqualEqual, "=="},   {OO_ExclaimEqual, "!="}, {OO_Less, "<"},
+    {OO_GreaterEqual, ">="}, {OO_Greater, ">"},       {OO_LessEqual, "<="}};
+
+StringRef getOperatorName(OverloadedOperatorKind OpKind) {
+  for (auto Name : OperatorNames) {
+    if (Name.first == OpKind)
+      return Name.second;
+  }
+
+  return StringRef();
+}
+
+std::pair<OverloadedOperatorKind, OverloadedOperatorKind> OppositeOverloads[] =
+    {{OO_EqualEqual, OO_ExclaimEqual},
+     {OO_Less, OO_GreaterEqual},
+     {OO_Greater, OO_LessEqual}};
+
+StringRef negatedOperator(const CXXOperatorCallExpr *OpCall) {
+  const OverloadedOperatorKind Opcode = OpCall->getOperator();
+  for (auto NegatableOp : OppositeOverloads) {
+    if (Opcode == NegatableOp.first)
+      return getOperatorName(NegatableOp.second);
+    if (Opcode == NegatableOp.second)
+      return getOperatorName(NegatableOp.first);
+  }
+  return StringRef();
+}
+
+std::string asBool(StringRef text, bool NeedsStaticCast) {
+  if (NeedsStaticCast)
+    return ("static_cast<bool>(" + text + ")").str();
+
+  return text;
+}
+
+bool needsNullPtrComparison(const Expr *E) {
+  if (const auto *ImpCast = dyn_cast<ImplicitCastExpr>(E))
+    return ImpCast->getCastKind() == CK_PointerToBoolean ||
+           ImpCast->getCastKind() == CK_MemberPointerToBoolean;
+
+  return false;
+}
+
+bool needsZeroComparison(const Expr *E) {
+  if (const auto *ImpCast = dyn_cast<ImplicitCastExpr>(E))
+    return ImpCast->getCastKind() == CK_IntegralToBoolean;
+
+  return false;
+}
+
+bool needsStaticCast(const Expr *E) {
+  if (const auto *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
+    if (ImpCast->getCastKind() == CK_UserDefinedConversion &&
+        ImpCast->getSubExpr()->getType()->isBooleanType()) {
+      if (const auto *MemCall =
+              dyn_cast<CXXMemberCallExpr>(ImpCast->getSubExpr())) {
+        if (const auto *MemDecl =
+                dyn_cast<CXXConversionDecl>(MemCall->getMethodDecl())) {
+          if (MemDecl->isExplicit())
+            return true;
+        }
+      }
+    }
+  }
+
+  E = E->IgnoreImpCasts();
+  return !E->getType()->isBooleanType();
+}
+
+std::string compareExpressionToConstant(const MatchFinder::MatchResult &Result,
+                                        const Expr *E, bool Negated,
+                                        const char *Constant) {
+  E = E->IgnoreImpCasts();
+  const std::string ExprText =
+      (isa<BinaryOperator>(E) ? ("(" + getText(Result, *E) + ")")
+                              : getText(Result, *E))
+          .str();
+  return ExprText + " " + (Negated ? "!=" : "==") + " " + Constant;
+}
+
+std::string compareExpressionToNullPtr(const MatchFinder::MatchResult &Result,
+                                       const Expr *E, bool Negated) {
+  const char *NullPtr =
+      Result.Context->getLangOpts().CPlusPlus11 ? "nullptr" : "NULL";
+  return compareExpressionToConstant(Result, E, Negated, NullPtr);
+}
+
+std::string compareExpressionToZero(const MatchFinder::MatchResult &Result,
+                                    const Expr *E, bool Negated) {
+  return compareExpressionToConstant(Result, E, Negated, "0");
+}
+
+std::string replacementExpression(const MatchFinder::MatchResult &Result,
+                                  bool Negated, const Expr *E) {
+  E = E->ignoreParenBaseCasts();
+  if (const auto *EC = dyn_cast<ExprWithCleanups>(E))
+    E = EC->getSubExpr();
+
+  const bool NeedsStaticCast = needsStaticCast(E);
+  if (Negated) {
+    if (const auto *UnOp = dyn_cast<UnaryOperator>(E)) {
+      if (UnOp->getOpcode() == UO_LNot) {
+        if (needsNullPtrComparison(UnOp->getSubExpr()))
+          return compareExpressionToNullPtr(Result, UnOp->getSubExpr(), true);
+
+        if (needsZeroComparison(UnOp->getSubExpr()))
+          return compareExpressionToZero(Result, UnOp->getSubExpr(), true);
+
+        return replacementExpression(Result, false, UnOp->getSubExpr());
+      }
+    }
+
+    if (needsNullPtrComparison(E))
+      return compareExpressionToNullPtr(Result, E, false);
+
+    if (needsZeroComparison(E))
+      return compareExpressionToZero(Result, E, false);
+
+    StringRef NegatedOperator;
+    const Expr *LHS = nullptr;
+    const Expr *RHS = nullptr;
+    if (const auto *BinOp = dyn_cast<BinaryOperator>(E)) {
+      NegatedOperator = negatedOperator(BinOp);
+      LHS = BinOp->getLHS();
+      RHS = BinOp->getRHS();
+    } else if (const auto *OpExpr = dyn_cast<CXXOperatorCallExpr>(E)) {
+      if (OpExpr->getNumArgs() == 2) {
+        NegatedOperator = negatedOperator(OpExpr);
+        LHS = OpExpr->getArg(0);
+        RHS = OpExpr->getArg(1);
+      }
+    }
+    if (!NegatedOperator.empty() && LHS && RHS)
+      return (asBool((getText(Result, *LHS) + " " + NegatedOperator + " " +
+                      getText(Result, *RHS))
+                         .str(),
+                     NeedsStaticCast));
+
+    StringRef Text = getText(Result, *E);
+    if (!NeedsStaticCast && needsParensAfterUnaryNegation(E))
+      return ("!(" + Text + ")").str();
+
+    if (needsNullPtrComparison(E))
+      return compareExpressionToNullPtr(Result, E, false);
+
+    if (needsZeroComparison(E))
+      return compareExpressionToZero(Result, E, false);
+
+    return ("!" + asBool(Text, NeedsStaticCast));
+  }
+
+  if (const auto *UnOp = dyn_cast<UnaryOperator>(E)) {
+    if (UnOp->getOpcode() == UO_LNot) {
+      if (needsNullPtrComparison(UnOp->getSubExpr()))
+        return compareExpressionToNullPtr(Result, UnOp->getSubExpr(), false);
+
+      if (needsZeroComparison(UnOp->getSubExpr()))
+        return compareExpressionToZero(Result, UnOp->getSubExpr(), false);
+    }
+  }
+
+  if (needsNullPtrComparison(E))
+    return compareExpressionToNullPtr(Result, E, true);
+
+  if (needsZeroComparison(E))
+    return compareExpressionToZero(Result, E, true);
+
+  return asBool(getText(Result, *E), NeedsStaticCast);
+}
+
+const CXXBoolLiteralExpr *stmtReturnsBool(const ReturnStmt *Ret, bool Negated) {
+  if (const auto *Bool = dyn_cast<CXXBoolLiteralExpr>(Ret->getRetValue())) {
+    if (Bool->getValue() == !Negated)
+      return Bool;
+  }
+
+  return nullptr;
+}
+
+const CXXBoolLiteralExpr *stmtReturnsBool(const IfStmt *IfRet, bool Negated) {
+  if (IfRet->getElse() != nullptr)
+    return nullptr;
+
+  if (const auto *Ret = dyn_cast<ReturnStmt>(IfRet->getThen()))
+    return stmtReturnsBool(Ret, Negated);
+
+  if (const auto *Compound = dyn_cast<CompoundStmt>(IfRet->getThen())) {
+    if (Compound->size() == 1) {
+      if (const auto *CompoundRet = dyn_cast<ReturnStmt>(Compound->body_back()))
+        return stmtReturnsBool(CompoundRet, Negated);
+    }
+  }
+
+  return nullptr;
+}
+
+bool containsDiscardedTokens(const MatchFinder::MatchResult &Result,
+                             CharSourceRange CharRange) {
+  std::string ReplacementText =
+      Lexer::getSourceText(CharRange, *Result.SourceManager,
+                           Result.Context->getLangOpts())
+          .str();
+  Lexer Lex(CharRange.getBegin(), Result.Context->getLangOpts(),
+            ReplacementText.data(), ReplacementText.data(),
+            ReplacementText.data() + ReplacementText.size());
+  Lex.SetCommentRetentionState(true);
+
+  Token Tok;
+  while (!Lex.LexFromRawLexer(Tok)) {
+    if (Tok.is(tok::TokenKind::comment) || Tok.is(tok::TokenKind::hash))
+      return true;
+  }
+
+  return false;
+}
+
+} // namespace
+
+class SimplifyBooleanExprCheck::Visitor : public RecursiveASTVisitor<Visitor> {
+  using Base = RecursiveASTVisitor<Visitor>;
+
+ public:
+  Visitor(SimplifyBooleanExprCheck *Check,
+          const MatchFinder::MatchResult &Result)
+      : Check(Check), Result(Result) {}
+
+  bool VisitBinaryOperator(BinaryOperator *Op) {
+    Check->reportBinOp(Result, Op);
+    return true;
+  }
+
+ private:
+  SimplifyBooleanExprCheck *Check;
+  const MatchFinder::MatchResult &Result;
+};
+
+
+SimplifyBooleanExprCheck::SimplifyBooleanExprCheck(StringRef Name,
+                                                   ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      ChainedConditionalReturn(Options.get("ChainedConditionalReturn", 0U)),
+      ChainedConditionalAssignment(
+          Options.get("ChainedConditionalAssignment", 0U)) {}
+
+bool containsBoolLiteral(const Expr *E) {
+  if (!E)
+    return false;
+  E = E->IgnoreParenImpCasts();
+  if (isa<CXXBoolLiteralExpr>(E))
+    return true;
+  if (const auto *BinOp = dyn_cast<BinaryOperator>(E))
+    return containsBoolLiteral(BinOp->getLHS()) ||
+           containsBoolLiteral(BinOp->getRHS());
+  if (const auto *UnaryOp = dyn_cast<UnaryOperator>(E))
+    return containsBoolLiteral(UnaryOp->getSubExpr());
+  return false;
+}
+
+void SimplifyBooleanExprCheck::reportBinOp(
+    const MatchFinder::MatchResult &Result, const BinaryOperator *Op) {
+  const auto *LHS = Op->getLHS()->IgnoreParenImpCasts();
+  const auto *RHS = Op->getRHS()->IgnoreParenImpCasts();
+
+  const CXXBoolLiteralExpr *Bool = nullptr;
+  const Expr *Other = nullptr;
+  if ((Bool = dyn_cast<CXXBoolLiteralExpr>(LHS)))
+    Other = RHS;
+  else if ((Bool = dyn_cast<CXXBoolLiteralExpr>(RHS)))
+    Other = LHS;
+  else
+    return;
+
+  if (Bool->getLocStart().isMacroID())
+    return;
+
+  // FIXME: why do we need this?
+  if (!isa<CXXBoolLiteralExpr>(Other) && containsBoolLiteral(Other))
+    return;
+
+  bool BoolValue = Bool->getValue();
+
+  auto replaceWithExpression = [this, &Result, LHS, RHS, Bool](
+                                   const Expr *ReplaceWith, bool Negated) {
+    std::string Replacement =
+        replacementExpression(Result, Negated, ReplaceWith);
+    SourceRange Range(LHS->getLocStart(), RHS->getLocEnd());
+    issueDiag(Result, Bool->getLocStart(), SimplifyOperatorDiagnostic, Range,
+              Replacement);
+  };
+
+  switch (Op->getOpcode()) {
+    case BO_LAnd:
+      if (BoolValue) {
+        // expr && true -> expr
+        replaceWithExpression(Other, /*Negated=*/false);
+      } else {
+        // expr && false -> false
+        replaceWithExpression(Bool, /*Negated=*/false);
+      }
+      break;
+    case BO_LOr:
+      if (BoolValue) {
+        // expr || true -> true
+        replaceWithExpression(Bool, /*Negated=*/false);
+      } else {
+        // expr || false -> expr
+        replaceWithExpression(Other, /*Negated=*/false);
+      }
+      break;
+    case BO_EQ:
+      // expr == true -> expr, expr == false -> !expr
+      replaceWithExpression(Other, /*Negated=*/!BoolValue);
+      break;
+    case BO_NE:
+      // expr != true -> !expr, expr != false -> expr
+      replaceWithExpression(Other, /*Negated=*/BoolValue);
+      break;
+    default:
+      break;
+  }
+}
+
+void SimplifyBooleanExprCheck::matchBoolCondition(MatchFinder *Finder,
+                                                  bool Value,
+                                                  StringRef BooleanId) {
+  Finder->addMatcher(
+      ifStmt(isExpansionInMainFile(),
+             hasCondition(cxxBoolLiteral(equals(Value)).bind(BooleanId)))
+          .bind(IfStmtId),
+      this);
+}
+
+void SimplifyBooleanExprCheck::matchTernaryResult(MatchFinder *Finder,
+                                                  bool Value,
+                                                  StringRef TernaryId) {
+  Finder->addMatcher(
+      conditionalOperator(isExpansionInMainFile(),
+                          hasTrueExpression(cxxBoolLiteral(equals(Value))),
+                          hasFalseExpression(cxxBoolLiteral(equals(!Value))))
+          .bind(TernaryId),
+      this);
+}
+
+void SimplifyBooleanExprCheck::matchIfReturnsBool(MatchFinder *Finder,
+                                                  bool Value, StringRef Id) {
+  if (ChainedConditionalReturn)
+    Finder->addMatcher(ifStmt(isExpansionInMainFile(),
+                              hasThen(returnsBool(Value, ThenLiteralId)),
+                              hasElse(returnsBool(!Value)))
+                           .bind(Id),
+                       this);
+  else
+    Finder->addMatcher(ifStmt(isExpansionInMainFile(),
+                              unless(hasParent(ifStmt())),
+                              hasThen(returnsBool(Value, ThenLiteralId)),
+                              hasElse(returnsBool(!Value)))
+                           .bind(Id),
+                       this);
+}
+
+void SimplifyBooleanExprCheck::matchIfAssignsBool(MatchFinder *Finder,
+                                                  bool Value, StringRef Id) {
+  auto SimpleThen = binaryOperator(
+      hasOperatorName("="),
+      hasLHS(declRefExpr(hasDeclaration(decl().bind(IfAssignObjId)))),
+      hasLHS(expr().bind(IfAssignVariableId)),
+      hasRHS(cxxBoolLiteral(equals(Value)).bind(IfAssignLocId)));
+  auto Then = anyOf(SimpleThen, compoundStmt(statementCountIs(1),
+                                             hasAnySubstatement(SimpleThen)));
+  auto SimpleElse = binaryOperator(
+      hasOperatorName("="),
+      hasLHS(declRefExpr(hasDeclaration(equalsBoundNode(IfAssignObjId)))),
+      hasRHS(cxxBoolLiteral(equals(!Value))));
+  auto Else = anyOf(SimpleElse, compoundStmt(statementCountIs(1),
+                                             hasAnySubstatement(SimpleElse)));
+  if (ChainedConditionalAssignment)
+    Finder->addMatcher(
+        ifStmt(isExpansionInMainFile(), hasThen(Then), hasElse(Else)).bind(Id),
+        this);
+  else
+    Finder->addMatcher(ifStmt(isExpansionInMainFile(),
+                              unless(hasParent(ifStmt())), hasThen(Then),
+                              hasElse(Else))
+                           .bind(Id),
+                       this);
+}
+
+void SimplifyBooleanExprCheck::matchCompoundIfReturnsBool(MatchFinder *Finder,
+                                                          bool Value,
+                                                          StringRef Id) {
+  Finder->addMatcher(
+      compoundStmt(allOf(hasAnySubstatement(ifStmt(hasThen(returnsBool(Value)),
+                                                   unless(hasElse(stmt())))),
+                         hasAnySubstatement(
+                             returnStmt(has(ignoringParenImpCasts(
+                                            cxxBoolLiteral(equals(!Value)))))
+                                 .bind(CompoundReturnId))))
+          .bind(Id),
+      this);
+}
+
+void SimplifyBooleanExprCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "ChainedConditionalReturn", ChainedConditionalReturn);
+  Options.store(Opts, "ChainedConditionalAssignment",
+                ChainedConditionalAssignment);
+}
+
+void SimplifyBooleanExprCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(translationUnitDecl().bind("top"), this);
+
+  matchBoolCondition(Finder, true, ConditionThenStmtId);
+  matchBoolCondition(Finder, false, ConditionElseStmtId);
+
+  matchTernaryResult(Finder, true, TernaryId);
+  matchTernaryResult(Finder, false, TernaryNegatedId);
+
+  matchIfReturnsBool(Finder, true, IfReturnsBoolId);
+  matchIfReturnsBool(Finder, false, IfReturnsNotBoolId);
+
+  matchIfAssignsBool(Finder, true, IfAssignBoolId);
+  matchIfAssignsBool(Finder, false, IfAssignNotBoolId);
+
+  matchCompoundIfReturnsBool(Finder, true, CompoundBoolId);
+  matchCompoundIfReturnsBool(Finder, false, CompoundNotBoolId);
+}
+
+void SimplifyBooleanExprCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const CXXBoolLiteralExpr *TrueConditionRemoved =
+          getBoolLiteral(Result, ConditionThenStmtId))
+    replaceWithThenStatement(Result, TrueConditionRemoved);
+  else if (const CXXBoolLiteralExpr *FalseConditionRemoved =
+               getBoolLiteral(Result, ConditionElseStmtId))
+    replaceWithElseStatement(Result, FalseConditionRemoved);
+  else if (const auto *Ternary =
+               Result.Nodes.getNodeAs<ConditionalOperator>(TernaryId))
+    replaceWithCondition(Result, Ternary);
+  else if (const auto *TernaryNegated =
+               Result.Nodes.getNodeAs<ConditionalOperator>(TernaryNegatedId))
+    replaceWithCondition(Result, TernaryNegated, true);
+  else if (const auto *If = Result.Nodes.getNodeAs<IfStmt>(IfReturnsBoolId))
+    replaceWithReturnCondition(Result, If);
+  else if (const auto *IfNot =
+               Result.Nodes.getNodeAs<IfStmt>(IfReturnsNotBoolId))
+    replaceWithReturnCondition(Result, IfNot, true);
+  else if (const auto *IfAssign =
+               Result.Nodes.getNodeAs<IfStmt>(IfAssignBoolId))
+    replaceWithAssignment(Result, IfAssign);
+  else if (const auto *IfAssignNot =
+               Result.Nodes.getNodeAs<IfStmt>(IfAssignNotBoolId))
+    replaceWithAssignment(Result, IfAssignNot, true);
+  else if (const auto *Compound =
+               Result.Nodes.getNodeAs<CompoundStmt>(CompoundBoolId))
+    replaceCompoundReturnWithCondition(Result, Compound);
+  else if (const auto *Compound =
+               Result.Nodes.getNodeAs<CompoundStmt>(CompoundNotBoolId))
+    replaceCompoundReturnWithCondition(Result, Compound, true);
+  else if (const auto TU = Result.Nodes.getNodeAs<Decl>("top"))
+    Visitor(this, Result).TraverseDecl(const_cast<Decl*>(TU));
+}
+
+void SimplifyBooleanExprCheck::issueDiag(
+    const ast_matchers::MatchFinder::MatchResult &Result, SourceLocation Loc,
+    StringRef Description, SourceRange ReplacementRange,
+    StringRef Replacement) {
+  CharSourceRange CharRange =
+      Lexer::makeFileCharRange(CharSourceRange::getTokenRange(ReplacementRange),
+                               *Result.SourceManager, getLangOpts());
+
+  DiagnosticBuilder Diag = diag(Loc, Description);
+  if (!containsDiscardedTokens(Result, CharRange))
+    Diag << FixItHint::CreateReplacement(CharRange, Replacement);
+}
+
+void SimplifyBooleanExprCheck::replaceWithThenStatement(
+    const MatchFinder::MatchResult &Result,
+    const CXXBoolLiteralExpr *TrueConditionRemoved) {
+  const auto *IfStatement = Result.Nodes.getNodeAs<IfStmt>(IfStmtId);
+  issueDiag(Result, TrueConditionRemoved->getLocStart(),
+            SimplifyConditionDiagnostic, IfStatement->getSourceRange(),
+            getText(Result, *IfStatement->getThen()));
+}
+
+void SimplifyBooleanExprCheck::replaceWithElseStatement(
+    const MatchFinder::MatchResult &Result,
+    const CXXBoolLiteralExpr *FalseConditionRemoved) {
+  const auto *IfStatement = Result.Nodes.getNodeAs<IfStmt>(IfStmtId);
+  const Stmt *ElseStatement = IfStatement->getElse();
+  issueDiag(Result, FalseConditionRemoved->getLocStart(),
+            SimplifyConditionDiagnostic, IfStatement->getSourceRange(),
+            ElseStatement ? getText(Result, *ElseStatement) : "");
+}
+
+void SimplifyBooleanExprCheck::replaceWithCondition(
+    const MatchFinder::MatchResult &Result, const ConditionalOperator *Ternary,
+    bool Negated) {
+  std::string Replacement =
+      replacementExpression(Result, Negated, Ternary->getCond());
+  issueDiag(Result, Ternary->getTrueExpr()->getLocStart(),
+            "redundant boolean literal in ternary expression result",
+            Ternary->getSourceRange(), Replacement);
+}
+
+void SimplifyBooleanExprCheck::replaceWithReturnCondition(
+    const MatchFinder::MatchResult &Result, const IfStmt *If, bool Negated) {
+  StringRef Terminator = isa<CompoundStmt>(If->getElse()) ? ";" : "";
+  std::string Condition = replacementExpression(Result, Negated, If->getCond());
+  std::string Replacement = ("return " + Condition + Terminator).str();
+  SourceLocation Start =
+      Result.Nodes.getNodeAs<CXXBoolLiteralExpr>(ThenLiteralId)->getLocStart();
+  issueDiag(Result, Start, SimplifyConditionalReturnDiagnostic,
+            If->getSourceRange(), Replacement);
+}
+
+void SimplifyBooleanExprCheck::replaceCompoundReturnWithCondition(
+    const MatchFinder::MatchResult &Result, const CompoundStmt *Compound,
+    bool Negated) {
+  const auto *Ret = Result.Nodes.getNodeAs<ReturnStmt>(CompoundReturnId);
+
+  // The body shouldn't be empty because the matcher ensures that it must
+  // contain at least two statements:
+  // 1) A `return` statement returning a boolean literal `false` or `true`
+  // 2) An `if` statement with no `else` clause that consists of a single
+  //    `return` statement returning the opposite boolean literal `true` or
+  //    `false`.
+  assert(Compound->size() >= 2);
+  const IfStmt *BeforeIf = nullptr;
+  CompoundStmt::const_body_iterator Current = Compound->body_begin();
+  CompoundStmt::const_body_iterator After = Compound->body_begin();
+  for (++After; After != Compound->body_end() && *Current != Ret;
+       ++Current, ++After) {
+    if (const auto *If = dyn_cast<IfStmt>(*Current)) {
+      if (const CXXBoolLiteralExpr *Lit = stmtReturnsBool(If, Negated)) {
+        if (*After == Ret) {
+          if (!ChainedConditionalReturn && BeforeIf)
+            continue;
+
+          const Expr *Condition = If->getCond();
+          std::string Replacement =
+              "return " + replacementExpression(Result, Negated, Condition);
+          issueDiag(
+              Result, Lit->getLocStart(), SimplifyConditionalReturnDiagnostic,
+              SourceRange(If->getLocStart(), Ret->getLocEnd()), Replacement);
+          return;
+        }
+
+        BeforeIf = If;
+      }
+    } else {
+      BeforeIf = nullptr;
+    }
+  }
+}
+
+void SimplifyBooleanExprCheck::replaceWithAssignment(
+    const MatchFinder::MatchResult &Result, const IfStmt *IfAssign,
+    bool Negated) {
+  SourceRange Range = IfAssign->getSourceRange();
+  StringRef VariableName =
+      getText(Result, *Result.Nodes.getNodeAs<Expr>(IfAssignVariableId));
+  StringRef Terminator = isa<CompoundStmt>(IfAssign->getElse()) ? ";" : "";
+  std::string Condition =
+      replacementExpression(Result, Negated, IfAssign->getCond());
+  std::string Replacement =
+      (VariableName + " = " + Condition + Terminator).str();
+  SourceLocation Location =
+      Result.Nodes.getNodeAs<CXXBoolLiteralExpr>(IfAssignLocId)->getLocStart();
+  issueDiag(Result, Location,
+            "redundant boolean literal in conditional assignment", Range,
+            Replacement);
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.h
new file mode 100644
index 0000000..af47453
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.h
@@ -0,0 +1,90 @@
+//===--- SimplifyBooleanExpr.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_SIMPLIFY_BOOLEAN_EXPR_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SIMPLIFY_BOOLEAN_EXPR_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Looks for boolean expressions involving boolean constants and simplifies
+/// them to use the appropriate boolean expression directly.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-simplify-boolean-expr.html
+class SimplifyBooleanExprCheck : public ClangTidyCheck {
+public:
+  SimplifyBooleanExprCheck(StringRef Name, ClangTidyContext *Context);
+
+  void storeOptions(ClangTidyOptions::OptionMap &Options) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  class Visitor;
+
+  void reportBinOp(const ast_matchers::MatchFinder::MatchResult &Result,
+                   const BinaryOperator *Op);
+
+  void matchBoolCondition(ast_matchers::MatchFinder *Finder, bool Value,
+                          StringRef BooleanId);
+
+  void matchTernaryResult(ast_matchers::MatchFinder *Finder, bool Value,
+                          StringRef TernaryId);
+
+  void matchIfReturnsBool(ast_matchers::MatchFinder *Finder, bool Value,
+                          StringRef Id);
+
+  void matchIfAssignsBool(ast_matchers::MatchFinder *Finder, bool Value,
+                          StringRef Id);
+
+  void matchCompoundIfReturnsBool(ast_matchers::MatchFinder *Finder, bool Value,
+                                  StringRef Id);
+
+  void
+  replaceWithThenStatement(const ast_matchers::MatchFinder::MatchResult &Result,
+                           const CXXBoolLiteralExpr *BoolLiteral);
+
+  void
+  replaceWithElseStatement(const ast_matchers::MatchFinder::MatchResult &Result,
+                           const CXXBoolLiteralExpr *FalseConditionRemoved);
+
+  void
+  replaceWithCondition(const ast_matchers::MatchFinder::MatchResult &Result,
+                       const ConditionalOperator *Ternary,
+                       bool Negated = false);
+
+  void replaceWithReturnCondition(
+      const ast_matchers::MatchFinder::MatchResult &Result, const IfStmt *If,
+      bool Negated = false);
+
+  void
+  replaceWithAssignment(const ast_matchers::MatchFinder::MatchResult &Result,
+                        const IfStmt *If, bool Negated = false);
+
+  void replaceCompoundReturnWithCondition(
+      const ast_matchers::MatchFinder::MatchResult &Result,
+      const CompoundStmt *Compound, bool Negated = false);
+
+  void issueDiag(const ast_matchers::MatchFinder::MatchResult &Result,
+                 SourceLocation Loc, StringRef Description,
+                 SourceRange ReplacementRange, StringRef Replacement);
+
+  const bool ChainedConditionalReturn;
+  const bool ChainedConditionalAssignment;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SIMPLIFY_BOOLEAN_EXPR_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifySubscriptExprCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifySubscriptExprCheck.cpp
new file mode 100644
index 0000000..28cc576
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifySubscriptExprCheck.cpp
@@ -0,0 +1,76 @@
+//===--- SimplifySubscriptExprCheck.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 "SimplifySubscriptExprCheck.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+static const char kDefaultTypes[] =
+    "::std::basic_string;::std::basic_string_view;::std::vector;::std::array";
+
+SimplifySubscriptExprCheck::SimplifySubscriptExprCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context), Types(utils::options::parseStringList(
+                                         Options.get("Types", kDefaultTypes))) {
+}
+
+void SimplifySubscriptExprCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  const auto TypesMatcher = hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(cxxRecordDecl(hasAnyName(
+          llvm::SmallVector<StringRef, 8>(Types.begin(), Types.end()))))));
+
+  Finder->addMatcher(
+      arraySubscriptExpr(hasBase(ignoringParenImpCasts(
+          cxxMemberCallExpr(
+              has(memberExpr().bind("member")),
+              on(hasType(qualType(
+                  unless(anyOf(substTemplateTypeParmType(),
+                               hasDescendant(substTemplateTypeParmType()))),
+                  anyOf(TypesMatcher, pointerType(pointee(TypesMatcher)))))),
+              callee(namedDecl(hasName("data"))))
+              .bind("call")))),
+      this);
+}
+
+void SimplifySubscriptExprCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Call = Result.Nodes.getNodeAs<CXXMemberCallExpr>("call");
+  if (Result.Context->getSourceManager().isMacroBodyExpansion(
+          Call->getExprLoc()))
+    return;
+
+  const auto *Member = Result.Nodes.getNodeAs<MemberExpr>("member");
+  auto DiagBuilder =
+      diag(Member->getMemberLoc(),
+           "accessing an element of the container does not require a call to "
+           "'data()'; did you mean to use 'operator[]'?");
+  if (Member->isArrow())
+    DiagBuilder << FixItHint::CreateInsertion(Member->getLocStart(), "(*")
+                << FixItHint::CreateInsertion(Member->getOperatorLoc(), ")");
+  DiagBuilder << FixItHint::CreateRemoval(
+      {Member->getOperatorLoc(), Call->getLocEnd()});
+}
+
+void SimplifySubscriptExprCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "Types", utils::options::serializeStringList(Types));
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifySubscriptExprCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifySubscriptExprCheck.h
new file mode 100644
index 0000000..86a21b9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifySubscriptExprCheck.h
@@ -0,0 +1,38 @@
+//===--- SimplifySubscriptExprCheck.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_SIMPLIFYSUBSCRIPTEXPRCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SIMPLIFYSUBSCRIPTEXPRCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Simplifies subscript expressions.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-simplify-subscript-expr.html
+class SimplifySubscriptExprCheck : public ClangTidyCheck {
+public:
+  SimplifySubscriptExprCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap& Opts) override;
+
+private:
+  const std::vector<std::string> Types;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SIMPLIFYSUBSCRIPTEXPRCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
new file mode 100644
index 0000000..b136577
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h
new file mode 100644
index 0000000..c2eebab
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.cpp
new file mode 100644
index 0000000..0554605
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.cpp
@@ -0,0 +1,66 @@
+//===--- StaticDefinitionInAnonymousNamespaceCheck.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 "StaticDefinitionInAnonymousNamespaceCheck.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 readability {
+
+void StaticDefinitionInAnonymousNamespaceCheck::registerMatchers(
+    MatchFinder *Finder) {
+  Finder->addMatcher(
+      namedDecl(anyOf(functionDecl(isDefinition(), isStaticStorageClass()),
+                      varDecl(isDefinition(), isStaticStorageClass())),
+                hasParent(namespaceDecl(isAnonymous())))
+          .bind("static-def"),
+      this);
+}
+
+void StaticDefinitionInAnonymousNamespaceCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *Def = Result.Nodes.getNodeAs<NamedDecl>("static-def");
+  // Skips all static definitions defined in Macro.
+  if (Def->getLocation().isMacroID())
+    return;
+
+  // Skips all static definitions in function scope.
+  const DeclContext *DC = Def->getDeclContext();
+  if (DC->getDeclKind() != Decl::Namespace)
+    return;
+
+  auto Diag =
+      diag(Def->getLocation(), "%0 is a static definition in "
+                               "anonymous namespace; static is redundant here")
+      << Def;
+  Token Tok;
+  SourceLocation Loc = Def->getSourceRange().getBegin();
+  while (Loc < Def->getSourceRange().getEnd() &&
+         !Lexer::getRawToken(Loc, Tok, *Result.SourceManager, getLangOpts(),
+                             true)) {
+    SourceRange TokenRange(Tok.getLocation(), Tok.getEndLoc());
+    StringRef SourceText =
+        Lexer::getSourceText(CharSourceRange::getTokenRange(TokenRange),
+                             *Result.SourceManager, getLangOpts());
+    if (SourceText == "static") {
+      Diag << FixItHint::CreateRemoval(TokenRange);
+      break;
+    }
+    Loc = Tok.getEndLoc();
+  }
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h
new file mode 100644
index 0000000..03e99fd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h
@@ -0,0 +1,36 @@
+//===--- StaticDefinitionInAnonymousNamespaceCheck.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_DEFINITION_IN_ANONYMOUS_NAMESPACE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STATIC_DEFINITION_IN_ANONYMOUS_NAMESPACE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Finds static function and variable definitions in anonymous namespace.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-static-definition-in-anonymous-namespace.html
+class StaticDefinitionInAnonymousNamespaceCheck : public ClangTidyCheck {
+public:
+  StaticDefinitionInAnonymousNamespaceCheck(StringRef Name,
+                                            ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STATIC_DEFINITION_IN_ANONYMOUS_NAMESPACE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
new file mode 100644
index 0000000..e75e80b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
@@ -0,0 +1,82 @@
+//===--- MiscStringCompare.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 "StringCompareCheck.h"
+#include "../utils/FixItHintUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+static const StringRef CompareMessage = "do not use 'compare' to test equality "
+                                        "of strings; use the string equality "
+                                        "operator instead";
+
+void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  const auto StrCompare = cxxMemberCallExpr(
+      callee(cxxMethodDecl(hasName("compare"),
+                           ofClass(classTemplateSpecializationDecl(
+                               hasName("::std::basic_string"))))),
+      hasArgument(0, expr().bind("str2")), argumentCountIs(1),
+      callee(memberExpr().bind("str1")));
+
+  // First and second case: cast str.compare(str) to boolean.
+  Finder->addMatcher(implicitCastExpr(hasImplicitDestinationType(booleanType()),
+                                      has(StrCompare))
+                         .bind("match1"),
+                     this);
+
+  // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0.
+  Finder->addMatcher(
+      binaryOperator(anyOf(hasOperatorName("=="), hasOperatorName("!=")),
+                     hasEitherOperand(StrCompare.bind("compare")),
+                     hasEitherOperand(integerLiteral(equals(0)).bind("zero")))
+          .bind("match2"),
+      this);
+}
+
+void StringCompareCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *Matched = Result.Nodes.getNodeAs<Stmt>("match1")) {
+    diag(Matched->getLocStart(), CompareMessage);
+    return;
+  }
+
+  if (const auto *Matched = Result.Nodes.getNodeAs<Stmt>("match2")) {
+    const ASTContext &Ctx = *Result.Context;
+
+    if (const auto *Zero = Result.Nodes.getNodeAs<Stmt>("zero")) {
+      const auto *Str1 = Result.Nodes.getNodeAs<MemberExpr>("str1");
+      const auto *Str2 = Result.Nodes.getNodeAs<Stmt>("str2");
+      const auto *Compare = Result.Nodes.getNodeAs<Stmt>("compare");
+
+      auto Diag = diag(Matched->getLocStart(), CompareMessage);
+
+      if (Str1->isArrow())
+        Diag << FixItHint::CreateInsertion(Str1->getLocStart(), "*");
+
+      Diag << tooling::fixit::createReplacement(*Zero, *Str2, Ctx)
+           << tooling::fixit::createReplacement(*Compare, *Str1->getBase(),
+                                                Ctx);
+    }
+  }
+
+  // FIXME: Add fixit to fix the code for case one and two (match1).
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StringCompareCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StringCompareCheck.h
new file mode 100644
index 0000000..248d2ee
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/StringCompareCheck.h
@@ -0,0 +1,36 @@
+//===--- StringCompareCheck.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_STRINGCOMPARECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STRINGCOMPARECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// This check flags all calls compare when used to check for string
+/// equality or inequality.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-string-compare.html
+class StringCompareCheck : public ClangTidyCheck {
+public:
+  StringCompareCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STRINGCOMPARECHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp
new file mode 100644
index 0000000..3ad346c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp
@@ -0,0 +1,69 @@
+//===--- UniqueptrDeleteReleaseCheck.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 "UniqueptrDeleteReleaseCheck.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 readability {
+
+void UniqueptrDeleteReleaseCheck::registerMatchers(MatchFinder *Finder) {
+  auto IsSusbstituted = qualType(anyOf(
+      substTemplateTypeParmType(), hasDescendant(substTemplateTypeParmType())));
+
+  auto UniquePtrWithDefaultDelete = classTemplateSpecializationDecl(
+      hasName("std::unique_ptr"),
+      hasTemplateArgument(1, refersToType(qualType(hasDeclaration(cxxRecordDecl(
+                                 hasName("std::default_delete")))))));
+
+  Finder->addMatcher(
+      cxxDeleteExpr(has(ignoringParenImpCasts(cxxMemberCallExpr(
+                        on(expr(hasType(UniquePtrWithDefaultDelete),
+                                unless(hasType(IsSusbstituted)))
+                               .bind("uptr")),
+                        callee(cxxMethodDecl(hasName("release")))))))
+          .bind("delete"),
+      this);
+}
+
+void UniqueptrDeleteReleaseCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *PtrExpr = Result.Nodes.getNodeAs<Expr>("uptr");
+  const auto *DeleteExpr = Result.Nodes.getNodeAs<Expr>("delete");
+
+  if (PtrExpr->getLocStart().isMacroID())
+    return;
+
+  // Ignore dependent types.
+  // It can give us false positives, so we go with false negatives instead to
+  // be safe.
+  if (PtrExpr->getType()->isDependentType())
+    return;
+
+  SourceLocation AfterPtr = Lexer::getLocForEndOfToken(
+      PtrExpr->getLocEnd(), 0, *Result.SourceManager, getLangOpts());
+
+  diag(DeleteExpr->getLocStart(),
+       "prefer '= nullptr' to 'delete x.release()' to reset unique_ptr<> "
+       "objects")
+      << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
+             DeleteExpr->getLocStart(), PtrExpr->getLocStart()))
+      << FixItHint::CreateReplacement(
+             CharSourceRange::getTokenRange(AfterPtr, DeleteExpr->getLocEnd()),
+             " = nullptr");
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/UniqueptrDeleteReleaseCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/UniqueptrDeleteReleaseCheck.h
new file mode 100644
index 0000000..fd86bdb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/readability/UniqueptrDeleteReleaseCheck.h
@@ -0,0 +1,36 @@
+//===--- UniqueptrDeleteReleaseCheck.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_UNIQUEPTR_DELETE_RELEASE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_UNIQUEPTR_DELETE_RELEASE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Flags statements of the form ``delete <unique_ptr expr>.release();`` and
+/// replaces them with: ``<unique_ptr expr> = nullptr;``
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-uniqueptr-delete-release.html
+class UniqueptrDeleteReleaseCheck : public ClangTidyCheck {
+public:
+  UniqueptrDeleteReleaseCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_UNIQUEPTR_DELETE_RELEASE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/rename_check.py b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/rename_check.py
new file mode 100755
index 0000000..53a5ff9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/rename_check.py
@@ -0,0 +1,272 @@
+#!/usr/bin/env python
+#
+#===- rename_check.py - clang-tidy check renamer -------------*- python -*--===#
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+import argparse
+import glob
+import os
+import re
+
+
+def replaceInFile(fileName, sFrom, sTo):
+  if sFrom == sTo:
+    return
+  txt = None
+  with open(fileName, "r") as f:
+    txt = f.read()
+
+  if sFrom not in txt:
+    return
+
+  txt = txt.replace(sFrom, sTo)
+  print("Replacing '%s' -> '%s' in '%s'..." % (sFrom, sTo, fileName))
+  with open(fileName, "w") as f:
+    f.write(txt)
+
+
+def generateCommentLineHeader(filename):
+  return ''.join(['//===--- ',
+                  os.path.basename(filename),
+                  ' - clang-tidy ',
+                  '-' * max(0, 42 - len(os.path.basename(filename))),
+                  '*- C++ -*-===//'])
+
+
+def generateCommentLineSource(filename):
+  return ''.join(['//===--- ',
+                  os.path.basename(filename),
+                  ' - clang-tidy',
+                  '-' * max(0, 52 - len(os.path.basename(filename))),
+                  '-===//'])
+
+
+def fileRename(fileName, sFrom, sTo):
+  if sFrom not in fileName or sFrom == sTo:
+    return fileName
+  newFileName = fileName.replace(sFrom, sTo)
+  print("Renaming '%s' -> '%s'..." % (fileName, newFileName))
+  os.rename(fileName, newFileName)
+  return newFileName
+
+def deleteMatchingLines(fileName, pattern):
+  lines = None
+  with open(fileName, "r") as f:
+    lines = f.readlines()
+
+  not_matching_lines = [l for l in lines if not re.search(pattern, l)]
+  if len(not_matching_lines) == len(lines):
+    return False
+
+  print("Removing lines matching '%s' in '%s'..." % (pattern, fileName))
+  print('  ' + '  '.join([l for l in lines if re.search(pattern, l)]))
+  with open(fileName, "w") as f:
+    f.writelines(not_matching_lines)
+
+  return True
+
+def getListOfFiles(clang_tidy_path):
+  files = glob.glob(os.path.join(clang_tidy_path, '*'))
+  for dirname in files:
+    if os.path.isdir(dirname):
+      files += glob.glob(os.path.join(dirname, '*'))
+  files += glob.glob(os.path.join(clang_tidy_path, '..', 'test',
+                                  'clang-tidy', '*'))
+  files += glob.glob(os.path.join(clang_tidy_path, '..', 'docs',
+                                  'clang-tidy', 'checks', '*'))
+  return [filename for filename in files if os.path.isfile(filename)]
+
+# Adapts the module's CMakelist file. Returns 'True' if it could add a new entry
+# and 'False' if the entry already existed.
+def adapt_cmake(module_path, check_name_camel):
+  filename = os.path.join(module_path, 'CMakeLists.txt')
+  with open(filename, 'r') as f:
+    lines = f.readlines()
+
+  cpp_file = check_name_camel + '.cpp'
+
+  # Figure out whether this check already exists.
+  for line in lines:
+    if line.strip() == cpp_file:
+      return False
+
+  print('Updating %s...' % filename)
+  with open(filename, 'wb') as f:
+    cpp_found = False
+    file_added = False
+    for line in lines:
+      cpp_line = line.strip().endswith('.cpp')
+      if (not file_added) and (cpp_line or cpp_found):
+        cpp_found = True
+        if (line.strip() > cpp_file) or (not cpp_line):
+          f.write('  ' + cpp_file + '\n')
+          file_added = True
+      f.write(line)
+
+  return True
+
+# Modifies the module to include the new check.
+def adapt_module(module_path, module, check_name, check_name_camel):
+  modulecpp = filter(lambda p: p.lower() == module.lower() + 'tidymodule.cpp',
+                     os.listdir(module_path))[0]
+  filename = os.path.join(module_path, modulecpp)
+  with open(filename, 'r') as f:
+    lines = f.readlines()
+
+  print('Updating %s...' % filename)
+  with open(filename, 'wb') as f:
+    header_added = False
+    header_found = False
+    check_added = False
+    check_decl = ('    CheckFactories.registerCheck<' + check_name_camel +
+                  '>(\n        "' + check_name + '");\n')
+
+    for line in lines:
+      if not header_added:
+        match = re.search('#include "(.*)"', line)
+        if match:
+          header_found = True
+          if match.group(1) > check_name_camel:
+            header_added = True
+            f.write('#include "' + check_name_camel + '.h"\n')
+        elif header_found:
+          header_added = True
+          f.write('#include "' + check_name_camel + '.h"\n')
+
+      if not check_added:
+        if line.strip() == '}':
+          check_added = True
+          f.write(check_decl)
+        else:
+          match = re.search('registerCheck<(.*)>', line)
+          if match and match.group(1) > check_name_camel:
+            check_added = True
+            f.write(check_decl)
+      f.write(line)
+
+
+# Adds a release notes entry.
+def add_release_notes(clang_tidy_path, old_check_name, new_check_name):
+  filename = os.path.normpath(os.path.join(clang_tidy_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("""
+- The '%s' check was renamed to :doc:`%s
+  <clang-tidy/checks/%s>`
+""" % (old_check_name, new_check_name, new_check_name))
+            note_added = True
+
+      f.write(line)
+
+def main():
+  parser = argparse.ArgumentParser(description='Rename clang-tidy check.')
+  parser.add_argument('old_check_name', type=str,
+                      help='Old check name.')
+  parser.add_argument('new_check_name', type=str,
+                      help='New check name.')
+  parser.add_argument('--check_class_name', type=str,
+                      help='Old name of the class implementing the check.')
+  args = parser.parse_args()
+
+  old_module = args.old_check_name.split('-')[0]
+  new_module = args.new_check_name.split('-')[0]
+  if args.check_class_name:
+    check_name_camel = args.check_class_name
+  else:
+    check_name_camel = (''.join(map(lambda elem: elem.capitalize(),
+                                    args.old_check_name.split('-')[1:])) +
+                        'Check')
+
+  new_check_name_camel = (''.join(map(lambda elem: elem.capitalize(),
+                                      args.new_check_name.split('-')[1:])) +
+                          'Check')
+
+  clang_tidy_path = os.path.dirname(__file__)
+
+  header_guard_variants = [
+      (old_module + '_' + new_check_name_camel).upper(),
+      args.old_check_name.replace('-', '_').upper()]
+  header_guard_new = (new_module + '_' + new_check_name_camel).upper()
+
+  old_module_path = os.path.join(clang_tidy_path, old_module)
+  new_module_path = os.path.join(clang_tidy_path, new_module)
+
+  # Remove the check from the old module.
+  cmake_lists = os.path.join(old_module_path, 'CMakeLists.txt')
+  check_found = deleteMatchingLines(cmake_lists, '\\b' + check_name_camel)
+  if not check_found:
+    print("Check name '%s' not found in %s. Exiting." %
+            (check_name_camel, cmake_lists))
+    return 1
+
+  modulecpp = filter(
+      lambda p: p.lower() == old_module.lower() + 'tidymodule.cpp',
+      os.listdir(old_module_path))[0]
+  deleteMatchingLines(os.path.join(old_module_path, modulecpp),
+                      '\\b' + check_name_camel + '|\\b' + args.old_check_name)
+
+  for filename in getListOfFiles(clang_tidy_path):
+    originalName = filename
+    filename = fileRename(filename, args.old_check_name,
+                          args.new_check_name)
+    filename = fileRename(filename, check_name_camel, new_check_name_camel)
+    replaceInFile(filename, generateCommentLineHeader(originalName),
+                  generateCommentLineHeader(filename))
+    replaceInFile(filename, generateCommentLineSource(originalName),
+                  generateCommentLineSource(filename))
+    for header_guard in header_guard_variants:
+      replaceInFile(filename, header_guard, header_guard_new)
+
+    if args.new_check_name + '.rst' in filename:
+      replaceInFile(
+          filename,
+          args.old_check_name + '\n' + '=' * len(args.old_check_name) + '\n',
+          args.new_check_name + '\n' + '=' * len(args.new_check_name) + '\n')
+
+    replaceInFile(filename, args.old_check_name, args.new_check_name)
+    replaceInFile(filename, old_module + '::' + check_name_camel,
+                  new_module + '::' + new_check_name_camel)
+    replaceInFile(filename, old_module + '/' + check_name_camel,
+                  new_module + '/' + new_check_name_camel)
+    replaceInFile(filename, check_name_camel, new_check_name_camel)
+
+  if old_module != new_module:
+    check_implementation_files = glob.glob(
+        os.path.join(old_module_path, new_check_name_camel + '*'))
+    for filename in check_implementation_files:
+      # Move check implementation to the directory of the new module.
+      filename = fileRename(filename, old_module_path, new_module_path)
+      replaceInFile(filename, 'namespace ' + old_module,
+                    'namespace ' + new_module)
+
+  # Add check to the new module.
+  adapt_cmake(new_module_path, new_check_name_camel)
+  adapt_module(new_module_path, new_module, args.new_check_name,
+               new_check_name_camel)
+
+  os.system(os.path.join(clang_tidy_path, 'add_new_check.py')
+            + ' --update-docs')
+  add_release_notes(clang_tidy_path, args.old_check_name, args.new_check_name)
+
+if __name__ == '__main__':
+  main()
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/tool/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/tool/CMakeLists.txt
new file mode 100644
index 0000000..a3ec4ae
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/tool/CMakeLists.txt
@@ -0,0 +1,47 @@
+set(LLVM_LINK_COMPONENTS
+  AllTargetsAsmParsers
+  AllTargetsDescs
+  AllTargetsInfos
+  support
+  )
+
+add_clang_tool(clang-tidy
+  ClangTidyMain.cpp
+  )
+add_dependencies(clang-tidy
+  clang-headers
+  )
+target_link_libraries(clang-tidy
+  PRIVATE
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangTidy
+  clangTidyAndroidModule
+  clangTidyAbseilModule
+  clangTidyBoostModule
+  clangTidyBugproneModule
+  clangTidyCERTModule
+  clangTidyCppCoreGuidelinesModule
+  clangTidyFuchsiaModule
+  clangTidyGoogleModule
+  clangTidyHICPPModule
+  clangTidyLLVMModule
+  clangTidyMiscModule
+  clangTidyModernizeModule
+  clangTidyMPIModule
+  clangTidyObjCModule
+  clangTidyPerformanceModule
+  clangTidyPortabilityModule
+  clangTidyReadabilityModule
+  clangTidyZirconModule
+  clangTooling
+  clangToolingCore
+  )
+
+install(PROGRAMS clang-tidy-diff.py
+  DESTINATION share/clang
+  COMPONENT clang-tidy)
+install(PROGRAMS run-clang-tidy.py
+  DESTINATION share/clang
+  COMPONENT clang-tidy)
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
new file mode 100644
index 0000000..b458b29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -0,0 +1,577 @@
+//===--- tools/extra/clang-tidy/ClangTidyMain.cpp - Clang tidy tool -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+///  \file This file implements a clang-tidy tool.
+///
+///  This tool uses the Clang Tooling infrastructure, see
+///    http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
+///  for details on setting it up with LLVM source tree.
+///
+//===----------------------------------------------------------------------===//
+
+#include "../ClangTidy.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/TargetSelect.h"
+
+using namespace clang::ast_matchers;
+using namespace clang::driver;
+using namespace clang::tooling;
+using namespace llvm;
+
+static cl::OptionCategory ClangTidyCategory("clang-tidy options");
+
+static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
+static cl::extrahelp ClangTidyHelp(R"(
+Configuration files:
+  clang-tidy attempts to read configuration for each source file from a
+  .clang-tidy file located in the closest parent directory of the source
+  file. If any configuration options have a corresponding command-line
+  option, command-line option takes precedence. The effective
+  configuration can be inspected using -dump-config:
+
+    $ clang-tidy -dump-config
+    ---
+    Checks:          '-*,some-check'
+    WarningsAsErrors: ''
+    HeaderFilterRegex: ''
+    FormatStyle:     none
+    User:            user
+    CheckOptions:
+      - key:             some-check.SomeOption
+        value:           'some value'
+    ...
+
+)");
+
+const char DefaultChecks[] = // Enable these checks by default:
+    "clang-diagnostic-*,"    //   * compiler diagnostics
+    "clang-analyzer-*";      //   * Static Analyzer checks
+
+static cl::opt<std::string> Checks("checks", cl::desc(R"(
+Comma-separated list of globs with optional '-'
+prefix. Globs are processed in order of
+appearance in the list. Globs without '-'
+prefix add checks with matching names to the
+set, globs with the '-' prefix remove checks
+with matching names from the set of enabled
+checks. This option's value is appended to the
+value of the 'Checks' option in .clang-tidy
+file, if any.
+)"),
+                                   cl::init(""), cl::cat(ClangTidyCategory));
+
+static cl::opt<std::string> WarningsAsErrors("warnings-as-errors", cl::desc(R"(
+Upgrades warnings to errors. Same format as
+'-checks'.
+This option's value is appended to the value of
+the 'WarningsAsErrors' option in .clang-tidy
+file, if any.
+)"),
+                                             cl::init(""),
+                                             cl::cat(ClangTidyCategory));
+
+static cl::opt<std::string> HeaderFilter("header-filter", cl::desc(R"(
+Regular expression matching the names of the
+headers to output diagnostics from. Diagnostics
+from the main file of each translation unit are
+always displayed.
+Can be used together with -line-filter.
+This option overrides the 'HeaderFilter' option
+in .clang-tidy file, if any.
+)"),
+                                         cl::init(""),
+                                         cl::cat(ClangTidyCategory));
+
+static cl::opt<bool>
+    SystemHeaders("system-headers",
+                  cl::desc("Display the errors from system headers."),
+                  cl::init(false), cl::cat(ClangTidyCategory));
+static cl::opt<std::string> LineFilter("line-filter", cl::desc(R"(
+List of files with line ranges to filter the
+warnings. Can be used together with
+-header-filter. The format of the list is a
+JSON array of objects:
+  [
+    {"name":"file1.cpp","lines":[[1,3],[5,7]]},
+    {"name":"file2.h"}
+  ]
+)"),
+                                       cl::init(""),
+                                       cl::cat(ClangTidyCategory));
+
+static cl::opt<bool> Fix("fix", cl::desc(R"(
+Apply suggested fixes. Without -fix-errors
+clang-tidy will bail out if any compilation
+errors were found.
+)"),
+                         cl::init(false), cl::cat(ClangTidyCategory));
+
+static cl::opt<bool> FixErrors("fix-errors", cl::desc(R"(
+Apply suggested fixes even if compilation
+errors were found. If compiler errors have
+attached fix-its, clang-tidy will apply them as
+well.
+)"),
+                               cl::init(false), cl::cat(ClangTidyCategory));
+
+static cl::opt<std::string> FormatStyle("format-style", cl::desc(R"(
+Style for formatting code around applied fixes:
+  - 'none' (default) turns off formatting
+  - 'file' (literally 'file', not a placeholder)
+    uses .clang-format file in the closest parent
+    directory
+  - '{ <json> }' specifies options inline, e.g.
+    -format-style='{BasedOnStyle: llvm, IndentWidth: 8}'
+  - 'llvm', 'google', 'webkit', 'mozilla'
+See clang-format documentation for the up-to-date
+information about formatting styles and options.
+This option overrides the 'FormatStyle` option in
+.clang-tidy file, if any.
+)"),
+                                   cl::init("none"),
+                                   cl::cat(ClangTidyCategory));
+
+static cl::opt<bool> ListChecks("list-checks", cl::desc(R"(
+List all enabled checks and exit. Use with
+-checks=* to list all available checks.
+)"),
+                                cl::init(false), cl::cat(ClangTidyCategory));
+
+static cl::opt<bool> ExplainConfig("explain-config", cl::desc(R"(
+For each enabled check explains, where it is
+enabled, i.e. in clang-tidy binary, command
+line or a specific configuration file.
+)"),
+                                   cl::init(false), cl::cat(ClangTidyCategory));
+
+static cl::opt<std::string> Config("config", cl::desc(R"(
+Specifies a configuration in YAML/JSON format:
+  -config="{Checks: '*',
+            CheckOptions: [{key: x,
+                            value: y}]}"
+When the value is empty, clang-tidy will
+attempt to find a file named .clang-tidy for
+each source file in its parent directories.
+)"),
+                                   cl::init(""), cl::cat(ClangTidyCategory));
+
+static cl::opt<bool> DumpConfig("dump-config", cl::desc(R"(
+Dumps configuration in the YAML format to
+stdout. This option can be used along with a
+file name (and '--' if the file is outside of a
+project with configured compilation database).
+The configuration used for this file will be
+printed.
+Use along with -checks=* to include
+configuration of all checks.
+)"),
+                                cl::init(false), cl::cat(ClangTidyCategory));
+
+static cl::opt<bool> EnableCheckProfile("enable-check-profile", cl::desc(R"(
+Enable per-check timing profiles, and print a
+report to stderr.
+)"),
+                                        cl::init(false),
+                                        cl::cat(ClangTidyCategory));
+
+static cl::opt<std::string> StoreCheckProfile("store-check-profile",
+                                              cl::desc(R"(
+By default reports are printed in tabulated
+format to stderr. When this option is passed,
+these per-TU profiles are instead stored as JSON.
+)"),
+                                              cl::value_desc("prefix"),
+                                              cl::cat(ClangTidyCategory));
+
+/// This option allows enabling the experimental alpha checkers from the static
+/// analyzer. This option is set to false and not visible in help, because it is
+/// highly not recommended for users.
+static cl::opt<bool>
+    AllowEnablingAnalyzerAlphaCheckers("allow-enabling-analyzer-alpha-checkers",
+                                       cl::init(false), cl::Hidden,
+                                       cl::cat(ClangTidyCategory));
+
+static cl::opt<std::string> ExportFixes("export-fixes", cl::desc(R"(
+YAML file to store suggested fixes in. The
+stored fixes can be applied to the input source
+code with clang-apply-replacements.
+)"),
+                                        cl::value_desc("filename"),
+                                        cl::cat(ClangTidyCategory));
+
+static cl::opt<bool> Quiet("quiet", cl::desc(R"(
+Run clang-tidy in quiet mode. This suppresses
+printing statistics about ignored warnings and
+warnings treated as errors if the respective
+options are specified.
+)"),
+                           cl::init(false),
+                           cl::cat(ClangTidyCategory));
+
+static cl::opt<std::string> VfsOverlay("vfsoverlay", cl::desc(R"(
+Overlay the virtual filesystem described by file
+over the real file system.
+)"),
+                                       cl::value_desc("filename"),
+                                       cl::cat(ClangTidyCategory));
+
+namespace clang {
+namespace tidy {
+
+static void printStats(const ClangTidyStats &Stats) {
+  if (Stats.errorsIgnored()) {
+    llvm::errs() << "Suppressed " << Stats.errorsIgnored() << " warnings (";
+    StringRef Separator = "";
+    if (Stats.ErrorsIgnoredNonUserCode) {
+      llvm::errs() << Stats.ErrorsIgnoredNonUserCode << " in non-user code";
+      Separator = ", ";
+    }
+    if (Stats.ErrorsIgnoredLineFilter) {
+      llvm::errs() << Separator << Stats.ErrorsIgnoredLineFilter
+                   << " due to line filter";
+      Separator = ", ";
+    }
+    if (Stats.ErrorsIgnoredNOLINT) {
+      llvm::errs() << Separator << Stats.ErrorsIgnoredNOLINT << " NOLINT";
+      Separator = ", ";
+    }
+    if (Stats.ErrorsIgnoredCheckFilter)
+      llvm::errs() << Separator << Stats.ErrorsIgnoredCheckFilter
+                   << " with check filters";
+    llvm::errs() << ").\n";
+    if (Stats.ErrorsIgnoredNonUserCode)
+      llvm::errs() << "Use -header-filter=.* to display errors from all "
+                      "non-system headers. Use -system-headers to display "
+                      "errors from system headers as well.\n";
+  }
+}
+
+static std::unique_ptr<ClangTidyOptionsProvider> createOptionsProvider(
+   llvm::IntrusiveRefCntPtr<vfs::FileSystem> FS) {
+  ClangTidyGlobalOptions GlobalOptions;
+  if (std::error_code Err = parseLineFilter(LineFilter, GlobalOptions)) {
+    llvm::errs() << "Invalid LineFilter: " << Err.message() << "\n\nUsage:\n";
+    llvm::cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/true);
+    return nullptr;
+  }
+
+  ClangTidyOptions DefaultOptions;
+  DefaultOptions.Checks = DefaultChecks;
+  DefaultOptions.WarningsAsErrors = "";
+  DefaultOptions.HeaderFilterRegex = HeaderFilter;
+  DefaultOptions.SystemHeaders = SystemHeaders;
+  DefaultOptions.FormatStyle = FormatStyle;
+  DefaultOptions.User = llvm::sys::Process::GetEnv("USER");
+  // USERNAME is used on Windows.
+  if (!DefaultOptions.User)
+    DefaultOptions.User = llvm::sys::Process::GetEnv("USERNAME");
+
+  ClangTidyOptions OverrideOptions;
+  if (Checks.getNumOccurrences() > 0)
+    OverrideOptions.Checks = Checks;
+  if (WarningsAsErrors.getNumOccurrences() > 0)
+    OverrideOptions.WarningsAsErrors = WarningsAsErrors;
+  if (HeaderFilter.getNumOccurrences() > 0)
+    OverrideOptions.HeaderFilterRegex = HeaderFilter;
+  if (SystemHeaders.getNumOccurrences() > 0)
+    OverrideOptions.SystemHeaders = SystemHeaders;
+  if (FormatStyle.getNumOccurrences() > 0)
+    OverrideOptions.FormatStyle = FormatStyle;
+
+  if (!Config.empty()) {
+    if (llvm::ErrorOr<ClangTidyOptions> ParsedConfig =
+            parseConfiguration(Config)) {
+      return llvm::make_unique<ConfigOptionsProvider>(
+          GlobalOptions,
+          ClangTidyOptions::getDefaults().mergeWith(DefaultOptions),
+          *ParsedConfig, OverrideOptions);
+    } else {
+      llvm::errs() << "Error: invalid configuration specified.\n"
+                   << ParsedConfig.getError().message() << "\n";
+      return nullptr;
+    }
+  }
+  return llvm::make_unique<FileOptionsProvider>(GlobalOptions, DefaultOptions,
+                                                OverrideOptions, std::move(FS));
+}
+
+llvm::IntrusiveRefCntPtr<vfs::FileSystem>
+getVfsOverlayFromFile(const std::string &OverlayFile) {
+  llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFS(
+      new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
+      OverlayFS->getBufferForFile(OverlayFile);
+  if (!Buffer) {
+    llvm::errs() << "Can't load virtual filesystem overlay file '"
+                 << OverlayFile << "': " << Buffer.getError().message()
+                 << ".\n";
+    return nullptr;
+  }
+
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getVFSFromYAML(
+      std::move(Buffer.get()), /*DiagHandler*/ nullptr, OverlayFile);
+  if (!FS) {
+    llvm::errs() << "Error: invalid virtual filesystem overlay file '"
+                 << OverlayFile << "'.\n";
+    return nullptr;
+  }
+  OverlayFS->pushOverlay(FS);
+  return OverlayFS;
+}
+
+static int clangTidyMain(int argc, const char **argv) {
+  CommonOptionsParser OptionsParser(argc, argv, ClangTidyCategory,
+                                    cl::ZeroOrMore);
+  llvm::IntrusiveRefCntPtr<vfs::FileSystem> BaseFS(
+      VfsOverlay.empty() ? vfs::getRealFileSystem()
+                         : getVfsOverlayFromFile(VfsOverlay));
+  if (!BaseFS)
+    return 1;
+
+  auto OwningOptionsProvider = createOptionsProvider(BaseFS);
+  auto *OptionsProvider = OwningOptionsProvider.get();
+  if (!OptionsProvider)
+    return 1;
+
+  auto MakeAbsolute = [](const std::string &Input) -> SmallString<256> {
+    if (Input.empty())
+      return {};
+    SmallString<256> AbsolutePath(Input);
+    if (std::error_code EC = llvm::sys::fs::make_absolute(AbsolutePath)) {
+      llvm::errs() << "Can't make absolute path from " << Input << ": "
+                   << EC.message() << "\n";
+    }
+    return AbsolutePath;
+  };
+
+  SmallString<256> ProfilePrefix = MakeAbsolute(StoreCheckProfile);
+
+  StringRef FileName("dummy");
+  auto PathList = OptionsParser.getSourcePathList();
+  if (!PathList.empty()) {
+    FileName = PathList.front();
+  }
+
+  SmallString<256> FilePath = MakeAbsolute(FileName);
+
+  ClangTidyOptions EffectiveOptions = OptionsProvider->getOptions(FilePath);
+  std::vector<std::string> EnabledChecks =
+      getCheckNames(EffectiveOptions, AllowEnablingAnalyzerAlphaCheckers);
+
+  if (ExplainConfig) {
+    // FIXME: Show other ClangTidyOptions' fields, like ExtraArg.
+    std::vector<clang::tidy::ClangTidyOptionsProvider::OptionsSource>
+        RawOptions = OptionsProvider->getRawOptions(FilePath);
+    for (const std::string &Check : EnabledChecks) {
+      for (auto It = RawOptions.rbegin(); It != RawOptions.rend(); ++It) {
+        if (It->first.Checks && GlobList(*It->first.Checks).contains(Check)) {
+          llvm::outs() << "'" << Check << "' is enabled in the " << It->second
+                       << ".\n";
+          break;
+        }
+      }
+    }
+    return 0;
+  }
+
+  if (ListChecks) {
+    if (EnabledChecks.empty()) {
+      llvm::errs() << "No checks enabled.\n";
+      return 1;
+    }
+    llvm::outs() << "Enabled checks:";
+    for (const auto &CheckName : EnabledChecks)
+      llvm::outs() << "\n    " << CheckName;
+    llvm::outs() << "\n\n";
+    return 0;
+  }
+
+  if (DumpConfig) {
+    EffectiveOptions.CheckOptions =
+        getCheckOptions(EffectiveOptions, AllowEnablingAnalyzerAlphaCheckers);
+    llvm::outs() << configurationAsText(
+                        ClangTidyOptions::getDefaults().mergeWith(
+                            EffectiveOptions))
+                 << "\n";
+    return 0;
+  }
+
+  if (EnabledChecks.empty()) {
+    llvm::errs() << "Error: no checks enabled.\n";
+    llvm::cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/true);
+    return 1;
+  }
+
+  if (PathList.empty()) {
+    llvm::errs() << "Error: no input files specified.\n";
+    llvm::cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/true);
+    return 1;
+  }
+
+  llvm::InitializeAllTargetInfos();
+  llvm::InitializeAllTargetMCs();
+  llvm::InitializeAllAsmParsers();
+
+  ClangTidyContext Context(std::move(OwningOptionsProvider),
+                           AllowEnablingAnalyzerAlphaCheckers);
+  runClangTidy(Context, OptionsParser.getCompilations(), PathList, BaseFS,
+               EnableCheckProfile, ProfilePrefix);
+  ArrayRef<ClangTidyError> Errors = Context.getErrors();
+  bool FoundErrors = llvm::find_if(Errors, [](const ClangTidyError &E) {
+                       return E.DiagLevel == ClangTidyError::Error;
+                     }) != Errors.end();
+
+  const bool DisableFixes = Fix && FoundErrors && !FixErrors;
+
+  unsigned WErrorCount = 0;
+
+  // -fix-errors implies -fix.
+  handleErrors(Context, (FixErrors || Fix) && !DisableFixes, WErrorCount,
+               BaseFS);
+
+  if (!ExportFixes.empty() && !Errors.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';
+      return 1;
+    }
+    exportReplacements(FilePath.str(), Errors, OS);
+  }
+
+  if (!Quiet) {
+    printStats(Context.getStats());
+    if (DisableFixes)
+      llvm::errs()
+          << "Found compiler errors, but -fix-errors was not specified.\n"
+             "Fixes have NOT been applied.\n\n";
+  }
+
+  if (WErrorCount) {
+    if (!Quiet) {
+      StringRef Plural = WErrorCount == 1 ? "" : "s";
+      llvm::errs() << WErrorCount << " warning" << Plural << " treated as error"
+                   << Plural << "\n";
+    }
+    return WErrorCount;
+  }
+
+  if (FoundErrors) {
+    // TODO: Figure out when zero exit code should be used with -fix-errors:
+    //   a. when a fix has been applied for an error
+    //   b. when a fix has been applied for all errors
+    //   c. some other condition.
+    // For now always returning zero when -fix-errors is used.
+    if (FixErrors)
+      return 0;
+    if (!Quiet)
+      llvm::errs() << "Found compiler error(s).\n";
+    return 1;
+  }
+
+  return 0;
+}
+
+// This anchor is used to force the linker to link the CERTModule.
+extern volatile int CERTModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED CERTModuleAnchorDestination =
+    CERTModuleAnchorSource;
+
+// This anchor is used to force the linker to link the AbseilModule.
+extern volatile int AbseilModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED AbseilModuleAnchorDestination =
+    AbseilModuleAnchorSource;
+
+// This anchor is used to force the linker to link the BoostModule.
+extern volatile int BoostModuleAnchorSource;
+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 =
+    LLVMModuleAnchorSource;
+
+// This anchor is used to force the linker to link the CppCoreGuidelinesModule.
+extern volatile int CppCoreGuidelinesModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED CppCoreGuidelinesModuleAnchorDestination =
+    CppCoreGuidelinesModuleAnchorSource;
+
+// This anchor is used to force the linker to link the FuchsiaModule.
+extern volatile int FuchsiaModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED FuchsiaModuleAnchorDestination =
+    FuchsiaModuleAnchorSource;
+
+// This anchor is used to force the linker to link the GoogleModule.
+extern volatile int GoogleModuleAnchorSource;
+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 =
+    MiscModuleAnchorSource;
+
+// This anchor is used to force the linker to link the ModernizeModule.
+extern volatile int ModernizeModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination =
+    ModernizeModuleAnchorSource;
+
+// This anchor is used to force the linker to link the MPIModule.
+extern volatile int MPIModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED MPIModuleAnchorDestination =
+    MPIModuleAnchorSource;
+
+// This anchor is used to force the linker to link the PerformanceModule.
+extern volatile int PerformanceModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED PerformanceModuleAnchorDestination =
+    PerformanceModuleAnchorSource;
+
+// This anchor is used to force the linker to link the PortabilityModule.
+extern volatile int PortabilityModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED PortabilityModuleAnchorDestination =
+    PortabilityModuleAnchorSource;
+
+// This anchor is used to force the linker to link the ReadabilityModule.
+extern volatile int ReadabilityModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED ReadabilityModuleAnchorDestination =
+    ReadabilityModuleAnchorSource;
+
+// This anchor is used to force the linker to link the ObjCModule.
+extern volatile int ObjCModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED ObjCModuleAnchorDestination =
+    ObjCModuleAnchorSource;
+
+// This anchor is used to force the linker to link the HICPPModule.
+extern volatile int HICPPModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED HICPPModuleAnchorDestination =
+    HICPPModuleAnchorSource;
+
+// This anchor is used to force the linker to link the ZirconModule.
+extern volatile int ZirconModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED ZirconModuleAnchorDestination =
+    ZirconModuleAnchorSource;
+
+} // namespace tidy
+} // namespace clang
+
+int main(int argc, const char **argv) {
+  return clang::tidy::clangTidyMain(argc, argv);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
new file mode 100755
index 0000000..f2c15e5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+#
+#===- clang-tidy-diff.py - ClangTidy Diff Checker ------------*- python -*--===#
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+r"""
+ClangTidy Diff Checker
+======================
+
+This script reads input from a unified diff, runs clang-tidy on all changed
+files and outputs clang-tidy warnings in changed lines only. This is useful to
+detect clang-tidy regressions in the lines touched by a specific patch.
+Example usage for git/svn users:
+
+  git diff -U0 HEAD^ | clang-tidy-diff.py -p1
+  svn diff --diff-cmd=diff -x-U0 | \
+      clang-tidy-diff.py -fix -checks=-*,modernize-use-override
+
+"""
+
+import argparse
+import json
+import re
+import subprocess
+import sys
+
+
+def main():
+  parser = argparse.ArgumentParser(description=
+                                   'Run clang-tidy against changed files, and '
+                                   'output diagnostics only for modified '
+                                   'lines.')
+  parser.add_argument('-clang-tidy-binary', metavar='PATH',
+                      default='clang-tidy',
+                      help='path to clang-tidy binary')
+  parser.add_argument('-p', metavar='NUM', default=0,
+                      help='strip the smallest prefix containing P slashes')
+  parser.add_argument('-regex', metavar='PATTERN', default=None,
+                      help='custom pattern selecting file paths to check '
+                      '(case sensitive, overrides -iregex)')
+  parser.add_argument('-iregex', metavar='PATTERN', default=
+                      r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc)',
+                      help='custom pattern selecting file paths to check '
+                      '(case insensitive, overridden by -regex)')
+
+  parser.add_argument('-fix', action='store_true', default=False,
+                      help='apply suggested fixes')
+  parser.add_argument('-checks',
+                      help='checks filter, when not specified, use clang-tidy '
+                      'default',
+                      default='')
+  parser.add_argument('-path', dest='build_path',
+                      help='Path used to read a compile command database.')
+  parser.add_argument('-extra-arg', dest='extra_arg',
+                      action='append', default=[],
+                      help='Additional argument to append to the compiler '
+                      'command line.')
+  parser.add_argument('-extra-arg-before', dest='extra_arg_before',
+                      action='append', default=[],
+                      help='Additional argument to prepend to the compiler '
+                      'command line.')
+  parser.add_argument('-quiet', action='store_true', default=False,
+                      help='Run clang-tidy in quiet mode')
+  clang_tidy_args = []
+  argv = sys.argv[1:]
+  if '--' in argv:
+    clang_tidy_args.extend(argv[argv.index('--'):])
+    argv = argv[:argv.index('--')]
+
+  args = parser.parse_args(argv)
+
+  # Extract changed lines for each file.
+  filename = None
+  lines_by_file = {}
+  for line in sys.stdin:
+    match = re.search('^\+\+\+\ \"?(.*?/){%s}([^ \t\n\"]*)' % args.p, line)
+    if match:
+      filename = match.group(2)
+    if filename == None:
+      continue
+
+    if args.regex is not None:
+      if not re.match('^%s$' % args.regex, filename):
+        continue
+    else:
+      if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
+        continue
+
+    match = re.search('^@@.*\+(\d+)(,(\d+))?', line)
+    if match:
+      start_line = int(match.group(1))
+      line_count = 1
+      if match.group(3):
+        line_count = int(match.group(3))
+      if line_count == 0:
+        continue
+      end_line = start_line + line_count - 1;
+      lines_by_file.setdefault(filename, []).append([start_line, end_line])
+
+  if len(lines_by_file) == 0:
+    print("No relevant changes found.")
+    sys.exit(0)
+
+  line_filter_json = json.dumps(
+    [{"name" : name, "lines" : lines_by_file[name]} for name in lines_by_file],
+    separators = (',', ':'))
+
+  quote = "";
+  if sys.platform == 'win32':
+    line_filter_json=re.sub(r'"', r'"""', line_filter_json)
+  else:
+    quote = "'";
+
+  # Run clang-tidy on files containing changes.
+  command = [args.clang_tidy_binary]
+  command.append('-line-filter=' + quote + line_filter_json + quote)
+  if args.fix:
+    command.append('-fix')
+  if args.checks != '':
+    command.append('-checks=' + quote + args.checks + quote)
+  if args.quiet:
+    command.append('-quiet')
+  if args.build_path is not None:
+    command.append('-p=%s' % args.build_path)
+  command.extend(lines_by_file.keys())
+  for arg in args.extra_arg:
+      command.append('-extra-arg=%s' % arg)
+  for arg in args.extra_arg_before:
+      command.append('-extra-arg-before=%s' % arg)
+  command.extend(clang_tidy_args)
+
+  sys.exit(subprocess.call(' '.join(command), shell=True))
+
+if __name__ == '__main__':
+  main()
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
new file mode 100755
index 0000000..ce46c0e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
@@ -0,0 +1,313 @@
+#!/usr/bin/env python
+#
+#===- run-clang-tidy.py - Parallel clang-tidy runner ---------*- python -*--===#
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+# FIXME: Integrate with clang-tidy-diff.py
+
+"""
+Parallel clang-tidy runner
+==========================
+
+Runs clang-tidy over all files in a compilation database. Requires clang-tidy
+and clang-apply-replacements in $PATH.
+
+Example invocations.
+- Run clang-tidy on all files in the current working directory with a default
+  set of checks and show warnings in the cpp files and all project headers.
+    run-clang-tidy.py $PWD
+
+- Fix all header guards.
+    run-clang-tidy.py -fix -checks=-*,llvm-header-guard
+
+- Fix all header guards included from clang-tidy and header guards
+  for clang-tidy headers.
+    run-clang-tidy.py -fix -checks=-*,llvm-header-guard extra/clang-tidy \
+                      -header-filter=extra/clang-tidy
+
+Compilation database setup:
+http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
+"""
+
+from __future__ import print_function
+
+import argparse
+import glob
+import json
+import multiprocessing
+import os
+import re
+import shutil
+import subprocess
+import sys
+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."""
+  result = './'
+  while not os.path.isfile(os.path.join(result, path)):
+    if os.path.realpath(result) == '/':
+      print('Error: could not find compilation database.')
+      sys.exit(1)
+    result += '../'
+  return os.path.realpath(result)
+
+
+def make_absolute(f, directory):
+  if os.path.isabs(f):
+    return f
+  return os.path.normpath(os.path.join(directory, f))
+
+
+def get_tidy_invocation(f, clang_tidy_binary, checks, tmpdir, build_path,
+                        header_filter, extra_arg, extra_arg_before, quiet,
+                        config):
+  """Gets a command line for clang-tidy."""
+  start = [clang_tidy_binary]
+  if header_filter is not None:
+    start.append('-header-filter=' + header_filter)
+  else:
+    # Show warnings in all in-project headers by default.
+    start.append('-header-filter=^' + build_path + '/.*')
+  if checks:
+    start.append('-checks=' + checks)
+  if tmpdir is not None:
+    start.append('-export-fixes')
+    # Get a temporary file. We immediately close the handle so clang-tidy can
+    # overwrite it.
+    (handle, name) = tempfile.mkstemp(suffix='.yaml', dir=tmpdir)
+    os.close(handle)
+    start.append(name)
+  for arg in extra_arg:
+      start.append('-extra-arg=%s' % arg)
+  for arg in extra_arg_before:
+      start.append('-extra-arg-before=%s' % arg)
+  start.append('-p=' + build_path)
+  if quiet:
+      start.append('-quiet')
+  if config:
+      start.append('-config=' + config)
+  start.append(f)
+  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:
+    subprocess.check_call([args.clang_apply_replacements_binary, '--version'])
+  except:
+    print('Unable to run clang-apply-replacements. Is clang-apply-replacements '
+          'binary correctly specified?', file=sys.stderr)
+    traceback.print_exc()
+    sys.exit(1)
+
+
+def apply_fixes(args, tmpdir):
+  """Calls clang-apply-fixes on a given directory."""
+  invocation = [args.clang_apply_replacements_binary]
+  if args.format:
+    invocation.append('-format')
+  if args.style:
+    invocation.append('-style=' + args.style)
+  invocation.append(tmpdir)
+  subprocess.call(invocation)
+
+
+def run_tidy(args, tmpdir, build_path, queue, failed_files):
+  """Takes filenames out of queue and runs clang-tidy on them."""
+  while True:
+    name = queue.get()
+    invocation = get_tidy_invocation(name, args.clang_tidy_binary, args.checks,
+                                     tmpdir, build_path, args.header_filter,
+                                     args.extra_arg, args.extra_arg_before,
+                                     args.quiet, args.config)
+    sys.stdout.write(' '.join(invocation) + '\n')
+    return_code = subprocess.call(invocation)
+    if return_code != 0:
+      failed_files.append(name)
+    queue.task_done()
+
+
+def main():
+  parser = argparse.ArgumentParser(description='Runs clang-tidy over all files '
+                                   'in a compilation database. Requires '
+                                   'clang-tidy and clang-apply-replacements in '
+                                   '$PATH.')
+  parser.add_argument('-clang-tidy-binary', metavar='PATH',
+                      default='clang-tidy',
+                      help='path to clang-tidy binary')
+  parser.add_argument('-clang-apply-replacements-binary', metavar='PATH',
+                      default='clang-apply-replacements',
+                      help='path to clang-apply-replacements binary')
+  parser.add_argument('-checks', default=None,
+                      help='checks filter, when not specified, use clang-tidy '
+                      'default')
+  parser.add_argument('-config', default=None,
+                      help='Specifies a configuration in YAML/JSON format: '
+                      '  -config="{Checks: \'*\', '
+                      '                       CheckOptions: [{key: x, '
+                      '                                       value: y}]}" '
+                      'When the value is empty, clang-tidy will '
+                      'attempt to find a file named .clang-tidy for '
+                      'each source file in its parent directories.')
+  parser.add_argument('-header-filter', default=None,
+                      help='regular expression matching the names of the '
+                      '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=['.*'],
+                      help='files to be processed (regex on path)')
+  parser.add_argument('-fix', action='store_true', help='apply fix-its')
+  parser.add_argument('-format', action='store_true', help='Reformat code '
+                      'after applying fixes')
+  parser.add_argument('-style', default='file', help='The style of reformat '
+                      'code after applying fixes')
+  parser.add_argument('-p', dest='build_path',
+                      help='Path used to read a compile command database.')
+  parser.add_argument('-extra-arg', dest='extra_arg',
+                      action='append', default=[],
+                      help='Additional argument to append to the compiler '
+                      'command line.')
+  parser.add_argument('-extra-arg-before', dest='extra_arg_before',
+                      action='append', default=[],
+                      help='Additional argument to prepend to the compiler '
+                      'command line.')
+  parser.add_argument('-quiet', action='store_true',
+                      help='Run clang-tidy in quiet mode')
+  args = parser.parse_args()
+
+  db_path = 'compile_commands.json'
+
+  if args.build_path is not None:
+    build_path = args.build_path
+  else:
+    # Find our database
+    build_path = find_compilation_database(db_path)
+
+  try:
+    invocation = [args.clang_tidy_binary, '-list-checks']
+    invocation.append('-p=' + build_path)
+    if args.checks:
+      invocation.append('-checks=' + args.checks)
+    invocation.append('-')
+    subprocess.check_call(invocation)
+  except:
+    print("Unable to run clang-tidy.", file=sys.stderr)
+    sys.exit(1)
+
+  # Load the database and extract all files.
+  database = json.load(open(os.path.join(build_path, db_path)))
+  files = [make_absolute(entry['file'], entry['directory'])
+           for entry in database]
+
+  max_task = args.j
+  if max_task == 0:
+    max_task = multiprocessing.cpu_count()
+
+  tmpdir = None
+  if args.fix or args.export_fixes:
+    check_clang_apply_replacements_binary(args)
+    tmpdir = tempfile.mkdtemp()
+
+  # Build up a big regexy filter from all command line arguments.
+  file_name_re = re.compile('|'.join(args.files))
+
+  return_code = 0
+  try:
+    # Spin up a bunch of tidy-launching threads.
+    task_queue = queue.Queue(max_task)
+    # List of files with a non-zero return code.
+    failed_files = []
+    for _ in range(max_task):
+      t = threading.Thread(target=run_tidy,
+                           args=(args, tmpdir, build_path, task_queue, failed_files))
+      t.daemon = True
+      t.start()
+
+    # Fill the queue with files.
+    for name in files:
+      if file_name_re.search(name):
+        task_queue.put(name)
+
+    # Wait for all threads to be done.
+    task_queue.join()
+    if len(failed_files):
+      return_code = 1
+
+  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 tmpdir:
+      shutil.rmtree(tmpdir)
+    os.kill(0, 9)
+
+  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 ...')
+    try:
+      apply_fixes(args, tmpdir)
+    except:
+      print('Error applying fixes.\n', file=sys.stderr)
+      traceback.print_exc()
+      return_code=1
+
+  if tmpdir:
+    shutil.rmtree(tmpdir)
+  sys.exit(return_code)
+
+if __name__ == '__main__':
+  main()
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ASTUtils.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ASTUtils.cpp
new file mode 100644
index 0000000..ab6077a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ASTUtils.cpp
@@ -0,0 +1,72 @@
+//===---------- ASTUtils.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 "ASTUtils.h"
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+using namespace ast_matchers;
+
+const FunctionDecl *getSurroundingFunction(ASTContext &Context,
+                                           const Stmt &Statement) {
+  return selectFirst<const FunctionDecl>(
+      "function", match(stmt(hasAncestor(functionDecl().bind("function"))),
+                        Statement, Context));
+}
+
+bool IsBinaryOrTernary(const Expr *E) {
+  const Expr *E_base = E->IgnoreImpCasts();
+  if (clang::isa<clang::BinaryOperator>(E_base) ||
+      clang::isa<clang::ConditionalOperator>(E_base)) {
+    return true;
+  }
+
+  if (const auto *Operator =
+          clang::dyn_cast<clang::CXXOperatorCallExpr>(E_base)) {
+    return Operator->isInfixBinaryOp();
+  }
+
+  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 macro 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/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ASTUtils.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ASTUtils.h
new file mode 100644
index 0000000..ccff000
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ASTUtils.h
@@ -0,0 +1,34 @@
+//===---------- ASTUtils.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_ASTUTILS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ASTUTILS_H
+
+#include "clang/AST/AST.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+// Returns the (closest) Function declaration surrounding |Statement| or NULL.
+const FunctionDecl *getSurroundingFunction(ASTContext &Context,
+                                           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
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ASTUTILS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/CMakeLists.txt
new file mode 100644
index 0000000..487b09a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/CMakeLists.txt
@@ -0,0 +1,25 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyUtils
+  ASTUtils.cpp
+  DeclRefExprUtils.cpp
+  ExprMutationAnalyzer.cpp
+  ExprSequence.cpp
+  FixItHintUtils.cpp
+  HeaderFileExtensionsUtils.cpp
+  HeaderGuard.cpp
+  IncludeInserter.cpp
+  IncludeSorter.cpp
+  LexerUtils.cpp
+  NamespaceAliaser.cpp
+  OptionsUtils.cpp
+  TypeTraits.cpp
+  UsingInserter.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp
new file mode 100644
index 0000000..06acd31
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp
@@ -0,0 +1,172 @@
+//===--- DeclRefExprUtils.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 "DeclRefExprUtils.h"
+#include "Matchers.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+namespace decl_ref_expr {
+
+using namespace ::clang::ast_matchers;
+using llvm::SmallPtrSet;
+
+namespace {
+
+template <typename S> bool isSetDifferenceEmpty(const S &S1, const S &S2) {
+  for (const auto &E : S1)
+    if (S2.count(E) == 0)
+      return false;
+  return true;
+}
+
+// Extracts all Nodes keyed by ID from Matches and inserts them into Nodes.
+template <typename Node>
+void extractNodesByIdTo(ArrayRef<BoundNodes> Matches, StringRef ID,
+                        SmallPtrSet<const Node *, 16> &Nodes) {
+  for (const auto &Match : Matches)
+    Nodes.insert(Match.getNodeAs<Node>(ID));
+}
+
+} // namespace
+
+// Finds all DeclRefExprs where a const method is called on VarDecl or VarDecl
+// is the a const reference or value argument to a CallExpr or CXXConstructExpr.
+SmallPtrSet<const DeclRefExpr *, 16>
+constReferenceDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt,
+                           ASTContext &Context) {
+  auto DeclRefToVar =
+      declRefExpr(to(varDecl(equalsNode(&VarDecl)))).bind("declRef");
+  auto ConstMethodCallee = callee(cxxMethodDecl(isConst()));
+  // Match method call expressions where the variable is referenced as the this
+  // implicit object argument and opertor call expression for member operators
+  // where the variable is the 0-th argument.
+  auto Matches = match(
+      findAll(expr(anyOf(cxxMemberCallExpr(ConstMethodCallee, on(DeclRefToVar)),
+                         cxxOperatorCallExpr(ConstMethodCallee,
+                                             hasArgument(0, DeclRefToVar))))),
+      Stmt, Context);
+  SmallPtrSet<const DeclRefExpr *, 16> DeclRefs;
+  extractNodesByIdTo(Matches, "declRef", DeclRefs);
+  auto ConstReferenceOrValue =
+      qualType(anyOf(referenceType(pointee(qualType(isConstQualified()))),
+                     unless(anyOf(referenceType(), pointerType()))));
+  auto UsedAsConstRefOrValueArg = forEachArgumentWithParam(
+      DeclRefToVar, parmVarDecl(hasType(ConstReferenceOrValue)));
+  Matches = match(findAll(callExpr(UsedAsConstRefOrValueArg)), Stmt, Context);
+  extractNodesByIdTo(Matches, "declRef", DeclRefs);
+  Matches =
+      match(findAll(cxxConstructExpr(UsedAsConstRefOrValueArg)), Stmt, Context);
+  extractNodesByIdTo(Matches, "declRef", DeclRefs);
+  return DeclRefs;
+}
+
+// Finds all DeclRefExprs where a const method is called on VarDecl or VarDecl
+// is the a const reference or value argument to a CallExpr or CXXConstructExpr.
+SmallPtrSet<const DeclRefExpr *, 16>
+constReferenceDeclRefExprs(const VarDecl &VarDecl, const Decl &Decl,
+                           ASTContext &Context) {
+  auto DeclRefToVar =
+      declRefExpr(to(varDecl(equalsNode(&VarDecl)))).bind("declRef");
+  auto ConstMethodCallee = callee(cxxMethodDecl(isConst()));
+  // Match method call expressions where the variable is referenced as the this
+  // implicit object argument and opertor call expression for member operators
+  // where the variable is the 0-th argument.
+  auto Matches =
+      match(decl(forEachDescendant(expr(
+                anyOf(cxxMemberCallExpr(ConstMethodCallee, on(DeclRefToVar)),
+                      cxxOperatorCallExpr(ConstMethodCallee,
+                                          hasArgument(0, DeclRefToVar)))))),
+            Decl, Context);
+  SmallPtrSet<const DeclRefExpr *, 16> DeclRefs;
+  extractNodesByIdTo(Matches, "declRef", DeclRefs);
+  auto ConstReferenceOrValue =
+      qualType(anyOf(referenceType(pointee(qualType(isConstQualified()))),
+                     unless(anyOf(referenceType(), pointerType()))));
+  auto UsedAsConstRefOrValueArg = forEachArgumentWithParam(
+      DeclRefToVar, parmVarDecl(hasType(ConstReferenceOrValue)));
+  Matches = match(decl(forEachDescendant(callExpr(UsedAsConstRefOrValueArg))),
+                  Decl, Context);
+  extractNodesByIdTo(Matches, "declRef", DeclRefs);
+  Matches =
+      match(decl(forEachDescendant(cxxConstructExpr(UsedAsConstRefOrValueArg))),
+            Decl, Context);
+  extractNodesByIdTo(Matches, "declRef", DeclRefs);
+  return DeclRefs;
+}
+
+bool isOnlyUsedAsConst(const VarDecl &Var, const Stmt &Stmt,
+                       ASTContext &Context) {
+  // Collect all DeclRefExprs to the loop variable and all CallExprs and
+  // CXXConstructExprs where the loop variable is used as argument to a const
+  // reference parameter.
+  // If the difference is empty it is safe for the loop variable to be a const
+  // reference.
+  auto AllDeclRefs = allDeclRefExprs(Var, Stmt, Context);
+  auto ConstReferenceDeclRefs = constReferenceDeclRefExprs(Var, Stmt, Context);
+  return isSetDifferenceEmpty(AllDeclRefs, ConstReferenceDeclRefs);
+}
+
+SmallPtrSet<const DeclRefExpr *, 16>
+allDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt, ASTContext &Context) {
+  auto Matches = match(
+      findAll(declRefExpr(to(varDecl(equalsNode(&VarDecl)))).bind("declRef")),
+      Stmt, Context);
+  SmallPtrSet<const DeclRefExpr *, 16> DeclRefs;
+  extractNodesByIdTo(Matches, "declRef", DeclRefs);
+  return DeclRefs;
+}
+
+SmallPtrSet<const DeclRefExpr *, 16>
+allDeclRefExprs(const VarDecl &VarDecl, const Decl &Decl, ASTContext &Context) {
+  auto Matches = match(
+      decl(forEachDescendant(
+          declRefExpr(to(varDecl(equalsNode(&VarDecl)))).bind("declRef"))),
+      Decl, Context);
+  SmallPtrSet<const DeclRefExpr *, 16> DeclRefs;
+  extractNodesByIdTo(Matches, "declRef", DeclRefs);
+  return DeclRefs;
+}
+
+bool isCopyConstructorArgument(const DeclRefExpr &DeclRef, const Decl &Decl,
+                               ASTContext &Context) {
+  auto UsedAsConstRefArg = forEachArgumentWithParam(
+      declRefExpr(equalsNode(&DeclRef)),
+      parmVarDecl(hasType(matchers::isReferenceToConst())));
+  auto Matches = match(
+      decl(hasDescendant(
+          cxxConstructExpr(UsedAsConstRefArg, hasDeclaration(cxxConstructorDecl(
+                                                  isCopyConstructor())))
+              .bind("constructExpr"))),
+      Decl, Context);
+  return !Matches.empty();
+}
+
+bool isCopyAssignmentArgument(const DeclRefExpr &DeclRef, const Decl &Decl,
+                              ASTContext &Context) {
+  auto UsedAsConstRefArg = forEachArgumentWithParam(
+      declRefExpr(equalsNode(&DeclRef)),
+      parmVarDecl(hasType(matchers::isReferenceToConst())));
+  auto Matches = match(
+      decl(hasDescendant(
+          cxxOperatorCallExpr(UsedAsConstRefArg, hasOverloadedOperatorName("="),
+                              callee(cxxMethodDecl(isCopyAssignmentOperator())))
+              .bind("operatorCallExpr"))),
+      Decl, Context);
+  return !Matches.empty();
+}
+
+} // namespace decl_ref_expr
+} // namespace utils
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.h
new file mode 100644
index 0000000..c25102f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.h
@@ -0,0 +1,66 @@
+//===--- DeclRefExprUtils.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_UTILS_DECLREFEXPRUTILS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_DECLREFEXPRUTILS_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+namespace decl_ref_expr {
+
+/// \brief Returns true if all ``DeclRefExpr`` to the variable within ``Stmt``
+/// do not modify it.
+///
+/// Returns ``true`` if only const methods or operators are called on the
+/// variable or the variable is a const reference or value argument to a
+/// ``callExpr()``.
+bool isOnlyUsedAsConst(const VarDecl &Var, const Stmt &Stmt,
+                       ASTContext &Context);
+
+/// Returns set of all ``DeclRefExprs`` to ``VarDecl`` within ``Stmt``.
+llvm::SmallPtrSet<const DeclRefExpr *, 16>
+allDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt, ASTContext &Context);
+
+/// Returns set of all ``DeclRefExprs`` to ``VarDecl`` within ``Decl``.
+llvm::SmallPtrSet<const DeclRefExpr *, 16>
+allDeclRefExprs(const VarDecl &VarDecl, const Decl &Decl, ASTContext &Context);
+
+/// Returns set of all ``DeclRefExprs`` to ``VarDecl`` within ``Stmt`` where
+/// ``VarDecl`` is guaranteed to be accessed in a const fashion.
+llvm::SmallPtrSet<const DeclRefExpr *, 16>
+constReferenceDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt,
+                           ASTContext &Context);
+
+/// Returns set of all ``DeclRefExprs`` to ``VarDecl`` within ``Decl`` where
+/// ``VarDecl`` is guaranteed to be accessed in a const fashion.
+llvm::SmallPtrSet<const DeclRefExpr *, 16>
+constReferenceDeclRefExprs(const VarDecl &VarDecl, const Decl &Decl,
+                           ASTContext &Context);
+
+/// Returns ``true`` if ``DeclRefExpr`` is the argument of a copy-constructor
+/// call expression within ``Decl``.
+bool isCopyConstructorArgument(const DeclRefExpr &DeclRef, const Decl &Decl,
+                               ASTContext &Context);
+
+/// Returns ``true`` if ``DeclRefExpr`` is the argument of a copy-assignment
+/// operator CallExpr within ``Decl``.
+bool isCopyAssignmentArgument(const DeclRefExpr &DeclRef, const Decl &Decl,
+                              ASTContext &Context);
+
+} // namespace decl_ref_expr
+} // namespace utils
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_DECLREFEXPRUTILS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ExprMutationAnalyzer.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ExprMutationAnalyzer.cpp
new file mode 100644
index 0000000..424fa8f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ExprMutationAnalyzer.cpp
@@ -0,0 +1,260 @@
+//===---------- ExprMutationAnalyzer.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 "ExprMutationAnalyzer.h"
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/STLExtras.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+using namespace ast_matchers;
+
+namespace {
+
+AST_MATCHER_P(LambdaExpr, hasCaptureInit, const Expr *, E) {
+  return llvm::is_contained(Node.capture_inits(), E);
+}
+
+AST_MATCHER_P(CXXForRangeStmt, hasRangeStmt,
+              ast_matchers::internal::Matcher<DeclStmt>, InnerMatcher) {
+  const DeclStmt *const Range = Node.getRangeStmt();
+  return InnerMatcher.matches(*Range, Finder, Builder);
+}
+
+const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr>
+    cxxTypeidExpr;
+
+AST_MATCHER(CXXTypeidExpr, isPotentiallyEvaluated) {
+  return Node.isPotentiallyEvaluated();
+}
+
+const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt, CXXNoexceptExpr>
+    cxxNoexceptExpr;
+
+const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt,
+                                                          GenericSelectionExpr>
+    genericSelectionExpr;
+
+AST_MATCHER_P(GenericSelectionExpr, hasControllingExpr,
+              ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
+  return InnerMatcher.matches(*Node.getControllingExpr(), Finder, Builder);
+}
+
+const auto nonConstReferenceType = [] {
+  return referenceType(pointee(unless(isConstQualified())));
+};
+
+} // namespace
+
+const Stmt *ExprMutationAnalyzer::findMutation(const Expr *Exp) {
+  const auto Memoized = Results.find(Exp);
+  if (Memoized != Results.end())
+    return Memoized->second;
+
+  if (isUnevaluated(Exp))
+    return Results[Exp] = nullptr;
+
+  for (const auto &Finder : {&ExprMutationAnalyzer::findDirectMutation,
+                             &ExprMutationAnalyzer::findMemberMutation,
+                             &ExprMutationAnalyzer::findArrayElementMutation,
+                             &ExprMutationAnalyzer::findCastMutation,
+                             &ExprMutationAnalyzer::findRangeLoopMutation,
+                             &ExprMutationAnalyzer::findReferenceMutation}) {
+    if (const Stmt *S = (this->*Finder)(Exp))
+      return Results[Exp] = S;
+  }
+
+  return Results[Exp] = nullptr;
+}
+
+bool ExprMutationAnalyzer::isUnevaluated(const Expr *Exp) {
+  return selectFirst<Expr>(
+             "expr",
+             match(
+                 findAll(
+                     expr(equalsNode(Exp),
+                          anyOf(
+                              // `Exp` is part of the underlying expression of
+                              // decltype/typeof if it has an ancestor of
+                              // typeLoc.
+                              hasAncestor(typeLoc(unless(
+                                  hasAncestor(unaryExprOrTypeTraitExpr())))),
+                              hasAncestor(expr(anyOf(
+                                  // `UnaryExprOrTypeTraitExpr` is unevaluated
+                                  // unless it's sizeof on VLA.
+                                  unaryExprOrTypeTraitExpr(unless(sizeOfExpr(
+                                      hasArgumentOfType(variableArrayType())))),
+                                  // `CXXTypeidExpr` is unevaluated unless it's
+                                  // applied to an expression of glvalue of
+                                  // polymorphic class type.
+                                  cxxTypeidExpr(
+                                      unless(isPotentiallyEvaluated())),
+                                  // The controlling expression of
+                                  // `GenericSelectionExpr` is unevaluated.
+                                  genericSelectionExpr(hasControllingExpr(
+                                      hasDescendant(equalsNode(Exp)))),
+                                  cxxNoexceptExpr())))))
+                         .bind("expr")),
+                 *Stm, *Context)) != nullptr;
+}
+
+const Stmt *
+ExprMutationAnalyzer::findExprMutation(ArrayRef<BoundNodes> Matches) {
+  for (const auto &Nodes : Matches) {
+    if (const Stmt *S = findMutation(Nodes.getNodeAs<Expr>("expr")))
+      return S;
+  }
+  return nullptr;
+}
+
+const Stmt *
+ExprMutationAnalyzer::findDeclMutation(ArrayRef<BoundNodes> Matches) {
+  for (const auto &DeclNodes : Matches) {
+    if (const Stmt *S = findDeclMutation(DeclNodes.getNodeAs<Decl>("decl")))
+      return S;
+  }
+  return nullptr;
+}
+
+const Stmt *ExprMutationAnalyzer::findDeclMutation(const Decl *Dec) {
+  const auto Refs = match(
+      findAll(declRefExpr(to(equalsNode(Dec))).bind("expr")), *Stm, *Context);
+  for (const auto &RefNodes : Refs) {
+    const auto *E = RefNodes.getNodeAs<Expr>("expr");
+    if (findMutation(E))
+      return E;
+  }
+  return nullptr;
+}
+
+const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) {
+  // LHS of any assignment operators.
+  const auto AsAssignmentLhs =
+      binaryOperator(isAssignmentOperator(), hasLHS(equalsNode(Exp)));
+
+  // Operand of increment/decrement operators.
+  const auto AsIncDecOperand =
+      unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--")),
+                    hasUnaryOperand(equalsNode(Exp)));
+
+  // Invoking non-const member function.
+  const auto NonConstMethod = cxxMethodDecl(unless(isConst()));
+  const auto AsNonConstThis =
+      expr(anyOf(cxxMemberCallExpr(callee(NonConstMethod), on(equalsNode(Exp))),
+                 cxxOperatorCallExpr(callee(NonConstMethod),
+                                     hasArgument(0, equalsNode(Exp)))));
+
+  // Taking address of 'Exp'.
+  // We're assuming 'Exp' is mutated as soon as its address is taken, though in
+  // theory we can follow the pointer and see whether it escaped `Stm` or is
+  // dereferenced and then mutated. This is left for future improvements.
+  const auto AsAmpersandOperand =
+      unaryOperator(hasOperatorName("&"),
+                    // A NoOp implicit cast is adding const.
+                    unless(hasParent(implicitCastExpr(hasCastKind(CK_NoOp)))),
+                    hasUnaryOperand(equalsNode(Exp)));
+  const auto AsPointerFromArrayDecay =
+      castExpr(hasCastKind(CK_ArrayToPointerDecay),
+               unless(hasParent(arraySubscriptExpr())), has(equalsNode(Exp)));
+
+  // Used as non-const-ref argument when calling a function.
+  const auto NonConstRefParam = forEachArgumentWithParam(
+      equalsNode(Exp), parmVarDecl(hasType(nonConstReferenceType())));
+  const auto AsNonConstRefArg =
+      anyOf(callExpr(NonConstRefParam), cxxConstructExpr(NonConstRefParam));
+
+  // Captured by a lambda by reference.
+  // If we're initializing a capture with 'Exp' directly then we're initializing
+  // a reference capture.
+  // For value captures there will be an ImplicitCastExpr <LValueToRValue>.
+  const auto AsLambdaRefCaptureInit = lambdaExpr(hasCaptureInit(Exp));
+
+  // Returned as non-const-ref.
+  // If we're returning 'Exp' directly then it's returned as non-const-ref.
+  // For returning by value there will be an ImplicitCastExpr <LValueToRValue>.
+  // For returning by const-ref there will be an ImplicitCastExpr <NoOp> (for
+  // adding const.)
+  const auto AsNonConstRefReturn = returnStmt(hasReturnValue(equalsNode(Exp)));
+
+  const auto Matches =
+      match(findAll(stmt(anyOf(AsAssignmentLhs, AsIncDecOperand, AsNonConstThis,
+                               AsAmpersandOperand, AsPointerFromArrayDecay,
+                               AsNonConstRefArg, AsLambdaRefCaptureInit,
+                               AsNonConstRefReturn))
+                        .bind("stmt")),
+            *Stm, *Context);
+  return selectFirst<Stmt>("stmt", Matches);
+}
+
+const Stmt *ExprMutationAnalyzer::findMemberMutation(const Expr *Exp) {
+  // Check whether any member of 'Exp' is mutated.
+  const auto MemberExprs = match(
+      findAll(memberExpr(hasObjectExpression(equalsNode(Exp))).bind("expr")),
+      *Stm, *Context);
+  return findExprMutation(MemberExprs);
+}
+
+const Stmt *ExprMutationAnalyzer::findArrayElementMutation(const Expr *Exp) {
+  // Check whether any element of an array is mutated.
+  const auto SubscriptExprs = match(
+      findAll(arraySubscriptExpr(hasBase(ignoringImpCasts(equalsNode(Exp))))
+                  .bind("expr")),
+      *Stm, *Context);
+  return findExprMutation(SubscriptExprs);
+}
+
+const Stmt *ExprMutationAnalyzer::findCastMutation(const Expr *Exp) {
+  // If 'Exp' is casted to any non-const reference type, check the castExpr.
+  const auto Casts =
+      match(findAll(castExpr(hasSourceExpression(equalsNode(Exp)),
+                             anyOf(explicitCastExpr(hasDestinationType(
+                                       nonConstReferenceType())),
+                                   implicitCastExpr(hasImplicitDestinationType(
+                                       nonConstReferenceType()))))
+                        .bind("expr")),
+            *Stm, *Context);
+  return findExprMutation(Casts);
+}
+
+const Stmt *ExprMutationAnalyzer::findRangeLoopMutation(const Expr *Exp) {
+  // If range for looping over 'Exp' with a non-const reference loop variable,
+  // check all declRefExpr of the loop variable.
+  const auto LoopVars =
+      match(findAll(cxxForRangeStmt(
+                hasLoopVariable(
+                    varDecl(hasType(nonConstReferenceType())).bind("decl")),
+                hasRangeInit(equalsNode(Exp)))),
+            *Stm, *Context);
+  return findDeclMutation(LoopVars);
+}
+
+const Stmt *ExprMutationAnalyzer::findReferenceMutation(const Expr *Exp) {
+  // If 'Exp' is bound to a non-const reference, check all declRefExpr to that.
+  const auto Refs = match(
+      stmt(forEachDescendant(
+          varDecl(
+              hasType(nonConstReferenceType()),
+              hasInitializer(anyOf(equalsNode(Exp),
+                                   conditionalOperator(anyOf(
+                                       hasTrueExpression(equalsNode(Exp)),
+                                       hasFalseExpression(equalsNode(Exp)))))),
+              hasParent(declStmt().bind("stmt")),
+              // Don't follow the reference in range statement, we've handled
+              // that separately.
+              unless(hasParent(declStmt(hasParent(
+                  cxxForRangeStmt(hasRangeStmt(equalsBoundNode("stmt"))))))))
+              .bind("decl"))),
+      *Stm, *Context);
+  return findDeclMutation(Refs);
+}
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ExprMutationAnalyzer.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ExprMutationAnalyzer.h
new file mode 100644
index 0000000..256bb71
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ExprMutationAnalyzer.h
@@ -0,0 +1,56 @@
+//===---------- ExprMutationAnalyzer.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_EXPRMUTATIONANALYZER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_EXPRMUTATIONANALYZER_H
+
+#include <type_traits>
+
+#include "clang/AST/AST.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+/// Analyzes whether any mutative operations are applied to an expression within
+/// a given statement.
+class ExprMutationAnalyzer {
+public:
+  ExprMutationAnalyzer(const Stmt *Stm, ASTContext *Context)
+      : Stm(Stm), Context(Context) {}
+
+  bool isMutated(const Decl *Dec) { return findDeclMutation(Dec) != nullptr; }
+  bool isMutated(const Expr *Exp) { return findMutation(Exp) != nullptr; }
+  const Stmt *findMutation(const Expr *Exp);
+
+private:
+  bool isUnevaluated(const Expr *Exp);
+
+  const Stmt *findExprMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
+  const Stmt *findDeclMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
+  const Stmt *findDeclMutation(const Decl *Dec);
+
+  const Stmt *findDirectMutation(const Expr *Exp);
+  const Stmt *findMemberMutation(const Expr *Exp);
+  const Stmt *findArrayElementMutation(const Expr *Exp);
+  const Stmt *findCastMutation(const Expr *Exp);
+  const Stmt *findRangeLoopMutation(const Expr *Exp);
+  const Stmt *findReferenceMutation(const Expr *Exp);
+
+  const Stmt *const Stm;
+  ASTContext *const Context;
+  llvm::DenseMap<const Expr *, const Stmt *> Results;
+};
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_EXPRMUTATIONANALYZER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp
new file mode 100644
index 0000000..02d4a0b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp
@@ -0,0 +1,182 @@
+//===---------- ExprSequence.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 "ExprSequence.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+// Returns the Stmt nodes that are parents of 'S', skipping any potential
+// intermediate non-Stmt nodes.
+//
+// In almost all cases, this function returns a single parent or no parents at
+// all.
+//
+// The case that a Stmt has multiple parents is rare but does actually occur in
+// the parts of the AST that we're interested in. Specifically, InitListExpr
+// nodes cause ASTContext::getParent() to return multiple parents for certain
+// nodes in their subtree because RecursiveASTVisitor visits both the syntactic
+// and semantic forms of InitListExpr, and the parent-child relationships are
+// different between the two forms.
+static SmallVector<const Stmt *, 1> getParentStmts(const Stmt *S,
+                                                   ASTContext *Context) {
+  SmallVector<const Stmt *, 1> Result;
+
+  ASTContext::DynTypedNodeList Parents = Context->getParents(*S);
+
+  SmallVector<ast_type_traits::DynTypedNode, 1> NodesToProcess(Parents.begin(),
+                                                               Parents.end());
+
+  while (!NodesToProcess.empty()) {
+    ast_type_traits::DynTypedNode Node = NodesToProcess.back();
+    NodesToProcess.pop_back();
+
+    if (const auto *S = Node.get<Stmt>()) {
+      Result.push_back(S);
+    } else {
+      Parents = Context->getParents(Node);
+      NodesToProcess.append(Parents.begin(), Parents.end());
+    }
+  }
+
+  return Result;
+}
+
+namespace {
+bool isDescendantOrEqual(const Stmt *Descendant, const Stmt *Ancestor,
+                         ASTContext *Context) {
+  if (Descendant == Ancestor)
+    return true;
+  for (const Stmt *Parent : getParentStmts(Descendant, Context)) {
+    if (isDescendantOrEqual(Parent, Ancestor, Context))
+      return true;
+  }
+
+  return false;
+}
+}
+
+ExprSequence::ExprSequence(const CFG *TheCFG, ASTContext *TheContext)
+    : Context(TheContext) {
+  for (const auto &SyntheticStmt : TheCFG->synthetic_stmts()) {
+    SyntheticStmtSourceMap[SyntheticStmt.first] = SyntheticStmt.second;
+  }
+}
+
+bool ExprSequence::inSequence(const Stmt *Before, const Stmt *After) const {
+  Before = resolveSyntheticStmt(Before);
+  After = resolveSyntheticStmt(After);
+
+  // If 'After' is in the subtree of the siblings that follow 'Before' in the
+  // chain of successors, we know that 'After' is sequenced after 'Before'.
+  for (const Stmt *Successor = getSequenceSuccessor(Before); Successor;
+       Successor = getSequenceSuccessor(Successor)) {
+    if (isDescendantOrEqual(After, Successor, Context))
+      return true;
+  }
+
+  // If 'After' is a parent of 'Before' or is sequenced after one of these
+  // parents, we know that it is sequenced after 'Before'.
+  for (const Stmt *Parent : getParentStmts(Before, Context)) {
+    if (Parent == After || inSequence(Parent, After))
+      return true;
+  }
+
+  return false;
+}
+
+bool ExprSequence::potentiallyAfter(const Stmt *After,
+                                    const Stmt *Before) const {
+  return !inSequence(After, Before);
+}
+
+const Stmt *ExprSequence::getSequenceSuccessor(const Stmt *S) const {
+  for (const Stmt *Parent : getParentStmts(S, Context)) {
+    if (const auto *BO = dyn_cast<BinaryOperator>(Parent)) {
+      // Comma operator: Right-hand side is sequenced after the left-hand side.
+      if (BO->getLHS() == S && BO->getOpcode() == BO_Comma)
+        return BO->getRHS();
+    } else if (const auto *InitList = dyn_cast<InitListExpr>(Parent)) {
+      // Initializer list: Each initializer clause is sequenced after the
+      // clauses that precede it.
+      for (unsigned I = 1; I < InitList->getNumInits(); ++I) {
+        if (InitList->getInit(I - 1) == S)
+          return InitList->getInit(I);
+      }
+    } else if (const auto *Compound = dyn_cast<CompoundStmt>(Parent)) {
+      // Compound statement: Each sub-statement is sequenced after the
+      // statements that precede it.
+      const Stmt *Previous = nullptr;
+      for (const auto *Child : Compound->body()) {
+        if (Previous == S)
+          return Child;
+        Previous = Child;
+      }
+    } else if (const auto *TheDeclStmt = dyn_cast<DeclStmt>(Parent)) {
+      // Declaration: Every initializer expression is sequenced after the
+      // initializer expressions that precede it.
+      const Expr *PreviousInit = nullptr;
+      for (const Decl *TheDecl : TheDeclStmt->decls()) {
+        if (const auto *TheVarDecl = dyn_cast<VarDecl>(TheDecl)) {
+          if (const Expr *Init = TheVarDecl->getInit()) {
+            if (PreviousInit == S)
+              return Init;
+            PreviousInit = Init;
+          }
+        }
+      }
+    } else if (const auto *ForRange = dyn_cast<CXXForRangeStmt>(Parent)) {
+      // Range-based for: Loop variable declaration is sequenced before the
+      // body. (We need this rule because these get placed in the same
+      // CFGBlock.)
+      if (S == ForRange->getLoopVarStmt())
+        return ForRange->getBody();
+    } else if (const auto *TheIfStmt = dyn_cast<IfStmt>(Parent)) {
+      // If statement: If a variable is declared inside the condition, the
+      // expression used to initialize the variable is sequenced before the
+      // evaluation of the condition.
+      if (S == TheIfStmt->getConditionVariableDeclStmt())
+        return TheIfStmt->getCond();
+    }
+  }
+
+  return nullptr;
+}
+
+const Stmt *ExprSequence::resolveSyntheticStmt(const Stmt *S) const {
+  if (SyntheticStmtSourceMap.count(S))
+    return SyntheticStmtSourceMap.lookup(S);
+  return S;
+}
+
+StmtToBlockMap::StmtToBlockMap(const CFG *TheCFG, ASTContext *TheContext)
+    : Context(TheContext) {
+  for (const auto *B : *TheCFG) {
+    for (const auto &Elem : *B) {
+      if (Optional<CFGStmt> S = Elem.getAs<CFGStmt>())
+        Map[S->getStmt()] = B;
+    }
+  }
+}
+
+const CFGBlock *StmtToBlockMap::blockContainingStmt(const Stmt *S) const {
+  while (!Map.count(S)) {
+    SmallVector<const Stmt *, 1> Parents = getParentStmts(S, Context);
+    if (Parents.empty())
+      return nullptr;
+    S = Parents[0];
+  }
+
+  return Map.lookup(S);
+}
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ExprSequence.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ExprSequence.h
new file mode 100644
index 0000000..2b355d9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/ExprSequence.h
@@ -0,0 +1,124 @@
+//===------------- ExprSequence.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_EXPRSEQUENCE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_EXPRSEQUENCE_H
+
+#include "clang/Analysis/CFG.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+/// Provides information about the evaluation order of (sub-)expressions within
+/// a `CFGBlock`.
+///
+/// While a `CFGBlock` does contain individual `CFGElement`s for some
+/// sub-expressions, the order in which those `CFGElement`s appear reflects
+/// only one possible order in which the sub-expressions may be evaluated.
+/// However, we want to warn if any of the potential evaluation orders can lead
+/// to a use-after-move, not just the one contained in the `CFGBlock`.
+///
+/// This class implements only a simplified version of the C++ sequencing
+/// rules. The main limitation is that we do not distinguish between value
+/// computation and side effect -- see the "Implementation" section for more
+/// details.
+///
+/// Note: `SequenceChecker` from SemaChecking.cpp does a similar job (and much
+/// more thoroughly), but using it would require
+/// - Pulling `SequenceChecker` out into a header file (i.e. making it part of
+///   the API),
+/// - Removing the dependency of `SequenceChecker` on `Sema`, and
+/// - (Probably) modifying `SequenceChecker` to make it suitable to be used in
+///   this context.
+/// For the moment, it seems preferable to re-implement our own version of
+/// sequence checking that is special-cased to what we need here.
+///
+/// Implementation
+/// --------------
+///
+/// `ExprSequence` uses two types of sequencing edges between nodes in the AST:
+///
+/// - Every `Stmt` is assumed to be sequenced after its children. This is
+///   overly optimistic because the standard only states that value computations
+///   of operands are sequenced before the value computation of the operator,
+///   making no guarantees about side effects (in general).
+///
+///   For our purposes, this rule is sufficient, however, because this check is
+///   interested in operations on objects, which are generally performed through
+///   function calls (whether explicit and implicit). Function calls guarantee
+///   that the value computations and side effects for all function arguments
+///   are sequenced before the execution of the function.
+///
+/// - In addition, some `Stmt`s are known to be sequenced before or after
+///   their siblings. For example, the `Stmt`s that make up a `CompoundStmt`are
+///   all sequenced relative to each other. The function
+///   `getSequenceSuccessor()` implements these sequencing rules.
+class ExprSequence {
+public:
+  /// Initializes this `ExprSequence` with sequence information for the given
+  /// `CFG`.
+  ExprSequence(const CFG *TheCFG, ASTContext *TheContext);
+
+  /// Returns whether \p Before is sequenced before \p After.
+  bool inSequence(const Stmt *Before, const Stmt *After) const;
+
+  /// Returns whether \p After can potentially be evaluated after \p Before.
+  /// This is exactly equivalent to `!inSequence(After, Before)` but makes some
+  /// conditions read more naturally.
+  bool potentiallyAfter(const Stmt *After, const Stmt *Before) const;
+
+private:
+  // Returns the sibling of \p S (if any) that is directly sequenced after \p S,
+  // or nullptr if no such sibling exists. For example, if \p S is the child of
+  // a `CompoundStmt`, this would return the Stmt that directly follows \p S in
+  // the `CompoundStmt`.
+  //
+  // As the sequencing of many constructs that change control flow is already
+  // encoded in the `CFG`, this function only implements the sequencing rules
+  // for those constructs where sequencing cannot be inferred from the `CFG`.
+  const Stmt *getSequenceSuccessor(const Stmt *S) const;
+
+  const Stmt *resolveSyntheticStmt(const Stmt *S) const;
+
+  ASTContext *Context;
+
+  llvm::DenseMap<const Stmt *, const Stmt *> SyntheticStmtSourceMap;
+};
+
+/// Maps `Stmt`s to the `CFGBlock` that contains them. Some `Stmt`s may be
+/// contained in more than one `CFGBlock`; in this case, they are mapped to the
+/// innermost block (i.e. the one that is furthest from the root of the tree).
+class StmtToBlockMap {
+public:
+  /// Initializes the map for the given `CFG`.
+  StmtToBlockMap(const CFG *TheCFG, ASTContext *TheContext);
+
+  /// Returns the block that \p S is contained in. Some `Stmt`s may be contained
+  /// in more than one `CFGBlock`; in this case, this function returns the
+  /// innermost block (i.e. the one that is furthest from the root of the tree).
+  const CFGBlock *blockContainingStmt(const Stmt *S) const;
+
+private:
+  ASTContext *Context;
+
+  llvm::DenseMap<const Stmt *, const CFGBlock *> Map;
+};
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_EXPRSEQUENCE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
new file mode 100644
index 0000000..0627e51
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
@@ -0,0 +1,36 @@
+//===--- FixItHintUtils.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 "FixItHintUtils.h"
+#include "LexerUtils.h"
+#include "clang/AST/ASTContext.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+namespace fixit {
+
+FixItHint changeVarDeclToReference(const VarDecl &Var, ASTContext &Context) {
+  SourceLocation AmpLocation = Var.getLocation();
+  auto Token = utils::lexer::getPreviousToken(Context, AmpLocation);
+  if (!Token.is(tok::unknown))
+    AmpLocation = Lexer::getLocForEndOfToken(Token.getLocation(), 0,
+                                             Context.getSourceManager(),
+                                             Context.getLangOpts());
+  return FixItHint::CreateInsertion(AmpLocation, "&");
+}
+
+FixItHint changeVarDeclToConst(const VarDecl &Var) {
+  return FixItHint::CreateInsertion(Var.getTypeSpecStartLoc(), "const ");
+}
+
+} // namespace fixit
+} // namespace utils
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/FixItHintUtils.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
new file mode 100644
index 0000000..e64a6e4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/FixItHintUtils.h
@@ -0,0 +1,32 @@
+//===--- FixItHintUtils.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_UTILS_FIXITHINTUTILS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_FIXITHINTUTILS_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+namespace fixit {
+
+/// \brief Creates fix to make ``VarDecl`` a reference by adding ``&``.
+FixItHint changeVarDeclToReference(const VarDecl &Var, ASTContext &Context);
+
+/// \brief Creates fix to make ``VarDecl`` const qualified.
+FixItHint changeVarDeclToConst(const VarDecl &Var);
+
+} // namespace fixit
+} // namespace utils
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_FIXITHINTUTILS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/HeaderFileExtensionsUtils.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/HeaderFileExtensionsUtils.cpp
new file mode 100644
index 0000000..b734b89
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/HeaderFileExtensionsUtils.cpp
@@ -0,0 +1,71 @@
+//===--- HeaderFileExtensionsUtils.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 "HeaderFileExtensionsUtils.h"
+#include "clang/Basic/CharInfo.h"
+#include "llvm/Support/Path.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+bool isExpansionLocInHeaderFile(
+    SourceLocation Loc, const SourceManager &SM,
+    const HeaderFileExtensionsSet &HeaderFileExtensions) {
+  SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc);
+  return isHeaderFileExtension(SM.getFilename(ExpansionLoc),
+                               HeaderFileExtensions);
+}
+
+bool isPresumedLocInHeaderFile(
+    SourceLocation Loc, SourceManager &SM,
+    const HeaderFileExtensionsSet &HeaderFileExtensions) {
+  PresumedLoc PresumedLocation = SM.getPresumedLoc(Loc);
+  return isHeaderFileExtension(PresumedLocation.getFilename(),
+                               HeaderFileExtensions);
+}
+
+bool isSpellingLocInHeaderFile(
+    SourceLocation Loc, SourceManager &SM,
+    const HeaderFileExtensionsSet &HeaderFileExtensions) {
+  SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
+  return isHeaderFileExtension(SM.getFilename(SpellingLoc),
+                               HeaderFileExtensions);
+}
+
+bool parseHeaderFileExtensions(StringRef AllHeaderFileExtensions,
+                               HeaderFileExtensionsSet &HeaderFileExtensions,
+                               char delimiter) {
+  SmallVector<StringRef, 5> Suffixes;
+  AllHeaderFileExtensions.split(Suffixes, delimiter);
+  HeaderFileExtensions.clear();
+  for (StringRef Suffix : Suffixes) {
+    StringRef Extension = Suffix.trim();
+    for (StringRef::const_iterator it = Extension.begin();
+         it != Extension.end(); ++it) {
+      if (!isAlphanumeric(*it))
+        return false;
+    }
+    HeaderFileExtensions.insert(Extension);
+  }
+  return true;
+}
+
+bool isHeaderFileExtension(
+    StringRef FileName, const HeaderFileExtensionsSet &HeaderFileExtensions) {
+  StringRef extension = llvm::sys::path::extension(FileName);
+  if (extension.empty())
+    return false;
+  // Skip "." prefix.
+  return HeaderFileExtensions.count(extension.substr(1)) > 0;
+}
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/HeaderFileExtensionsUtils.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/HeaderFileExtensionsUtils.h
new file mode 100644
index 0000000..2012017
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/HeaderFileExtensionsUtils.h
@@ -0,0 +1,56 @@
+//===--- HeaderFileExtensionsUtils.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_UTILS_HEADER_FILE_EXTENSIONS_UTILS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_HEADER_FILE_EXTENSIONS_UTILS_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+typedef llvm::SmallSet<llvm::StringRef, 5> HeaderFileExtensionsSet;
+
+/// \brief Checks whether expansion location of \p Loc is in header file.
+bool isExpansionLocInHeaderFile(
+    SourceLocation Loc, const SourceManager &SM,
+    const HeaderFileExtensionsSet &HeaderFileExtensions);
+
+/// \brief Checks whether presumed location of \p Loc is in header file.
+bool isPresumedLocInHeaderFile(
+    SourceLocation Loc, SourceManager &SM,
+    const HeaderFileExtensionsSet &HeaderFileExtensions);
+
+/// \brief Checks whether spelling location of \p Loc is in header file.
+bool isSpellingLocInHeaderFile(
+    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,
+                               char delimiter);
+
+/// \brief Decides whether a file has a header file extension.
+bool isHeaderFileExtension(StringRef FileName,
+                           const HeaderFileExtensionsSet &HeaderFileExtensions);
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_HEADER_FILE_EXTENSIONS_UTILS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/HeaderGuard.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/HeaderGuard.cpp
new file mode 100644
index 0000000..515f882
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/HeaderGuard.cpp
@@ -0,0 +1,292 @@
+//===--- HeaderGuard.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 "HeaderGuard.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/Path.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+/// \brief canonicalize a path by removing ./ and ../ components.
+static std::string cleanPath(StringRef Path) {
+  SmallString<256> Result = Path;
+  llvm::sys::path::remove_dots(Result, true);
+  return Result.str();
+}
+
+namespace {
+class HeaderGuardPPCallbacks : public PPCallbacks {
+public:
+  HeaderGuardPPCallbacks(Preprocessor *PP, HeaderGuardCheck *Check)
+      : PP(PP), Check(Check) {}
+
+  void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+                   SrcMgr::CharacteristicKind FileType,
+                   FileID PrevFID) override {
+    // Record all files we enter. We'll need them to diagnose headers without
+    // guards.
+    SourceManager &SM = PP->getSourceManager();
+    if (Reason == EnterFile && FileType == SrcMgr::C_User) {
+      if (const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(Loc))) {
+        std::string FileName = cleanPath(FE->getName());
+        Files[FileName] = FE;
+      }
+    }
+  }
+
+  void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+              const MacroDefinition &MD) override {
+    if (MD)
+      return;
+
+    // Record #ifndefs that succeeded. We also need the Location of the Name.
+    Ifndefs[MacroNameTok.getIdentifierInfo()] =
+        std::make_pair(Loc, MacroNameTok.getLocation());
+  }
+
+  void MacroDefined(const Token &MacroNameTok,
+                    const MacroDirective *MD) override {
+    // Record all defined macros. We store the whole token to get info on the
+    // name later.
+    Macros.emplace_back(MacroNameTok, MD->getMacroInfo());
+  }
+
+  void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
+    // Record all #endif and the corresponding #ifs (including #ifndefs).
+    EndIfs[IfLoc] = Loc;
+  }
+
+  void EndOfMainFile() override {
+    // Now that we have all this information from the preprocessor, use it!
+    SourceManager &SM = PP->getSourceManager();
+
+    for (const auto &MacroEntry : Macros) {
+      const MacroInfo *MI = MacroEntry.second;
+
+      // We use clang's header guard detection. This has the advantage of also
+      // emitting a warning for cases where a pseudo header guard is found but
+      // preceded by something blocking the header guard optimization.
+      if (!MI->isUsedForHeaderGuard())
+        continue;
+
+      const FileEntry *FE =
+          SM.getFileEntryForID(SM.getFileID(MI->getDefinitionLoc()));
+      std::string FileName = cleanPath(FE->getName());
+      Files.erase(FileName);
+
+      // See if we should check and fix this header guard.
+      if (!Check->shouldFixHeaderGuard(FileName))
+        continue;
+
+      // Look up Locations for this guard.
+      SourceLocation Ifndef =
+          Ifndefs[MacroEntry.first.getIdentifierInfo()].second;
+      SourceLocation Define = MacroEntry.first.getLocation();
+      SourceLocation EndIf =
+          EndIfs[Ifndefs[MacroEntry.first.getIdentifierInfo()].first];
+
+      // If the macro Name is not equal to what we can compute, correct it in
+      // the #ifndef and #define.
+      StringRef CurHeaderGuard =
+          MacroEntry.first.getIdentifierInfo()->getName();
+      std::vector<FixItHint> FixIts;
+      std::string NewGuard = checkHeaderGuardDefinition(
+          Ifndef, Define, EndIf, FileName, CurHeaderGuard, FixIts);
+
+      // Now look at the #endif. We want a comment with the header guard. Fix it
+      // at the slightest deviation.
+      checkEndifComment(FileName, EndIf, NewGuard, FixIts);
+
+      // Bundle all fix-its into one warning. The message depends on whether we
+      // changed the header guard or not.
+      if (!FixIts.empty()) {
+        if (CurHeaderGuard != NewGuard) {
+          Check->diag(Ifndef, "header guard does not follow preferred style")
+              << FixIts;
+        } else {
+          Check->diag(EndIf, "#endif for a header guard should reference the "
+                             "guard macro in a comment")
+              << FixIts;
+        }
+      }
+    }
+
+    // Emit warnings for headers that are missing guards.
+    checkGuardlessHeaders();
+
+    // Clear all state.
+    Macros.clear();
+    Files.clear();
+    Ifndefs.clear();
+    EndIfs.clear();
+  }
+
+  bool wouldFixEndifComment(StringRef FileName, SourceLocation EndIf,
+                            StringRef HeaderGuard,
+                            size_t *EndIfLenPtr = nullptr) {
+    if (!EndIf.isValid())
+      return false;
+    const char *EndIfData = PP->getSourceManager().getCharacterData(EndIf);
+    size_t EndIfLen = std::strcspn(EndIfData, "\r\n");
+    if (EndIfLenPtr)
+      *EndIfLenPtr = EndIfLen;
+
+    StringRef EndIfStr(EndIfData, EndIfLen);
+    EndIfStr = EndIfStr.substr(EndIfStr.find_first_not_of("#endif \t"));
+
+    // Give up if there's an escaped newline.
+    size_t FindEscapedNewline = EndIfStr.find_last_not_of(' ');
+    if (FindEscapedNewline != StringRef::npos &&
+        EndIfStr[FindEscapedNewline] == '\\')
+      return false;
+
+    if (!Check->shouldSuggestEndifComment(FileName) &&
+        !(EndIfStr.startswith("//") ||
+          (EndIfStr.startswith("/*") && EndIfStr.endswith("*/"))))
+      return false;
+
+    return (EndIfStr != "// " + HeaderGuard.str()) &&
+           (EndIfStr != "/* " + HeaderGuard.str() + " */");
+  }
+
+  /// \brief Look for header guards that don't match the preferred style. Emit
+  /// fix-its and return the suggested header guard (or the original if no
+  /// change was made.
+  std::string checkHeaderGuardDefinition(SourceLocation Ifndef,
+                                         SourceLocation Define,
+                                         SourceLocation EndIf,
+                                         StringRef FileName,
+                                         StringRef CurHeaderGuard,
+                                         std::vector<FixItHint> &FixIts) {
+    std::string CPPVar = Check->getHeaderGuard(FileName, CurHeaderGuard);
+    std::string CPPVarUnder = CPPVar + '_';
+
+    // Allow a trailing underscore iff we don't have to change the endif comment
+    // too.
+    if (Ifndef.isValid() && CurHeaderGuard != CPPVar &&
+        (CurHeaderGuard != CPPVarUnder ||
+         wouldFixEndifComment(FileName, EndIf, CurHeaderGuard))) {
+      FixIts.push_back(FixItHint::CreateReplacement(
+          CharSourceRange::getTokenRange(
+              Ifndef, Ifndef.getLocWithOffset(CurHeaderGuard.size())),
+          CPPVar));
+      FixIts.push_back(FixItHint::CreateReplacement(
+          CharSourceRange::getTokenRange(
+              Define, Define.getLocWithOffset(CurHeaderGuard.size())),
+          CPPVar));
+      return CPPVar;
+    }
+    return CurHeaderGuard;
+  }
+
+  /// \brief Checks the comment after the #endif of a header guard and fixes it
+  /// if it doesn't match \c HeaderGuard.
+  void checkEndifComment(StringRef FileName, SourceLocation EndIf,
+                         StringRef HeaderGuard,
+                         std::vector<FixItHint> &FixIts) {
+    size_t EndIfLen;
+    if (wouldFixEndifComment(FileName, EndIf, HeaderGuard, &EndIfLen)) {
+      FixIts.push_back(FixItHint::CreateReplacement(
+          CharSourceRange::getCharRange(EndIf,
+                                        EndIf.getLocWithOffset(EndIfLen)),
+          Check->formatEndIf(HeaderGuard)));
+    }
+  }
+
+  /// \brief Looks for files that were visited but didn't have a header guard.
+  /// Emits a warning with fixits suggesting adding one.
+  void checkGuardlessHeaders() {
+    // Look for header files that didn't have a header guard. Emit a warning and
+    // fix-its to add the guard.
+    // TODO: Insert the guard after top comments.
+    for (const auto &FE : Files) {
+      StringRef FileName = FE.getKey();
+      if (!Check->shouldSuggestToAddHeaderGuard(FileName))
+        continue;
+
+      SourceManager &SM = PP->getSourceManager();
+      FileID FID = SM.translateFile(FE.getValue());
+      SourceLocation StartLoc = SM.getLocForStartOfFile(FID);
+      if (StartLoc.isInvalid())
+        continue;
+
+      std::string CPPVar = Check->getHeaderGuard(FileName);
+      std::string CPPVarUnder = CPPVar + '_'; // Allow a trailing underscore.
+      // If there's a macro with a name that follows the header guard convention
+      // but was not recognized by the preprocessor as a header guard there must
+      // be code outside of the guarded area. Emit a plain warning without
+      // fix-its.
+      // FIXME: Can we move it into the right spot?
+      bool SeenMacro = false;
+      for (const auto &MacroEntry : Macros) {
+        StringRef Name = MacroEntry.first.getIdentifierInfo()->getName();
+        SourceLocation DefineLoc = MacroEntry.first.getLocation();
+        if ((Name == CPPVar || Name == CPPVarUnder) &&
+            SM.isWrittenInSameFile(StartLoc, DefineLoc)) {
+          Check->diag(DefineLoc, "code/includes outside of area guarded by "
+                                 "header guard; consider moving it");
+          SeenMacro = true;
+          break;
+        }
+      }
+
+      if (SeenMacro)
+        continue;
+
+      Check->diag(StartLoc, "header is missing header guard")
+          << FixItHint::CreateInsertion(
+                 StartLoc, "#ifndef " + CPPVar + "\n#define " + CPPVar + "\n\n")
+          << FixItHint::CreateInsertion(
+                 SM.getLocForEndOfFile(FID),
+                 Check->shouldSuggestEndifComment(FileName)
+                     ? "\n#" + Check->formatEndIf(CPPVar) + "\n"
+                     : "\n#endif\n");
+    }
+  }
+
+private:
+  std::vector<std::pair<Token, const MacroInfo *>> Macros;
+  llvm::StringMap<const FileEntry *> Files;
+  std::map<const IdentifierInfo *, std::pair<SourceLocation, SourceLocation>>
+      Ifndefs;
+  std::map<SourceLocation, SourceLocation> EndIfs;
+
+  Preprocessor *PP;
+  HeaderGuardCheck *Check;
+};
+} // namespace
+
+void HeaderGuardCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  Compiler.getPreprocessor().addPPCallbacks(
+      llvm::make_unique<HeaderGuardPPCallbacks>(&Compiler.getPreprocessor(),
+                                                this));
+}
+
+bool HeaderGuardCheck::shouldSuggestEndifComment(StringRef FileName) {
+  return utils::isHeaderFileExtension(FileName, HeaderFileExtensions);
+}
+
+bool HeaderGuardCheck::shouldFixHeaderGuard(StringRef FileName) { return true; }
+
+bool HeaderGuardCheck::shouldSuggestToAddHeaderGuard(StringRef FileName) {
+  return utils::isHeaderFileExtension(FileName, HeaderFileExtensions);
+}
+
+std::string HeaderGuardCheck::formatEndIf(StringRef HeaderGuard) {
+  return "endif // " + HeaderGuard.str();
+}
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/HeaderGuard.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/HeaderGuard.h
new file mode 100644
index 0000000..a2d8288
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/HeaderGuard.h
@@ -0,0 +1,64 @@
+//===--- HeaderGuard.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_UTILS_HEADERGUARD_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_HEADERGUARD_H
+
+#include "../ClangTidy.h"
+#include "../utils/HeaderFileExtensionsUtils.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+/// Finds and fixes header guards.
+/// The check supports these options:
+///   - `HeaderFileExtensions`: a comma-separated list of filename extensions of
+///     header files (The filename extension should not contain "." prefix).
+///     ",h,hh,hpp,hxx" by default.
+///     For extension-less header files, using an empty string or leaving an
+///     empty string between "," if there are other filename extensions.
+class HeaderGuardCheck : public ClangTidyCheck {
+public:
+  HeaderGuardCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context),
+        RawStringHeaderFileExtensions(Options.getLocalOrGlobal(
+            "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) {
+    utils::parseHeaderFileExtensions(RawStringHeaderFileExtensions,
+                                     HeaderFileExtensions, ',');
+  }
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+
+  /// Returns ``true`` if the check should suggest inserting a trailing comment
+  /// on the ``#endif`` of the header guard. It will use the same name as
+  /// returned by ``HeaderGuardCheck::getHeaderGuard``.
+  virtual bool shouldSuggestEndifComment(StringRef Filename);
+  /// Returns ``true`` if the check should suggest changing an existing header
+  /// guard to the string returned by ``HeaderGuardCheck::getHeaderGuard``.
+  virtual bool shouldFixHeaderGuard(StringRef Filename);
+  /// Returns ``true`` if the check should add a header guard to the file
+  /// if it has none.
+  virtual bool shouldSuggestToAddHeaderGuard(StringRef Filename);
+  /// Returns a replacement for the ``#endif`` line with a comment mentioning
+  /// \p HeaderGuard. The replacement should start with ``endif``.
+  virtual std::string formatEndIf(StringRef HeaderGuard);
+  /// Gets the canonical header guard for a file.
+  virtual std::string getHeaderGuard(StringRef Filename,
+                                     StringRef OldGuard = StringRef()) = 0;
+
+private:
+  std::string RawStringHeaderFileExtensions;
+  utils::HeaderFileExtensionsSet HeaderFileExtensions;
+};
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_HEADERGUARD_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/IncludeInserter.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/IncludeInserter.cpp
new file mode 100644
index 0000000..64e4213
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/IncludeInserter.cpp
@@ -0,0 +1,86 @@
+//===-------- IncludeInserter.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 "IncludeInserter.h"
+#include "clang/Lex/Token.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+class IncludeInserterCallback : public PPCallbacks {
+public:
+  explicit IncludeInserterCallback(IncludeInserter *Inserter)
+      : Inserter(Inserter) {}
+  // Implements PPCallbacks::InclusionDerective(). Records the names and source
+  // locations of the inclusions in the main source file being processed.
+  void InclusionDirective(SourceLocation HashLocation,
+                          const Token &IncludeToken, StringRef FileNameRef,
+                          bool IsAngled, CharSourceRange FileNameRange,
+                          const FileEntry * /*IncludedFile*/,
+                          StringRef /*SearchPath*/, StringRef /*RelativePath*/,
+                          const Module * /*ImportedModule*/,
+                          SrcMgr::CharacteristicKind /*FileType*/) override {
+    Inserter->AddInclude(FileNameRef, IsAngled, HashLocation,
+                         IncludeToken.getEndLoc());
+  }
+
+private:
+  IncludeInserter *Inserter;
+};
+
+IncludeInserter::IncludeInserter(const SourceManager &SourceMgr,
+                                 const LangOptions &LangOpts,
+                                 IncludeSorter::IncludeStyle Style)
+    : SourceMgr(SourceMgr), LangOpts(LangOpts), Style(Style) {}
+
+IncludeInserter::~IncludeInserter() {}
+
+std::unique_ptr<PPCallbacks> IncludeInserter::CreatePPCallbacks() {
+  return llvm::make_unique<IncludeInserterCallback>(this);
+}
+
+llvm::Optional<FixItHint>
+IncludeInserter::CreateIncludeInsertion(FileID FileID, StringRef Header,
+                                        bool IsAngled) {
+  // We assume the same Header will never be included both angled and not
+  // angled.
+  if (!InsertedHeaders[FileID].insert(Header).second)
+    return llvm::None;
+
+  if (IncludeSorterByFile.find(FileID) == IncludeSorterByFile.end()) {
+    // This may happen if there have been no preprocessor directives in this
+    // file.
+    IncludeSorterByFile.insert(std::make_pair(
+        FileID,
+        llvm::make_unique<IncludeSorter>(
+            &SourceMgr, &LangOpts, FileID,
+            SourceMgr.getFilename(SourceMgr.getLocForStartOfFile(FileID)),
+            Style)));
+  }
+  return IncludeSorterByFile[FileID]->CreateIncludeInsertion(Header, IsAngled);
+}
+
+void IncludeInserter::AddInclude(StringRef FileName, bool IsAngled,
+                                 SourceLocation HashLocation,
+                                 SourceLocation EndLocation) {
+  FileID FileID = SourceMgr.getFileID(HashLocation);
+  if (IncludeSorterByFile.find(FileID) == IncludeSorterByFile.end()) {
+    IncludeSorterByFile.insert(std::make_pair(
+        FileID, llvm::make_unique<IncludeSorter>(
+                    &SourceMgr, &LangOpts, FileID,
+                    SourceMgr.getFilename(HashLocation), Style)));
+  }
+  IncludeSorterByFile[FileID]->AddInclude(FileName, IsAngled, HashLocation,
+                                          EndLocation);
+}
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/IncludeInserter.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/IncludeInserter.h
new file mode 100644
index 0000000..75f2554
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/IncludeInserter.h
@@ -0,0 +1,84 @@
+//===---------- IncludeInserter.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_INCLUDEINSERTER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INCLUDEINSERTER_H
+
+#include "IncludeSorter.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/PPCallbacks.h"
+#include <memory>
+#include <string>
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+/// \brief Produces fixes to insert specified includes to source files, if not
+/// yet present.
+///
+/// ``IncludeInserter`` can be used by ``ClangTidyCheck`` in the following
+/// fashion:
+/// \code
+/// class MyCheck : public ClangTidyCheck {
+///  public:
+///   void registerPPCallbacks(CompilerInstance& Compiler) override {
+///     Inserter.reset(new IncludeInserter(&Compiler.getSourceManager(),
+///                                        &Compiler.getLangOpts()));
+///     Compiler.getPreprocessor().addPPCallbacks(
+///         Inserter->CreatePPCallback());
+///   }
+///
+///   void registerMatchers(ast_matchers::MatchFinder* Finder) override { ... }
+///
+///   void check(
+///       const ast_matchers::MatchFinder::MatchResult& Result) override {
+///     ...
+///     Inserter->CreateIncludeInsertion(
+///         Result.SourceManager->getMainFileID(), "path/to/Header.h",
+///         /*IsAngled=*/false);
+///     ...
+///   }
+///
+///  private:
+///   std::unique_ptr<IncludeInserter> Inserter;
+/// };
+/// \endcode
+class IncludeInserter {
+public:
+  IncludeInserter(const SourceManager &SourceMgr, const LangOptions &LangOpts,
+                  IncludeSorter::IncludeStyle Style);
+  ~IncludeInserter();
+
+  /// Create ``PPCallbacks`` for registration with the compiler's preprocessor.
+  std::unique_ptr<PPCallbacks> CreatePPCallbacks();
+
+  /// Creates a \p Header inclusion directive fixit. Returns ``llvm::None`` on
+  /// error or if inclusion directive already exists.
+  llvm::Optional<FixItHint>
+  CreateIncludeInsertion(FileID FileID, llvm::StringRef Header, bool IsAngled);
+
+private:
+  void AddInclude(StringRef FileName, bool IsAngled,
+                  SourceLocation HashLocation, SourceLocation EndLocation);
+
+  llvm::DenseMap<FileID, std::unique_ptr<IncludeSorter>> IncludeSorterByFile;
+  llvm::DenseMap<FileID, std::set<std::string>> InsertedHeaders;
+  const SourceManager &SourceMgr;
+  const LangOptions &LangOpts;
+  const IncludeSorter::IncludeStyle Style;
+  friend class IncludeInserterCallback;
+};
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INCLUDEINSERTER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp
new file mode 100644
index 0000000..1502da7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp
@@ -0,0 +1,290 @@
+//===---------- IncludeSorter.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 "IncludeSorter.h"
+#include "clang/Lex/Lexer.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+namespace {
+
+StringRef RemoveFirstSuffix(StringRef Str, ArrayRef<const char *> Suffixes) {
+  for (StringRef Suffix : Suffixes) {
+    if (Str.endswith(Suffix)) {
+      return Str.substr(0, Str.size() - Suffix.size());
+    }
+  }
+  return Str;
+}
+
+StringRef MakeCanonicalName(StringRef Str, IncludeSorter::IncludeStyle Style) {
+  // The list of suffixes to remove from source file names to get the
+  // "canonical" file names.
+  // E.g. tools/sort_includes.cc and tools/sort_includes_test.cc
+  // would both canonicalize to tools/sort_includes and tools/sort_includes.h
+  // (once canonicalized) will match as being the main include file associated
+  // with the source files.
+  if (Style == IncludeSorter::IS_LLVM) {
+    return RemoveFirstSuffix(
+        RemoveFirstSuffix(Str, {".cc", ".cpp", ".c", ".h", ".hpp"}), {"Test"});
+  }
+  return RemoveFirstSuffix(
+      RemoveFirstSuffix(Str, {".cc", ".cpp", ".c", ".h", ".hpp"}),
+      {"_unittest", "_regtest", "_test"});
+}
+
+// Scan to the end of the line and return the offset of the next line.
+size_t FindNextLine(const char *Text) {
+  size_t EOLIndex = std::strcspn(Text, "\n");
+  return Text[EOLIndex] == '\0' ? EOLIndex : EOLIndex + 1;
+}
+
+IncludeSorter::IncludeKinds
+DetermineIncludeKind(StringRef CanonicalFile, StringRef IncludeFile,
+                     bool IsAngled, IncludeSorter::IncludeStyle Style) {
+  // Compute the two "canonical" forms of the include's filename sans extension.
+  // The first form is the include's filename without ".h" or "-inl.h" at the
+  // end. The second form is the first form with "/public/" in the file path
+  // replaced by "/internal/".
+  if (IsAngled) {
+    // If the system include (<foo>) ends with ".h", then it is a normal C-style
+    // include. Otherwise assume it is a C++-style extensionless include.
+    return IncludeFile.endswith(".h") ? IncludeSorter::IK_CSystemInclude
+                                      : IncludeSorter::IK_CXXSystemInclude;
+  }
+  StringRef CanonicalInclude = MakeCanonicalName(IncludeFile, Style);
+  if (CanonicalFile.endswith(CanonicalInclude)
+      || CanonicalInclude.endswith(CanonicalFile)) {
+    return IncludeSorter::IK_MainTUInclude;
+  }
+  if (Style == IncludeSorter::IS_Google) {
+    std::pair<StringRef, StringRef> Parts = CanonicalInclude.split("/public/");
+    std::string AltCanonicalInclude =
+        Parts.first.str() + "/internal/" + Parts.second.str();
+    std::string ProtoCanonicalInclude =
+        Parts.first.str() + "/proto/" + Parts.second.str();
+
+    // Determine the kind of this inclusion.
+    if (CanonicalFile.equals(AltCanonicalInclude) ||
+        CanonicalFile.equals(ProtoCanonicalInclude)) {
+      return IncludeSorter::IK_MainTUInclude;
+    }
+  }
+  return IncludeSorter::IK_NonSystemInclude;
+}
+
+} // namespace
+
+IncludeSorter::IncludeSorter(const SourceManager *SourceMgr,
+                             const LangOptions *LangOpts, const FileID FileID,
+                             StringRef FileName, IncludeStyle Style)
+    : SourceMgr(SourceMgr), LangOpts(LangOpts), Style(Style),
+      CurrentFileID(FileID), CanonicalFile(MakeCanonicalName(FileName, Style)) {
+}
+
+void IncludeSorter::AddInclude(StringRef FileName, bool IsAngled,
+                               SourceLocation HashLocation,
+                               SourceLocation EndLocation) {
+  int Offset = FindNextLine(SourceMgr->getCharacterData(EndLocation));
+
+  // Record the relevant location information for this inclusion directive.
+  IncludeLocations[FileName].push_back(
+      SourceRange(HashLocation, EndLocation.getLocWithOffset(Offset)));
+  SourceLocations.push_back(IncludeLocations[FileName].back());
+
+  // Stop if this inclusion is a duplicate.
+  if (IncludeLocations[FileName].size() > 1)
+    return;
+
+  // Add the included file's name to the appropriate bucket.
+  IncludeKinds Kind =
+      DetermineIncludeKind(CanonicalFile, FileName, IsAngled, Style);
+  if (Kind != IK_InvalidInclude)
+    IncludeBucket[Kind].push_back(FileName.str());
+}
+
+Optional<FixItHint> IncludeSorter::CreateIncludeInsertion(StringRef FileName,
+                                                          bool IsAngled) {
+  std::string IncludeStmt =
+      IsAngled ? llvm::Twine("#include <" + FileName + ">\n").str()
+               : llvm::Twine("#include \"" + FileName + "\"\n").str();
+  if (SourceLocations.empty()) {
+    // If there are no includes in this file, add it in the first line.
+    // FIXME: insert after the file comment or the header guard, if present.
+    IncludeStmt.append("\n");
+    return FixItHint::CreateInsertion(
+        SourceMgr->getLocForStartOfFile(CurrentFileID), IncludeStmt);
+  }
+
+  auto IncludeKind =
+      DetermineIncludeKind(CanonicalFile, FileName, IsAngled, Style);
+
+  if (!IncludeBucket[IncludeKind].empty()) {
+    for (const std::string &IncludeEntry : IncludeBucket[IncludeKind]) {
+      if (FileName < IncludeEntry) {
+        const auto &Location = IncludeLocations[IncludeEntry][0];
+        return FixItHint::CreateInsertion(Location.getBegin(), IncludeStmt);
+      } else if (FileName == IncludeEntry) {
+        return llvm::None;
+      }
+    }
+    // FileName comes after all include entries in bucket, insert it after
+    // last.
+    const std::string &LastInclude = IncludeBucket[IncludeKind].back();
+    SourceRange LastIncludeLocation = IncludeLocations[LastInclude].back();
+    return FixItHint::CreateInsertion(LastIncludeLocation.getEnd(),
+                                      IncludeStmt);
+  }
+  // Find the non-empty include bucket to be sorted directly above
+  // 'IncludeKind'. If such a bucket exists, we'll want to sort the include
+  // after that bucket. If no such bucket exists, find the first non-empty
+  // include bucket in the file. In that case, we'll want to sort the include
+  // before that bucket.
+  IncludeKinds NonEmptyKind = IK_InvalidInclude;
+  for (int i = IK_InvalidInclude - 1; i >= 0; --i) {
+    if (!IncludeBucket[i].empty()) {
+      NonEmptyKind = static_cast<IncludeKinds>(i);
+      if (NonEmptyKind < IncludeKind)
+        break;
+    }
+  }
+  if (NonEmptyKind == IK_InvalidInclude) {
+    return llvm::None;
+  }
+
+  if (NonEmptyKind < IncludeKind) {
+    // Create a block after.
+    const std::string &LastInclude = IncludeBucket[NonEmptyKind].back();
+    SourceRange LastIncludeLocation = IncludeLocations[LastInclude].back();
+    IncludeStmt = '\n' + IncludeStmt;
+    return FixItHint::CreateInsertion(LastIncludeLocation.getEnd(),
+                                      IncludeStmt);
+  }
+  // Create a block before.
+  const std::string &FirstInclude = IncludeBucket[NonEmptyKind][0];
+  SourceRange FirstIncludeLocation = IncludeLocations[FirstInclude].back();
+  IncludeStmt.append("\n");
+  return FixItHint::CreateInsertion(FirstIncludeLocation.getBegin(),
+                                    IncludeStmt);
+}
+
+std::vector<FixItHint> IncludeSorter::GetEdits() {
+  if (SourceLocations.empty())
+    return {};
+
+  typedef std::map<int, std::pair<SourceRange, std::string>>
+      FileLineToSourceEditMap;
+  FileLineToSourceEditMap Edits;
+  auto SourceLocationIterator = SourceLocations.begin();
+  auto SourceLocationIteratorEnd = SourceLocations.end();
+
+  // Compute the Edits that need to be done to each line to add, replace, or
+  // delete inclusions.
+  for (int IncludeKind = 0; IncludeKind < IK_InvalidInclude; ++IncludeKind) {
+    std::sort(IncludeBucket[IncludeKind].begin(),
+              IncludeBucket[IncludeKind].end());
+    for (const auto &IncludeEntry : IncludeBucket[IncludeKind]) {
+      auto &Location = IncludeLocations[IncludeEntry];
+      SourceRangeVector::iterator LocationIterator = Location.begin();
+      SourceRangeVector::iterator LocationIteratorEnd = Location.end();
+      SourceRange FirstLocation = *LocationIterator;
+
+      // If the first occurrence of a particular include is on the current
+      // source line we are examining, leave it alone.
+      if (FirstLocation == *SourceLocationIterator)
+        ++LocationIterator;
+
+      // Add the deletion Edits for any (remaining) instances of this inclusion,
+      // and remove their Locations from the source Locations to be processed.
+      for (; LocationIterator != LocationIteratorEnd; ++LocationIterator) {
+        int LineNumber =
+            SourceMgr->getSpellingLineNumber(LocationIterator->getBegin());
+        Edits[LineNumber] = std::make_pair(*LocationIterator, "");
+        SourceLocationIteratorEnd =
+            std::remove(SourceLocationIterator, SourceLocationIteratorEnd,
+                        *LocationIterator);
+      }
+
+      if (FirstLocation == *SourceLocationIterator) {
+        // Do nothing except move to the next source Location (Location of an
+        // inclusion in the original, unchanged source file).
+        ++SourceLocationIterator;
+        continue;
+      }
+
+      // Add (or append to) the replacement text for this line in source file.
+      int LineNumber =
+          SourceMgr->getSpellingLineNumber(SourceLocationIterator->getBegin());
+      if (Edits.find(LineNumber) == Edits.end()) {
+        Edits[LineNumber].first =
+            SourceRange(SourceLocationIterator->getBegin());
+      }
+      StringRef SourceText = Lexer::getSourceText(
+          CharSourceRange::getCharRange(FirstLocation), *SourceMgr, *LangOpts);
+      Edits[LineNumber].second.append(SourceText.data(), SourceText.size());
+    }
+
+    // Clear the bucket.
+    IncludeBucket[IncludeKind].clear();
+  }
+
+  // Go through the single-line Edits and combine them into blocks of Edits.
+  int CurrentEndLine = 0;
+  SourceRange CurrentRange;
+  std::string CurrentText;
+  std::vector<FixItHint> Fixes;
+  for (const auto &LineEdit : Edits) {
+    // If the current edit is on the next line after the previous edit, add it
+    // to the current block edit.
+    if (LineEdit.first == CurrentEndLine + 1 &&
+        CurrentRange.getBegin() != CurrentRange.getEnd()) {
+      SourceRange EditRange = LineEdit.second.first;
+      if (EditRange.getBegin() != EditRange.getEnd()) {
+        ++CurrentEndLine;
+        CurrentRange.setEnd(EditRange.getEnd());
+      }
+      CurrentText += LineEdit.second.second;
+      // Otherwise report the current block edit and start a new block.
+    } else {
+      if (CurrentEndLine) {
+        Fixes.push_back(FixItHint::CreateReplacement(
+            CharSourceRange::getCharRange(CurrentRange), CurrentText));
+      }
+
+      CurrentEndLine = LineEdit.first;
+      CurrentRange = LineEdit.second.first;
+      CurrentText = LineEdit.second.second;
+    }
+  }
+  // Finally, report the current block edit if there is one.
+  if (CurrentEndLine) {
+    Fixes.push_back(FixItHint::CreateReplacement(
+        CharSourceRange::getCharRange(CurrentRange), CurrentText));
+  }
+
+  // Reset the remaining internal state.
+  SourceLocations.clear();
+  IncludeLocations.clear();
+  return Fixes;
+}
+
+IncludeSorter::IncludeStyle
+IncludeSorter::parseIncludeStyle(const std::string &Value) {
+  return Value == "llvm" ? IS_LLVM : IS_Google;
+}
+
+StringRef IncludeSorter::toString(IncludeStyle Style) {
+  return Style == IS_LLVM ? "llvm" : "google";
+}
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/IncludeSorter.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/IncludeSorter.h
new file mode 100644
index 0000000..07fa293
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/IncludeSorter.h
@@ -0,0 +1,86 @@
+//===------------ IncludeSorter.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_INCLUDESORTER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INCLUDESORTER_H
+
+#include "../ClangTidy.h"
+#include <string>
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+/// Class used by ``IncludeInserterCallback`` to record the names of the
+/// inclusions in a given source file being processed and generate the necessary
+/// commands to sort the inclusions according to the precedence encoded in
+/// ``IncludeKinds``.
+class IncludeSorter {
+public:
+  /// Supported include styles.
+  enum IncludeStyle { IS_LLVM = 0, IS_Google = 1 };
+
+  /// Converts "llvm" to ``IS_LLVM``, otherwise returns ``IS_Google``.
+  static IncludeStyle parseIncludeStyle(const std::string &Value);
+
+  /// Converts ``IncludeStyle`` to string representation.
+  static StringRef toString(IncludeStyle Style);
+
+  /// The classifications of inclusions, in the order they should be sorted.
+  enum IncludeKinds {
+    IK_MainTUInclude = 0,    ///< e.g. ``#include "foo.h"`` when editing foo.cc
+    IK_CSystemInclude = 1,   ///< e.g. ``#include <stdio.h>``
+    IK_CXXSystemInclude = 2, ///< e.g. ``#include <vector>``
+    IK_NonSystemInclude = 3, ///< e.g. ``#include "bar.h"``
+    IK_InvalidInclude = 4    ///< total number of valid ``IncludeKind``s
+  };
+
+  /// ``IncludeSorter`` constructor; takes the FileID and name of the file to be
+  /// processed by the sorter.
+  IncludeSorter(const SourceManager *SourceMgr, const LangOptions *LangOpts,
+                const FileID FileID, StringRef FileName, IncludeStyle Style);
+
+  /// Returns the ``SourceManager``-specific file ID for the file being handled
+  /// by the sorter.
+  const FileID current_FileID() const { return CurrentFileID; }
+
+  /// Adds the given include directive to the sorter.
+  void AddInclude(StringRef FileName, bool IsAngled,
+                  SourceLocation HashLocation, SourceLocation EndLocation);
+
+  /// Returns the edits needed to sort the current set of includes and reset the
+  /// internal state (so that different blocks of includes are sorted separately
+  /// within the same file).
+  std::vector<FixItHint> GetEdits();
+
+  /// Creates a quoted inclusion directive in the right sort order. Returns None
+  /// on error or if header inclusion directive for header already exists.
+  Optional<FixItHint> CreateIncludeInsertion(StringRef FileName, bool IsAngled);
+
+private:
+  typedef SmallVector<SourceRange, 1> SourceRangeVector;
+
+  const SourceManager *SourceMgr;
+  const LangOptions *LangOpts;
+  const IncludeStyle Style;
+  FileID CurrentFileID;
+  /// The file name stripped of common suffixes.
+  StringRef CanonicalFile;
+  /// Locations of visited include directives.
+  SourceRangeVector SourceLocations;
+  /// Mapping from file name to #include locations.
+  llvm::StringMap<SourceRangeVector> IncludeLocations;
+  /// Includes sorted into buckets.
+  SmallVector<std::string, 1> IncludeBucket[IK_InvalidInclude];
+};
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INCLUDESORTER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
new file mode 100644
index 0000000..d027219
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
@@ -0,0 +1,41 @@
+//===--- LexerUtils.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 "LexerUtils.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+namespace lexer {
+
+Token getPreviousToken(const ASTContext &Context, SourceLocation Location,
+                       bool SkipComments) {
+  const auto &SourceManager = Context.getSourceManager();
+  Token Token;
+  Token.setKind(tok::unknown);
+  Location = Location.getLocWithOffset(-1);
+  auto StartOfFile =
+      SourceManager.getLocForStartOfFile(SourceManager.getFileID(Location));
+  while (Location != StartOfFile) {
+    Location = Lexer::GetBeginningOfToken(Location, SourceManager,
+                                          Context.getLangOpts());
+    if (!Lexer::getRawToken(Location, Token, SourceManager,
+                            Context.getLangOpts()) &&
+        (!SkipComments || !Token.is(tok::comment))) {
+      break;
+    }
+    Location = Location.getLocWithOffset(-1);
+  }
+  return Token;
+}
+
+} // namespace lexer
+} // namespace utils
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/LexerUtils.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/LexerUtils.h
new file mode 100644
index 0000000..f7bcd6f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/LexerUtils.h
@@ -0,0 +1,30 @@
+//===--- LexerUtils.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_UTILS_LEXER_UTILS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_LEXER_UTILS_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/Lex/Lexer.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+namespace lexer {
+
+/// Returns previous token or ``tok::unknown`` if not found.
+Token getPreviousToken(const ASTContext &Context, SourceLocation Location,
+                       bool SkipComments = true);
+
+} // namespace lexer
+} // namespace utils
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_LEXER_UTILS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/Matchers.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/Matchers.h
new file mode 100644
index 0000000..aeb639f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/Matchers.h
@@ -0,0 +1,55 @@
+//===--- Matchers.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_UTILS_MATCHERS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
+
+#include "TypeTraits.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+namespace clang {
+namespace tidy {
+namespace matchers {
+
+AST_MATCHER(BinaryOperator, isAssignmentOperator) {
+  return Node.isAssignmentOp();
+}
+
+AST_MATCHER(BinaryOperator, isRelationalOperator) {
+  return Node.isRelationalOp();
+}
+
+AST_MATCHER(BinaryOperator, isEqualityOperator) { return Node.isEqualityOp(); }
+
+AST_MATCHER(BinaryOperator, isComparisonOperator) {
+  return Node.isComparisonOp();
+}
+
+AST_MATCHER(QualType, isExpensiveToCopy) {
+  llvm::Optional<bool> IsExpensive =
+      utils::type_traits::isExpensiveToCopy(Node, Finder->getASTContext());
+  return IsExpensive && *IsExpensive;
+}
+
+AST_MATCHER(RecordDecl, isTriviallyDefaultConstructible) {
+  return utils::type_traits::recordIsTriviallyDefaultConstructible(
+      Node, Finder->getASTContext());
+}
+
+// Returns QualType matcher for references to const.
+AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher, isReferenceToConst) {
+  using namespace ast_matchers;
+  return referenceType(pointee(qualType(isConstQualified())));
+}
+
+} // namespace matchers
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/NamespaceAliaser.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/NamespaceAliaser.cpp
new file mode 100644
index 0000000..1a5120d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/NamespaceAliaser.cpp
@@ -0,0 +1,97 @@
+//===---------- NamespaceAliaser.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 "NamespaceAliaser.h"
+
+#include "ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+namespace clang {
+namespace tidy {
+namespace utils {
+
+using namespace ast_matchers;
+
+NamespaceAliaser::NamespaceAliaser(const SourceManager &SourceMgr)
+    : SourceMgr(SourceMgr) {}
+
+AST_MATCHER_P(NamespaceAliasDecl, hasTargetNamespace,
+              ast_matchers::internal::Matcher<NamespaceDecl>, innerMatcher) {
+  return innerMatcher.matches(*Node.getNamespace(), Finder, Builder);
+}
+
+Optional<FixItHint>
+NamespaceAliaser::createAlias(ASTContext &Context, const Stmt &Statement,
+                              StringRef Namespace,
+                              const std::vector<std::string> &Abbreviations) {
+  const FunctionDecl *Function = getSurroundingFunction(Context, Statement);
+  if (!Function || !Function->hasBody())
+    return None;
+
+  if (AddedAliases[Function].count(Namespace.str()) != 0)
+    return None;
+
+  // FIXME: Doesn't consider the order of declarations.
+  // If we accidentially pick an alias defined later in the function,
+  // the output won't compile.
+  // FIXME: Also doesn't consider file or class-scope aliases.
+
+  const auto *ExistingAlias = selectFirst<NamedDecl>(
+      "alias",
+      match(functionDecl(hasBody(compoundStmt(has(declStmt(
+                has(namespaceAliasDecl(hasTargetNamespace(hasName(Namespace)))
+                        .bind("alias"))))))),
+            *Function, Context));
+
+  if (ExistingAlias != nullptr) {
+    AddedAliases[Function][Namespace.str()] = ExistingAlias->getName().str();
+    return None;
+  }
+
+  for (const auto &Abbreviation : Abbreviations) {
+    DeclarationMatcher ConflictMatcher = namedDecl(hasName(Abbreviation));
+    const auto HasConflictingChildren =
+        !match(findAll(ConflictMatcher), *Function, Context).empty();
+    const auto HasConflictingAncestors =
+        !match(functionDecl(hasAncestor(decl(has(ConflictMatcher)))), *Function,
+               Context)
+             .empty();
+    if (HasConflictingAncestors || HasConflictingChildren)
+      continue;
+
+    std::string Declaration =
+        (llvm::Twine("\nnamespace ") + Abbreviation + " = " + Namespace + ";")
+            .str();
+    SourceLocation Loc =
+        Lexer::getLocForEndOfToken(Function->getBody()->getLocStart(), 0,
+                                   SourceMgr, Context.getLangOpts());
+    AddedAliases[Function][Namespace.str()] = Abbreviation;
+    return FixItHint::CreateInsertion(Loc, Declaration);
+  }
+
+  return None;
+}
+
+std::string NamespaceAliaser::getNamespaceName(ASTContext &Context,
+                                               const Stmt &Statement,
+                                               StringRef Namespace) const {
+  const auto *Function = getSurroundingFunction(Context, Statement);
+  auto FunctionAliases = AddedAliases.find(Function);
+  if (FunctionAliases != AddedAliases.end()) {
+    if (FunctionAliases->second.count(Namespace) != 0) {
+      return FunctionAliases->second.find(Namespace)->getValue();
+    }
+  }
+  return Namespace.str();
+}
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/NamespaceAliaser.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/NamespaceAliaser.h
new file mode 100644
index 0000000..e56d69d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/NamespaceAliaser.h
@@ -0,0 +1,52 @@
+//===---------- NamespaceAliaser.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_NAMESPACEALIASER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_NAMESPACEALIASER_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+#include <map>
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+// This class creates function-level namespace aliases.
+class NamespaceAliaser {
+public:
+  explicit NamespaceAliaser(const SourceManager &SourceMgr);
+  // Adds a namespace alias for \p Namespace valid near \p
+  // Statement. Picks the first available name from \p Abbreviations.
+  // Returns ``llvm::None`` if an alias already exists or there is an error.
+  llvm::Optional<FixItHint>
+  createAlias(ASTContext &Context, const Stmt &Statement,
+              llvm::StringRef Namespace,
+              const std::vector<std::string> &Abbreviations);
+
+  // Get an alias name for \p Namespace valid at \p Statement. Returns \p
+  // Namespace if there is no alias.
+  std::string getNamespaceName(ASTContext &Context, const Stmt &Statement,
+                               llvm::StringRef Namespace) const;
+
+private:
+  const SourceManager &SourceMgr;
+  llvm::DenseMap<const FunctionDecl *, llvm::StringMap<std::string>>
+      AddedAliases;
+};
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_NAMESPACEALIASER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/OptionsUtils.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/OptionsUtils.cpp
new file mode 100644
index 0000000..0b1d27d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/OptionsUtils.cpp
@@ -0,0 +1,38 @@
+//===--- DanglingHandleCheck.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 "OptionsUtils.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+namespace options {
+
+static const char StringsDelimiter[] = ";";
+
+std::vector<std::string> parseStringList(StringRef Option) {
+  SmallVector<StringRef, 4> Names;
+  Option.split(Names, StringsDelimiter);
+  std::vector<std::string> Result;
+  for (StringRef &Name : Names) {
+    Name = Name.trim();
+    if (!Name.empty())
+      Result.push_back(Name);
+  }
+  return Result;
+}
+
+std::string serializeStringList(ArrayRef<std::string> Strings) {
+  return llvm::join(Strings.begin(), Strings.end(), StringsDelimiter);
+}
+
+} // namespace options
+} // namespace utils
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/OptionsUtils.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/OptionsUtils.h
new file mode 100644
index 0000000..d822ac9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/OptionsUtils.h
@@ -0,0 +1,32 @@
+//===--- DanglingHandleCheck.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_MISC_OPTIONUTILS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_OPTIONUTILS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+namespace options {
+
+/// \brief Parse a semicolon separated list of strings.
+std::vector<std::string> parseStringList(StringRef Option);
+
+/// \brief Serialize a sequence of names that can be parsed by
+/// ``parseStringList``.
+std::string serializeStringList(ArrayRef<std::string> Strings);
+
+} // namespace options
+} // namespace utils
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_OPTIONUTILS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp
new file mode 100644
index 0000000..2cdc506
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp
@@ -0,0 +1,150 @@
+//===--- TypeTraits.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 "TypeTraits.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+namespace type_traits {
+
+namespace {
+
+bool classHasTrivialCopyAndDestroy(QualType Type) {
+  auto *Record = Type->getAsCXXRecordDecl();
+  return Record && Record->hasDefinition() &&
+         !Record->hasNonTrivialCopyConstructor() &&
+         !Record->hasNonTrivialDestructor();
+}
+
+bool hasDeletedCopyConstructor(QualType Type) {
+  auto *Record = Type->getAsCXXRecordDecl();
+  if (!Record || !Record->hasDefinition())
+    return false;
+  for (const auto *Constructor : Record->ctors()) {
+    if (Constructor->isCopyConstructor() && Constructor->isDeleted())
+      return true;
+  }
+  return false;
+}
+
+} // namespace
+
+llvm::Optional<bool> isExpensiveToCopy(QualType Type,
+                                       const ASTContext &Context) {
+  if (Type->isDependentType() || Type->isIncompleteType())
+    return llvm::None;
+  return !Type.isTriviallyCopyableType(Context) &&
+         !classHasTrivialCopyAndDestroy(Type) &&
+         !hasDeletedCopyConstructor(Type) &&
+         !Type->isObjCLifetimeType();
+}
+
+bool recordIsTriviallyDefaultConstructible(const RecordDecl &RecordDecl,
+                                           const ASTContext &Context) {
+  const auto *ClassDecl = dyn_cast<CXXRecordDecl>(&RecordDecl);
+  // Non-C++ records are always trivially constructible.
+  if (!ClassDecl)
+    return true;
+  // A class with a user-provided default constructor is not trivially
+  // constructible.
+  if (ClassDecl->hasUserProvidedDefaultConstructor())
+    return false;
+  // A polymorphic class is not trivially constructible
+  if (ClassDecl->isPolymorphic())
+    return false;
+  // A class is trivially constructible if it has a trivial default constructor.
+  if (ClassDecl->hasTrivialDefaultConstructor())
+    return true;
+
+  // If all its fields are trivially constructible and have no default
+  // initializers.
+  for (const FieldDecl *Field : ClassDecl->fields()) {
+    if (Field->hasInClassInitializer())
+      return false;
+    if (!isTriviallyDefaultConstructible(Field->getType(), Context))
+      return false;
+  }
+  // If all its direct bases are trivially constructible.
+  for (const CXXBaseSpecifier &Base : ClassDecl->bases()) {
+    if (!isTriviallyDefaultConstructible(Base.getType(), Context))
+      return false;
+    if (Base.isVirtual())
+      return false;
+  }
+
+  return true;
+}
+
+// Based on QualType::isTrivial.
+bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context) {
+  if (Type.isNull())
+    return false;
+
+  if (Type->isArrayType())
+    return isTriviallyDefaultConstructible(Context.getBaseElementType(Type),
+                                           Context);
+
+  // Return false for incomplete types after skipping any incomplete array
+  // types which are expressly allowed by the standard and thus our API.
+  if (Type->isIncompleteType())
+    return false;
+
+  if (Context.getLangOpts().ObjCAutoRefCount) {
+    switch (Type.getObjCLifetime()) {
+    case Qualifiers::OCL_ExplicitNone:
+      return true;
+
+    case Qualifiers::OCL_Strong:
+    case Qualifiers::OCL_Weak:
+    case Qualifiers::OCL_Autoreleasing:
+      return false;
+
+    case Qualifiers::OCL_None:
+      if (Type->isObjCLifetimeType())
+        return false;
+      break;
+    }
+  }
+
+  QualType CanonicalType = Type.getCanonicalType();
+  if (CanonicalType->isDependentType())
+    return false;
+
+  // As an extension, Clang treats vector types as Scalar types.
+  if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
+    return true;
+
+  if (const auto *RT = CanonicalType->getAs<RecordType>()) {
+    return recordIsTriviallyDefaultConstructible(*RT->getDecl(), Context);
+  }
+
+  // No other types can match.
+  return false;
+}
+
+bool hasNonTrivialMoveConstructor(QualType Type) {
+  auto *Record = Type->getAsCXXRecordDecl();
+  return Record && Record->hasDefinition() &&
+         Record->hasNonTrivialMoveConstructor();
+}
+
+bool hasNonTrivialMoveAssignment(QualType Type) {
+  auto *Record = Type->getAsCXXRecordDecl();
+  return Record && Record->hasDefinition() &&
+         Record->hasNonTrivialMoveAssignment();
+}
+
+} // namespace type_traits
+} // namespace utils
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/TypeTraits.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/TypeTraits.h
new file mode 100644
index 0000000..ae0b3f0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/TypeTraits.h
@@ -0,0 +1,43 @@
+//===--- TypeTraits.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_UTILS_TYPETRAITS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_TYPETRAITS_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+namespace type_traits {
+
+/// Returns `true` if `Type` is expensive to copy.
+llvm::Optional<bool> isExpensiveToCopy(QualType Type,
+                                       const ASTContext &Context);
+
+/// Returns `true` if `Type` is trivially default constructible.
+bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context);
+
+/// Returns `true` if `RecordDecl` is trivially default constructible.
+bool recordIsTriviallyDefaultConstructible(const RecordDecl &RecordDecl,
+                                           const ASTContext &Context);
+
+/// Returns true if `Type` has a non-trivial move constructor.
+bool hasNonTrivialMoveConstructor(QualType Type);
+
+/// Return true if `Type` has a non-trivial move assignment operator.
+bool hasNonTrivialMoveAssignment(QualType Type);
+
+} // type_traits
+} // namespace utils
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_TYPETRAITS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/UsingInserter.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/UsingInserter.cpp
new file mode 100644
index 0000000..e7200c9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/UsingInserter.cpp
@@ -0,0 +1,89 @@
+//===---------- UsingInserter.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 "UsingInserter.h"
+
+#include "ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+using namespace ast_matchers;
+
+static StringRef getUnqualifiedName(StringRef QualifiedName) {
+  size_t LastSeparatorPos = QualifiedName.rfind("::");
+  if (LastSeparatorPos == StringRef::npos)
+    return QualifiedName;
+  return QualifiedName.drop_front(LastSeparatorPos + 2);
+}
+
+UsingInserter::UsingInserter(const SourceManager &SourceMgr)
+    : SourceMgr(SourceMgr) {}
+
+Optional<FixItHint> UsingInserter::createUsingDeclaration(
+    ASTContext &Context, const Stmt &Statement, StringRef QualifiedName) {
+  StringRef UnqualifiedName = getUnqualifiedName(QualifiedName);
+  const FunctionDecl *Function = getSurroundingFunction(Context, Statement);
+  if (!Function)
+    return None;
+
+  if (AddedUsing.count(std::make_pair(Function, QualifiedName.str())) != 0)
+    return None;
+
+  SourceLocation InsertLoc = Lexer::getLocForEndOfToken(
+      Function->getBody()->getLocStart(), 0, SourceMgr, Context.getLangOpts());
+
+  // Only use using declarations in the main file, not in includes.
+  if (SourceMgr.getFileID(InsertLoc) != SourceMgr.getMainFileID())
+    return None;
+
+  // FIXME: This declaration could be masked. Investigate if
+  // there is a way to avoid using Sema.
+  bool AlreadyHasUsingDecl =
+      !match(stmt(hasAncestor(decl(has(usingDecl(hasAnyUsingShadowDecl(
+                 hasTargetDecl(hasName(QualifiedName.str())))))))),
+             Statement, Context)
+           .empty();
+  if (AlreadyHasUsingDecl) {
+    AddedUsing.emplace(NameInFunction(Function, QualifiedName.str()));
+    return None;
+  }
+  // Find conflicting declarations and references.
+  auto ConflictingDecl = namedDecl(hasName(UnqualifiedName));
+  bool HasConflictingDeclaration =
+      !match(findAll(ConflictingDecl), *Function, Context).empty();
+  bool HasConflictingDeclRef =
+      !match(findAll(declRefExpr(to(ConflictingDecl))), *Function, Context)
+           .empty();
+  if (HasConflictingDeclaration || HasConflictingDeclRef)
+    return None;
+
+  std::string Declaration =
+      (llvm::Twine("\nusing ") + QualifiedName + ";").str();
+
+  AddedUsing.emplace(std::make_pair(Function, QualifiedName.str()));
+  return FixItHint::CreateInsertion(InsertLoc, Declaration);
+}
+
+StringRef UsingInserter::getShortName(ASTContext &Context,
+                                      const Stmt &Statement,
+                                      StringRef QualifiedName) {
+  const FunctionDecl *Function = getSurroundingFunction(Context, Statement);
+  if (AddedUsing.count(NameInFunction(Function, QualifiedName.str())) != 0)
+    return getUnqualifiedName(QualifiedName);
+  return QualifiedName;
+}
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/UsingInserter.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/UsingInserter.h
new file mode 100644
index 0000000..62108e4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/utils/UsingInserter.h
@@ -0,0 +1,50 @@
+//===---------- UsingInserter.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_USINGINSERTER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_USINGINSERTER_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include <set>
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+// UsingInserter adds using declarations for |QualifiedName| to the surrounding
+// function.
+// This allows using a shorter name without clobbering other scopes.
+class UsingInserter {
+public:
+  UsingInserter(const SourceManager &SourceMgr);
+
+  // Creates a \p using declaration fixit. Returns ``llvm::None`` on error
+  // or if the using declaration already exists.
+  llvm::Optional<FixItHint>
+  createUsingDeclaration(ASTContext &Context, const Stmt &Statement,
+                         llvm::StringRef QualifiedName);
+
+  // Returns the unqualified version of the name if there is an
+  // appropriate using declaration and the qualified name otherwise.
+  llvm::StringRef getShortName(ASTContext &Context, const Stmt &Statement,
+                               llvm::StringRef QualifiedName);
+
+private:
+  typedef std::pair<const FunctionDecl *, std::string> NameInFunction;
+  const SourceManager &SourceMgr;
+  std::set<NameInFunction> AddedUsing;
+};
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_USINGINSERTER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/zircon/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/zircon/CMakeLists.txt
new file mode 100644
index 0000000..7aa7cd3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/zircon/CMakeLists.txt
@@ -0,0 +1,14 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyZirconModule
+  TemporaryObjectsCheck.cpp
+  ZirconTidyModule.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyUtils
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp
new file mode 100644
index 0000000..5fff67b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp
@@ -0,0 +1,60 @@
+//===--- TemporaryObjectsCheck.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 "TemporaryObjectsCheck.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace zircon {
+
+AST_MATCHER_P(CXXRecordDecl, matchesAnyName, ArrayRef<std::string>, Names) {
+  std::string QualifiedName = Node.getQualifiedNameAsString();
+  return llvm::any_of(Names,
+                      [&](StringRef Name) { return QualifiedName == Name; });
+}
+
+void TemporaryObjectsCheck::registerMatchers(MatchFinder *Finder) {
+  // Matcher for default constructors.
+  Finder->addMatcher(
+      cxxTemporaryObjectExpr(hasDeclaration(cxxConstructorDecl(hasParent(
+                                 cxxRecordDecl(matchesAnyName(Names))))))
+          .bind("temps"),
+      this);
+
+  // Matcher for user-defined constructors.
+  Finder->addMatcher(
+      cxxConstructExpr(allOf(hasParent(cxxFunctionalCastExpr()),
+                             hasDeclaration(cxxConstructorDecl(hasParent(
+                                 cxxRecordDecl(matchesAnyName(Names)))))))
+          .bind("temps"),
+      this);
+}
+
+void TemporaryObjectsCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *D = Result.Nodes.getNodeAs<CXXConstructExpr>("temps"))
+    diag(D->getLocation(),
+         "creating a temporary object of type %q0 is prohibited")
+        << D->getConstructor()->getParent();
+}
+
+void TemporaryObjectsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "Names", utils::options::serializeStringList(Names));
+}
+
+} // namespace zircon
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.h b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.h
new file mode 100644
index 0000000..302ef72
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.h
@@ -0,0 +1,42 @@
+//===--- TemporaryObjectsCheck.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_ZIRCON_TEMPORARYOBJECTSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ZIRCON_TEMPORARYOBJECTSCHECK_H
+
+#include "../ClangTidy.h"
+#include "../utils/OptionsUtils.h"
+
+namespace clang {
+namespace tidy {
+namespace zircon {
+
+/// Construction of specific temporary objects in the Zircon kernel is
+/// discouraged.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/zircon-temporary-objects.html
+class TemporaryObjectsCheck : public ClangTidyCheck {
+public:
+  TemporaryObjectsCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context),
+        Names(utils::options::parseStringList(Options.get("Names", ""))) {}
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  std::vector<std::string> Names;
+};
+
+} // namespace zircon
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ZIRCON_TEMPORARYOBJECTSCHECK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clang-tidy/zircon/ZirconTidyModule.cpp b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/zircon/ZirconTidyModule.cpp
new file mode 100644
index 0000000..3e53c23
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clang-tidy/zircon/ZirconTidyModule.cpp
@@ -0,0 +1,40 @@
+//===--- ZirconTidyModule.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 "TemporaryObjectsCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace zircon {
+
+/// This module is for Zircon-specific checks.
+class ZirconModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<TemporaryObjectsCheck>(
+        "zircon-temporary-objects");
+  }
+};
+
+// Register the ZirconTidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<ZirconModule>
+    X("zircon-module", "Adds Zircon kernel checks.");
+} // namespace zircon
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the ZirconModule.
+volatile int ZirconModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/AST.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/AST.cpp
new file mode 100644
index 0000000..ec1862c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/AST.cpp
@@ -0,0 +1,57 @@
+//===--- AST.cpp - Utility AST functions  -----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AST.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/Basic/SourceManager.h"
+
+namespace clang {
+namespace clangd {
+using namespace llvm;
+
+SourceLocation findNameLoc(const clang::Decl* D) {
+  const auto& SM = D->getASTContext().getSourceManager();
+  // FIXME: Revisit the strategy, the heuristic is limitted when handling
+  // macros, we should use the location where the whole definition occurs.
+  SourceLocation SpellingLoc = SM.getSpellingLoc(D->getLocation());
+  if (D->getLocation().isMacroID()) {
+    std::string PrintLoc = SpellingLoc.printToString(SM);
+    if (llvm::StringRef(PrintLoc).startswith("<scratch") ||
+        llvm::StringRef(PrintLoc).startswith("<command line>")) {
+      // We use the expansion location for the following symbols, as spelling
+      // locations of these symbols are not interesting to us:
+      //   * symbols formed via macro concatenation, the spelling location will
+      //     be "<scratch space>"
+      //   * symbols controlled and defined by a compile command-line option
+      //     `-DName=foo`, the spelling location will be "<command line>".
+      SpellingLoc = SM.getExpansionRange(D->getLocation()).getBegin();
+    }
+  }
+  return SpellingLoc;
+}
+
+std::string printQualifiedName(const NamedDecl &ND) {
+  std::string QName;
+  llvm::raw_string_ostream OS(QName);
+  PrintingPolicy Policy(ND.getASTContext().getLangOpts());
+  // Note that inline namespaces are treated as transparent scopes. This
+  // reflects the way they're most commonly used for lookup. Ideally we'd
+  // include them, but at query time it's hard to find all the inline
+  // namespaces to query: the preamble doesn't have a dedicated list.
+  Policy.SuppressUnwrittenScope = true;
+  ND.printQualifiedName(OS, Policy);
+  OS.flush();
+  assert(!StringRef(QName).startswith("::"));
+  return QName;
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/AST.h b/src/third_party/llvm-project/clang-tools-extra/clangd/AST.h
new file mode 100644
index 0000000..cb47c10
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/AST.h
@@ -0,0 +1,39 @@
+//===--- AST.h - Utility AST functions  -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Various code that examines C++ source code using AST.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_AST_H_
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_AST_H_
+
+#include "clang/AST/Decl.h"
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+class SourceManager;
+class Decl;
+
+namespace clangd {
+
+/// Find the identifier source location of the given D.
+///
+/// The returned location is usually the spelling location where the name of the
+/// decl occurs in the code.
+SourceLocation findNameLoc(const clang::Decl *D);
+
+/// Returns the qualified name of ND. The scope doesn't contain unwritten scopes
+/// like inline namespaces.
+std::string printQualifiedName(const NamedDecl &ND);
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_AST_H_
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clangd/CMakeLists.txt
new file mode 100644
index 0000000..33a6e84
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/CMakeLists.txt
@@ -0,0 +1,72 @@
+set(LLVM_LINK_COMPONENTS
+  Support
+  )
+
+set(CLANGD_ATOMIC_LIB "")
+if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
+  list(APPEND CLANGD_ATOMIC_LIB "atomic")
+endif()
+
+add_clang_library(clangDaemon
+  AST.cpp
+  ClangdLSPServer.cpp
+  ClangdServer.cpp
+  ClangdUnit.cpp
+  CodeComplete.cpp
+  CodeCompletionStrings.cpp
+  Compiler.cpp
+  Context.cpp
+  Diagnostics.cpp
+  DraftStore.cpp
+  FindSymbols.cpp
+  FileDistance.cpp
+  FuzzyMatch.cpp
+  GlobalCompilationDatabase.cpp
+  Headers.cpp
+  JSONRPCDispatcher.cpp
+  Logger.cpp
+  Protocol.cpp
+  ProtocolHandlers.cpp
+  Quality.cpp
+  SourceCode.cpp
+  Threading.cpp
+  Trace.cpp
+  TUScheduler.cpp
+  URI.cpp
+  XRefs.cpp
+
+  index/CanonicalIncludes.cpp
+  index/FileIndex.cpp
+  index/Index.cpp
+  index/MemIndex.cpp
+  index/Merge.cpp
+  index/SymbolCollector.cpp
+  index/SymbolYAML.cpp
+
+  index/dex/Iterator.cpp
+  index/dex/Trigram.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangDriver
+  clangFormat
+  clangFrontend
+  clangIndex
+  clangLex
+  clangSema
+  clangSerialization
+  clangTooling
+  clangToolingCore
+  clangToolingInclusions
+  clangToolingRefactor
+  ${LLVM_PTHREAD_LIB}
+  ${CLANGD_ATOMIC_LIB}
+  )
+
+if( LLVM_LIB_FUZZING_ENGINE OR LLVM_USE_SANITIZE_COVERAGE )
+  add_subdirectory(fuzzer)
+endif()
+add_subdirectory(tool)
+add_subdirectory(global-symbol-builder)
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdLSPServer.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdLSPServer.cpp
new file mode 100644
index 0000000..7374c6d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -0,0 +1,506 @@
+//===--- ClangdLSPServer.cpp - LSP server ------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "ClangdLSPServer.h"
+#include "Diagnostics.h"
+#include "JSONRPCDispatcher.h"
+#include "SourceCode.h"
+#include "URI.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang::clangd;
+using namespace clang;
+using namespace llvm;
+
+namespace {
+
+/// \brief Supports a test URI scheme with relaxed constraints for lit tests.
+/// The path in a test URI will be combined with a platform-specific fake
+/// directory to form an absolute path. For example, test:///a.cpp is resolved
+/// C:\clangd-test\a.cpp on Windows and /clangd-test/a.cpp on Unix.
+class TestScheme : public URIScheme {
+public:
+  llvm::Expected<std::string>
+  getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body,
+                  llvm::StringRef /*HintPath*/) const override {
+    using namespace llvm::sys;
+    // Still require "/" in body to mimic file scheme, as we want lengths of an
+    // equivalent URI in both schemes to be the same.
+    if (!Body.startswith("/"))
+      return llvm::make_error<llvm::StringError>(
+          "Expect URI body to be an absolute path starting with '/': " + Body,
+          llvm::inconvertibleErrorCode());
+    Body = Body.ltrim('/');
+#ifdef _WIN32
+    constexpr char TestDir[] = "C:\\clangd-test";
+#else
+    constexpr char TestDir[] = "/clangd-test";
+#endif
+    llvm::SmallVector<char, 16> Path(Body.begin(), Body.end());
+    path::native(Path);
+    auto Err = fs::make_absolute(TestDir, Path);
+    if (Err)
+      llvm_unreachable("Failed to make absolute path in test scheme.");
+    return std::string(Path.begin(), Path.end());
+  }
+
+  llvm::Expected<URI>
+  uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override {
+    llvm_unreachable("Clangd must never create a test URI.");
+  }
+};
+
+static URISchemeRegistry::Add<TestScheme>
+    X("test", "Test scheme for clangd lit tests.");
+
+SymbolKindBitset defaultSymbolKinds() {
+  SymbolKindBitset Defaults;
+  for (size_t I = SymbolKindMin; I <= static_cast<size_t>(SymbolKind::Array);
+       ++I)
+    Defaults.set(I);
+  return Defaults;
+}
+
+} // namespace
+
+void ClangdLSPServer::onInitialize(InitializeParams &Params) {
+  if (Params.initializationOptions)
+    applyConfiguration(*Params.initializationOptions);
+
+  if (Params.rootUri && *Params.rootUri)
+    Server.setRootPath(Params.rootUri->file());
+  else if (Params.rootPath && !Params.rootPath->empty())
+    Server.setRootPath(*Params.rootPath);
+
+  CCOpts.EnableSnippets =
+      Params.capabilities.textDocument.completion.completionItem.snippetSupport;
+
+  if (Params.capabilities.workspace && Params.capabilities.workspace->symbol &&
+      Params.capabilities.workspace->symbol->symbolKind) {
+    for (SymbolKind Kind :
+         *Params.capabilities.workspace->symbol->symbolKind->valueSet) {
+      SupportedSymbolKinds.set(static_cast<size_t>(Kind));
+    }
+  }
+
+  reply(json::Object{
+      {{"capabilities",
+        json::Object{
+            {"textDocumentSync", (int)TextDocumentSyncKind::Incremental},
+            {"documentFormattingProvider", true},
+            {"documentRangeFormattingProvider", true},
+            {"documentOnTypeFormattingProvider",
+             json::Object{
+                 {"firstTriggerCharacter", "}"},
+                 {"moreTriggerCharacter", {}},
+             }},
+            {"codeActionProvider", true},
+            {"completionProvider",
+             json::Object{
+                 {"resolveProvider", false},
+                 {"triggerCharacters", {".", ">", ":"}},
+             }},
+            {"signatureHelpProvider",
+             json::Object{
+                 {"triggerCharacters", {"(", ","}},
+             }},
+            {"definitionProvider", true},
+            {"documentHighlightProvider", true},
+            {"hoverProvider", true},
+            {"renameProvider", true},
+            {"documentSymbolProvider", true},
+            {"workspaceSymbolProvider", true},
+            {"executeCommandProvider",
+             json::Object{
+                 {"commands", {ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND}},
+             }},
+        }}}});
+}
+
+void ClangdLSPServer::onShutdown(ShutdownParams &Params) {
+  // Do essentially nothing, just say we're ready to exit.
+  ShutdownRequestReceived = true;
+  reply(nullptr);
+}
+
+void ClangdLSPServer::onExit(ExitParams &Params) { IsDone = true; }
+
+void ClangdLSPServer::onDocumentDidOpen(DidOpenTextDocumentParams &Params) {
+  PathRef File = Params.textDocument.uri.file();
+  if (Params.metadata && !Params.metadata->extraFlags.empty()) {
+    NonCachedCDB.setExtraFlagsForFile(File,
+                                      std::move(Params.metadata->extraFlags));
+    CDB.invalidate(File);
+  }
+
+  std::string &Contents = Params.textDocument.text;
+
+  DraftMgr.addDraft(File, Contents);
+  Server.addDocument(File, Contents, WantDiagnostics::Yes);
+}
+
+void ClangdLSPServer::onDocumentDidChange(DidChangeTextDocumentParams &Params) {
+  auto WantDiags = WantDiagnostics::Auto;
+  if (Params.wantDiagnostics.hasValue())
+    WantDiags = Params.wantDiagnostics.getValue() ? WantDiagnostics::Yes
+                                                  : WantDiagnostics::No;
+
+  PathRef File = Params.textDocument.uri.file();
+  llvm::Expected<std::string> Contents =
+      DraftMgr.updateDraft(File, Params.contentChanges);
+  if (!Contents) {
+    // If this fails, we are most likely going to be not in sync anymore with
+    // the client.  It is better to remove the draft and let further operations
+    // fail rather than giving wrong results.
+    DraftMgr.removeDraft(File);
+    Server.removeDocument(File);
+    CDB.invalidate(File);
+    elog("Failed to update {0}: {1}", File, Contents.takeError());
+    return;
+  }
+
+  Server.addDocument(File, *Contents, WantDiags);
+}
+
+void ClangdLSPServer::onFileEvent(DidChangeWatchedFilesParams &Params) {
+  Server.onFileEvent(Params);
+}
+
+void ClangdLSPServer::onCommand(ExecuteCommandParams &Params) {
+  auto ApplyEdit = [](WorkspaceEdit WE) {
+    ApplyWorkspaceEditParams Edit;
+    Edit.edit = std::move(WE);
+    // We don't need the response so id == 1 is OK.
+    // Ideally, we would wait for the response and if there is no error, we
+    // would reply success/failure to the original RPC.
+    call("workspace/applyEdit", Edit);
+  };
+  if (Params.command == ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND &&
+      Params.workspaceEdit) {
+    // The flow for "apply-fix" :
+    // 1. We publish a diagnostic, including fixits
+    // 2. The user clicks on the diagnostic, the editor asks us for code actions
+    // 3. We send code actions, with the fixit embedded as context
+    // 4. The user selects the fixit, the editor asks us to apply it
+    // 5. We unwrap the changes and send them back to the editor
+    // 6. The editor applies the changes (applyEdit), and sends us a reply (but
+    // we ignore it)
+
+    reply("Fix applied.");
+    ApplyEdit(*Params.workspaceEdit);
+  } else {
+    // We should not get here because ExecuteCommandParams would not have
+    // parsed in the first place and this handler should not be called. But if
+    // more commands are added, this will be here has a safe guard.
+    replyError(
+        ErrorCode::InvalidParams,
+        llvm::formatv("Unsupported command \"{0}\".", Params.command).str());
+  }
+}
+
+void ClangdLSPServer::onWorkspaceSymbol(WorkspaceSymbolParams &Params) {
+  Server.workspaceSymbols(
+      Params.query, CCOpts.Limit,
+      [this](llvm::Expected<std::vector<SymbolInformation>> Items) {
+        if (!Items)
+          return replyError(ErrorCode::InternalError,
+                            llvm::toString(Items.takeError()));
+        for (auto &Sym : *Items)
+          Sym.kind = adjustKindToCapability(Sym.kind, SupportedSymbolKinds);
+
+        reply(json::Array(*Items));
+      });
+}
+
+void ClangdLSPServer::onRename(RenameParams &Params) {
+  Path File = Params.textDocument.uri.file();
+  llvm::Optional<std::string> Code = DraftMgr.getDraft(File);
+  if (!Code)
+    return replyError(ErrorCode::InvalidParams,
+                      "onRename called for non-added file");
+
+  Server.rename(
+      File, Params.position, Params.newName,
+      [File, Code,
+       Params](llvm::Expected<std::vector<tooling::Replacement>> Replacements) {
+        if (!Replacements)
+          return replyError(ErrorCode::InternalError,
+                            llvm::toString(Replacements.takeError()));
+
+        // Turn the replacements into the format specified by the Language
+        // Server Protocol. Fuse them into one big JSON array.
+        std::vector<TextEdit> Edits;
+        for (const auto &R : *Replacements)
+          Edits.push_back(replacementToEdit(*Code, R));
+        WorkspaceEdit WE;
+        WE.changes = {{Params.textDocument.uri.uri(), Edits}};
+        reply(WE);
+      });
+}
+
+void ClangdLSPServer::onDocumentDidClose(DidCloseTextDocumentParams &Params) {
+  PathRef File = Params.textDocument.uri.file();
+  DraftMgr.removeDraft(File);
+  Server.removeDocument(File);
+}
+
+void ClangdLSPServer::onDocumentOnTypeFormatting(
+    DocumentOnTypeFormattingParams &Params) {
+  auto File = Params.textDocument.uri.file();
+  auto Code = DraftMgr.getDraft(File);
+  if (!Code)
+    return replyError(ErrorCode::InvalidParams,
+                      "onDocumentOnTypeFormatting called for non-added file");
+
+  auto ReplacementsOrError = Server.formatOnType(*Code, File, Params.position);
+  if (ReplacementsOrError)
+    reply(json::Array(replacementsToEdits(*Code, ReplacementsOrError.get())));
+  else
+    replyError(ErrorCode::UnknownErrorCode,
+               llvm::toString(ReplacementsOrError.takeError()));
+}
+
+void ClangdLSPServer::onDocumentRangeFormatting(
+    DocumentRangeFormattingParams &Params) {
+  auto File = Params.textDocument.uri.file();
+  auto Code = DraftMgr.getDraft(File);
+  if (!Code)
+    return replyError(ErrorCode::InvalidParams,
+                      "onDocumentRangeFormatting called for non-added file");
+
+  auto ReplacementsOrError = Server.formatRange(*Code, File, Params.range);
+  if (ReplacementsOrError)
+    reply(json::Array(replacementsToEdits(*Code, ReplacementsOrError.get())));
+  else
+    replyError(ErrorCode::UnknownErrorCode,
+               llvm::toString(ReplacementsOrError.takeError()));
+}
+
+void ClangdLSPServer::onDocumentFormatting(DocumentFormattingParams &Params) {
+  auto File = Params.textDocument.uri.file();
+  auto Code = DraftMgr.getDraft(File);
+  if (!Code)
+    return replyError(ErrorCode::InvalidParams,
+                      "onDocumentFormatting called for non-added file");
+
+  auto ReplacementsOrError = Server.formatFile(*Code, File);
+  if (ReplacementsOrError)
+    reply(json::Array(replacementsToEdits(*Code, ReplacementsOrError.get())));
+  else
+    replyError(ErrorCode::UnknownErrorCode,
+               llvm::toString(ReplacementsOrError.takeError()));
+}
+
+void ClangdLSPServer::onDocumentSymbol(DocumentSymbolParams &Params) {
+  Server.documentSymbols(
+      Params.textDocument.uri.file(),
+      [this](llvm::Expected<std::vector<SymbolInformation>> Items) {
+        if (!Items)
+          return replyError(ErrorCode::InvalidParams,
+                            llvm::toString(Items.takeError()));
+        for (auto &Sym : *Items)
+          Sym.kind = adjustKindToCapability(Sym.kind, SupportedSymbolKinds);
+        reply(json::Array(*Items));
+      });
+}
+
+void ClangdLSPServer::onCodeAction(CodeActionParams &Params) {
+  // We provide a code action for each diagnostic at the requested location
+  // which has FixIts available.
+  auto Code = DraftMgr.getDraft(Params.textDocument.uri.file());
+  if (!Code)
+    return replyError(ErrorCode::InvalidParams,
+                      "onCodeAction called for non-added file");
+
+  json::Array Commands;
+  for (Diagnostic &D : Params.context.diagnostics) {
+    for (auto &F : getFixes(Params.textDocument.uri.file(), D)) {
+      WorkspaceEdit WE;
+      std::vector<TextEdit> Edits(F.Edits.begin(), F.Edits.end());
+      WE.changes = {{Params.textDocument.uri.uri(), std::move(Edits)}};
+      Commands.push_back(json::Object{
+          {"title", llvm::formatv("Apply fix: {0}", F.Message)},
+          {"command", ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND},
+          {"arguments", {WE}},
+      });
+    }
+  }
+  reply(std::move(Commands));
+}
+
+void ClangdLSPServer::onCompletion(TextDocumentPositionParams &Params) {
+  Server.codeComplete(Params.textDocument.uri.file(), Params.position, CCOpts,
+                      [this](llvm::Expected<CodeCompleteResult> List) {
+                        if (!List)
+                          return replyError(ErrorCode::InvalidParams,
+                                            llvm::toString(List.takeError()));
+                        CompletionList LSPList;
+                        LSPList.isIncomplete = List->HasMore;
+                        for (const auto &R : List->Completions)
+                          LSPList.items.push_back(R.render(CCOpts));
+                        reply(std::move(LSPList));
+                      });
+}
+
+void ClangdLSPServer::onSignatureHelp(TextDocumentPositionParams &Params) {
+  Server.signatureHelp(Params.textDocument.uri.file(), Params.position,
+                       [](llvm::Expected<SignatureHelp> SignatureHelp) {
+                         if (!SignatureHelp)
+                           return replyError(
+                               ErrorCode::InvalidParams,
+                               llvm::toString(SignatureHelp.takeError()));
+                         reply(*SignatureHelp);
+                       });
+}
+
+void ClangdLSPServer::onGoToDefinition(TextDocumentPositionParams &Params) {
+  Server.findDefinitions(
+      Params.textDocument.uri.file(), Params.position,
+      [](llvm::Expected<std::vector<Location>> Items) {
+        if (!Items)
+          return replyError(ErrorCode::InvalidParams,
+                            llvm::toString(Items.takeError()));
+        reply(json::Array(*Items));
+      });
+}
+
+void ClangdLSPServer::onSwitchSourceHeader(TextDocumentIdentifier &Params) {
+  llvm::Optional<Path> Result = Server.switchSourceHeader(Params.uri.file());
+  reply(Result ? URI::createFile(*Result).toString() : "");
+}
+
+void ClangdLSPServer::onDocumentHighlight(TextDocumentPositionParams &Params) {
+  Server.findDocumentHighlights(
+      Params.textDocument.uri.file(), Params.position,
+      [](llvm::Expected<std::vector<DocumentHighlight>> Highlights) {
+        if (!Highlights)
+          return replyError(ErrorCode::InternalError,
+                            llvm::toString(Highlights.takeError()));
+        reply(json::Array(*Highlights));
+      });
+}
+
+void ClangdLSPServer::onHover(TextDocumentPositionParams &Params) {
+  Server.findHover(Params.textDocument.uri.file(), Params.position,
+                   [](llvm::Expected<llvm::Optional<Hover>> H) {
+                     if (!H) {
+                       replyError(ErrorCode::InternalError,
+                                  llvm::toString(H.takeError()));
+                       return;
+                     }
+
+                     reply(*H);
+                   });
+}
+
+void ClangdLSPServer::applyConfiguration(
+    const ClangdConfigurationParamsChange &Settings) {
+  // Compilation database change.
+  if (Settings.compilationDatabasePath.hasValue()) {
+    NonCachedCDB.setCompileCommandsDir(
+        Settings.compilationDatabasePath.getValue());
+    CDB.clear();
+
+    reparseOpenedFiles();
+  }
+}
+
+// FIXME: This function needs to be properly tested.
+void ClangdLSPServer::onChangeConfiguration(
+    DidChangeConfigurationParams &Params) {
+  applyConfiguration(Params.settings);
+}
+
+ClangdLSPServer::ClangdLSPServer(JSONOutput &Out,
+                                 const clangd::CodeCompleteOptions &CCOpts,
+                                 llvm::Optional<Path> CompileCommandsDir,
+                                 const ClangdServer::Options &Opts)
+    : Out(Out), NonCachedCDB(std::move(CompileCommandsDir)), CDB(NonCachedCDB),
+      CCOpts(CCOpts), SupportedSymbolKinds(defaultSymbolKinds()),
+      Server(CDB, FSProvider, /*DiagConsumer=*/*this, Opts) {}
+
+bool ClangdLSPServer::run(std::FILE *In, JSONStreamStyle InputStyle) {
+  assert(!IsDone && "Run was called before");
+
+  // Set up JSONRPCDispatcher.
+  JSONRPCDispatcher Dispatcher([](const json::Value &Params) {
+    replyError(ErrorCode::MethodNotFound, "method not found");
+  });
+  registerCallbackHandlers(Dispatcher, /*Callbacks=*/*this);
+
+  // Run the Language Server loop.
+  runLanguageServerLoop(In, Out, InputStyle, Dispatcher, IsDone);
+
+  // Make sure IsDone is set to true after this method exits to ensure assertion
+  // at the start of the method fires if it's ever executed again.
+  IsDone = true;
+
+  return ShutdownRequestReceived;
+}
+
+std::vector<Fix> ClangdLSPServer::getFixes(StringRef File,
+                                           const clangd::Diagnostic &D) {
+  std::lock_guard<std::mutex> Lock(FixItsMutex);
+  auto DiagToFixItsIter = FixItsMap.find(File);
+  if (DiagToFixItsIter == FixItsMap.end())
+    return {};
+
+  const auto &DiagToFixItsMap = DiagToFixItsIter->second;
+  auto FixItsIter = DiagToFixItsMap.find(D);
+  if (FixItsIter == DiagToFixItsMap.end())
+    return {};
+
+  return FixItsIter->second;
+}
+
+void ClangdLSPServer::onDiagnosticsReady(PathRef File,
+                                         std::vector<Diag> Diagnostics) {
+  json::Array DiagnosticsJSON;
+
+  DiagnosticToReplacementMap LocalFixIts; // Temporary storage
+  for (auto &Diag : Diagnostics) {
+    toLSPDiags(Diag, [&](clangd::Diagnostic Diag, llvm::ArrayRef<Fix> Fixes) {
+      DiagnosticsJSON.push_back(json::Object{
+          {"range", Diag.range},
+          {"severity", Diag.severity},
+          {"message", Diag.message},
+      });
+
+      auto &FixItsForDiagnostic = LocalFixIts[Diag];
+      std::copy(Fixes.begin(), Fixes.end(),
+                std::back_inserter(FixItsForDiagnostic));
+    });
+  }
+
+  // Cache FixIts
+  {
+    // FIXME(ibiryukov): should be deleted when documents are removed
+    std::lock_guard<std::mutex> Lock(FixItsMutex);
+    FixItsMap[File] = LocalFixIts;
+  }
+
+  // Publish diagnostics.
+  Out.writeMessage(json::Object{
+      {"jsonrpc", "2.0"},
+      {"method", "textDocument/publishDiagnostics"},
+      {"params",
+       json::Object{
+           {"uri", URIForFile{File}},
+           {"diagnostics", std::move(DiagnosticsJSON)},
+       }},
+  });
+}
+
+void ClangdLSPServer::reparseOpenedFiles() {
+  for (const Path &FilePath : DraftMgr.getActiveFiles())
+    Server.addDocument(FilePath, *DraftMgr.getDraft(FilePath),
+                       WantDiagnostics::Auto);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdLSPServer.h b/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdLSPServer.h
new file mode 100644
index 0000000..644e762
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdLSPServer.h
@@ -0,0 +1,126 @@
+//===--- ClangdLSPServer.h - LSP server --------------------------*- 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_CLANGDLSPSERVER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDLSPSERVER_H
+
+#include "ClangdServer.h"
+#include "DraftStore.h"
+#include "FindSymbols.h"
+#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 {
+
+class JSONOutput;
+class SymbolIndex;
+
+/// This class provides implementation of an LSP server, glueing the JSON
+/// dispatch and ClangdServer together.
+class ClangdLSPServer : private DiagnosticsConsumer, private ProtocolCallbacks {
+public:
+  /// 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, const clangd::CodeCompleteOptions &CCOpts,
+                  llvm::Optional<Path> CompileCommandsDir,
+                  const ClangdServer::Options &Opts);
+
+  /// 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
+  /// class constructor. This method must not be executed more than once for
+  /// each instance of ClangdLSPServer.
+  ///
+  /// \return Whether we received a 'shutdown' request before an 'exit' request.
+  bool run(std::FILE *In,
+           JSONStreamStyle InputStyle = JSONStreamStyle::Standard);
+
+private:
+  // Implement DiagnosticsConsumer.
+  void onDiagnosticsReady(PathRef File, std::vector<Diag> Diagnostics) override;
+
+  // Implement ProtocolCallbacks.
+  void onInitialize(InitializeParams &Params) override;
+  void onShutdown(ShutdownParams &Params) override;
+  void onExit(ExitParams &Params) override;
+  void onDocumentDidOpen(DidOpenTextDocumentParams &Params) override;
+  void onDocumentDidChange(DidChangeTextDocumentParams &Params) override;
+  void onDocumentDidClose(DidCloseTextDocumentParams &Params) override;
+  void
+  onDocumentOnTypeFormatting(DocumentOnTypeFormattingParams &Params) override;
+  void
+  onDocumentRangeFormatting(DocumentRangeFormattingParams &Params) override;
+  void onDocumentFormatting(DocumentFormattingParams &Params) override;
+  void onDocumentSymbol(DocumentSymbolParams &Params) override;
+  void onCodeAction(CodeActionParams &Params) override;
+  void onCompletion(TextDocumentPositionParams &Params) override;
+  void onSignatureHelp(TextDocumentPositionParams &Params) override;
+  void onGoToDefinition(TextDocumentPositionParams &Params) override;
+  void onSwitchSourceHeader(TextDocumentIdentifier &Params) override;
+  void onDocumentHighlight(TextDocumentPositionParams &Params) override;
+  void onFileEvent(DidChangeWatchedFilesParams &Params) override;
+  void onCommand(ExecuteCommandParams &Params) override;
+  void onWorkspaceSymbol(WorkspaceSymbolParams &Params) override;
+  void onRename(RenameParams &Parames) override;
+  void onHover(TextDocumentPositionParams &Params) override;
+  void onChangeConfiguration(DidChangeConfigurationParams &Params) override;
+
+  std::vector<Fix> getFixes(StringRef File, const clangd::Diagnostic &D);
+
+  /// Forces a reparse of all currently opened files.  As a result, this method
+  /// may be very expensive.  This method is normally called when the
+  /// compilation database is changed.
+  void reparseOpenedFiles();
+  void applyConfiguration(const ClangdConfigurationParamsChange &Settings);
+
+  JSONOutput &Out;
+  /// Used to indicate that the 'shutdown' request was received from the
+  /// Language Server client.
+  bool ShutdownRequestReceived = false;
+
+  /// Used to indicate that the 'exit' notification was received from the
+  /// Language Server client.
+  /// It's used to break out of the LSP parsing loop.
+  bool IsDone = false;
+
+  std::mutex FixItsMutex;
+  typedef std::map<clangd::Diagnostic, std::vector<Fix>, LSPDiagnosticCompare>
+      DiagnosticToReplacementMap;
+  /// Caches FixIts per file and diagnostics
+  llvm::StringMap<DiagnosticToReplacementMap> FixItsMap;
+
+  // Various ClangdServer parameters go here. It's important they're created
+  // before ClangdServer.
+  DirectoryBasedGlobalCompilationDatabase NonCachedCDB;
+  CachingCompilationDb CDB;
+
+  RealFileSystemProvider FSProvider;
+  /// Options used for code completion
+  clangd::CodeCompleteOptions CCOpts;
+  /// The supported kinds of the client.
+  SymbolKindBitset SupportedSymbolKinds;
+
+  // Store of the current versions of the open documents.
+  DraftStore DraftMgr;
+
+  // Server must be the last member of the class to allow its destructor to exit
+  // the worker thread that may otherwise run an async callback on partially
+  // destructed instance of ClangdLSPServer.
+  ClangdServer Server;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdServer.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdServer.cpp
new file mode 100644
index 0000000..01cc823
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdServer.cpp
@@ -0,0 +1,475 @@
+//===--- ClangdServer.cpp - Main clangd server code --------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===-------------------------------------------------------------------===//
+
+#include "ClangdServer.h"
+#include "CodeComplete.h"
+#include "FindSymbols.h"
+#include "Headers.h"
+#include "SourceCode.h"
+#include "XRefs.h"
+#include "index/Merge.h"
+#include "clang/Format/Format.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Refactoring/RefactoringResultConsumer.h"
+#include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include <future>
+
+using namespace clang;
+using namespace clang::clangd;
+
+namespace {
+
+void ignoreError(llvm::Error Err) {
+  handleAllErrors(std::move(Err), [](const llvm::ErrorInfoBase &) {});
+}
+
+std::string getStandardResourceDir() {
+  static int Dummy; // Just an address in this process.
+  return CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy);
+}
+
+class RefactoringResultCollector final
+    : public tooling::RefactoringResultConsumer {
+public:
+  void handleError(llvm::Error Err) override {
+    assert(!Result.hasValue());
+    // FIXME: figure out a way to return better message for DiagnosticError.
+    // clangd uses llvm::toString to convert the Err to string, however, for
+    // DiagnosticError, only "clang diagnostic" will be generated.
+    Result = std::move(Err);
+  }
+
+  // Using the handle(SymbolOccurrences) from parent class.
+  using tooling::RefactoringResultConsumer::handle;
+
+  void handle(tooling::AtomicChanges SourceReplacements) override {
+    assert(!Result.hasValue());
+    Result = std::move(SourceReplacements);
+  }
+
+  Optional<Expected<tooling::AtomicChanges>> Result;
+};
+
+} // namespace
+
+ClangdServer::Options ClangdServer::optsForTest() {
+  ClangdServer::Options Opts;
+  Opts.UpdateDebounce = std::chrono::steady_clock::duration::zero(); // Faster!
+  Opts.StorePreamblesInMemory = true;
+  Opts.AsyncThreadsCount = 4; // Consistent!
+  return Opts;
+}
+
+ClangdServer::ClangdServer(GlobalCompilationDatabase &CDB,
+                           FileSystemProvider &FSProvider,
+                           DiagnosticsConsumer &DiagConsumer,
+                           const Options &Opts)
+    : CDB(CDB), DiagConsumer(DiagConsumer), FSProvider(FSProvider),
+      ResourceDir(Opts.ResourceDir ? Opts.ResourceDir->str()
+                                   : getStandardResourceDir()),
+      FileIdx(Opts.BuildDynamicSymbolIndex ? new FileIndex(Opts.URISchemes)
+                                           : nullptr),
+      PCHs(std::make_shared<PCHContainerOperations>()),
+      // Pass a callback into `WorkScheduler` to extract symbols from a newly
+      // parsed file and rebuild the file index synchronously each time an AST
+      // is parsed.
+      // FIXME(ioeric): this can be slow and we may be able to index on less
+      // critical paths.
+      WorkScheduler(
+          Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
+          FileIdx
+              ? [this](PathRef Path, ASTContext &AST,
+                       std::shared_ptr<Preprocessor>
+                           PP) { FileIdx->update(Path, &AST, std::move(PP)); }
+              : PreambleParsedCallback(),
+          Opts.UpdateDebounce, Opts.RetentionPolicy) {
+  if (FileIdx && Opts.StaticIndex) {
+    MergedIndex = mergeIndex(FileIdx.get(), Opts.StaticIndex);
+    Index = MergedIndex.get();
+  } else if (FileIdx)
+    Index = FileIdx.get();
+  else if (Opts.StaticIndex)
+    Index = Opts.StaticIndex;
+  else
+    Index = nullptr;
+}
+
+void ClangdServer::setRootPath(PathRef RootPath) {
+  auto FS = FSProvider.getFileSystem();
+  auto Status = FS->status(RootPath);
+  if (!Status)
+    elog("Failed to get status for RootPath {0}: {1}", RootPath,
+         Status.getError().message());
+  else if (Status->isDirectory())
+    this->RootPath = RootPath;
+  else
+    elog("The provided RootPath {0} is not a directory.", RootPath);
+}
+
+void ClangdServer::addDocument(PathRef File, StringRef Contents,
+                               WantDiagnostics WantDiags) {
+  DocVersion Version = ++InternalVersion[File];
+  ParseInputs Inputs = {getCompileCommand(File), FSProvider.getFileSystem(),
+                        Contents.str()};
+
+  Path FileStr = File.str();
+  WorkScheduler.update(File, std::move(Inputs), WantDiags,
+                       [this, FileStr, Version](std::vector<Diag> Diags) {
+                         consumeDiagnostics(FileStr, Version, std::move(Diags));
+                       });
+}
+
+void ClangdServer::removeDocument(PathRef File) {
+  ++InternalVersion[File];
+  WorkScheduler.remove(File);
+}
+
+void ClangdServer::codeComplete(PathRef File, Position Pos,
+                                const clangd::CodeCompleteOptions &Opts,
+                                Callback<CodeCompleteResult> CB) {
+  // Copy completion options for passing them to async task handler.
+  auto CodeCompleteOpts = Opts;
+  if (!CodeCompleteOpts.Index) // Respect overridden index.
+    CodeCompleteOpts.Index = Index;
+
+  // Copy PCHs to avoid accessing this->PCHs concurrently
+  std::shared_ptr<PCHContainerOperations> PCHs = this->PCHs;
+  auto FS = FSProvider.getFileSystem();
+  auto Task = [PCHs, Pos, FS,
+               CodeCompleteOpts](Path File, Callback<CodeCompleteResult> CB,
+                                 llvm::Expected<InputsAndPreamble> IP) {
+    if (!IP)
+      return CB(IP.takeError());
+
+    auto PreambleData = IP->Preamble;
+
+    // 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.
+    CodeCompleteResult Result = clangd::codeComplete(
+        File, IP->Command, PreambleData ? &PreambleData->Preamble : nullptr,
+        PreambleData ? PreambleData->Includes : IncludeStructure(),
+        IP->Contents, Pos, FS, PCHs, CodeCompleteOpts);
+    CB(std::move(Result));
+  };
+
+  WorkScheduler.runWithPreamble("CodeComplete", File,
+                                Bind(Task, File.str(), std::move(CB)));
+}
+
+void ClangdServer::signatureHelp(PathRef File, Position Pos,
+                                 Callback<SignatureHelp> CB) {
+
+  auto PCHs = this->PCHs;
+  auto FS = FSProvider.getFileSystem();
+  auto Action = [Pos, FS, PCHs](Path File, Callback<SignatureHelp> CB,
+                                llvm::Expected<InputsAndPreamble> IP) {
+    if (!IP)
+      return CB(IP.takeError());
+
+    auto PreambleData = IP->Preamble;
+    CB(clangd::signatureHelp(File, IP->Command,
+                             PreambleData ? &PreambleData->Preamble : nullptr,
+                             IP->Contents, Pos, FS, PCHs));
+  };
+
+  WorkScheduler.runWithPreamble("SignatureHelp", File,
+                                Bind(Action, File.str(), std::move(CB)));
+}
+
+llvm::Expected<tooling::Replacements>
+ClangdServer::formatRange(StringRef Code, PathRef File, Range Rng) {
+  llvm::Expected<size_t> Begin = positionToOffset(Code, Rng.start);
+  if (!Begin)
+    return Begin.takeError();
+  llvm::Expected<size_t> End = positionToOffset(Code, Rng.end);
+  if (!End)
+    return End.takeError();
+  return formatCode(Code, File, {tooling::Range(*Begin, *End - *Begin)});
+}
+
+llvm::Expected<tooling::Replacements> ClangdServer::formatFile(StringRef Code,
+                                                               PathRef File) {
+  // Format everything.
+  return formatCode(Code, File, {tooling::Range(0, Code.size())});
+}
+
+llvm::Expected<tooling::Replacements>
+ClangdServer::formatOnType(StringRef Code, PathRef File, Position Pos) {
+  // Look for the previous opening brace from the character position and
+  // format starting from there.
+  llvm::Expected<size_t> CursorPos = positionToOffset(Code, Pos);
+  if (!CursorPos)
+    return CursorPos.takeError();
+  size_t PreviousLBracePos = StringRef(Code).find_last_of('{', *CursorPos);
+  if (PreviousLBracePos == StringRef::npos)
+    PreviousLBracePos = *CursorPos;
+  size_t Len = *CursorPos - PreviousLBracePos;
+
+  return formatCode(Code, File, {tooling::Range(PreviousLBracePos, Len)});
+}
+
+void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
+                          Callback<std::vector<tooling::Replacement>> CB) {
+  auto Action = [Pos](Path File, std::string NewName,
+                      Callback<std::vector<tooling::Replacement>> CB,
+                      Expected<InputsAndAST> InpAST) {
+    if (!InpAST)
+      return CB(InpAST.takeError());
+    auto &AST = InpAST->AST;
+
+    RefactoringResultCollector ResultCollector;
+    const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
+    SourceLocation SourceLocationBeg =
+        clangd::getBeginningOfIdentifier(AST, Pos, SourceMgr.getMainFileID());
+    tooling::RefactoringRuleContext Context(
+        AST.getASTContext().getSourceManager());
+    Context.setASTContext(AST.getASTContext());
+    auto Rename = clang::tooling::RenameOccurrences::initiate(
+        Context, SourceRange(SourceLocationBeg), NewName);
+    if (!Rename)
+      return CB(Rename.takeError());
+
+    Rename->invoke(ResultCollector, Context);
+
+    assert(ResultCollector.Result.hasValue());
+    if (!ResultCollector.Result.getValue())
+      return CB(ResultCollector.Result->takeError());
+
+    std::vector<tooling::Replacement> Replacements;
+    for (const tooling::AtomicChange &Change : ResultCollector.Result->get()) {
+      tooling::Replacements ChangeReps = Change.getReplacements();
+      for (const auto &Rep : ChangeReps) {
+        // FIXME: Right now we only support renaming the main file, so we
+        // drop replacements not for the main file. In the future, we might
+        // consider to support:
+        //   * rename in any included header
+        //   * rename only in the "main" header
+        //   * provide an error if there are symbols we won't rename (e.g.
+        //     std::vector)
+        //   * rename globally in project
+        //   * rename in open files
+        if (Rep.getFilePath() == File)
+          Replacements.push_back(Rep);
+      }
+    }
+    return CB(std::move(Replacements));
+  };
+
+  WorkScheduler.runWithAST(
+      "Rename", File, Bind(Action, File.str(), NewName.str(), std::move(CB)));
+}
+
+void ClangdServer::dumpAST(PathRef File,
+                           llvm::unique_function<void(std::string)> Callback) {
+  auto Action = [](decltype(Callback) Callback,
+                   llvm::Expected<InputsAndAST> InpAST) {
+    if (!InpAST) {
+      ignoreError(InpAST.takeError());
+      return Callback("<no-ast>");
+    }
+    std::string Result;
+
+    llvm::raw_string_ostream ResultOS(Result);
+    clangd::dumpAST(InpAST->AST, ResultOS);
+    ResultOS.flush();
+
+    Callback(Result);
+  };
+
+  WorkScheduler.runWithAST("DumpAST", File, Bind(Action, std::move(Callback)));
+}
+
+void ClangdServer::findDefinitions(PathRef File, Position Pos,
+                                   Callback<std::vector<Location>> CB) {
+  auto Action = [Pos, this](Callback<std::vector<Location>> CB,
+                            llvm::Expected<InputsAndAST> InpAST) {
+    if (!InpAST)
+      return CB(InpAST.takeError());
+    CB(clangd::findDefinitions(InpAST->AST, Pos, Index));
+  };
+
+  WorkScheduler.runWithAST("Definitions", File, Bind(Action, std::move(CB)));
+}
+
+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 the 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.getFileSystem();
+
+  // 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;
+}
+
+llvm::Expected<tooling::Replacements>
+ClangdServer::formatCode(llvm::StringRef Code, PathRef File,
+                         ArrayRef<tooling::Range> Ranges) {
+  // Call clang-format.
+  auto FS = FSProvider.getFileSystem();
+  auto Style = format::getStyle(format::DefaultFormatStyle, File,
+                                format::DefaultFallbackStyle, Code, FS.get());
+  if (!Style)
+    return Style.takeError();
+
+  tooling::Replacements IncludeReplaces =
+      format::sortIncludes(*Style, Code, Ranges, File);
+  auto Changed = tooling::applyAllReplacements(Code, IncludeReplaces);
+  if (!Changed)
+    return Changed.takeError();
+
+  return IncludeReplaces.merge(format::reformat(
+      Style.get(), *Changed,
+      tooling::calculateRangesAfterReplacements(IncludeReplaces, Ranges),
+      File));
+}
+
+void ClangdServer::findDocumentHighlights(
+    PathRef File, Position Pos, Callback<std::vector<DocumentHighlight>> CB) {
+  auto Action = [Pos](Callback<std::vector<DocumentHighlight>> CB,
+                      llvm::Expected<InputsAndAST> InpAST) {
+    if (!InpAST)
+      return CB(InpAST.takeError());
+    CB(clangd::findDocumentHighlights(InpAST->AST, Pos));
+  };
+
+  WorkScheduler.runWithAST("Highlights", File, Bind(Action, std::move(CB)));
+}
+
+void ClangdServer::findHover(PathRef File, Position Pos,
+                             Callback<llvm::Optional<Hover>> CB) {
+  auto Action = [Pos](Callback<llvm::Optional<Hover>> CB,
+                      llvm::Expected<InputsAndAST> InpAST) {
+    if (!InpAST)
+      return CB(InpAST.takeError());
+    CB(clangd::getHover(InpAST->AST, Pos));
+  };
+
+  WorkScheduler.runWithAST("Hover", File, Bind(Action, std::move(CB)));
+}
+
+void ClangdServer::consumeDiagnostics(PathRef File, DocVersion Version,
+                                      std::vector<Diag> Diags) {
+  // 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[File];
+
+  // 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(File, std::move(Diags));
+}
+
+tooling::CompileCommand ClangdServer::getCompileCommand(PathRef File) {
+  llvm::Optional<tooling::CompileCommand> C = CDB.getCompileCommand(File);
+  if (!C) // FIXME: Suppress diagnostics? Let the user know?
+    C = CDB.getFallbackCommand(File);
+
+  // Inject the resource dir.
+  // FIXME: Don't overwrite it if it's already there.
+  C->CommandLine.push_back("-resource-dir=" + ResourceDir);
+  return std::move(*C);
+}
+
+void ClangdServer::onFileEvent(const DidChangeWatchedFilesParams &Params) {
+  // FIXME: Do nothing for now. This will be used for indexing and potentially
+  // invalidating other caches.
+}
+
+void ClangdServer::workspaceSymbols(
+    StringRef Query, int Limit, Callback<std::vector<SymbolInformation>> CB) {
+  CB(clangd::getWorkspaceSymbols(Query, Limit, Index,
+                                 RootPath ? *RootPath : ""));
+}
+
+void ClangdServer::documentSymbols(
+    StringRef File, Callback<std::vector<SymbolInformation>> CB) {
+  auto Action = [](Callback<std::vector<SymbolInformation>> CB,
+                   llvm::Expected<InputsAndAST> InpAST) {
+    if (!InpAST)
+      return CB(InpAST.takeError());
+    CB(clangd::getDocumentSymbols(InpAST->AST));
+  };
+  WorkScheduler.runWithAST("documentSymbols", File,
+                           Bind(Action, std::move(CB)));
+}
+
+std::vector<std::pair<Path, std::size_t>>
+ClangdServer::getUsedBytesPerFile() const {
+  return WorkScheduler.getUsedBytesPerFile();
+}
+
+LLVM_NODISCARD bool
+ClangdServer::blockUntilIdleForTest(llvm::Optional<double> TimeoutSeconds) {
+  return WorkScheduler.blockUntilIdle(timeoutSeconds(TimeoutSeconds));
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdServer.h b/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdServer.h
new file mode 100644
index 0000000..745f8c3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdServer.h
@@ -0,0 +1,246 @@
+//===--- ClangdServer.h - Main clangd server code ----------------*- 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_CLANGDSERVER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDSERVER_H
+
+#include "ClangdUnit.h"
+#include "CodeComplete.h"
+#include "FSProvider.h"
+#include "Function.h"
+#include "GlobalCompilationDatabase.h"
+#include "Protocol.h"
+#include "TUScheduler.h"
+#include "index/FileIndex.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include <functional>
+#include <future>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+namespace clang {
+class PCHContainerOperations;
+
+namespace clangd {
+
+class DiagnosticsConsumer {
+public:
+  virtual ~DiagnosticsConsumer() = default;
+
+  /// Called by ClangdServer when \p Diagnostics for \p File are ready.
+  virtual void onDiagnosticsReady(PathRef File,
+                                  std::vector<Diag> Diagnostics) = 0;
+};
+
+/// Provides API to manage ASTs for a collection of C++ files and request
+/// various language features.
+/// Currently supports async diagnostics, code completion, formatting and goto
+/// definition.
+class ClangdServer {
+public:
+  struct Options {
+    /// To process requests asynchronously, ClangdServer spawns worker threads.
+    /// If 0, all requests are processed on the calling thread.
+    unsigned AsyncThreadsCount = getDefaultAsyncThreadsCount();
+
+    /// AST caching policy. The default is to keep up to 3 ASTs in memory.
+    ASTRetentionPolicy RetentionPolicy;
+
+    /// Cached preambles are potentially large. If false, store them on disk.
+    bool StorePreamblesInMemory = true;
+
+    /// If true, ClangdServer builds a dynamic in-memory index for symbols in
+    /// opened files and uses the index to augment code completion results.
+    bool BuildDynamicSymbolIndex = false;
+
+    /// URI schemes to use when building the dynamic index.
+    /// If empty, the default schemes in SymbolCollector will be used.
+    std::vector<std::string> URISchemes;
+
+    /// If set, use this index to augment code completion results.
+    SymbolIndex *StaticIndex = nullptr;
+
+    /// The resource directory is used to find internal headers, overriding
+    /// defaults and -resource-dir compiler flag).
+    /// If None, ClangdServer calls CompilerInvocation::GetResourcePath() to
+    /// obtain the standard resource directory.
+    llvm::Optional<StringRef> ResourceDir = llvm::None;
+
+    /// Time to wait after a new file version before computing diagnostics.
+    std::chrono::steady_clock::duration UpdateDebounce =
+        std::chrono::milliseconds(500);
+  };
+  // Sensible default options for use in tests.
+  // Features like indexing must be enabled if desired.
+  static Options optsForTest();
+
+  /// Creates a new ClangdServer instance.
+  ///
+  /// 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.
+  ClangdServer(GlobalCompilationDatabase &CDB, FileSystemProvider &FSProvider,
+               DiagnosticsConsumer &DiagConsumer, const Options &Opts);
+
+  /// 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,
+                   WantDiagnostics WD = WantDiagnostics::Auto);
+
+  /// Remove \p File from list of tracked files, schedule a request to free
+  /// resources associated with it.
+  void removeDocument(PathRef File);
+
+  /// Run code completion for \p File at \p Pos.
+  /// Request is processed asynchronously.
+  ///
+  /// 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.
+  /// A version of `codeComplete` that runs \p Callback on the processing thread
+  /// when codeComplete results become available.
+  void codeComplete(PathRef File, Position Pos,
+                    const clangd::CodeCompleteOptions &Opts,
+                    Callback<CodeCompleteResult> CB);
+
+  /// Provide signature help for \p File at \p Pos.  This method should only be
+  /// called for tracked files.
+  void signatureHelp(PathRef File, Position Pos, Callback<SignatureHelp> CB);
+
+  /// Get definition of symbol at a specified \p Line and \p Column in \p File.
+  void findDefinitions(PathRef File, Position Pos,
+                       Callback<std::vector<Location>> CB);
+
+  /// 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);
+
+  /// Get document highlights for a given position.
+  void findDocumentHighlights(PathRef File, Position Pos,
+                              Callback<std::vector<DocumentHighlight>> CB);
+
+  /// Get code hover for a given position.
+  void findHover(PathRef File, Position Pos,
+                 Callback<llvm::Optional<Hover>> CB);
+
+  /// Retrieve the top symbols from the workspace matching a query.
+  void workspaceSymbols(StringRef Query, int Limit,
+                        Callback<std::vector<SymbolInformation>> CB);
+
+  /// Retrieve the symbols within the specified file.
+  void documentSymbols(StringRef File,
+                       Callback<std::vector<SymbolInformation>> CB);
+
+  /// Run formatting for \p Rng inside \p File with content \p Code.
+  llvm::Expected<tooling::Replacements> formatRange(StringRef Code,
+                                                    PathRef File, Range Rng);
+
+  /// Run formatting for the whole \p File with content \p Code.
+  llvm::Expected<tooling::Replacements> formatFile(StringRef Code,
+                                                   PathRef File);
+
+  /// Run formatting after a character was typed at \p Pos in \p File with
+  /// content \p Code.
+  llvm::Expected<tooling::Replacements>
+  formatOnType(StringRef Code, PathRef File, Position Pos);
+
+  /// Rename all occurrences of the symbol at the \p Pos in \p File to
+  /// \p NewName.
+  void rename(PathRef File, Position Pos, llvm::StringRef NewName,
+              Callback<std::vector<tooling::Replacement>> CB);
+
+  /// Only for testing purposes.
+  /// 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.
+  void dumpAST(PathRef File, llvm::unique_function<void(std::string)> Callback);
+  /// Called when an event occurs for a watched file in the workspace.
+  void onFileEvent(const DidChangeWatchedFilesParams &Params);
+
+  /// Returns estimated memory usage for each of the currently open files.
+  /// The order of results is unspecified.
+  /// Overall memory usage of clangd may be significantly more than reported
+  /// here, as this metric does not account (at least) for:
+  ///   - memory occupied by static and dynamic index,
+  ///   - memory required for in-flight requests,
+  /// FIXME: those metrics might be useful too, we should add them.
+  std::vector<std::pair<Path, std::size_t>> getUsedBytesPerFile() const;
+
+  // Blocks the main thread until the server is idle. Only for use in tests.
+  // Returns false if the timeout expires.
+  LLVM_NODISCARD bool
+  blockUntilIdleForTest(llvm::Optional<double> TimeoutSeconds = 10);
+
+private:
+  /// FIXME: This stats several files to find a .clang-format file. I/O can be
+  /// slow. Think of a way to cache this.
+  llvm::Expected<tooling::Replacements>
+  formatCode(llvm::StringRef Code, PathRef File,
+             ArrayRef<tooling::Range> Ranges);
+
+  typedef uint64_t DocVersion;
+
+  void consumeDiagnostics(PathRef File, DocVersion Version,
+                          std::vector<Diag> Diags);
+
+  tooling::CompileCommand getCompileCommand(PathRef File);
+
+  GlobalCompilationDatabase &CDB;
+  DiagnosticsConsumer &DiagConsumer;
+  FileSystemProvider &FSProvider;
+
+  /// Used to synchronize diagnostic responses for added and removed files.
+  llvm::StringMap<DocVersion> InternalVersion;
+
+  Path ResourceDir;
+  // The index used to look up symbols. This could be:
+  //   - null (all index functionality is optional)
+  //   - the dynamic index owned by ClangdServer (FileIdx)
+  //   - the static index passed to the constructor
+  //   - a merged view of a static and dynamic index (MergedIndex)
+  SymbolIndex *Index;
+  // If present, an up-to-date of symbols in open files. Read via Index.
+  std::unique_ptr<FileIndex> FileIdx;
+  // If present, a merged view of FileIdx and an external index. Read via Index.
+  std::unique_ptr<SymbolIndex> MergedIndex;
+  // If set, this represents the workspace path.
+  llvm::Optional<std::string> RootPath;
+  std::shared_ptr<PCHContainerOperations> PCHs;
+  /// 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.
+  TUScheduler WorkScheduler;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdUnit.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdUnit.cpp
new file mode 100644
index 0000000..86e7497
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdUnit.cpp
@@ -0,0 +1,407 @@
+//===--- ClangdUnit.cpp -----------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "ClangdUnit.h"
+#include "Compiler.h"
+#include "Diagnostics.h"
+#include "Logger.h"
+#include "SourceCode.h"
+#include "Trace.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/LangOptions.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/raw_ostream.h"
+#include <algorithm>
+
+using namespace clang::clangd;
+using namespace clang;
+
+namespace {
+
+bool compileCommandsAreEqual(const tooling::CompileCommand &LHS,
+                             const tooling::CompileCommand &RHS) {
+  // We don't check for Output, it should not matter to clangd.
+  return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename &&
+         llvm::makeArrayRef(LHS.CommandLine).equals(RHS.CommandLine);
+}
+
+template <class T> std::size_t getUsedBytes(const std::vector<T> &Vec) {
+  return Vec.capacity() * sizeof(T);
+}
+
+class DeclTrackingASTConsumer : public ASTConsumer {
+public:
+  DeclTrackingASTConsumer(std::vector<Decl *> &TopLevelDecls)
+      : TopLevelDecls(TopLevelDecls) {}
+
+  bool HandleTopLevelDecl(DeclGroupRef DG) override {
+    for (Decl *D : DG) {
+      // ObjCMethodDecl are not actually top-level decls.
+      if (isa<ObjCMethodDecl>(D))
+        continue;
+
+      TopLevelDecls.push_back(D);
+    }
+    return true;
+  }
+
+private:
+  std::vector<Decl *> &TopLevelDecls;
+};
+
+class ClangdFrontendAction : public SyntaxOnlyAction {
+public:
+  std::vector<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<Decl *> TopLevelDecls;
+};
+
+class CppFilePreambleCallbacks : public PreambleCallbacks {
+public:
+  CppFilePreambleCallbacks(PathRef File, PreambleParsedCallback ParsedCallback)
+      : File(File), ParsedCallback(ParsedCallback) {}
+
+  IncludeStructure takeIncludes() { return std::move(Includes); }
+
+  void AfterExecute(CompilerInstance &CI) override {
+    if (!ParsedCallback)
+      return;
+    trace::Span Tracer("Running PreambleCallback");
+    ParsedCallback(File, CI.getASTContext(), CI.getPreprocessorPtr());
+  }
+
+  void BeforeExecute(CompilerInstance &CI) override {
+    SourceMgr = &CI.getSourceManager();
+  }
+
+  std::unique_ptr<PPCallbacks> createPPCallbacks() override {
+    assert(SourceMgr && "SourceMgr must be set at this point");
+    return collectIncludeStructureCallback(*SourceMgr, &Includes);
+  }
+
+private:
+  PathRef File;
+  PreambleParsedCallback ParsedCallback;
+  IncludeStructure Includes;
+  SourceManager *SourceMgr = nullptr;
+};
+
+} // namespace
+
+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,
+                 std::shared_ptr<const PreambleData> Preamble,
+                 std::unique_ptr<llvm::MemoryBuffer> Buffer,
+                 std::shared_ptr<PCHContainerOperations> PCHs,
+                 IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+  assert(CI);
+  // Command-line parsing sets DisableFree to true by default, but we don't want
+  // to leak memory in clangd.
+  CI->getFrontendOpts().DisableFree = false;
+  const PrecompiledPreamble *PreamblePCH =
+      Preamble ? &Preamble->Preamble : nullptr;
+
+  StoreDiags ASTDiags;
+  auto Clang =
+      prepareCompilerInstance(std::move(CI), PreamblePCH, std::move(Buffer),
+                              std::move(PCHs), std::move(VFS), ASTDiags);
+  if (!Clang)
+    return llvm::None;
+
+  // 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)) {
+    log("BeginSourceFile() failed when building AST for {0}",
+        MainInput.getFile());
+    return llvm::None;
+  }
+
+  // Copy over the includes from the preamble, then combine with the
+  // non-preamble includes below.
+  auto Includes = Preamble ? Preamble->Includes : IncludeStructure{};
+  Clang->getPreprocessor().addPPCallbacks(
+      collectIncludeStructureCallback(Clang->getSourceManager(), &Includes));
+
+  if (!Action->Execute())
+    log("Execute() failed when building AST for {0}", MainInput.getFile());
+
+  // UnitDiagsConsumer is local, we can not store it in CompilerInstance that
+  // has a longer lifetime.
+  Clang->getDiagnostics().setClient(new IgnoreDiagnostics);
+  // CompilerInstance won't run this callback, do it directly.
+  ASTDiags.EndSourceFile();
+
+  std::vector<Decl *> ParsedDecls = Action->takeTopLevelDecls();
+  std::vector<Diag> Diags = ASTDiags.take();
+  // Add diagnostics from the preamble, if any.
+  if (Preamble)
+    Diags.insert(Diags.begin(), Preamble->Diags.begin(), Preamble->Diags.end());
+  return ParsedAST(std::move(Preamble), std::move(Clang), std::move(Action),
+                   std::move(ParsedDecls), std::move(Diags),
+                   std::move(Includes));
+}
+
+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(); }
+
+std::shared_ptr<Preprocessor> ParsedAST::getPreprocessorPtr() {
+  return Clang->getPreprocessorPtr();
+}
+
+const Preprocessor &ParsedAST::getPreprocessor() const {
+  return Clang->getPreprocessor();
+}
+
+ArrayRef<Decl *> ParsedAST::getLocalTopLevelDecls() {
+  return LocalTopLevelDecls;
+}
+
+const std::vector<Diag> &ParsedAST::getDiagnostics() const { return Diags; }
+
+std::size_t ParsedAST::getUsedBytes() const {
+  auto &AST = getASTContext();
+  // FIXME(ibiryukov): we do not account for the dynamically allocated part of
+  // Message and Fixes inside each diagnostic.
+  std::size_t Total =
+      ::getUsedBytes(LocalTopLevelDecls) + ::getUsedBytes(Diags);
+
+  // FIXME: the rest of the function is almost a direct copy-paste from
+  // libclang's clang_getCXTUResourceUsage. We could share the implementation.
+
+  // Sum up variaous allocators inside the ast context and the preprocessor.
+  Total += AST.getASTAllocatedMemory();
+  Total += AST.getSideTableAllocatedMemory();
+  Total += AST.Idents.getAllocator().getTotalMemory();
+  Total += AST.Selectors.getTotalMemory();
+
+  Total += AST.getSourceManager().getContentCacheSize();
+  Total += AST.getSourceManager().getDataStructureSizes();
+  Total += AST.getSourceManager().getMemoryBufferSizes().malloc_bytes;
+
+  if (ExternalASTSource *Ext = AST.getExternalSource())
+    Total += Ext->getMemoryBufferSizes().malloc_bytes;
+
+  const Preprocessor &PP = getPreprocessor();
+  Total += PP.getTotalMemory();
+  if (PreprocessingRecord *PRec = PP.getPreprocessingRecord())
+    Total += PRec->getTotalMemory();
+  Total += PP.getHeaderSearchInfo().getTotalMemory();
+
+  return Total;
+}
+
+const IncludeStructure &ParsedAST::getIncludeStructure() const {
+  return Includes;
+}
+
+PreambleData::PreambleData(PrecompiledPreamble Preamble,
+                           std::vector<Diag> Diags, IncludeStructure Includes)
+    : Preamble(std::move(Preamble)), Diags(std::move(Diags)),
+      Includes(std::move(Includes)) {}
+
+ParsedAST::ParsedAST(std::shared_ptr<const PreambleData> Preamble,
+                     std::unique_ptr<CompilerInstance> Clang,
+                     std::unique_ptr<FrontendAction> Action,
+                     std::vector<Decl *> LocalTopLevelDecls,
+                     std::vector<Diag> Diags, IncludeStructure Includes)
+    : Preamble(std::move(Preamble)), Clang(std::move(Clang)),
+      Action(std::move(Action)), Diags(std::move(Diags)),
+      LocalTopLevelDecls(std::move(LocalTopLevelDecls)),
+      Includes(std::move(Includes)) {
+  assert(this->Clang);
+  assert(this->Action);
+}
+
+std::unique_ptr<CompilerInvocation>
+clangd::buildCompilerInvocation(const ParseInputs &Inputs) {
+  std::vector<const char *> ArgStrs;
+  for (const auto &S : Inputs.CompileCommand.CommandLine)
+    ArgStrs.push_back(S.c_str());
+
+  if (Inputs.FS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
+    log("Couldn't set working directory when creating compiler invocation.");
+    // We proceed anyway, our lit-tests rely on results for non-existing working
+    // dirs.
+  }
+
+  // FIXME(ibiryukov): store diagnostics from CommandLine when we start
+  // reporting them.
+  IgnoreDiagnostics IgnoreDiagnostics;
+  IntrusiveRefCntPtr<DiagnosticsEngine> CommandLineDiagsEngine =
+      CompilerInstance::createDiagnostics(new DiagnosticOptions,
+                                          &IgnoreDiagnostics, false);
+  std::unique_ptr<CompilerInvocation> CI = createInvocationFromCommandLine(
+      ArgStrs, CommandLineDiagsEngine, Inputs.FS);
+  if (!CI)
+    return nullptr;
+  // createInvocationFromCommandLine sets DisableFree.
+  CI->getFrontendOpts().DisableFree = false;
+  CI->getLangOpts()->CommentOpts.ParseAllComments = true;
+  return CI;
+}
+
+std::shared_ptr<const PreambleData> clangd::buildPreamble(
+    PathRef FileName, CompilerInvocation &CI,
+    std::shared_ptr<const PreambleData> OldPreamble,
+    const tooling::CompileCommand &OldCompileCommand, const ParseInputs &Inputs,
+    std::shared_ptr<PCHContainerOperations> PCHs, bool StoreInMemory,
+    PreambleParsedCallback PreambleCallback) {
+  // Note that we don't need to copy the input contents, preamble can live
+  // without those.
+  auto ContentsBuffer = llvm::MemoryBuffer::getMemBuffer(Inputs.Contents);
+  auto Bounds =
+      ComputePreambleBounds(*CI.getLangOpts(), ContentsBuffer.get(), 0);
+
+  if (OldPreamble &&
+      compileCommandsAreEqual(Inputs.CompileCommand, OldCompileCommand) &&
+      OldPreamble->Preamble.CanReuse(CI, ContentsBuffer.get(), Bounds,
+                                     Inputs.FS.get())) {
+    vlog("Reusing preamble for file {0}", Twine(FileName));
+    return OldPreamble;
+  }
+  vlog("Preamble for file {0} cannot be reused. Attempting to rebuild it.",
+       FileName);
+
+  trace::Span Tracer("BuildPreamble");
+  SPAN_ATTACH(Tracer, "File", FileName);
+  StoreDiags PreambleDiagnostics;
+  IntrusiveRefCntPtr<DiagnosticsEngine> PreambleDiagsEngine =
+      CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(),
+                                          &PreambleDiagnostics, false);
+
+  // Skip function bodies when building the preamble to speed up building
+  // the preamble and make it smaller.
+  assert(!CI.getFrontendOpts().SkipFunctionBodies);
+  CI.getFrontendOpts().SkipFunctionBodies = true;
+  // We don't want to write comment locations into PCH. They are racy and slow
+  // to read back. We rely on dynamic index for the comments instead.
+  CI.getPreprocessorOpts().WriteCommentListToPCH = false;
+
+  CppFilePreambleCallbacks SerializedDeclsCollector(FileName, PreambleCallback);
+  if (Inputs.FS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
+    log("Couldn't set working directory when building the preamble.");
+    // We proceed anyway, our lit-tests rely on results for non-existing working
+    // dirs.
+  }
+  auto BuiltPreamble = PrecompiledPreamble::Build(
+      CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine, Inputs.FS, PCHs,
+      StoreInMemory, SerializedDeclsCollector);
+
+  // When building the AST for the main file, we do want the function
+  // bodies.
+  CI.getFrontendOpts().SkipFunctionBodies = false;
+
+  if (BuiltPreamble) {
+    vlog("Built preamble of size {0} for file {1}", BuiltPreamble->getSize(),
+         FileName);
+    return std::make_shared<PreambleData>(
+        std::move(*BuiltPreamble), PreambleDiagnostics.take(),
+        SerializedDeclsCollector.takeIncludes());
+  } else {
+    elog("Could not build a preamble for file {0}", FileName);
+    return nullptr;
+  }
+}
+
+llvm::Optional<ParsedAST> clangd::buildAST(
+    PathRef FileName, std::unique_ptr<CompilerInvocation> Invocation,
+    const ParseInputs &Inputs, std::shared_ptr<const PreambleData> Preamble,
+    std::shared_ptr<PCHContainerOperations> PCHs) {
+  trace::Span Tracer("BuildAST");
+  SPAN_ATTACH(Tracer, "File", FileName);
+
+  if (Inputs.FS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
+    log("Couldn't set working directory when building the preamble.");
+    // We proceed anyway, our lit-tests rely on results for non-existing working
+    // dirs.
+  }
+
+  return ParsedAST::build(
+      llvm::make_unique<CompilerInvocation>(*Invocation), Preamble,
+      llvm::MemoryBuffer::getMemBufferCopy(Inputs.Contents), PCHs, Inputs.FS);
+}
+
+SourceLocation clangd::getBeginningOfIdentifier(ParsedAST &Unit,
+                                                const Position &Pos,
+                                                const FileID FID) {
+  const ASTContext &AST = Unit.getASTContext();
+  const SourceManager &SourceMgr = AST.getSourceManager();
+  auto Offset = positionToOffset(SourceMgr.getBufferData(FID), Pos);
+  if (!Offset) {
+    log("getBeginningOfIdentifier: {0}", Offset.takeError());
+    return SourceLocation();
+  }
+  SourceLocation InputLoc = SourceMgr.getComposedLoc(FID, *Offset);
+
+  // GetBeginningOfToken(pos) is almost what we want, but does the wrong thing
+  // if the cursor is at the end of the identifier.
+  // Instead, we lex at GetBeginningOfToken(pos - 1). The cases are:
+  //  1) at the beginning of an identifier, we'll be looking at something
+  //  that isn't an identifier.
+  //  2) at the middle or end of an identifier, we get the identifier.
+  //  3) anywhere outside an identifier, we'll get some non-identifier thing.
+  // We can't actually distinguish cases 1 and 3, but returning the original
+  // location is correct for both!
+  if (*Offset == 0) // Case 1 or 3.
+    return SourceMgr.getMacroArgExpandedLocation(InputLoc);
+  SourceLocation Before =
+      SourceMgr.getMacroArgExpandedLocation(InputLoc.getLocWithOffset(-1));
+  Before = Lexer::GetBeginningOfToken(Before, SourceMgr, AST.getLangOpts());
+  Token Tok;
+  if (Before.isValid() &&
+      !Lexer::getRawToken(Before, Tok, SourceMgr, AST.getLangOpts(), false) &&
+      Tok.is(tok::raw_identifier))
+    return Before;                                        // Case 2.
+  return SourceMgr.getMacroArgExpandedLocation(InputLoc); // Case 1 or 3.
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdUnit.h b/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdUnit.h
new file mode 100644
index 0000000..c7aca17
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/ClangdUnit.h
@@ -0,0 +1,171 @@
+//===--- ClangdUnit.h -------------------------------------------*- 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_CLANGDUNIT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H
+
+#include "Diagnostics.h"
+#include "Function.h"
+#include "Headers.h"
+#include "Path.h"
+#include "Protocol.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Frontend/PrecompiledPreamble.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace llvm {
+class raw_ostream;
+}
+
+namespace clang {
+class PCHContainerOperations;
+
+namespace vfs {
+class FileSystem;
+}
+
+namespace tooling {
+struct CompileCommand;
+}
+
+namespace clangd {
+
+// Stores Preamble and associated data.
+struct PreambleData {
+  PreambleData(PrecompiledPreamble Preamble, std::vector<Diag> Diags,
+               IncludeStructure Includes);
+
+  tooling::CompileCommand CompileCommand;
+  PrecompiledPreamble Preamble;
+  std::vector<Diag> Diags;
+  // Processes like code completions and go-to-definitions will need #include
+  // information, and their compile action skips preamble range.
+  IncludeStructure Includes;
+};
+
+/// Information required to run clang, e.g. to parse AST or do code completion.
+struct ParseInputs {
+  tooling::CompileCommand CompileCommand;
+  IntrusiveRefCntPtr<vfs::FileSystem> FS;
+  std::string Contents;
+};
+
+/// Stores and provides access to parsed AST.
+class ParsedAST {
+public:
+  /// 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,
+        std::shared_ptr<const PreambleData> Preamble,
+        std::unique_ptr<llvm::MemoryBuffer> Buffer,
+        std::shared_ptr<PCHContainerOperations> PCHs,
+        IntrusiveRefCntPtr<vfs::FileSystem> VFS);
+
+  ParsedAST(ParsedAST &&Other);
+  ParsedAST &operator=(ParsedAST &&Other);
+
+  ~ParsedAST();
+
+  /// Note that the returned ast will not contain decls from the preamble that
+  /// were not deserialized during parsing. Clients should expect only decls
+  /// from the main file to be in the AST.
+  ASTContext &getASTContext();
+  const ASTContext &getASTContext() const;
+
+  Preprocessor &getPreprocessor();
+  std::shared_ptr<Preprocessor> getPreprocessorPtr();
+  const Preprocessor &getPreprocessor() const;
+
+  /// This function returns top-level decls present in the main file of the AST.
+  /// The result does not include the decls that come from the preamble.
+  /// (These should be const, but RecursiveASTVisitor requires Decl*).
+  ArrayRef<Decl *> getLocalTopLevelDecls();
+
+  const std::vector<Diag> &getDiagnostics() const;
+
+  /// Returns the esitmated size of the AST and the accessory structures, in
+  /// bytes. Does not include the size of the preamble.
+  std::size_t getUsedBytes() const;
+  const IncludeStructure &getIncludeStructure() const;
+
+private:
+  ParsedAST(std::shared_ptr<const PreambleData> Preamble,
+            std::unique_ptr<CompilerInstance> Clang,
+            std::unique_ptr<FrontendAction> Action,
+            std::vector<Decl *> LocalTopLevelDecls, std::vector<Diag> Diags,
+            IncludeStructure Includes);
+
+  // In-memory preambles must outlive the AST, it is important that this member
+  // goes before Clang and Action.
+  std::shared_ptr<const PreambleData> Preamble;
+  // 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<Diag> Diags;
+  // Top-level decls inside the current file. Not that this does not include
+  // top-level decls from the preamble.
+  std::vector<Decl *> LocalTopLevelDecls;
+  IncludeStructure Includes;
+};
+
+using PreambleParsedCallback = std::function<void(
+    PathRef Path, ASTContext &, std::shared_ptr<clang::Preprocessor>)>;
+
+/// Builds compiler invocation that could be used to build AST or preamble.
+std::unique_ptr<CompilerInvocation>
+buildCompilerInvocation(const ParseInputs &Inputs);
+
+/// Rebuild the preamble for the new inputs unless the old one can be reused.
+/// If \p OldPreamble can be reused, it is returned unchanged.
+/// If \p OldPreamble is null, always builds the preamble.
+/// If \p PreambleCallback is set, it will be run on top of the AST while
+/// building the preamble. Note that if the old preamble was reused, no AST is
+/// built and, therefore, the callback will not be executed.
+std::shared_ptr<const PreambleData>
+buildPreamble(PathRef FileName, CompilerInvocation &CI,
+              std::shared_ptr<const PreambleData> OldPreamble,
+              const tooling::CompileCommand &OldCompileCommand,
+              const ParseInputs &Inputs,
+              std::shared_ptr<PCHContainerOperations> PCHs, bool StoreInMemory,
+              PreambleParsedCallback PreambleCallback);
+
+/// Build an AST from provided user inputs. This function does not check if
+/// preamble can be reused, as this function expects that \p Preamble is the
+/// result of calling buildPreamble.
+llvm::Optional<ParsedAST>
+buildAST(PathRef FileName, std::unique_ptr<CompilerInvocation> Invocation,
+         const ParseInputs &Inputs,
+         std::shared_ptr<const PreambleData> Preamble,
+         std::shared_ptr<PCHContainerOperations> PCHs);
+
+/// Get the beginning SourceLocation at a specified \p Pos.
+/// May be invalid if Pos is, or if there's no identifier.
+SourceLocation getBeginningOfIdentifier(ParsedAST &Unit, const Position &Pos,
+                                        const FileID FID);
+
+/// 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/src/third_party/llvm-project/clang-tools-extra/clangd/CodeComplete.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/CodeComplete.cpp
new file mode 100644
index 0000000..a040659
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/CodeComplete.cpp
@@ -0,0 +1,1303 @@
+//===--- CodeComplete.cpp ---------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// Code completion has several moving parts:
+//  - AST-based completions are provided using the completion hooks in Sema.
+//  - external completions are retrieved from the index (using hints from Sema)
+//  - the two sources overlap, and must be merged and overloads bundled
+//  - results must be scored and ranked (see Quality.h) before rendering
+//
+// Signature help works in a similar way as code completion, but it is simpler:
+// it's purely AST-based, and there are few candidates.
+//
+//===---------------------------------------------------------------------===//
+
+#include "CodeComplete.h"
+#include "AST.h"
+#include "CodeCompletionStrings.h"
+#include "Compiler.h"
+#include "FileDistance.h"
+#include "FuzzyMatch.h"
+#include "Headers.h"
+#include "Logger.h"
+#include "Quality.h"
+#include "SourceCode.h"
+#include "Trace.h"
+#include "URI.h"
+#include "index/Index.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Format/Format.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Index/USRGeneration.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include <queue>
+
+// We log detailed candidate here if you run with -debug-only=codecomplete.
+#define DEBUG_TYPE "CodeComplete"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) {
+  using SK = index::SymbolKind;
+  switch (Kind) {
+  case SK::Unknown:
+    return CompletionItemKind::Missing;
+  case SK::Module:
+  case SK::Namespace:
+  case SK::NamespaceAlias:
+    return CompletionItemKind::Module;
+  case SK::Macro:
+    return CompletionItemKind::Text;
+  case SK::Enum:
+    return CompletionItemKind::Enum;
+  // FIXME(ioeric): use LSP struct instead of class when it is suppoted in the
+  // protocol.
+  case SK::Struct:
+  case SK::Class:
+  case SK::Protocol:
+  case SK::Extension:
+  case SK::Union:
+    return CompletionItemKind::Class;
+  // FIXME(ioeric): figure out whether reference is the right type for aliases.
+  case SK::TypeAlias:
+  case SK::Using:
+    return CompletionItemKind::Reference;
+  case SK::Function:
+  // FIXME(ioeric): this should probably be an operator. This should be fixed
+  // when `Operator` is support type in the protocol.
+  case SK::ConversionFunction:
+    return CompletionItemKind::Function;
+  case SK::Variable:
+  case SK::Parameter:
+    return CompletionItemKind::Variable;
+  case SK::Field:
+    return CompletionItemKind::Field;
+  // FIXME(ioeric): use LSP enum constant when it is supported in the protocol.
+  case SK::EnumConstant:
+    return CompletionItemKind::Value;
+  case SK::InstanceMethod:
+  case SK::ClassMethod:
+  case SK::StaticMethod:
+  case SK::Destructor:
+    return CompletionItemKind::Method;
+  case SK::InstanceProperty:
+  case SK::ClassProperty:
+  case SK::StaticProperty:
+    return CompletionItemKind::Property;
+  case SK::Constructor:
+    return CompletionItemKind::Constructor;
+  }
+  llvm_unreachable("Unhandled clang::index::SymbolKind.");
+}
+
+CompletionItemKind
+toCompletionItemKind(CodeCompletionResult::ResultKind ResKind,
+                     const NamedDecl *Decl) {
+  if (Decl)
+    return toCompletionItemKind(index::getSymbolInfo(Decl).Kind);
+  switch (ResKind) {
+  case CodeCompletionResult::RK_Declaration:
+    llvm_unreachable("RK_Declaration without Decl");
+  case CodeCompletionResult::RK_Keyword:
+    return CompletionItemKind::Keyword;
+  case CodeCompletionResult::RK_Macro:
+    return CompletionItemKind::Text; // unfortunately, there's no 'Macro'
+                                     // completion items in LSP.
+  case CodeCompletionResult::RK_Pattern:
+    return CompletionItemKind::Snippet;
+  }
+  llvm_unreachable("Unhandled CodeCompletionResult::ResultKind.");
+}
+
+/// 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;
+}
+
+/// Creates a `HeaderFile` from \p Header which can be either a URI or a literal
+/// include.
+static llvm::Expected<HeaderFile> toHeaderFile(StringRef Header,
+                                               llvm::StringRef HintPath) {
+  if (isLiteralInclude(Header))
+    return HeaderFile{Header.str(), /*Verbatim=*/true};
+  auto U = URI::parse(Header);
+  if (!U)
+    return U.takeError();
+
+  auto IncludePath = URI::includeSpelling(*U);
+  if (!IncludePath)
+    return IncludePath.takeError();
+  if (!IncludePath->empty())
+    return HeaderFile{std::move(*IncludePath), /*Verbatim=*/true};
+
+  auto Resolved = URI::resolve(*U, HintPath);
+  if (!Resolved)
+    return Resolved.takeError();
+  return HeaderFile{std::move(*Resolved), /*Verbatim=*/false};
+}
+
+/// A code completion result, in clang-native form.
+/// It may be promoted to a CompletionItem if it's among the top-ranked results.
+struct CompletionCandidate {
+  llvm::StringRef Name; // Used for filtering and sorting.
+  // We may have a result from Sema, from the index, or both.
+  const CodeCompletionResult *SemaResult = nullptr;
+  const Symbol *IndexResult = nullptr;
+
+  // Returns a token identifying the overload set this is part of.
+  // 0 indicates it's not part of any overload set.
+  size_t overloadSet() const {
+    SmallString<256> Scratch;
+    if (IndexResult) {
+      switch (IndexResult->SymInfo.Kind) {
+      case index::SymbolKind::ClassMethod:
+      case index::SymbolKind::InstanceMethod:
+      case index::SymbolKind::StaticMethod:
+        assert(false && "Don't expect members from index in code completion");
+        // fall through
+      case index::SymbolKind::Function:
+        // We can't group overloads together that need different #includes.
+        // This could break #include insertion.
+        return hash_combine(
+            (IndexResult->Scope + IndexResult->Name).toStringRef(Scratch),
+            headerToInsertIfNotPresent().getValueOr(""));
+      default:
+        return 0;
+      }
+    }
+    assert(SemaResult);
+    // We need to make sure we're consistent with the IndexResult case!
+    const NamedDecl *D = SemaResult->Declaration;
+    if (!D || !D->isFunctionOrFunctionTemplate())
+      return 0;
+    {
+      llvm::raw_svector_ostream OS(Scratch);
+      D->printQualifiedName(OS);
+    }
+    return hash_combine(Scratch, headerToInsertIfNotPresent().getValueOr(""));
+  }
+
+  llvm::Optional<llvm::StringRef> headerToInsertIfNotPresent() const {
+    if (!IndexResult || !IndexResult->Detail ||
+        IndexResult->Detail->IncludeHeader.empty())
+      return llvm::None;
+    if (SemaResult && SemaResult->Declaration) {
+      // Avoid inserting new #include if the declaration is found in the current
+      // file e.g. the symbol is forward declared.
+      auto &SM = SemaResult->Declaration->getASTContext().getSourceManager();
+      for (const Decl *RD : SemaResult->Declaration->redecls())
+        if (SM.isInMainFile(SM.getExpansionLoc(RD->getLocStart())))
+          return llvm::None;
+    }
+    return IndexResult->Detail->IncludeHeader;
+  }
+
+  using Bundle = llvm::SmallVector<CompletionCandidate, 4>;
+};
+using ScoredBundle =
+    std::pair<CompletionCandidate::Bundle, CodeCompletion::Scores>;
+struct ScoredBundleGreater {
+  bool operator()(const ScoredBundle &L, const ScoredBundle &R) {
+    if (L.second.Total != R.second.Total)
+      return L.second.Total > R.second.Total;
+    return L.first.front().Name <
+           R.first.front().Name; // Earlier name is better.
+  }
+};
+
+// Assembles a code completion out of a bundle of >=1 completion candidates.
+// Many of the expensive strings are only computed at this point, once we know
+// the candidate bundle is going to be returned.
+//
+// Many fields are the same for all candidates in a bundle (e.g. name), and are
+// computed from the first candidate, in the constructor.
+// Others vary per candidate, so add() must be called for remaining candidates.
+struct CodeCompletionBuilder {
+  CodeCompletionBuilder(ASTContext &ASTCtx, const CompletionCandidate &C,
+                        CodeCompletionString *SemaCCS,
+                        const IncludeInserter &Includes, StringRef FileName,
+                        const CodeCompleteOptions &Opts)
+      : ASTCtx(ASTCtx), ExtractDocumentation(Opts.IncludeComments) {
+    add(C, SemaCCS);
+    if (C.SemaResult) {
+      Completion.Origin |= SymbolOrigin::AST;
+      Completion.Name = llvm::StringRef(SemaCCS->getTypedText());
+      if (Completion.Scope.empty()) {
+        if ((C.SemaResult->Kind == CodeCompletionResult::RK_Declaration) ||
+            (C.SemaResult->Kind == CodeCompletionResult::RK_Pattern))
+          if (const auto *D = C.SemaResult->getDeclaration())
+            if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))
+              Completion.Scope =
+                  splitQualifiedName(printQualifiedName(*ND)).first;
+      }
+      Completion.Kind =
+          toCompletionItemKind(C.SemaResult->Kind, C.SemaResult->Declaration);
+    }
+    if (C.IndexResult) {
+      Completion.Origin |= C.IndexResult->Origin;
+      if (Completion.Scope.empty())
+        Completion.Scope = C.IndexResult->Scope;
+      if (Completion.Kind == CompletionItemKind::Missing)
+        Completion.Kind = toCompletionItemKind(C.IndexResult->SymInfo.Kind);
+      if (Completion.Name.empty())
+        Completion.Name = C.IndexResult->Name;
+    }
+    if (auto Inserted = C.headerToInsertIfNotPresent()) {
+      // Turn absolute path into a literal string that can be #included.
+      auto Include = [&]() -> Expected<std::pair<std::string, bool>> {
+        auto ResolvedDeclaring =
+            toHeaderFile(C.IndexResult->CanonicalDeclaration.FileURI, FileName);
+        if (!ResolvedDeclaring)
+          return ResolvedDeclaring.takeError();
+        auto ResolvedInserted = toHeaderFile(*Inserted, FileName);
+        if (!ResolvedInserted)
+          return ResolvedInserted.takeError();
+        return std::make_pair(Includes.calculateIncludePath(*ResolvedDeclaring,
+                                                            *ResolvedInserted),
+                              Includes.shouldInsertInclude(*ResolvedDeclaring,
+                                                           *ResolvedInserted));
+      }();
+      if (Include) {
+        Completion.Header = Include->first;
+        if (Include->second)
+          Completion.HeaderInsertion = Includes.insert(Include->first);
+      } else
+        log("Failed to generate include insertion edits for adding header "
+            "(FileURI='{0}', IncludeHeader='{1}') into {2}",
+            C.IndexResult->CanonicalDeclaration.FileURI,
+            C.IndexResult->Detail->IncludeHeader, FileName);
+    }
+  }
+
+  void add(const CompletionCandidate &C, CodeCompletionString *SemaCCS) {
+    assert(bool(C.SemaResult) == bool(SemaCCS));
+    Bundled.emplace_back();
+    BundledEntry &S = Bundled.back();
+    if (C.SemaResult) {
+      getSignature(*SemaCCS, &S.Signature, &S.SnippetSuffix,
+                   &Completion.RequiredQualifier);
+      S.ReturnType = getReturnType(*SemaCCS);
+    } else if (C.IndexResult) {
+      S.Signature = C.IndexResult->Signature;
+      S.SnippetSuffix = C.IndexResult->CompletionSnippetSuffix;
+      if (auto *D = C.IndexResult->Detail)
+        S.ReturnType = D->ReturnType;
+    }
+    if (ExtractDocumentation && Completion.Documentation.empty()) {
+      if (C.IndexResult && C.IndexResult->Detail)
+        Completion.Documentation = C.IndexResult->Detail->Documentation;
+      else if (C.SemaResult)
+        Completion.Documentation = getDocComment(ASTCtx, *C.SemaResult,
+                                                 /*CommentsFromHeader=*/false);
+    }
+  }
+
+  CodeCompletion build() {
+    Completion.ReturnType = summarizeReturnType();
+    Completion.Signature = summarizeSignature();
+    Completion.SnippetSuffix = summarizeSnippet();
+    Completion.BundleSize = Bundled.size();
+    return std::move(Completion);
+  }
+
+private:
+  struct BundledEntry {
+    std::string SnippetSuffix;
+    std::string Signature;
+    std::string ReturnType;
+  };
+
+  // If all BundledEntrys have the same value for a property, return it.
+  template <std::string BundledEntry::*Member>
+  const std::string *onlyValue() const {
+    auto B = Bundled.begin(), E = Bundled.end();
+    for (auto I = B + 1; I != E; ++I)
+      if (I->*Member != B->*Member)
+        return nullptr;
+    return &(B->*Member);
+  }
+
+  std::string summarizeReturnType() const {
+    if (auto *RT = onlyValue<&BundledEntry::ReturnType>())
+      return *RT;
+    return "";
+  }
+
+  std::string summarizeSnippet() const {
+    if (auto *Snippet = onlyValue<&BundledEntry::SnippetSuffix>())
+      return *Snippet;
+    // All bundles are function calls.
+    return "(${0})";
+  }
+
+  std::string summarizeSignature() const {
+    if (auto *Signature = onlyValue<&BundledEntry::Signature>())
+      return *Signature;
+    // All bundles are function calls.
+    return "(…)";
+  }
+
+  ASTContext &ASTCtx;
+  CodeCompletion Completion;
+  SmallVector<BundledEntry, 1> Bundled;
+  bool ExtractDocumentation;
+};
+
+// Determine the symbol ID for a Sema code completion result, if possible.
+llvm::Optional<SymbolID> getSymbolID(const CodeCompletionResult &R) {
+  switch (R.Kind) {
+  case CodeCompletionResult::RK_Declaration:
+  case CodeCompletionResult::RK_Pattern: {
+    llvm::SmallString<128> USR;
+    if (/*Ignore=*/clang::index::generateUSRForDecl(R.Declaration, USR))
+      return None;
+    return SymbolID(USR);
+  }
+  case CodeCompletionResult::RK_Macro:
+    // FIXME: Macros do have USRs, but the CCR doesn't contain enough info.
+  case CodeCompletionResult::RK_Keyword:
+    return None;
+  }
+  llvm_unreachable("unknown CodeCompletionResult kind");
+}
+
+// Scopes of the paritial identifier we're trying to complete.
+// It is used when we query the index for more completion results.
+struct SpecifiedScope {
+  // The scopes we should look in, determined by Sema.
+  //
+  // If the qualifier was fully resolved, we look for completions in these
+  // scopes; if there is an unresolved part of the qualifier, it should be
+  // resolved within these scopes.
+  //
+  // Examples of qualified completion:
+  //
+  //   "::vec"                                      => {""}
+  //   "using namespace std; ::vec^"                => {"", "std::"}
+  //   "namespace ns {using namespace std;} ns::^"  => {"ns::", "std::"}
+  //   "std::vec^"                                  => {""}  // "std" unresolved
+  //
+  // Examples of unqualified completion:
+  //
+  //   "vec^"                                       => {""}
+  //   "using namespace std; vec^"                  => {"", "std::"}
+  //   "using namespace std; namespace ns { vec^ }" => {"ns::", "std::", ""}
+  //
+  // "" for global namespace, "ns::" for normal namespace.
+  std::vector<std::string> AccessibleScopes;
+  // The full scope qualifier as typed by the user (without the leading "::").
+  // Set if the qualifier is not fully resolved by Sema.
+  llvm::Optional<std::string> UnresolvedQualifier;
+
+  // Construct scopes being queried in indexes.
+  // This method format the scopes to match the index request representation.
+  std::vector<std::string> scopesForIndexQuery() {
+    std::vector<std::string> Results;
+    for (llvm::StringRef AS : AccessibleScopes) {
+      Results.push_back(AS);
+      if (UnresolvedQualifier)
+        Results.back() += *UnresolvedQualifier;
+    }
+    return Results;
+  }
+};
+
+// Get all scopes that will be queried in indexes.
+std::vector<std::string> getQueryScopes(CodeCompletionContext &CCContext,
+                                        const SourceManager &SM) {
+  auto GetAllAccessibleScopes = [](CodeCompletionContext &CCContext) {
+    SpecifiedScope Info;
+    for (auto *Context : CCContext.getVisitedContexts()) {
+      if (isa<TranslationUnitDecl>(Context))
+        Info.AccessibleScopes.push_back(""); // global namespace
+      else if (const auto *NS = dyn_cast<NamespaceDecl>(Context))
+        Info.AccessibleScopes.push_back(NS->getQualifiedNameAsString() + "::");
+    }
+    return Info;
+  };
+
+  auto SS = CCContext.getCXXScopeSpecifier();
+
+  // Unqualified completion (e.g. "vec^").
+  if (!SS) {
+    // FIXME: Once we can insert namespace qualifiers and use the in-scope
+    //        namespaces for scoring, search in all namespaces.
+    // FIXME: Capture scopes and use for scoring, for example,
+    //        "using namespace std; namespace foo {v^}" =>
+    //        foo::value > std::vector > boost::variant
+    return GetAllAccessibleScopes(CCContext).scopesForIndexQuery();
+  }
+
+  // Qualified completion ("std::vec^"), we have two cases depending on whether
+  // the qualifier can be resolved by Sema.
+  if ((*SS)->isValid()) { // Resolved qualifier.
+    return GetAllAccessibleScopes(CCContext).scopesForIndexQuery();
+  }
+
+  // Unresolved qualifier.
+  // FIXME: When Sema can resolve part of a scope chain (e.g.
+  // "known::unknown::id"), we should expand the known part ("known::") rather
+  // than treating the whole thing as unknown.
+  SpecifiedScope Info;
+  Info.AccessibleScopes.push_back(""); // global namespace
+
+  Info.UnresolvedQualifier =
+      Lexer::getSourceText(CharSourceRange::getCharRange((*SS)->getRange()), SM,
+                           clang::LangOptions())
+          .ltrim("::");
+  // Sema excludes the trailing "::".
+  if (!Info.UnresolvedQualifier->empty())
+    *Info.UnresolvedQualifier += "::";
+
+  return Info.scopesForIndexQuery();
+}
+
+// Should we perform index-based completion in a context of the specified kind?
+// FIXME: consider allowing completion, but restricting the result types.
+bool contextAllowsIndex(enum CodeCompletionContext::Kind K) {
+  switch (K) {
+  case CodeCompletionContext::CCC_TopLevel:
+  case CodeCompletionContext::CCC_ObjCInterface:
+  case CodeCompletionContext::CCC_ObjCImplementation:
+  case CodeCompletionContext::CCC_ObjCIvarList:
+  case CodeCompletionContext::CCC_ClassStructUnion:
+  case CodeCompletionContext::CCC_Statement:
+  case CodeCompletionContext::CCC_Expression:
+  case CodeCompletionContext::CCC_ObjCMessageReceiver:
+  case CodeCompletionContext::CCC_EnumTag:
+  case CodeCompletionContext::CCC_UnionTag:
+  case CodeCompletionContext::CCC_ClassOrStructTag:
+  case CodeCompletionContext::CCC_ObjCProtocolName:
+  case CodeCompletionContext::CCC_Namespace:
+  case CodeCompletionContext::CCC_Type:
+  case CodeCompletionContext::CCC_Name: // FIXME: why does ns::^ give this?
+  case CodeCompletionContext::CCC_PotentiallyQualifiedName:
+  case CodeCompletionContext::CCC_ParenthesizedExpression:
+  case CodeCompletionContext::CCC_ObjCInterfaceName:
+  case CodeCompletionContext::CCC_ObjCCategoryName:
+    return true;
+  case CodeCompletionContext::CCC_Other: // Be conservative.
+  case CodeCompletionContext::CCC_OtherWithMacros:
+  case CodeCompletionContext::CCC_DotMemberAccess:
+  case CodeCompletionContext::CCC_ArrowMemberAccess:
+  case CodeCompletionContext::CCC_ObjCPropertyAccess:
+  case CodeCompletionContext::CCC_MacroName:
+  case CodeCompletionContext::CCC_MacroNameUse:
+  case CodeCompletionContext::CCC_PreprocessorExpression:
+  case CodeCompletionContext::CCC_PreprocessorDirective:
+  case CodeCompletionContext::CCC_NaturalLanguage:
+  case CodeCompletionContext::CCC_SelectorName:
+  case CodeCompletionContext::CCC_TypeQualifiers:
+  case CodeCompletionContext::CCC_ObjCInstanceMessage:
+  case CodeCompletionContext::CCC_ObjCClassMessage:
+  case CodeCompletionContext::CCC_Recovery:
+    return false;
+  }
+  llvm_unreachable("unknown code completion context");
+}
+
+// Some member calls are blacklisted because they're so rarely useful.
+static bool isBlacklistedMember(const NamedDecl &D) {
+  // Destructor completion is rarely useful, and works inconsistently.
+  // (s.^ completes ~string, but s.~st^ is an error).
+  if (D.getKind() == Decl::CXXDestructor)
+    return true;
+  // Injected name may be useful for A::foo(), but who writes A::A::foo()?
+  if (auto *R = dyn_cast_or_null<RecordDecl>(&D))
+    if (R->isInjectedClassName())
+      return true;
+  // Explicit calls to operators are also rare.
+  auto NameKind = D.getDeclName().getNameKind();
+  if (NameKind == DeclarationName::CXXOperatorName ||
+      NameKind == DeclarationName::CXXLiteralOperatorName ||
+      NameKind == DeclarationName::CXXConversionFunctionName)
+    return true;
+  return false;
+}
+
+// The CompletionRecorder captures Sema code-complete output, including context.
+// It filters out ignored results (but doesn't apply fuzzy-filtering yet).
+// It doesn't do scoring or conversion to CompletionItem yet, as we want to
+// merge with index results first.
+// Generally the fields and methods of this object should only be used from
+// within the callback.
+struct CompletionRecorder : public CodeCompleteConsumer {
+  CompletionRecorder(const CodeCompleteOptions &Opts,
+                     llvm::unique_function<void()> ResultsCallback)
+      : CodeCompleteConsumer(Opts.getClangCompleteOpts(),
+                             /*OutputIsBinary=*/false),
+        CCContext(CodeCompletionContext::CCC_Other), Opts(Opts),
+        CCAllocator(std::make_shared<GlobalCodeCompletionAllocator>()),
+        CCTUInfo(CCAllocator), ResultsCallback(std::move(ResultsCallback)) {
+    assert(this->ResultsCallback);
+  }
+
+  std::vector<CodeCompletionResult> Results;
+  CodeCompletionContext CCContext;
+  Sema *CCSema = nullptr; // Sema that created the results.
+  // FIXME: Sema is scary. Can we store ASTContext and Preprocessor, instead?
+
+  void ProcessCodeCompleteResults(class Sema &S, CodeCompletionContext Context,
+                                  CodeCompletionResult *InResults,
+                                  unsigned NumResults) override final {
+    // Results from recovery mode are generally useless, and the callback after
+    // recovery (if any) is usually more interesting. To make sure we handle the
+    // future callback from sema, we just ignore all callbacks in recovery mode,
+    // as taking only results from recovery mode results in poor completion
+    // results.
+    // FIXME: in case there is no future sema completion callback after the
+    // recovery mode, we might still want to provide some results (e.g. trivial
+    // identifier-based completion).
+    if (Context.getKind() == CodeCompletionContext::CCC_Recovery) {
+      log("Code complete: Ignoring sema code complete callback with Recovery "
+          "context.");
+      return;
+    }
+    // If a callback is called without any sema result and the context does not
+    // support index-based completion, we simply skip it to give way to
+    // potential future callbacks with results.
+    if (NumResults == 0 && !contextAllowsIndex(Context.getKind()))
+      return;
+    if (CCSema) {
+      log("Multiple code complete callbacks (parser backtracked?). "
+          "Dropping results from context {0}, keeping results from {1}.",
+          getCompletionKindString(Context.getKind()),
+          getCompletionKindString(this->CCContext.getKind()));
+      return;
+    }
+    // Record the completion context.
+    CCSema = &S;
+    CCContext = Context;
+
+    // Retain the results we might want.
+    for (unsigned I = 0; I < NumResults; ++I) {
+      auto &Result = InResults[I];
+      // Drop hidden items which cannot be found by lookup after completion.
+      // Exception: some items can be named by using a qualifier.
+      if (Result.Hidden && (!Result.Qualifier || Result.QualifierIsInformative))
+        continue;
+      if (!Opts.IncludeIneligibleResults &&
+          (Result.Availability == CXAvailability_NotAvailable ||
+           Result.Availability == CXAvailability_NotAccessible))
+        continue;
+      if (Result.Declaration &&
+          !Context.getBaseType().isNull() // is this a member-access context?
+          && isBlacklistedMember(*Result.Declaration))
+        continue;
+      // We choose to never append '::' to completion results in clangd.
+      Result.StartsNestedNameSpecifier = false;
+      Results.push_back(Result);
+    }
+    ResultsCallback();
+  }
+
+  CodeCompletionAllocator &getAllocator() override { return *CCAllocator; }
+  CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
+
+  // Returns the filtering/sorting name for Result, which must be from Results.
+  // Returned string is owned by this recorder (or the AST).
+  llvm::StringRef getName(const CodeCompletionResult &Result) {
+    switch (Result.Kind) {
+    case CodeCompletionResult::RK_Declaration:
+      if (auto *ID = Result.Declaration->getIdentifier())
+        return ID->getName();
+      break;
+    case CodeCompletionResult::RK_Keyword:
+      return Result.Keyword;
+    case CodeCompletionResult::RK_Macro:
+      return Result.Macro->getName();
+    case CodeCompletionResult::RK_Pattern:
+      return Result.Pattern->getTypedText();
+    }
+    auto *CCS = codeCompletionString(Result);
+    return CCS->getTypedText();
+  }
+
+  // Build a CodeCompletion string for R, which must be from Results.
+  // The CCS will be owned by this recorder.
+  CodeCompletionString *codeCompletionString(const CodeCompletionResult &R) {
+    // CodeCompletionResult doesn't seem to be const-correct. We own it, anyway.
+    return const_cast<CodeCompletionResult &>(R).CreateCodeCompletionString(
+        *CCSema, CCContext, *CCAllocator, CCTUInfo,
+        /*IncludeBriefComments=*/false);
+  }
+
+private:
+  CodeCompleteOptions Opts;
+  std::shared_ptr<GlobalCodeCompletionAllocator> CCAllocator;
+  CodeCompletionTUInfo CCTUInfo;
+  llvm::unique_function<void()> ResultsCallback;
+};
+
+class SignatureHelpCollector final : public CodeCompleteConsumer {
+
+public:
+  SignatureHelpCollector(const clang::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");
+      // FIXME: for headers, we need to get a comment from the index.
+      SigHelp.signatures.push_back(processOverloadCandidate(
+          Candidate, *CCS,
+          getParameterDocComment(S.getASTContext(), Candidate, CurrentArg,
+                                 /*CommentsFromHeaders=*/false)));
+    }
+  }
+
+  GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }
+
+  CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
+
+private:
+  // FIXME(ioeric): consider moving CodeCompletionString logic here to
+  // CompletionString.h.
+  SignatureInformation
+  processOverloadCandidate(const OverloadCandidate &Candidate,
+                           const CodeCompletionString &CCS,
+                           llvm::StringRef DocComment) const {
+    SignatureInformation Result;
+    const char *ReturnType = nullptr;
+
+    Result.documentation = formatDocumentation(CCS, DocComment);
+
+    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
+
+struct SemaCompleteInput {
+  PathRef FileName;
+  const tooling::CompileCommand &Command;
+  PrecompiledPreamble const *Preamble;
+  StringRef Contents;
+  Position Pos;
+  IntrusiveRefCntPtr<vfs::FileSystem> VFS;
+  std::shared_ptr<PCHContainerOperations> PCHs;
+};
+
+// Invokes Sema code completion on a file.
+// If \p Includes is set, it will be updated based on the compiler invocation.
+bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
+                      const clang::CodeCompleteOptions &Options,
+                      const SemaCompleteInput &Input,
+                      IncludeStructure *Includes = nullptr) {
+  trace::Span Tracer("Sema completion");
+  std::vector<const char *> ArgStrs;
+  for (const auto &S : Input.Command.CommandLine)
+    ArgStrs.push_back(S.c_str());
+
+  if (Input.VFS->setCurrentWorkingDirectory(Input.Command.Directory)) {
+    log("Couldn't set working directory");
+    // We run parsing anyway, our lit-tests rely on results for non-existing
+    // working dirs.
+  }
+
+  IgnoreDiagnostics DummyDiagsConsumer;
+  auto CI = createInvocationFromCommandLine(
+      ArgStrs,
+      CompilerInstance::createDiagnostics(new DiagnosticOptions,
+                                          &DummyDiagsConsumer, false),
+      Input.VFS);
+  if (!CI) {
+    elog("Couldn't create CompilerInvocation");
+    return false;
+  }
+  auto &FrontendOpts = CI->getFrontendOpts();
+  FrontendOpts.DisableFree = false;
+  FrontendOpts.SkipFunctionBodies = true;
+  CI->getLangOpts()->CommentOpts.ParseAllComments = true;
+  // Disable typo correction in Sema.
+  CI->getLangOpts()->SpellChecking = false;
+  // Setup code completion.
+  FrontendOpts.CodeCompleteOpts = Options;
+  FrontendOpts.CodeCompletionAt.FileName = Input.FileName;
+  auto Offset = positionToOffset(Input.Contents, Input.Pos);
+  if (!Offset) {
+    elog("Code completion position was invalid {0}", Offset.takeError());
+    return false;
+  }
+  std::tie(FrontendOpts.CodeCompletionAt.Line,
+           FrontendOpts.CodeCompletionAt.Column) =
+      offsetToClangLineColumn(Input.Contents, *Offset);
+
+  std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer =
+      llvm::MemoryBuffer::getMemBufferCopy(Input.Contents, Input.FileName);
+  // The diagnostic options must be set before creating a CompilerInstance.
+  CI->getDiagnosticOpts().IgnoreWarnings = true;
+  // We reuse the preamble whether it's valid or not. This is a
+  // correctness/performance tradeoff: building without a preamble is slow, and
+  // completion is latency-sensitive.
+  // NOTE: we must call BeginSourceFile after prepareCompilerInstance. Otherwise
+  // the remapped buffers do not get freed.
+  auto Clang = prepareCompilerInstance(
+      std::move(CI), Input.Preamble, std::move(ContentsBuffer),
+      std::move(Input.PCHs), std::move(Input.VFS), DummyDiagsConsumer);
+  Clang->setCodeCompletionConsumer(Consumer.release());
+
+  SyntaxOnlyAction Action;
+  if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
+    log("BeginSourceFile() failed when running codeComplete for {0}",
+        Input.FileName);
+    return false;
+  }
+  if (Includes)
+    Clang->getPreprocessor().addPPCallbacks(
+        collectIncludeStructureCallback(Clang->getSourceManager(), Includes));
+  if (!Action.Execute()) {
+    log("Execute() failed when running codeComplete for {0}", Input.FileName);
+    return false;
+  }
+  Action.EndSourceFile();
+
+  return true;
+}
+
+// Should we allow index completions in the specified context?
+bool allowIndex(CodeCompletionContext &CC) {
+  if (!contextAllowsIndex(CC.getKind()))
+    return false;
+  // We also avoid ClassName::bar (but allow namespace::bar).
+  auto Scope = CC.getCXXScopeSpecifier();
+  if (!Scope)
+    return true;
+  NestedNameSpecifier *NameSpec = (*Scope)->getScopeRep();
+  if (!NameSpec)
+    return true;
+  // We only query the index when qualifier is a namespace.
+  // If it's a class, we rely solely on sema completions.
+  switch (NameSpec->getKind()) {
+  case NestedNameSpecifier::Global:
+  case NestedNameSpecifier::Namespace:
+  case NestedNameSpecifier::NamespaceAlias:
+    return true;
+  case NestedNameSpecifier::Super:
+  case NestedNameSpecifier::TypeSpec:
+  case NestedNameSpecifier::TypeSpecWithTemplate:
+  // Unresolved inside a template.
+  case NestedNameSpecifier::Identifier:
+    return false;
+  }
+  llvm_unreachable("invalid NestedNameSpecifier kind");
+}
+
+} // namespace
+
+clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const {
+  clang::CodeCompleteOptions Result;
+  Result.IncludeCodePatterns = EnableSnippets && IncludeCodePatterns;
+  Result.IncludeMacros = IncludeMacros;
+  Result.IncludeGlobals = true;
+  // We choose to include full comments and not do doxygen parsing in
+  // completion.
+  // FIXME: ideally, we should support doxygen in some form, e.g. do markdown
+  // formatting of the comments.
+  Result.IncludeBriefComments = false;
+
+  // When an is used, Sema is responsible for completing the main file,
+  // the index can provide results from the preamble.
+  // Tell Sema not to deserialize the preamble to look for results.
+  Result.LoadExternal = !Index;
+
+  return Result;
+}
+
+// Runs Sema-based (AST) and Index-based completion, returns merged results.
+//
+// There are a few tricky considerations:
+//   - the AST provides information needed for the index query (e.g. which
+//     namespaces to search in). So Sema must start first.
+//   - we only want to return the top results (Opts.Limit).
+//     Building CompletionItems for everything else is wasteful, so we want to
+//     preserve the "native" format until we're done with scoring.
+//   - the data underlying Sema completion items is owned by the AST and various
+//     other arenas, which must stay alive for us to build CompletionItems.
+//   - we may get duplicate results from Sema and the Index, we need to merge.
+//
+// So we start Sema completion first, and do all our work in its callback.
+// We use the Sema context information to query the index.
+// Then we merge the two result sets, producing items that are Sema/Index/Both.
+// These items are scored, and the top N are synthesized into the LSP response.
+// Finally, we can clean up the data structures created by Sema completion.
+//
+// Main collaborators are:
+//   - semaCodeComplete sets up the compiler machinery to run code completion.
+//   - CompletionRecorder captures Sema completion results, including context.
+//   - SymbolIndex (Opts.Index) provides index completion results as Symbols
+//   - CompletionCandidates are the result of merging Sema and Index results.
+//     Each candidate points to an underlying CodeCompletionResult (Sema), a
+//     Symbol (Index), or both. It computes the result quality score.
+//     CompletionCandidate also does conversion to CompletionItem (at the end).
+//   - FuzzyMatcher scores how the candidate matches the partial identifier.
+//     This score is combined with the result quality score for the final score.
+//   - TopN determines the results with the best score.
+class CodeCompleteFlow {
+  PathRef FileName;
+  IncludeStructure Includes; // Complete once the compiler runs.
+  const CodeCompleteOptions &Opts;
+  // Sema takes ownership of Recorder. Recorder is valid until Sema cleanup.
+  CompletionRecorder *Recorder = nullptr;
+  int NSema = 0, NIndex = 0, NBoth = 0; // Counters for logging.
+  bool Incomplete = false; // Would more be available with a higher limit?
+  llvm::Optional<FuzzyMatcher> Filter;       // Initialized once Sema runs.
+  std::vector<std::string> QueryScopes;      // Initialized once Sema runs.
+  // Include-insertion and proximity scoring rely on the include structure.
+  // This is available after Sema has run.
+  llvm::Optional<IncludeInserter> Inserter;  // Available during runWithSema.
+  llvm::Optional<URIDistance> FileProximity; // Initialized once Sema runs.
+
+public:
+  // A CodeCompleteFlow object is only useful for calling run() exactly once.
+  CodeCompleteFlow(PathRef FileName, const IncludeStructure &Includes,
+                   const CodeCompleteOptions &Opts)
+      : FileName(FileName), Includes(Includes), Opts(Opts) {}
+
+  CodeCompleteResult run(const SemaCompleteInput &SemaCCInput) && {
+    trace::Span Tracer("CodeCompleteFlow");
+
+    // We run Sema code completion first. It builds an AST and calculates:
+    //   - completion results based on the AST.
+    //   - partial identifier and context. We need these for the index query.
+    CodeCompleteResult Output;
+    auto RecorderOwner = llvm::make_unique<CompletionRecorder>(Opts, [&]() {
+      assert(Recorder && "Recorder is not set");
+      auto Style =
+          format::getStyle(format::DefaultFormatStyle, SemaCCInput.FileName,
+                           format::DefaultFallbackStyle, SemaCCInput.Contents,
+                           SemaCCInput.VFS.get());
+      if (!Style) {
+        log("getStyle() failed for file {0}: {1}. Fallback is LLVM style.",
+            SemaCCInput.FileName, Style.takeError());
+        Style = format::getLLVMStyle();
+      }
+      // If preprocessor was run, inclusions from preprocessor callback should
+      // already be added to Includes.
+      Inserter.emplace(
+          SemaCCInput.FileName, SemaCCInput.Contents, *Style,
+          SemaCCInput.Command.Directory,
+          Recorder->CCSema->getPreprocessor().getHeaderSearchInfo());
+      for (const auto &Inc : Includes.MainFileIncludes)
+        Inserter->addExisting(Inc);
+
+      // Most of the cost of file proximity is in initializing the FileDistance
+      // structures based on the observed includes, once per query. Conceptually
+      // that happens here (though the per-URI-scheme initialization is lazy).
+      // The per-result proximity scoring is (amortized) very cheap.
+      FileDistanceOptions ProxOpts{}; // Use defaults.
+      const auto &SM = Recorder->CCSema->getSourceManager();
+      llvm::StringMap<SourceParams> ProxSources;
+      for (auto &Entry : Includes.includeDepth(
+               SM.getFileEntryForID(SM.getMainFileID())->getName())) {
+        auto &Source = ProxSources[Entry.getKey()];
+        Source.Cost = Entry.getValue() * ProxOpts.IncludeCost;
+        // Symbols near our transitive includes are good, but only consider
+        // things in the same directory or below it. Otherwise there can be
+        // many false positives.
+        if (Entry.getValue() > 0)
+          Source.MaxUpTraversals = 1;
+      }
+      FileProximity.emplace(ProxSources, ProxOpts);
+
+      Output = runWithSema();
+      Inserter.reset(); // Make sure this doesn't out-live Clang.
+      SPAN_ATTACH(Tracer, "sema_completion_kind",
+                  getCompletionKindString(Recorder->CCContext.getKind()));
+      log("Code complete: sema context {0}, query scopes [{1}]",
+          getCompletionKindString(Recorder->CCContext.getKind()),
+          llvm::join(QueryScopes.begin(), QueryScopes.end(), ","));
+    });
+
+    Recorder = RecorderOwner.get();
+    semaCodeComplete(std::move(RecorderOwner), Opts.getClangCompleteOpts(),
+                     SemaCCInput, &Includes);
+
+    SPAN_ATTACH(Tracer, "sema_results", NSema);
+    SPAN_ATTACH(Tracer, "index_results", NIndex);
+    SPAN_ATTACH(Tracer, "merged_results", NBoth);
+    SPAN_ATTACH(Tracer, "returned_results", int64_t(Output.Completions.size()));
+    SPAN_ATTACH(Tracer, "incomplete", Output.HasMore);
+    log("Code complete: {0} results from Sema, {1} from Index, "
+        "{2} matched, {3} returned{4}.",
+        NSema, NIndex, NBoth, Output.Completions.size(),
+        Output.HasMore ? " (incomplete)" : "");
+    assert(!Opts.Limit || Output.Completions.size() <= Opts.Limit);
+    // We don't assert that isIncomplete means we hit a limit.
+    // Indexes may choose to impose their own limits even if we don't have one.
+    return Output;
+  }
+
+private:
+  // This is called by run() once Sema code completion is done, but before the
+  // Sema data structures are torn down. It does all the real work.
+  CodeCompleteResult runWithSema() {
+    Filter = FuzzyMatcher(
+        Recorder->CCSema->getPreprocessor().getCodeCompletionFilter());
+    QueryScopes = getQueryScopes(Recorder->CCContext,
+                                 Recorder->CCSema->getSourceManager());
+    // Sema provides the needed context to query the index.
+    // FIXME: in addition to querying for extra/overlapping symbols, we should
+    //        explicitly request symbols corresponding to Sema results.
+    //        We can use their signals even if the index can't suggest them.
+    // We must copy index results to preserve them, but there are at most Limit.
+    auto IndexResults = (Opts.Index && allowIndex(Recorder->CCContext))
+                            ? queryIndex()
+                            : SymbolSlab();
+    // Merge Sema and Index results, score them, and pick the winners.
+    auto Top = mergeResults(Recorder->Results, IndexResults);
+    // Convert the results to final form, assembling the expensive strings.
+    CodeCompleteResult Output;
+    for (auto &C : Top) {
+      Output.Completions.push_back(toCodeCompletion(C.first));
+      Output.Completions.back().Score = C.second;
+    }
+    Output.HasMore = Incomplete;
+    Output.Context = Recorder->CCContext.getKind();
+    return Output;
+  }
+
+  SymbolSlab queryIndex() {
+    trace::Span Tracer("Query index");
+    SPAN_ATTACH(Tracer, "limit", int64_t(Opts.Limit));
+
+    SymbolSlab::Builder ResultsBuilder;
+    // Build the query.
+    FuzzyFindRequest Req;
+    if (Opts.Limit)
+      Req.MaxCandidateCount = Opts.Limit;
+    Req.Query = Filter->pattern();
+    Req.RestrictForCodeCompletion = true;
+    Req.Scopes = QueryScopes;
+    // FIXME: we should send multiple weighted paths here.
+    Req.ProximityPaths.push_back(FileName);
+    vlog("Code complete: fuzzyFind(\"{0}\", scopes=[{1}])", Req.Query,
+         llvm::join(Req.Scopes.begin(), Req.Scopes.end(), ","));
+    // Run the query against the index.
+    if (Opts.Index->fuzzyFind(
+            Req, [&](const Symbol &Sym) { ResultsBuilder.insert(Sym); }))
+      Incomplete = true;
+    return std::move(ResultsBuilder).build();
+  }
+
+  // Merges Sema and Index results where possible, to form CompletionCandidates.
+  // Groups overloads if desired, to form CompletionCandidate::Bundles.
+  // The bundles are scored and top results are returned, best to worst.
+  std::vector<ScoredBundle>
+  mergeResults(const std::vector<CodeCompletionResult> &SemaResults,
+               const SymbolSlab &IndexResults) {
+    trace::Span Tracer("Merge and score results");
+    std::vector<CompletionCandidate::Bundle> Bundles;
+    llvm::DenseMap<size_t, size_t> BundleLookup;
+    auto AddToBundles = [&](const CodeCompletionResult *SemaResult,
+                            const Symbol *IndexResult) {
+      CompletionCandidate C;
+      C.SemaResult = SemaResult;
+      C.IndexResult = IndexResult;
+      C.Name = IndexResult ? IndexResult->Name : Recorder->getName(*SemaResult);
+      if (auto OverloadSet = Opts.BundleOverloads ? C.overloadSet() : 0) {
+        auto Ret = BundleLookup.try_emplace(OverloadSet, Bundles.size());
+        if (Ret.second)
+          Bundles.emplace_back();
+        Bundles[Ret.first->second].push_back(std::move(C));
+      } else {
+        Bundles.emplace_back();
+        Bundles.back().push_back(std::move(C));
+      }
+    };
+    llvm::DenseSet<const Symbol *> UsedIndexResults;
+    auto CorrespondingIndexResult =
+        [&](const CodeCompletionResult &SemaResult) -> const Symbol * {
+      if (auto SymID = getSymbolID(SemaResult)) {
+        auto I = IndexResults.find(*SymID);
+        if (I != IndexResults.end()) {
+          UsedIndexResults.insert(&*I);
+          return &*I;
+        }
+      }
+      return nullptr;
+    };
+    // Emit all Sema results, merging them with Index results if possible.
+    for (auto &SemaResult : Recorder->Results)
+      AddToBundles(&SemaResult, CorrespondingIndexResult(SemaResult));
+    // Now emit any Index-only results.
+    for (const auto &IndexResult : IndexResults) {
+      if (UsedIndexResults.count(&IndexResult))
+        continue;
+      AddToBundles(/*SemaResult=*/nullptr, &IndexResult);
+    }
+    // We only keep the best N results at any time, in "native" format.
+    TopN<ScoredBundle, ScoredBundleGreater> Top(
+        Opts.Limit == 0 ? std::numeric_limits<size_t>::max() : Opts.Limit);
+    for (auto &Bundle : Bundles)
+      addCandidate(Top, std::move(Bundle));
+    return std::move(Top).items();
+  }
+
+  Optional<float> fuzzyScore(const CompletionCandidate &C) {
+    // Macros can be very spammy, so we only support prefix completion.
+    // We won't end up with underfull index results, as macros are sema-only.
+    if (C.SemaResult && C.SemaResult->Kind == CodeCompletionResult::RK_Macro &&
+        !C.Name.startswith_lower(Filter->pattern()))
+      return None;
+    return Filter->match(C.Name);
+  }
+
+  // Scores a candidate and adds it to the TopN structure.
+  void addCandidate(TopN<ScoredBundle, ScoredBundleGreater> &Candidates,
+                    CompletionCandidate::Bundle Bundle) {
+    SymbolQualitySignals Quality;
+    SymbolRelevanceSignals Relevance;
+    Relevance.Context = Recorder->CCContext.getKind();
+    Relevance.Query = SymbolRelevanceSignals::CodeComplete;
+    Relevance.FileProximityMatch = FileProximity.getPointer();
+    auto &First = Bundle.front();
+    if (auto FuzzyScore = fuzzyScore(First))
+      Relevance.NameMatch = *FuzzyScore;
+    else
+      return;
+    SymbolOrigin Origin = SymbolOrigin::Unknown;
+    bool FromIndex = false;
+    for (const auto &Candidate : Bundle) {
+      if (Candidate.IndexResult) {
+        Quality.merge(*Candidate.IndexResult);
+        Relevance.merge(*Candidate.IndexResult);
+        Origin |= Candidate.IndexResult->Origin;
+        FromIndex = true;
+      }
+      if (Candidate.SemaResult) {
+        Quality.merge(*Candidate.SemaResult);
+        Relevance.merge(*Candidate.SemaResult);
+        Origin |= SymbolOrigin::AST;
+      }
+    }
+
+    CodeCompletion::Scores Scores;
+    Scores.Quality = Quality.evaluate();
+    Scores.Relevance = Relevance.evaluate();
+    Scores.Total = evaluateSymbolAndRelevance(Scores.Quality, Scores.Relevance);
+    // NameMatch is in fact a multiplier on total score, so rescoring is sound.
+    Scores.ExcludingName = Relevance.NameMatch
+                               ? Scores.Total / Relevance.NameMatch
+                               : Scores.Quality;
+
+    dlog("CodeComplete: {0} ({1}) = {2}\n{3}{4}\n", First.Name,
+         llvm::to_string(Origin), Scores.Total, llvm::to_string(Quality),
+         llvm::to_string(Relevance));
+
+    NSema += bool(Origin & SymbolOrigin::AST);
+    NIndex += FromIndex;
+    NBoth += bool(Origin & SymbolOrigin::AST) && FromIndex;
+    if (Candidates.push({std::move(Bundle), Scores}))
+      Incomplete = true;
+  }
+
+  CodeCompletion toCodeCompletion(const CompletionCandidate::Bundle &Bundle) {
+    llvm::Optional<CodeCompletionBuilder> Builder;
+    for (const auto &Item : Bundle) {
+      CodeCompletionString *SemaCCS =
+          Item.SemaResult ? Recorder->codeCompletionString(*Item.SemaResult)
+                          : nullptr;
+      if (!Builder)
+        Builder.emplace(Recorder->CCSema->getASTContext(), Item, SemaCCS,
+                        *Inserter, FileName, Opts);
+      else
+        Builder->add(Item, SemaCCS);
+    }
+    return Builder->build();
+  }
+};
+
+CodeCompleteResult codeComplete(PathRef FileName,
+                                const tooling::CompileCommand &Command,
+                                PrecompiledPreamble const *Preamble,
+                                const IncludeStructure &PreambleInclusions,
+                                StringRef Contents, Position Pos,
+                                IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                                std::shared_ptr<PCHContainerOperations> PCHs,
+                                CodeCompleteOptions Opts) {
+  return CodeCompleteFlow(FileName, PreambleInclusions, Opts)
+      .run({FileName, Command, Preamble, Contents, Pos, VFS, PCHs});
+}
+
+SignatureHelp signatureHelp(PathRef FileName,
+                            const tooling::CompileCommand &Command,
+                            PrecompiledPreamble const *Preamble,
+                            StringRef Contents, Position Pos,
+                            IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                            std::shared_ptr<PCHContainerOperations> PCHs) {
+  SignatureHelp Result;
+  clang::CodeCompleteOptions Options;
+  Options.IncludeGlobals = false;
+  Options.IncludeMacros = false;
+  Options.IncludeCodePatterns = false;
+  Options.IncludeBriefComments = false;
+  IncludeStructure PreambleInclusions; // Unused for signatureHelp
+  semaCodeComplete(llvm::make_unique<SignatureHelpCollector>(Options, Result),
+                   Options,
+                   {FileName, Command, Preamble, Contents, Pos, std::move(VFS),
+                    std::move(PCHs)});
+  return Result;
+}
+
+bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx) {
+  using namespace clang::ast_matchers;
+  auto InTopLevelScope = hasDeclContext(
+      anyOf(namespaceDecl(), translationUnitDecl(), linkageSpecDecl()));
+  return !match(decl(anyOf(InTopLevelScope,
+                           hasDeclContext(
+                               enumDecl(InTopLevelScope, unless(isScoped()))))),
+                ND, ASTCtx)
+              .empty();
+}
+
+CompletionItem CodeCompletion::render(const CodeCompleteOptions &Opts) const {
+  CompletionItem LSP;
+  LSP.label = (HeaderInsertion ? Opts.IncludeIndicator.Insert
+                               : Opts.IncludeIndicator.NoInsert) +
+              (Opts.ShowOrigins ? "[" + llvm::to_string(Origin) + "]" : "") +
+              RequiredQualifier + Name + Signature;
+
+  LSP.kind = Kind;
+  LSP.detail = BundleSize > 1 ? llvm::formatv("[{0} overloads]", BundleSize)
+                              : ReturnType;
+  if (!Header.empty())
+    LSP.detail += "\n" + Header;
+  LSP.documentation = Documentation;
+  LSP.sortText = sortText(Score.Total, Name);
+  LSP.filterText = Name;
+  LSP.insertText = RequiredQualifier + Name;
+  if (Opts.EnableSnippets)
+    LSP.insertText += SnippetSuffix;
+  LSP.insertTextFormat = Opts.EnableSnippets ? InsertTextFormat::Snippet
+                                             : InsertTextFormat::PlainText;
+  if (HeaderInsertion)
+    LSP.additionalTextEdits = {*HeaderInsertion};
+  return LSP;
+}
+
+raw_ostream &operator<<(raw_ostream &OS, const CodeCompletion &C) {
+  // For now just lean on CompletionItem.
+  return OS << C.render(CodeCompleteOptions());
+}
+
+raw_ostream &operator<<(raw_ostream &OS, const CodeCompleteResult &R) {
+  OS << "CodeCompleteResult: " << R.Completions.size() << (R.HasMore ? "+" : "")
+     << " (" << getCompletionKindString(R.Context) << ")"
+     << " items:\n";
+  for (const auto &C : R.Completions)
+    OS << C << "\n";
+  return OS;
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/CodeComplete.h b/src/third_party/llvm-project/clang-tools-extra/clangd/CodeComplete.h
new file mode 100644
index 0000000..884149d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/CodeComplete.h
@@ -0,0 +1,184 @@
+//===--- CodeComplete.h -----------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// Code completion provides suggestions for what the user might type next.
+// After "std::string S; S." we might suggest members of std::string.
+// Signature help describes the parameters of a function as you type them.
+//
+//===---------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
+
+#include "Headers.h"
+#include "Logger.h"
+#include "Path.h"
+#include "Protocol.h"
+#include "index/Index.h"
+#include "clang/Frontend/PrecompiledPreamble.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/CodeCompleteOptions.h"
+#include "clang/Tooling/CompilationDatabase.h"
+
+namespace clang {
+class NamedDecl;
+class PCHContainerOperations;
+namespace clangd {
+
+struct CodeCompleteOptions {
+  /// Returns options that can be passed to clang's completion engine.
+  clang::CodeCompleteOptions getClangCompleteOpts() const;
+
+  /// When true, completion items will contain expandable code snippets in
+  /// completion (e.g.  `return ${1:expression}` or `foo(${1:int a}, ${2:int
+  /// b})).
+  bool EnableSnippets = false;
+
+  /// Add code patterns to completion results.
+  /// If EnableSnippets is false, this options is ignored and code patterns will
+  /// always be omitted.
+  bool IncludeCodePatterns = true;
+
+  /// Add macros to code completion results.
+  bool IncludeMacros = true;
+
+  /// Add comments to code completion results, if available.
+  bool IncludeComments = true;
+
+  /// Include results that are not legal completions in the current context.
+  /// For example, private members are usually inaccessible.
+  bool IncludeIneligibleResults = false;
+
+  /// Combine overloads into a single completion item where possible.
+  bool BundleOverloads = false;
+
+  /// Limit the number of results returned (0 means no limit).
+  /// If more results are available, we set CompletionList.isIncomplete.
+  size_t Limit = 0;
+
+  /// A visual indicator to prepend to the completion label to indicate whether
+  /// completion result would trigger an #include insertion or not.
+  struct IncludeInsertionIndicator {
+    std::string Insert = "•";
+    std::string NoInsert = " ";
+  } IncludeIndicator;
+
+  /// Expose origins of completion items in the label (for debugging).
+  bool ShowOrigins = false;
+
+  // Populated internally by clangd, do not set.
+  /// If `Index` is set, it is used to augment the code completion
+  /// results.
+  /// FIXME(ioeric): we might want a better way to pass the index around inside
+  /// clangd.
+  const SymbolIndex *Index = nullptr;
+};
+
+// Semi-structured representation of a code-complete suggestion for our C++ API.
+// We don't use the LSP structures here (unlike most features) as we want
+// to expose more data to allow for more precise testing and evaluation.
+struct CodeCompletion {
+  // The unqualified name of the symbol or other completion item.
+  std::string Name;
+  // The scope qualifier for the symbol name. e.g. "ns1::ns2::"
+  // Empty for non-symbol completions. Not inserted, but may be displayed.
+  std::string Scope;
+  // Text that must be inserted before the name, and displayed (e.g. base::).
+  std::string RequiredQualifier;
+  // Details to be displayed following the name. Not inserted.
+  std::string Signature;
+  // Text to be inserted following the name, in snippet format.
+  std::string SnippetSuffix;
+  // Type to be displayed for this completion.
+  std::string ReturnType;
+  std::string Documentation;
+  CompletionItemKind Kind = CompletionItemKind::Missing;
+  // This completion item may represent several symbols that can be inserted in
+  // the same way, such as function overloads. In this case BundleSize > 1, and
+  // the following fields are summaries:
+  //  - Signature is e.g. "(...)" for functions.
+  //  - SnippetSuffix is similarly e.g. "(${0})".
+  //  - ReturnType may be empty
+  //  - Documentation may be from one symbol, or a combination of several
+  // Other fields should apply equally to all bundled completions.
+  unsigned BundleSize = 1;
+  SymbolOrigin Origin = SymbolOrigin::Unknown;
+  // The header through which this symbol could be included.
+  // Quoted string as expected by an #include directive, e.g. "<memory>".
+  // Empty for non-symbol completions, or when not known.
+  std::string Header;
+  // Present if Header is set and should be inserted to use this item.
+  llvm::Optional<TextEdit> HeaderInsertion;
+
+  // Scores are used to rank completion items.
+  struct Scores {
+    // The score that items are ranked by.
+    float Total = 0.f;
+
+    // The finalScore with the fuzzy name match score excluded.
+    // When filtering client-side, editors should calculate the new fuzzy score,
+    // whose scale is 0-1 (with 1 = prefix match, special case 2 = exact match),
+    // and recompute finalScore = fuzzyScore * symbolScore.
+    float ExcludingName = 0.f;
+
+    // Component scores that contributed to the final score:
+
+    // Quality describes how important we think this candidate is,
+    // independent of the query.
+    // e.g. symbols with lots of incoming references have higher quality.
+    float Quality = 0.f;
+    // Relevance describes how well this candidate matched the query.
+    // e.g. symbols from nearby files have higher relevance.
+    float Relevance = 0.f;
+  };
+  Scores Score;
+
+  // Serialize this to an LSP completion item. This is a lossy operation.
+  CompletionItem render(const CodeCompleteOptions &) const;
+};
+raw_ostream &operator<<(raw_ostream &, const CodeCompletion &);
+struct CodeCompleteResult {
+  std::vector<CodeCompletion> Completions;
+  bool HasMore = false;
+  CodeCompletionContext::Kind Context = CodeCompletionContext::CCC_Other;
+};
+raw_ostream &operator<<(raw_ostream &, const CodeCompleteResult &);
+
+/// Get code completions at a specified \p Pos in \p FileName.
+CodeCompleteResult codeComplete(PathRef FileName,
+                                const tooling::CompileCommand &Command,
+                                PrecompiledPreamble const *Preamble,
+                                const IncludeStructure &PreambleInclusions,
+                                StringRef Contents, Position Pos,
+                                IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                                std::shared_ptr<PCHContainerOperations> PCHs,
+                                CodeCompleteOptions Opts);
+
+/// Get signature help at a specified \p Pos in \p FileName.
+SignatureHelp signatureHelp(PathRef FileName,
+                            const tooling::CompileCommand &Command,
+                            PrecompiledPreamble const *Preamble,
+                            StringRef Contents, Position Pos,
+                            IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                            std::shared_ptr<PCHContainerOperations> PCHs);
+
+// For index-based completion, we only consider:
+//   * symbols in namespaces or translation unit scopes (e.g. no class
+//     members, no locals)
+//   * enum constants in unscoped enum decl (e.g. "red" in "enum {red};")
+//   * primary templates (no specializations)
+// For the other cases, we let Clang do the completion because it does not
+// need any non-local information and it will be much better at following
+// lookup rules. Other symbols still appear in the index for other purposes,
+// like workspace/symbols or textDocument/definition, but are not used for code
+// completion.
+bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx);
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/CodeCompletionStrings.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/CodeCompletionStrings.cpp
new file mode 100644
index 0000000..88b37da
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/CodeCompletionStrings.cpp
@@ -0,0 +1,204 @@
+//===--- CodeCompletionStrings.cpp -------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "CodeCompletionStrings.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/RawCommentList.h"
+#include "clang/Basic/SourceManager.h"
+#include <utility>
+
+namespace clang {
+namespace clangd {
+
+namespace {
+
+bool isInformativeQualifierChunk(CodeCompletionString::Chunk const &Chunk) {
+  return Chunk.Kind == CodeCompletionString::CK_Informative &&
+         StringRef(Chunk.Text).endswith("::");
+}
+
+void appendEscapeSnippet(const llvm::StringRef Text, std::string *Out) {
+  for (const auto Character : Text) {
+    if (Character == '$' || Character == '}' || Character == '\\')
+      Out->push_back('\\');
+    Out->push_back(Character);
+  }
+}
+
+bool looksLikeDocComment(llvm::StringRef CommentText) {
+  // We don't report comments that only contain "special" chars.
+  // This avoids reporting various delimiters, like:
+  //   =================
+  //   -----------------
+  //   *****************
+  return CommentText.find_first_not_of("/*-= \t\r\n") != llvm::StringRef::npos;
+}
+
+} // namespace
+
+std::string getDocComment(const ASTContext &Ctx,
+                          const CodeCompletionResult &Result,
+                          bool CommentsFromHeaders) {
+  // FIXME: clang's completion also returns documentation for RK_Pattern if they
+  // contain a pattern for ObjC properties. Unfortunately, there is no API to
+  // get this declaration, so we don't show documentation in that case.
+  if (Result.Kind != CodeCompletionResult::RK_Declaration)
+    return "";
+  auto *Decl = Result.getDeclaration();
+  if (!Decl || llvm::isa<NamespaceDecl>(Decl)) {
+    // Namespaces often have too many redecls for any particular redecl comment
+    // to be useful. Moreover, we often confuse file headers or generated
+    // comments with namespace comments. Therefore we choose to just ignore
+    // the comments for namespaces.
+    return "";
+  }
+  const RawComment *RC = getCompletionComment(Ctx, Decl);
+  if (!RC)
+    return "";
+
+  // Sanity check that the comment does not come from the PCH. We choose to not
+  // write them into PCH, because they are racy and slow to load.
+  assert(!Ctx.getSourceManager().isLoadedSourceLocation(RC->getLocStart()));
+  std::string Doc = RC->getFormattedText(Ctx.getSourceManager(), Ctx.getDiagnostics());
+  if (!looksLikeDocComment(Doc))
+    return "";
+  return Doc;
+}
+
+std::string
+getParameterDocComment(const ASTContext &Ctx,
+                       const CodeCompleteConsumer::OverloadCandidate &Result,
+                       unsigned ArgIndex, bool CommentsFromHeaders) {
+  auto *Func = Result.getFunction();
+  if (!Func)
+    return "";
+  const RawComment *RC = getParameterComment(Ctx, Result, ArgIndex);
+  if (!RC)
+    return "";
+  // Sanity check that the comment does not come from the PCH. We choose to not
+  // write them into PCH, because they are racy and slow to load.
+  assert(!Ctx.getSourceManager().isLoadedSourceLocation(RC->getLocStart()));
+  std::string Doc = RC->getFormattedText(Ctx.getSourceManager(), Ctx.getDiagnostics());
+  if (!looksLikeDocComment(Doc))
+    return "";
+  return Doc;
+}
+
+void getSignature(const CodeCompletionString &CCS, std::string *Signature,
+                  std::string *Snippet, std::string *RequiredQualifiers) {
+  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 typed-text chunk is the actual name. We don't record this chunk.
+      // In general our string looks like <qualifiers><name><signature>.
+      // So once we see the name, any text we recorded so far should be
+      // reclassified as qualifiers.
+      if (RequiredQualifiers)
+        *RequiredQualifiers = std::move(*Signature);
+      Signature->clear();
+      Snippet->clear();
+      break;
+    case CodeCompletionString::CK_Text:
+      *Signature += Chunk.Text;
+      *Snippet += Chunk.Text;
+      break;
+    case CodeCompletionString::CK_Optional:
+      break;
+    case CodeCompletionString::CK_Placeholder:
+      *Signature += Chunk.Text;
+      ++ArgCount;
+      *Snippet += "${" + std::to_string(ArgCount) + ':';
+      appendEscapeSnippet(Chunk.Text, Snippet);
+      *Snippet += '}';
+      break;
+    case CodeCompletionString::CK_Informative:
+      // 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.
+      *Signature += Chunk.Text;
+      // Don't put the informative chunks in the snippet.
+      break;
+    case CodeCompletionString::CK_ResultType:
+      // This is not part of the signature.
+      break;
+    case CodeCompletionString::CK_CurrentParameter:
+      // 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:
+    case CodeCompletionString::CK_RightParen:
+    case CodeCompletionString::CK_LeftBracket:
+    case CodeCompletionString::CK_RightBracket:
+    case CodeCompletionString::CK_LeftBrace:
+    case CodeCompletionString::CK_RightBrace:
+    case CodeCompletionString::CK_LeftAngle:
+    case CodeCompletionString::CK_RightAngle:
+    case CodeCompletionString::CK_Comma:
+    case CodeCompletionString::CK_Colon:
+    case CodeCompletionString::CK_SemiColon:
+    case CodeCompletionString::CK_Equal:
+    case CodeCompletionString::CK_HorizontalSpace:
+      *Signature += Chunk.Text;
+      *Snippet += Chunk.Text;
+      break;
+    case CodeCompletionString::CK_VerticalSpace:
+      *Snippet += Chunk.Text;
+      // Don't even add a space to the signature.
+      break;
+    }
+  }
+}
+
+std::string formatDocumentation(const CodeCompletionString &CCS,
+                                llvm::StringRef DocComment) {
+  // 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 (!DocComment.empty()) {
+    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 += DocComment;
+  }
+  return Result;
+}
+
+std::string getReturnType(const CodeCompletionString &CCS) {
+  for (const auto &Chunk : CCS)
+    if (Chunk.Kind == CodeCompletionString::CK_ResultType)
+      return Chunk.Text;
+  return "";
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/CodeCompletionStrings.h b/src/third_party/llvm-project/clang-tools-extra/clangd/CodeCompletionStrings.h
new file mode 100644
index 0000000..dac4ba5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/CodeCompletionStrings.h
@@ -0,0 +1,73 @@
+//===--- CodeCompletionStrings.h ---------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// Functions for retrieving code completion information from
+// `CodeCompletionString`.
+//
+//===---------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETIONSTRINGS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETIONSTRINGS_H
+
+#include "clang/Sema/CodeCompleteConsumer.h"
+
+namespace clang {
+class ASTContext;
+
+namespace clangd {
+
+/// Gets a minimally formatted documentation comment of \p Result, with comment
+/// markers stripped. See clang::RawComment::getFormattedText() for the detailed
+/// explanation of how the comment text is transformed.
+/// Returns empty string when no comment is available.
+/// If \p CommentsFromHeaders parameter is set, only comments from the main
+/// file will be returned. It is used to workaround crashes when parsing
+/// comments in the stale headers, coming from completion preamble.
+std::string getDocComment(const ASTContext &Ctx,
+                          const CodeCompletionResult &Result,
+                          bool CommentsFromHeaders);
+
+/// Gets a minimally formatted documentation for parameter of \p Result,
+/// corresponding to argument number \p ArgIndex.
+/// This currently looks for comments attached to the parameter itself, and
+/// doesn't extract them from function documentation.
+/// Returns empty string when no comment is available.
+/// If \p CommentsFromHeaders parameter is set, only comments from the main
+/// file will be returned. It is used to workaround crashes when parsing
+/// comments in the stale headers, coming from completion preamble.
+std::string
+getParameterDocComment(const ASTContext &Ctx,
+                       const CodeCompleteConsumer::OverloadCandidate &Result,
+                       unsigned ArgIndex, bool CommentsFromHeaders);
+
+/// Formats the signature for an item, as a display string and snippet.
+/// e.g. for const_reference std::vector<T>::at(size_type) const, this returns:
+///   *Signature = "(size_type) const"
+///   *Snippet = "(${0:size_type})"
+/// If set, RequiredQualifiers is the text that must be typed before the name.
+/// e.g "Base::" when calling a base class member function that's hidden.
+void getSignature(const CodeCompletionString &CCS, std::string *Signature,
+                  std::string *Snippet,
+                  std::string *RequiredQualifiers = nullptr);
+
+/// Assembles formatted documentation for a completion result. This includes
+/// documentation comments and other relevant information like annotations.
+///
+/// \param DocComment is a documentation comment for the original declaration,
+///        it should be obtained via getDocComment or getParameterDocComment.
+std::string formatDocumentation(const CodeCompletionString &CCS,
+                                llvm::StringRef DocComment);
+
+/// Gets detail to be used as the detail field in an LSP completion item. This
+/// is usually the return type of a function.
+std::string getReturnType(const CodeCompletionString &CCS);
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Compiler.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/Compiler.cpp
new file mode 100644
index 0000000..8fcc9a9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Compiler.cpp
@@ -0,0 +1,84 @@
+//===--- Compiler.cpp -------------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "Compiler.h"
+#include "Logger.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
+
+namespace clang {
+namespace clangd {
+
+void IgnoreDiagnostics::log(DiagnosticsEngine::Level DiagLevel,
+                            const clang::Diagnostic &Info) {
+  SmallString<64> Message;
+  Info.FormatDiagnostic(Message);
+
+  SmallString<64> Location;
+  if (Info.hasSourceManager() && Info.getLocation().isValid()) {
+    auto &SourceMgr = Info.getSourceManager();
+    auto Loc = SourceMgr.getFileLoc(Info.getLocation());
+    llvm::raw_svector_ostream OS(Location);
+    Loc.print(OS, SourceMgr);
+    OS << ":";
+  }
+
+  clangd::log("Ignored diagnostic. {0}{1}", Location, Message);
+}
+
+void IgnoreDiagnostics::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+                                         const clang::Diagnostic &Info) {
+  IgnoreDiagnostics::log(DiagLevel, Info);
+}
+
+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->OverridePreamble(*CI, VFS, 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;
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Compiler.h b/src/third_party/llvm-project/clang-tools-extra/clangd/Compiler.h
new file mode 100644
index 0000000..ce058ad
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Compiler.h
@@ -0,0 +1,53 @@
+//===--- Compiler.h ---------------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// Shared utilities for invoking the clang compiler.
+// ClangdUnit takes care of much of this, but some features like CodeComplete
+// run their own compile actions that share logic.
+//
+//===---------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_COMPILER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_COMPILER_H
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/PrecompiledPreamble.h"
+
+namespace clang {
+namespace clangd {
+
+class IgnoreDiagnostics : public DiagnosticConsumer {
+public:
+  static void log(DiagnosticsEngine::Level DiagLevel,
+                  const clang::Diagnostic &Info);
+
+  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+                        const clang::Diagnostic &Info) override;
+};
+
+/// Creates a compiler instance, configured so that:
+///   - Contents of the parsed file are remapped to \p MainFile.
+///   - Preamble is overriden to use PCH passed to this function. It means the
+///     changes to the preamble headers or files included in the preamble are
+///     not visible to this compiler instance.
+///   - vfs::FileSystem is used for all underlying file accesses. The actual
+///     vfs used by the compiler may be an overlay over the passed vfs.
+/// Returns null on errors. When non-null value is returned, it is expected to
+/// be consumed by FrontendAction::BeginSourceFile to properly destroy \p
+/// MainFile.
+std::unique_ptr<CompilerInstance> prepareCompilerInstance(
+    std::unique_ptr<clang::CompilerInvocation>, const PrecompiledPreamble *,
+    std::unique_ptr<llvm::MemoryBuffer> MainFile,
+    std::shared_ptr<PCHContainerOperations>,
+    IntrusiveRefCntPtr<vfs::FileSystem>, DiagnosticConsumer &);
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Context.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/Context.cpp
new file mode 100644
index 0000000..1a9ef24
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Context.cpp
@@ -0,0 +1,36 @@
+//===--- Context.cpp -----------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "Context.h"
+#include <cassert>
+
+namespace clang {
+namespace clangd {
+
+Context Context::empty() { return Context(/*DataPtr=*/nullptr); }
+
+Context::Context(std::shared_ptr<const Data> DataPtr)
+    : DataPtr(std::move(DataPtr)) {}
+
+Context Context::clone() const { return Context(DataPtr); }
+
+static Context &currentContext() {
+  static thread_local auto C = Context::empty();
+  return C;
+}
+
+const Context &Context::current() { return currentContext(); }
+
+Context Context::swapCurrent(Context Replacement) {
+  std::swap(Replacement, currentContext());
+  return Replacement;
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Context.h b/src/third_party/llvm-project/clang-tools-extra/clangd/Context.h
new file mode 100644
index 0000000..7e14f86
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Context.h
@@ -0,0 +1,223 @@
+//===--- Context.h - Mechanism for passing implicit data --------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Context for storing and retrieving implicit data. Useful for passing implicit
+// parameters on a per-request basis.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CONTEXT_H_
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CONTEXT_H_
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Compiler.h"
+#include <memory>
+#include <type_traits>
+
+namespace clang {
+namespace clangd {
+
+/// Values in a Context are indexed by typed keys.
+/// Key<T> serves two purposes:
+///   - it provides a lookup key for the context (each Key is unique),
+///   - it makes lookup type-safe: a Key<T> can only map to a T (or nothing).
+///
+/// Example:
+///    Key<int> RequestID;
+///    Key<int> Version;
+///
+///    Context Ctx = Context::empty().derive(RequestID, 10).derive(Version, 3);
+///    assert(*Ctx.get(RequestID) == 10);
+///    assert(*Ctx.get(Version) == 3);
+///
+/// Keys are typically used across multiple functions, so most of the time you
+/// would want to make them static class members or global variables.
+template <class Type> class Key {
+public:
+  static_assert(!std::is_reference<Type>::value,
+                "Reference arguments to Key<> are not allowed");
+
+  constexpr Key() = default;
+
+  Key(Key const &) = delete;
+  Key &operator=(Key const &) = delete;
+  Key(Key &&) = delete;
+  Key &operator=(Key &&) = delete;
+};
+
+/// A context is an immutable container for per-request data that must be
+/// propagated through layers that don't care about it. An example is a request
+/// ID that we may want to use when logging.
+///
+/// Conceptually, a context is a heterogeneous map<Key<T>, T>. Each key has
+/// an associated value type, which allows the map to be typesafe.
+///
+/// There is an "ambient" context for each thread, Context::current().
+/// Most functions should read from this, and use WithContextValue or
+/// WithContext to extend or replace the context within a block scope.
+/// Only code dealing with threads and extension points should need to use
+/// other Context objects.
+///
+/// You can't add data to an existing context, instead you create a new
+/// immutable context derived from it with extra data added. When you retrieve
+/// data, the context will walk up the parent chain until the key is found.
+class Context {
+public:
+  /// Returns an empty root context that contains no data.
+  static Context empty();
+  /// Returns the context for the current thread, creating it if needed.
+  static const Context &current();
+  // Sets the current() context to Replacement, and returns the old context.
+  // Prefer to use WithContext or WithContextValue to do this safely.
+  static Context swapCurrent(Context Replacement);
+
+private:
+  struct Data;
+  Context(std::shared_ptr<const Data> DataPtr);
+
+public:
+  /// Same as Context::empty(), please use Context::empty() instead.
+  /// Constructor is defined to workaround a bug in MSVC's version of STL.
+  /// (arguments of std::future<> must be default-construcitble in MSVC).
+  Context() = default;
+
+  /// Copy operations for this class are deleted, use an explicit clone() method
+  /// when you need a copy of the context instead.
+  Context(Context const &) = delete;
+  Context &operator=(const Context &) = delete;
+
+  Context(Context &&) = default;
+  Context &operator=(Context &&) = default;
+
+  /// Get data stored for a typed \p Key. If values are not found
+  /// \returns Pointer to the data associated with \p Key. If no data is
+  /// specified for \p Key, return null.
+  template <class Type> const Type *get(const Key<Type> &Key) const {
+    for (const Data *DataPtr = this->DataPtr.get(); DataPtr != nullptr;
+         DataPtr = DataPtr->Parent.get()) {
+      if (DataPtr->KeyPtr == &Key)
+        return static_cast<const Type *>(DataPtr->Value->getValuePtr());
+    }
+    return nullptr;
+  }
+
+  /// A helper to get a reference to a \p Key that must exist in the map.
+  /// Must not be called for keys that are not in the map.
+  template <class Type> const Type &getExisting(const Key<Type> &Key) const {
+    auto Val = get(Key);
+    assert(Val && "Key does not exist");
+    return *Val;
+  }
+
+  /// Derives a child context
+  /// It is safe to move or destroy a parent context after calling derive().
+  /// The child will keep its parent alive, and its data remains accessible.
+  template <class Type>
+  Context derive(const Key<Type> &Key,
+                 typename std::decay<Type>::type Value) const & {
+    return Context(std::make_shared<Data>(Data{
+        /*Parent=*/DataPtr, &Key,
+        llvm::make_unique<TypedAnyStorage<typename std::decay<Type>::type>>(
+            std::move(Value))}));
+  }
+
+  template <class Type>
+  Context
+  derive(const Key<Type> &Key,
+         typename std::decay<Type>::type Value) && /* takes ownership */ {
+    return Context(std::make_shared<Data>(Data{
+        /*Parent=*/std::move(DataPtr), &Key,
+        llvm::make_unique<TypedAnyStorage<typename std::decay<Type>::type>>(
+            std::move(Value))}));
+  }
+
+  /// Derives a child context, using an anonymous key.
+  /// Intended for objects stored only for their destructor's side-effect.
+  template <class Type> Context derive(Type &&Value) const & {
+    static Key<typename std::decay<Type>::type> Private;
+    return derive(Private, std::forward<Type>(Value));
+  }
+
+  template <class Type> Context derive(Type &&Value) && {
+    static Key<typename std::decay<Type>::type> Private;
+    return std::move(*this).derive(Private, std::forward<Type>(Value));
+  }
+
+  /// Clone this context object.
+  Context clone() const;
+
+private:
+  class AnyStorage {
+  public:
+    virtual ~AnyStorage() = default;
+    virtual void *getValuePtr() = 0;
+  };
+
+  template <class T> class TypedAnyStorage : public Context::AnyStorage {
+    static_assert(std::is_same<typename std::decay<T>::type, T>::value,
+                  "Argument to TypedAnyStorage must be decayed");
+
+  public:
+    TypedAnyStorage(T &&Value) : Value(std::move(Value)) {}
+
+    void *getValuePtr() override { return &Value; }
+
+  private:
+    T Value;
+  };
+
+  struct Data {
+    // We need to make sure Parent outlives the Value, so the order of members
+    // is important. We do that to allow classes stored in Context's child
+    // layers to store references to the data in the parent layers.
+    std::shared_ptr<const Data> Parent;
+    const void *KeyPtr;
+    std::unique_ptr<AnyStorage> Value;
+  };
+
+  std::shared_ptr<const Data> DataPtr;
+};
+
+/// WithContext replaces Context::current() with a provided scope.
+/// When the WithContext is destroyed, the original scope is restored.
+/// For extending the current context with new value, prefer WithContextValue.
+class LLVM_NODISCARD WithContext {
+public:
+  WithContext(Context C) : Restore(Context::swapCurrent(std::move(C))) {}
+  ~WithContext() { Context::swapCurrent(std::move(Restore)); }
+  WithContext(const WithContext &) = delete;
+  WithContext &operator=(const WithContext &) = delete;
+  WithContext(WithContext &&) = delete;
+  WithContext &operator=(WithContext &&) = delete;
+
+private:
+  Context Restore;
+};
+
+/// WithContextValue extends Context::current() with a single value.
+/// When the WithContextValue is destroyed, the original scope is restored.
+class LLVM_NODISCARD WithContextValue {
+public:
+  template <typename T>
+  WithContextValue(const Key<T> &K, typename std::decay<T>::type V)
+      : Restore(Context::current().derive(K, std::move(V))) {}
+
+  // Anonymous values can be used for the destructor side-effect.
+  template <typename T>
+  WithContextValue(T &&V)
+      : Restore(Context::current().derive(std::forward<T>(V))) {}
+
+private:
+  WithContext Restore;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_CONTEXT_H_
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Diagnostics.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/Diagnostics.cpp
new file mode 100644
index 0000000..73ac475
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Diagnostics.cpp
@@ -0,0 +1,384 @@
+//===--- Diagnostics.cpp ----------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "Diagnostics.h"
+#include "Compiler.h"
+#include "Logger.h"
+#include "SourceCode.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/Support/Capacity.h"
+#include "llvm/Support/Path.h"
+#include <algorithm>
+
+namespace clang {
+namespace clangd {
+
+namespace {
+
+bool mentionsMainFile(const Diag &D) {
+  if (D.InsideMainFile)
+    return true;
+  // Fixes are always in the main file.
+  if (!D.Fixes.empty())
+    return true;
+  for (auto &N : D.Notes) {
+    if (N.InsideMainFile)
+      return true;
+  }
+  return false;
+}
+
+// Checks whether a location is within a half-open range.
+// Note that clang also uses closed source ranges, which this can't handle!
+bool locationInRange(SourceLocation L, CharSourceRange R,
+                     const SourceManager &M) {
+  assert(R.isCharRange());
+  if (!R.isValid() || M.getFileID(R.getBegin()) != M.getFileID(R.getEnd()) ||
+      M.getFileID(R.getBegin()) != M.getFileID(L))
+    return false;
+  return L != R.getEnd() && M.isPointWithin(L, R.getBegin(), R.getEnd());
+}
+
+// Clang diags have a location (shown as ^) and 0 or more ranges (~~~~).
+// LSP needs a single range.
+Range diagnosticRange(const clang::Diagnostic &D, const LangOptions &L) {
+  auto &M = D.getSourceManager();
+  auto Loc = M.getFileLoc(D.getLocation());
+  // Accept the first range that contains the location.
+  for (const auto &CR : D.getRanges()) {
+    auto R = Lexer::makeFileCharRange(CR, M, L);
+    if (locationInRange(Loc, R, M))
+      return halfOpenToRange(M, R);
+  }
+  // The range may be given as a fixit hint instead.
+  for (const auto &F : D.getFixItHints()) {
+    auto R = Lexer::makeFileCharRange(F.RemoveRange, M, L);
+    if (locationInRange(Loc, R, M))
+      return halfOpenToRange(M, R);
+  }
+  // If no suitable range is found, just use the token at the location.
+  auto R = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Loc), M, L);
+  if (!R.isValid()) // Fall back to location only, let the editor deal with it.
+    R = CharSourceRange::getCharRange(Loc);
+  return halfOpenToRange(M, R);
+}
+
+TextEdit toTextEdit(const FixItHint &FixIt, const SourceManager &M,
+                    const LangOptions &L) {
+  TextEdit Result;
+  Result.range =
+      halfOpenToRange(M, Lexer::makeFileCharRange(FixIt.RemoveRange, M, L));
+  Result.newText = FixIt.CodeToInsert;
+  return Result;
+}
+
+bool isInsideMainFile(const SourceLocation Loc, const SourceManager &M) {
+  return Loc.isValid() && M.isInMainFile(Loc);
+}
+
+bool isInsideMainFile(const clang::Diagnostic &D) {
+  if (!D.hasSourceManager())
+    return false;
+
+  return isInsideMainFile(D.getLocation(), D.getSourceManager());
+}
+
+bool isNote(DiagnosticsEngine::Level L) {
+  return L == DiagnosticsEngine::Note || L == DiagnosticsEngine::Remark;
+}
+
+llvm::StringRef diagLeveltoString(DiagnosticsEngine::Level Lvl) {
+  switch (Lvl) {
+  case DiagnosticsEngine::Ignored:
+    return "ignored";
+  case DiagnosticsEngine::Note:
+    return "note";
+  case DiagnosticsEngine::Remark:
+    return "remark";
+  case DiagnosticsEngine::Warning:
+    return "warning";
+  case DiagnosticsEngine::Error:
+    return "error";
+  case DiagnosticsEngine::Fatal:
+    return "fatal error";
+  }
+  llvm_unreachable("unhandled DiagnosticsEngine::Level");
+}
+
+/// Prints a single diagnostic in a clang-like manner, the output includes
+/// location, severity and error message. An example of the output message is:
+///
+///     main.cpp:12:23: error: undeclared identifier
+///
+/// For main file we only print the basename and for all other files we print
+/// the filename on a separate line to provide a slightly more readable output
+/// in the editors:
+///
+///     dir1/dir2/dir3/../../dir4/header.h:12:23
+///     error: undeclared identifier
+void printDiag(llvm::raw_string_ostream &OS, const DiagBase &D) {
+  if (D.InsideMainFile) {
+    // Paths to main files are often taken from compile_command.json, where they
+    // are typically absolute. To reduce noise we print only basename for them,
+    // it should not be confusing and saves space.
+    OS << llvm::sys::path::filename(D.File) << ":";
+  } else {
+    OS << D.File << ":";
+  }
+  // Note +1 to line and character. clangd::Range is zero-based, but when
+  // printing for users we want one-based indexes.
+  auto Pos = D.Range.start;
+  OS << (Pos.line + 1) << ":" << (Pos.character + 1) << ":";
+  // The non-main-file paths are often too long, putting them on a separate
+  // line improves readability.
+  if (D.InsideMainFile)
+    OS << " ";
+  else
+    OS << "\n";
+  OS << diagLeveltoString(D.Severity) << ": " << D.Message;
+}
+
+/// Returns a message sent to LSP for the main diagnostic in \p D.
+/// The message includes all the notes with their corresponding locations.
+/// However, notes with fix-its are excluded as those usually only contain a
+/// fix-it message and just add noise if included in the message for diagnostic.
+/// Example output:
+///
+///     no matching function for call to 'foo'
+///
+///     main.cpp:3:5: note: candidate function not viable: requires 2 arguments
+///
+///     dir1/dir2/dir3/../../dir4/header.h:12:23
+///     note: candidate function not viable: requires 3 arguments
+std::string mainMessage(const Diag &D) {
+  std::string Result;
+  llvm::raw_string_ostream OS(Result);
+  OS << D.Message;
+  for (auto &Note : D.Notes) {
+    OS << "\n\n";
+    printDiag(OS, Note);
+  }
+  OS.flush();
+  return Result;
+}
+
+/// Returns a message sent to LSP for the note of the main diagnostic.
+/// The message includes the main diagnostic to provide the necessary context
+/// for the user to understand the note.
+std::string noteMessage(const Diag &Main, const DiagBase &Note) {
+  std::string Result;
+  llvm::raw_string_ostream OS(Result);
+  OS << Note.Message;
+  OS << "\n\n";
+  printDiag(OS, Main);
+  OS.flush();
+  return Result;
+}
+} // namespace
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const DiagBase &D) {
+  if (!D.InsideMainFile)
+    OS << "[in " << D.File << "] ";
+  return OS << D.Message;
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Fix &F) {
+  OS << F.Message << " {";
+  const char *Sep = "";
+  for (const auto &Edit : F.Edits) {
+    OS << Sep << Edit;
+    Sep = ", ";
+  }
+  return OS << "}";
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diag &D) {
+  OS << static_cast<const DiagBase &>(D);
+  if (!D.Notes.empty()) {
+    OS << ", notes: {";
+    const char *Sep = "";
+    for (auto &Note : D.Notes) {
+      OS << Sep << Note;
+      Sep = ", ";
+    }
+    OS << "}";
+  }
+  if (!D.Fixes.empty()) {
+    OS << ", fixes: {";
+    const char *Sep = "";
+    for (auto &Fix : D.Fixes) {
+      OS << Sep << Fix;
+      Sep = ", ";
+    }
+  }
+  return OS;
+}
+
+void toLSPDiags(
+    const Diag &D,
+    llvm::function_ref<void(clangd::Diagnostic, llvm::ArrayRef<Fix>)> OutFn) {
+  auto FillBasicFields = [](const DiagBase &D) -> clangd::Diagnostic {
+    clangd::Diagnostic Res;
+    Res.range = D.Range;
+    Res.severity = getSeverity(D.Severity);
+    return Res;
+  };
+
+  {
+    clangd::Diagnostic Main = FillBasicFields(D);
+    Main.message = mainMessage(D);
+    OutFn(std::move(Main), D.Fixes);
+  }
+
+  for (auto &Note : D.Notes) {
+    if (!Note.InsideMainFile)
+      continue;
+    clangd::Diagnostic Res = FillBasicFields(Note);
+    Res.message = noteMessage(D, Note);
+    OutFn(std::move(Res), llvm::ArrayRef<Fix>());
+  }
+}
+
+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!");
+}
+
+std::vector<Diag> StoreDiags::take() { return std::move(Output); }
+
+void StoreDiags::BeginSourceFile(const LangOptions &Opts,
+                                 const Preprocessor *) {
+  LangOpts = Opts;
+}
+
+void StoreDiags::EndSourceFile() {
+  flushLastDiag();
+  LangOpts = llvm::None;
+}
+
+void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+                                  const clang::Diagnostic &Info) {
+  DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
+
+  if (!LangOpts || !Info.hasSourceManager()) {
+    IgnoreDiagnostics::log(DiagLevel, Info);
+    return;
+  }
+
+  bool InsideMainFile = isInsideMainFile(Info);
+
+  auto FillDiagBase = [&](DiagBase &D) {
+    D.Range = diagnosticRange(Info, *LangOpts);
+    llvm::SmallString<64> Message;
+    Info.FormatDiagnostic(Message);
+    D.Message = Message.str();
+    D.InsideMainFile = InsideMainFile;
+    D.File = Info.getSourceManager().getFilename(Info.getLocation());
+    D.Severity = DiagLevel;
+    return D;
+  };
+
+  auto AddFix = [&](bool SyntheticMessage) -> bool {
+    assert(!Info.getFixItHints().empty() &&
+           "diagnostic does not have attached fix-its");
+    if (!InsideMainFile)
+      return false;
+
+    llvm::SmallVector<TextEdit, 1> Edits;
+    for (auto &FixIt : Info.getFixItHints()) {
+      if (!isInsideMainFile(FixIt.RemoveRange.getBegin(),
+                            Info.getSourceManager()))
+        return false;
+      Edits.push_back(toTextEdit(FixIt, Info.getSourceManager(), *LangOpts));
+    }
+
+    llvm::SmallString<64> Message;
+    // If requested and possible, create a message like "change 'foo' to 'bar'".
+    if (SyntheticMessage && Info.getNumFixItHints() == 1) {
+      const auto &FixIt = Info.getFixItHint(0);
+      bool Invalid = false;
+      StringRef Remove = Lexer::getSourceText(
+          FixIt.RemoveRange, Info.getSourceManager(), *LangOpts, &Invalid);
+      StringRef Insert = FixIt.CodeToInsert;
+      if (!Invalid) {
+        llvm::raw_svector_ostream M(Message);
+        if (!Remove.empty() && !Insert.empty())
+          M << "change '" << Remove << "' to '" << Insert << "'";
+        else if (!Remove.empty())
+          M << "remove '" << Remove << "'";
+        else if (!Insert.empty())
+          M << "insert '" << Insert << "'";
+        // Don't allow source code to inject newlines into diagnostics.
+        std::replace(Message.begin(), Message.end(), '\n', ' ');
+      }
+    }
+    if (Message.empty()) // either !SytheticMessage, or we failed to make one.
+      Info.FormatDiagnostic(Message);
+    LastDiag->Fixes.push_back(Fix{Message.str(), std::move(Edits)});
+    return true;
+  };
+
+  if (!isNote(DiagLevel)) {
+    // Handle the new main diagnostic.
+    flushLastDiag();
+
+    LastDiag = Diag();
+    FillDiagBase(*LastDiag);
+
+    if (!Info.getFixItHints().empty())
+      AddFix(true /* try to invent a message instead of repeating the diag */);
+  } else {
+    // Handle a note to an existing diagnostic.
+    if (!LastDiag) {
+      assert(false && "Adding a note without main diagnostic");
+      IgnoreDiagnostics::log(DiagLevel, Info);
+      return;
+    }
+
+    if (!Info.getFixItHints().empty()) {
+      // A clang note with fix-it is not a separate diagnostic in clangd. We
+      // attach it as a Fix to the main diagnostic instead.
+      if (!AddFix(false /* use the note as the message */))
+        IgnoreDiagnostics::log(DiagLevel, Info);
+    } else {
+      // A clang note without fix-its corresponds to clangd::Note.
+      Note N;
+      FillDiagBase(N);
+
+      LastDiag->Notes.push_back(std::move(N));
+    }
+  }
+}
+
+void StoreDiags::flushLastDiag() {
+  if (!LastDiag)
+    return;
+  if (mentionsMainFile(*LastDiag))
+    Output.push_back(std::move(*LastDiag));
+  else
+    log("Dropped diagnostic outside main file: {0}: {1}", LastDiag->File,
+        LastDiag->Message);
+  LastDiag.reset();
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Diagnostics.h b/src/third_party/llvm-project/clang-tools-extra/clangd/Diagnostics.h
new file mode 100644
index 0000000..b43f04a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Diagnostics.h
@@ -0,0 +1,98 @@
+//===--- Diagnostics.h ------------------------------------------*- 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_DIAGNOSTICS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_DIAGNOSTICS_H
+
+#include "Path.h"
+#include "Protocol.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSet.h"
+#include <cassert>
+#include <string>
+
+namespace clang {
+namespace clangd {
+
+/// Contains basic information about a diagnostic.
+struct DiagBase {
+  std::string Message;
+  // Intended to be used only in error messages.
+  // May be relative, absolute or even artifically constructed.
+  std::string File;
+  clangd::Range Range;
+  DiagnosticsEngine::Level Severity = DiagnosticsEngine::Note;
+  // Since File is only descriptive, we store a separate flag to distinguish
+  // diags from the main file.
+  bool InsideMainFile = false;
+};
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const DiagBase &D);
+
+/// Represents a single fix-it that editor can apply to fix the error.
+struct Fix {
+  /// Message for the fix-it.
+  std::string Message;
+  /// TextEdits from clang's fix-its. Must be non-empty.
+  llvm::SmallVector<TextEdit, 1> Edits;
+};
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Fix &F);
+
+/// Represents a note for the diagnostic. Severity of notes can only be 'note'
+/// or 'remark'.
+struct Note : DiagBase {};
+
+/// A top-level diagnostic that may have Notes and Fixes.
+struct Diag : DiagBase {
+  /// Elaborate on the problem, usually pointing to a related piece of code.
+  std::vector<Note> Notes;
+  /// *Alternative* fixes for this diagnostic, one should be chosen.
+  std::vector<Fix> Fixes;
+};
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diag &D);
+
+/// Conversion to LSP diagnostics. Formats the error message of each diagnostic
+/// to include all its notes. Notes inside main file are also provided as
+/// separate diagnostics with their corresponding fixits. Notes outside main
+/// file do not have a corresponding LSP diagnostic, but can still be included
+/// as part of their main diagnostic's message.
+void toLSPDiags(
+    const Diag &D,
+    llvm::function_ref<void(clangd::Diagnostic, llvm::ArrayRef<Fix>)> OutFn);
+
+/// Convert from clang diagnostic level to LSP severity.
+int getSeverity(DiagnosticsEngine::Level L);
+
+/// StoreDiags collects the diagnostics that can later be reported by
+/// clangd. It groups all notes for a diagnostic into a single Diag
+/// and filters out diagnostics that don't mention the main file (i.e. neither
+/// the diag itself nor its notes are in the main file).
+class StoreDiags : public DiagnosticConsumer {
+public:
+  std::vector<Diag> take();
+
+  void BeginSourceFile(const LangOptions &Opts, const Preprocessor *) override;
+  void EndSourceFile() override;
+  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+                        const clang::Diagnostic &Info) override;
+
+private:
+  void flushLastDiag();
+
+  std::vector<Diag> Output;
+  llvm::Optional<LangOptions> LangOpts;
+  llvm::Optional<Diag> LastDiag;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/DraftStore.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/DraftStore.cpp
new file mode 100644
index 0000000..8e1cf88
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/DraftStore.cpp
@@ -0,0 +1,107 @@
+//===--- DraftStore.cpp - File contents container ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DraftStore.h"
+#include "SourceCode.h"
+#include "llvm/Support/Errc.h"
+
+using namespace clang;
+using namespace clang::clangd;
+
+llvm::Optional<std::string> DraftStore::getDraft(PathRef File) const {
+  std::lock_guard<std::mutex> Lock(Mutex);
+
+  auto It = Drafts.find(File);
+  if (It == Drafts.end())
+    return llvm::None;
+
+  return It->second;
+}
+
+std::vector<Path> DraftStore::getActiveFiles() const {
+  std::lock_guard<std::mutex> Lock(Mutex);
+  std::vector<Path> ResultVector;
+
+  for (auto DraftIt = Drafts.begin(); DraftIt != Drafts.end(); DraftIt++)
+    ResultVector.push_back(DraftIt->getKey());
+
+  return ResultVector;
+}
+
+void DraftStore::addDraft(PathRef File, StringRef Contents) {
+  std::lock_guard<std::mutex> Lock(Mutex);
+
+  Drafts[File] = Contents;
+}
+
+llvm::Expected<std::string> DraftStore::updateDraft(
+    PathRef File, llvm::ArrayRef<TextDocumentContentChangeEvent> Changes) {
+  std::lock_guard<std::mutex> Lock(Mutex);
+
+  auto EntryIt = Drafts.find(File);
+  if (EntryIt == Drafts.end()) {
+    return llvm::make_error<llvm::StringError>(
+        "Trying to do incremental update on non-added document: " + File,
+        llvm::errc::invalid_argument);
+  }
+
+  std::string Contents = EntryIt->second;
+
+  for (const TextDocumentContentChangeEvent &Change : Changes) {
+    if (!Change.range) {
+      Contents = Change.text;
+      continue;
+    }
+
+    const Position &Start = Change.range->start;
+    llvm::Expected<size_t> StartIndex =
+        positionToOffset(Contents, Start, false);
+    if (!StartIndex)
+      return StartIndex.takeError();
+
+    const Position &End = Change.range->end;
+    llvm::Expected<size_t> EndIndex = positionToOffset(Contents, End, false);
+    if (!EndIndex)
+      return EndIndex.takeError();
+
+    if (*EndIndex < *StartIndex)
+      return llvm::make_error<llvm::StringError>(
+          llvm::formatv(
+              "Range's end position ({0}) is before start position ({1})", End,
+              Start),
+          llvm::errc::invalid_argument);
+
+    if (Change.rangeLength &&
+        (ssize_t)(*EndIndex - *StartIndex) != *Change.rangeLength)
+      return llvm::make_error<llvm::StringError>(
+          llvm::formatv("Change's rangeLength ({0}) doesn't match the "
+                        "computed range length ({1}).",
+                        *Change.rangeLength, *EndIndex - *StartIndex),
+          llvm::errc::invalid_argument);
+
+    std::string NewContents;
+    NewContents.reserve(*StartIndex + Change.text.length() +
+                        (Contents.length() - *EndIndex));
+
+    NewContents = Contents.substr(0, *StartIndex);
+    NewContents += Change.text;
+    NewContents += Contents.substr(*EndIndex);
+
+    Contents = std::move(NewContents);
+  }
+
+  EntryIt->second = Contents;
+  return Contents;
+}
+
+void DraftStore::removeDraft(PathRef File) {
+  std::lock_guard<std::mutex> Lock(Mutex);
+
+  Drafts.erase(File);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/DraftStore.h b/src/third_party/llvm-project/clang-tools-extra/clangd/DraftStore.h
new file mode 100644
index 0000000..90a2d2c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/DraftStore.h
@@ -0,0 +1,60 @@
+//===--- DraftStore.h - File contents container -----------------*- 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_DRAFTSTORE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_DRAFTSTORE_H
+
+#include "Path.h"
+#include "Protocol.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringMap.h"
+#include <mutex>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace clangd {
+
+/// A thread-safe container for files opened in a workspace, addressed by
+/// filenames. The contents are owned by the DraftStore. This class supports
+/// both whole and incremental updates of the documents.
+class DraftStore {
+public:
+  /// \return Contents of the stored document.
+  /// For untracked files, a llvm::None is returned.
+  llvm::Optional<std::string> getDraft(PathRef File) const;
+
+  /// \return List of names of the drafts in this store.
+  std::vector<Path> getActiveFiles() const;
+
+  /// Replace contents of the draft for \p File with \p Contents.
+  void addDraft(PathRef File, StringRef Contents);
+
+  /// Update the contents of the draft for \p File based on \p Changes.
+  /// If a position in \p Changes is invalid (e.g. out-of-range), the
+  /// draft is not modified.
+  ///
+  /// \return The new version of the draft for \p File, or an error if the
+  /// changes couldn't be applied.
+  llvm::Expected<std::string>
+  updateDraft(PathRef File,
+              llvm::ArrayRef<TextDocumentContentChangeEvent> Changes);
+
+  /// Remove the draft from the store.
+  void removeDraft(PathRef File);
+
+private:
+  mutable std::mutex Mutex;
+  llvm::StringMap<std::string> Drafts;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/FSProvider.h b/src/third_party/llvm-project/clang-tools-extra/clangd/FSProvider.h
new file mode 100644
index 0000000..70dfb44
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/FSProvider.h
@@ -0,0 +1,42 @@
+//===--- FSProvider.h - VFS provider for ClangdServer ------------*- 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_FSPROVIDER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FSPROVIDER_H
+
+#include "clang/Basic/VirtualFileSystem.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+
+namespace clang {
+namespace clangd {
+
+// Wrapper for vfs::FileSystem for use in multithreaded programs like clangd.
+// As FileSystem is not threadsafe, concurrent threads must each obtain one.
+class FileSystemProvider {
+public:
+  virtual ~FileSystemProvider() = default;
+  /// Called by ClangdServer to obtain a vfs::FileSystem to be used for parsing.
+  /// Context::current() will be the context passed to the clang entrypoint,
+  /// such as addDocument(), and will also be propagated to result callbacks.
+  /// Embedders may use this to isolate filesystem accesses.
+  virtual IntrusiveRefCntPtr<vfs::FileSystem> getFileSystem() = 0;
+};
+
+class RealFileSystemProvider : public FileSystemProvider {
+public:
+  // FIXME: returns the single real FS instance, which is not threadsafe.
+  IntrusiveRefCntPtr<vfs::FileSystem> getFileSystem() override {
+    return vfs::getRealFileSystem();
+  }
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/FileDistance.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/FileDistance.cpp
new file mode 100644
index 0000000..a0ce25b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/FileDistance.cpp
@@ -0,0 +1,171 @@
+//===--- FileDistance.cpp - File contents container -------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The FileDistance structure allows calculating the minimum distance to paths
+// in a single tree.
+// We simply walk up the path's ancestors until we find a node whose cost is
+// known, and add the cost of walking back down. Initialization ensures this
+// gives the correct path to the roots.
+// We cache the results, so that the runtime is O(|A|), where A is the set of
+// all distinct ancestors of visited paths.
+//
+// Example after initialization with /=2, /bar=0, DownCost = 1:
+//  / = 2
+//    /bar = 0
+//
+// After querying /foo/bar and /bar/foo:
+//  / = 2
+//    /bar = 0
+//      /bar/foo = 1
+//    /foo = 3
+//      /foo/bar = 4
+//
+// URIDistance creates FileDistance lazily for each URI scheme encountered. In
+// practice this is a small constant factor.
+//
+//===-------------------------------------------------------------------------//
+
+#include "FileDistance.h"
+#include "Logger.h"
+#include "llvm/ADT/STLExtras.h"
+#include <queue>
+
+namespace clang {
+namespace clangd {
+using namespace llvm;
+
+// Convert a path into the canonical form.
+// Canonical form is either "/", or "/segment" * N:
+//   C:\foo\bar --> /c:/foo/bar
+//   /foo/      --> /foo
+//   a/b/c      --> /a/b/c
+static SmallString<128> canonicalize(StringRef Path) {
+  SmallString<128> Result = Path.rtrim('/');
+  native(Result, sys::path::Style::posix);
+  if (Result.empty() || Result.front() != '/')
+    Result.insert(Result.begin(), '/');
+  return Result;
+}
+
+constexpr const unsigned FileDistance::kUnreachable;
+
+FileDistance::FileDistance(StringMap<SourceParams> Sources,
+                           const FileDistanceOptions &Opts)
+    : Opts(Opts) {
+  llvm::DenseMap<hash_code, SmallVector<hash_code, 4>> DownEdges;
+  // Compute the best distance following only up edges.
+  // Keep track of down edges, in case we can use them to improve on this.
+  for (const auto &S : Sources) {
+    auto Canonical = canonicalize(S.getKey());
+    dlog("Source {0} = {1}, MaxUp = {2}", Canonical, S.second.Cost,
+         S.second.MaxUpTraversals);
+    // Walk up to ancestors of this source, assigning cost.
+    StringRef Rest = Canonical;
+    llvm::hash_code Hash = hash_value(Rest);
+    for (unsigned I = 0; !Rest.empty(); ++I) {
+      Rest = parent_path(Rest, sys::path::Style::posix);
+      auto NextHash = hash_value(Rest);
+      auto &Down = DownEdges[NextHash];
+      if (std::find(Down.begin(), Down.end(), Hash) == Down.end())
+        DownEdges[NextHash].push_back(Hash);
+      // We can't just break after MaxUpTraversals, must still set DownEdges.
+      if (I > S.getValue().MaxUpTraversals) {
+        if (Cache.find(Hash) != Cache.end())
+          break;
+      } else {
+        unsigned Cost = S.getValue().Cost + I * Opts.UpCost;
+        auto R = Cache.try_emplace(Hash, Cost);
+        if (!R.second) {
+          if (Cost < R.first->second) {
+            R.first->second = Cost;
+          } else {
+            // If we're not the best way to get to this path, stop assigning.
+            break;
+          }
+        }
+      }
+      Hash = NextHash;
+    }
+  }
+  // Now propagate scores parent -> child if that's an improvement.
+  // BFS ensures we propagate down chains (must visit parents before children).
+  std::queue<hash_code> Next;
+  for (auto Child : DownEdges.lookup(hash_value(llvm::StringRef(""))))
+    Next.push(Child);
+  while (!Next.empty()) {
+    auto ParentCost = Cache.lookup(Next.front());
+    for (auto Child : DownEdges.lookup(Next.front())) {
+      auto &ChildCost =
+          Cache.try_emplace(Child, kUnreachable).first->getSecond();
+      if (ParentCost + Opts.DownCost < ChildCost)
+        ChildCost = ParentCost + Opts.DownCost;
+      Next.push(Child);
+    }
+    Next.pop();
+  }
+}
+
+unsigned FileDistance::distance(StringRef Path) {
+  auto Canonical = canonicalize(Path);
+  unsigned Cost = kUnreachable;
+  SmallVector<hash_code, 16> Ancestors;
+  // Walk up ancestors until we find a path we know the distance for.
+  for (StringRef Rest = Canonical; !Rest.empty();
+       Rest = parent_path(Rest, sys::path::Style::posix)) {
+    auto Hash = hash_value(Rest);
+    auto It = Cache.find(Hash);
+    if (It != Cache.end()) {
+      Cost = It->second;
+      break;
+    }
+    Ancestors.push_back(Hash);
+  }
+  // Now we know the costs for (known node, queried node].
+  // Fill these in, walking down the directory tree.
+  for (hash_code Hash : reverse(Ancestors)) {
+    if (Cost != kUnreachable)
+      Cost += Opts.DownCost;
+    Cache.try_emplace(Hash, Cost);
+  }
+  dlog("distance({0} = {1})", Path, Cost);
+  return Cost;
+}
+
+unsigned URIDistance::distance(llvm::StringRef URI) {
+  auto R = Cache.try_emplace(llvm::hash_value(URI), FileDistance::kUnreachable);
+  if (!R.second)
+    return R.first->getSecond();
+  if (auto U = clangd::URI::parse(URI)) {
+    dlog("distance({0} = {1})", URI, U->body());
+    R.first->second = forScheme(U->scheme()).distance(U->body());
+  } else {
+    log("URIDistance::distance() of unparseable {0}: {1}", URI, U.takeError());
+  }
+  return R.first->second;
+}
+
+FileDistance &URIDistance::forScheme(llvm::StringRef Scheme) {
+  auto &Delegate = ByScheme[Scheme];
+  if (!Delegate) {
+    llvm::StringMap<SourceParams> SchemeSources;
+    for (const auto &Source : Sources) {
+      if (auto U = clangd::URI::create(Source.getKey(), Scheme))
+        SchemeSources.try_emplace(U->body(), Source.getValue());
+      else
+        consumeError(U.takeError());
+    }
+    dlog("FileDistance for scheme {0}: {1}/{2} sources", Scheme,
+         SchemeSources.size(), Sources.size());
+    Delegate.reset(new FileDistance(std::move(SchemeSources), Opts));
+  }
+  return *Delegate;
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/FileDistance.h b/src/third_party/llvm-project/clang-tools-extra/clangd/FileDistance.h
new file mode 100644
index 0000000..f07804f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/FileDistance.h
@@ -0,0 +1,109 @@
+//===--- FileDistance.h - File proximity scoring -----------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This library measures the distance between file paths.
+// It's used for ranking symbols, e.g. in code completion.
+//  |foo/bar.h -> foo/bar.h| = 0.
+//  |foo/bar.h -> foo/baz.h| < |foo/bar.h -> baz.h|.
+// This is an edit-distance, where edits go up or down the directory tree.
+// It's not symmetrical, the costs of going up and down may not match.
+//
+// Dealing with multiple sources:
+// In practice we care about the distance from a source file, but files near
+// its main-header and #included files are considered "close".
+// So we start with a set of (anchor, cost) pairs, and call the distance to a
+// path the minimum of `cost + |source -> path|`.
+//
+// We allow each source to limit the number of up-traversals paths may start
+// with. Up-traversals may reach things that are not "semantically near".
+//
+// Symbol URI schemes:
+// Symbol locations may be represented by URIs rather than file paths directly.
+// In this case we want to perform distance computations in URI space rather
+// than in file-space, without performing redundant conversions.
+// Therefore we have a lookup structure that accepts URIs, so that intermediate
+// calculations for the same scheme can be reused.
+//
+// Caveats:
+// Assuming up and down traversals each have uniform costs is simplistic.
+// Often there are "semantic roots" whose children are almost unrelated.
+// (e.g. /usr/include/, or / in an umbrella repository). We ignore this.
+//
+//===----------------------------------------------------------------------===//
+
+#include "URI.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/StringSaver.h"
+
+namespace clang {
+namespace clangd {
+
+struct FileDistanceOptions {
+  unsigned UpCost = 2;      // |foo/bar.h -> foo|
+  unsigned DownCost = 1;    // |foo -> foo/bar.h|
+  unsigned IncludeCost = 2; // |foo.cc -> included_header.h|
+};
+
+struct SourceParams {
+  // Base cost for paths starting at this source.
+  unsigned Cost = 0;
+  // Limits the number of upwards traversals allowed from this source.
+  unsigned MaxUpTraversals = std::numeric_limits<unsigned>::max();
+};
+
+// Supports lookups to find the minimum distance to a file from any source.
+// This object should be reused, it memoizes intermediate computations.
+class FileDistance {
+public:
+  static constexpr unsigned kUnreachable = std::numeric_limits<unsigned>::max();
+
+  FileDistance(llvm::StringMap<SourceParams> Sources,
+               const FileDistanceOptions &Opts = {});
+
+  // Computes the minimum distance from any source to the file path.
+  unsigned distance(llvm::StringRef Path);
+
+private:
+  // Costs computed so far. Always contains sources and their ancestors.
+  // We store hash codes only. Collisions are rare and consequences aren't dire.
+  llvm::DenseMap<llvm::hash_code, unsigned> Cache;
+  FileDistanceOptions Opts;
+};
+
+// Supports lookups like FileDistance, but the lookup keys are URIs.
+// We convert each of the sources to the scheme of the URI and do a FileDistance
+// comparison on the bodies.
+class URIDistance {
+public:
+  URIDistance(llvm::StringMap<SourceParams> Sources,
+              const FileDistanceOptions &Opts = {})
+      : Sources(Sources), Opts(Opts) {}
+
+  // Computes the minimum distance from any source to the URI.
+  // Only sources that can be mapped into the URI's scheme are considered.
+  unsigned distance(llvm::StringRef URI);
+
+private:
+  // Returns the FileDistance for a URI scheme, creating it if needed.
+  FileDistance &forScheme(llvm::StringRef Scheme);
+
+  // We cache the results using the original strings so we can skip URI parsing.
+  llvm::DenseMap<llvm::hash_code, unsigned> Cache;
+  llvm::StringMap<SourceParams> Sources;
+  llvm::StringMap<std::unique_ptr<FileDistance>> ByScheme;
+  FileDistanceOptions Opts;
+};
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/FindSymbols.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/FindSymbols.cpp
new file mode 100644
index 0000000..c1ee678
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/FindSymbols.cpp
@@ -0,0 +1,279 @@
+//===--- FindSymbols.cpp ------------------------------------*- C++-*------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "FindSymbols.h"
+
+#include "AST.h"
+#include "ClangdUnit.h"
+#include "FuzzyMatch.h"
+#include "Logger.h"
+#include "Quality.h"
+#include "SourceCode.h"
+#include "index/Index.h"
+#include "clang/Index/IndexDataConsumer.h"
+#include "clang/Index/IndexSymbol.h"
+#include "clang/Index/IndexingAction.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Path.h"
+
+#define DEBUG_TYPE "FindSymbols"
+
+namespace clang {
+namespace clangd {
+
+namespace {
+
+// Convert a index::SymbolKind to clangd::SymbolKind (LSP)
+// Note, some are not perfect matches and should be improved when this LSP
+// issue is addressed:
+// https://github.com/Microsoft/language-server-protocol/issues/344
+SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind) {
+  switch (Kind) {
+  case index::SymbolKind::Unknown:
+    return SymbolKind::Variable;
+  case index::SymbolKind::Module:
+    return SymbolKind::Module;
+  case index::SymbolKind::Namespace:
+    return SymbolKind::Namespace;
+  case index::SymbolKind::NamespaceAlias:
+    return SymbolKind::Namespace;
+  case index::SymbolKind::Macro:
+    return SymbolKind::String;
+  case index::SymbolKind::Enum:
+    return SymbolKind::Enum;
+  case index::SymbolKind::Struct:
+    return SymbolKind::Struct;
+  case index::SymbolKind::Class:
+    return SymbolKind::Class;
+  case index::SymbolKind::Protocol:
+    return SymbolKind::Interface;
+  case index::SymbolKind::Extension:
+    return SymbolKind::Interface;
+  case index::SymbolKind::Union:
+    return SymbolKind::Class;
+  case index::SymbolKind::TypeAlias:
+    return SymbolKind::Class;
+  case index::SymbolKind::Function:
+    return SymbolKind::Function;
+  case index::SymbolKind::Variable:
+    return SymbolKind::Variable;
+  case index::SymbolKind::Field:
+    return SymbolKind::Field;
+  case index::SymbolKind::EnumConstant:
+    return SymbolKind::EnumMember;
+  case index::SymbolKind::InstanceMethod:
+  case index::SymbolKind::ClassMethod:
+  case index::SymbolKind::StaticMethod:
+    return SymbolKind::Method;
+  case index::SymbolKind::InstanceProperty:
+  case index::SymbolKind::ClassProperty:
+  case index::SymbolKind::StaticProperty:
+    return SymbolKind::Property;
+  case index::SymbolKind::Constructor:
+  case index::SymbolKind::Destructor:
+    return SymbolKind::Method;
+  case index::SymbolKind::ConversionFunction:
+    return SymbolKind::Function;
+  case index::SymbolKind::Parameter:
+    return SymbolKind::Variable;
+  case index::SymbolKind::Using:
+    return SymbolKind::Namespace;
+  }
+  llvm_unreachable("invalid symbol kind");
+}
+
+using ScoredSymbolInfo = std::pair<float, SymbolInformation>;
+struct ScoredSymbolGreater {
+  bool operator()(const ScoredSymbolInfo &L, const ScoredSymbolInfo &R) {
+    if (L.first != R.first)
+      return L.first > R.first;
+    return L.second.name < R.second.name; // Earlier name is better.
+  }
+};
+
+} // namespace
+
+llvm::Expected<std::vector<SymbolInformation>>
+getWorkspaceSymbols(StringRef Query, int Limit, const SymbolIndex *const Index,
+                    StringRef HintPath) {
+  std::vector<SymbolInformation> Result;
+  if (Query.empty() || !Index)
+    return Result;
+
+  auto Names = splitQualifiedName(Query);
+
+  FuzzyFindRequest Req;
+  Req.Query = Names.second;
+
+  // FuzzyFind doesn't want leading :: qualifier
+  bool IsGlobalQuery = Names.first.consume_front("::");
+  // Restrict results to the scope in the query string if present (global or
+  // not).
+  if (IsGlobalQuery || !Names.first.empty())
+    Req.Scopes = {Names.first};
+  if (Limit)
+    Req.MaxCandidateCount = Limit;
+  TopN<ScoredSymbolInfo, ScoredSymbolGreater> Top(Req.MaxCandidateCount);
+  FuzzyMatcher Filter(Req.Query);
+  Index->fuzzyFind(Req, [HintPath, &Top, &Filter](const Symbol &Sym) {
+    // Prefer the definition over e.g. a function declaration in a header
+    auto &CD = Sym.Definition ? Sym.Definition : Sym.CanonicalDeclaration;
+    auto Uri = URI::parse(CD.FileURI);
+    if (!Uri) {
+      log("Workspace symbol: Could not parse URI '{0}' for symbol '{1}'.",
+          CD.FileURI, Sym.Name);
+      return;
+    }
+    auto Path = URI::resolve(*Uri, HintPath);
+    if (!Path) {
+      log("Workspace symbol: Could not resolve path for URI '{0}' for symbol "
+          "'{1}'.",
+          Uri->toString(), Sym.Name);
+      return;
+    }
+    Location L;
+    L.uri = URIForFile((*Path));
+    Position Start, End;
+    Start.line = CD.Start.Line;
+    Start.character = CD.Start.Column;
+    End.line = CD.End.Line;
+    End.character = CD.End.Column;
+    L.range = {Start, End};
+    SymbolKind SK = indexSymbolKindToSymbolKind(Sym.SymInfo.Kind);
+    std::string Scope = Sym.Scope;
+    StringRef ScopeRef = Scope;
+    ScopeRef.consume_back("::");
+    SymbolInformation Info = {Sym.Name, SK, L, ScopeRef};
+
+    SymbolQualitySignals Quality;
+    Quality.merge(Sym);
+    SymbolRelevanceSignals Relevance;
+    Relevance.Query = SymbolRelevanceSignals::Generic;
+    if (auto NameMatch = Filter.match(Sym.Name))
+      Relevance.NameMatch = *NameMatch;
+    else {
+      log("Workspace symbol: {0} didn't match query {1}", Sym.Name,
+          Filter.pattern());
+      return;
+    }
+    Relevance.merge(Sym);
+    auto Score =
+        evaluateSymbolAndRelevance(Quality.evaluate(), Relevance.evaluate());
+    dlog("FindSymbols: {0}{1} = {2}\n{3}{4}\n", Sym.Scope, Sym.Name, Score,
+         Quality, Relevance);
+
+    Top.push({Score, std::move(Info)});
+  });
+  for (auto &R : std::move(Top).items())
+    Result.push_back(std::move(R.second));
+  return Result;
+}
+
+namespace {
+/// Finds document symbols in the main file of the AST.
+class DocumentSymbolsConsumer : public index::IndexDataConsumer {
+  ASTContext &AST;
+  std::vector<SymbolInformation> Symbols;
+  // We are always list document for the same file, so cache the value.
+  llvm::Optional<URIForFile> MainFileUri;
+
+public:
+  DocumentSymbolsConsumer(ASTContext &AST) : AST(AST) {}
+  std::vector<SymbolInformation> takeSymbols() { return std::move(Symbols); }
+
+  void initialize(ASTContext &Ctx) override {
+    // Compute the absolute path of the main file which we will use for all
+    // results.
+    const SourceManager &SM = AST.getSourceManager();
+    const FileEntry *F = SM.getFileEntryForID(SM.getMainFileID());
+    if (!F)
+      return;
+    auto FilePath = getAbsoluteFilePath(F, SM);
+    if (FilePath)
+      MainFileUri = URIForFile(*FilePath);
+  }
+
+  bool shouldIncludeSymbol(const NamedDecl *ND) {
+    if (!ND || ND->isImplicit())
+      return false;
+    // Skip anonymous declarations, e.g (anonymous enum/class/struct).
+    if (ND->getDeclName().isEmpty())
+      return false;
+    return true;
+  }
+
+  bool
+  handleDeclOccurence(const Decl *, index::SymbolRoleSet Roles,
+                      ArrayRef<index::SymbolRelation> Relations,
+                      SourceLocation Loc,
+                      index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
+    assert(ASTNode.OrigD);
+    // No point in continuing the index consumer if we could not get the
+    // absolute path of the main file.
+    if (!MainFileUri)
+      return false;
+    // We only want declarations and definitions, i.e. no references.
+    if (!(Roles & static_cast<unsigned>(index::SymbolRole::Declaration) ||
+          Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
+      return true;
+    SourceLocation NameLoc = findNameLoc(ASTNode.OrigD);
+    const SourceManager &SourceMgr = AST.getSourceManager();
+    // We should be only be looking at "local" decls in the main file.
+    if (!SourceMgr.isWrittenInMainFile(NameLoc)) {
+      // Even thought we are visiting only local (non-preamble) decls,
+      // we can get here when in the presense of "extern" decls.
+      return true;
+    }
+    const NamedDecl *ND = llvm::dyn_cast<NamedDecl>(ASTNode.OrigD);
+    if (!shouldIncludeSymbol(ND))
+      return true;
+
+    SourceLocation EndLoc =
+        Lexer::getLocForEndOfToken(NameLoc, 0, SourceMgr, AST.getLangOpts());
+    Position Begin = sourceLocToPosition(SourceMgr, NameLoc);
+    Position End = sourceLocToPosition(SourceMgr, EndLoc);
+    Range R = {Begin, End};
+    Location L;
+    L.uri = *MainFileUri;
+    L.range = R;
+
+    std::string QName = printQualifiedName(*ND);
+    StringRef Scope, Name;
+    std::tie(Scope, Name) = splitQualifiedName(QName);
+    Scope.consume_back("::");
+
+    index::SymbolInfo SymInfo = index::getSymbolInfo(ND);
+    SymbolKind SK = indexSymbolKindToSymbolKind(SymInfo.Kind);
+
+    SymbolInformation SI;
+    SI.name = Name;
+    SI.kind = SK;
+    SI.location = L;
+    SI.containerName = Scope;
+    Symbols.push_back(std::move(SI));
+    return true;
+  }
+};
+} // namespace
+
+llvm::Expected<std::vector<SymbolInformation>>
+getDocumentSymbols(ParsedAST &AST) {
+  DocumentSymbolsConsumer DocumentSymbolsCons(AST.getASTContext());
+
+  index::IndexingOptions IndexOpts;
+  IndexOpts.SystemSymbolFilter =
+      index::IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly;
+  IndexOpts.IndexFunctionLocals = false;
+  indexTopLevelDecls(AST.getASTContext(), AST.getLocalTopLevelDecls(),
+                     DocumentSymbolsCons, IndexOpts);
+
+  return DocumentSymbolsCons.takeSymbols();
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/FindSymbols.h b/src/third_party/llvm-project/clang-tools-extra/clangd/FindSymbols.h
new file mode 100644
index 0000000..4e6e75a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/FindSymbols.h
@@ -0,0 +1,45 @@
+//===--- FindSymbols.h --------------------------------------*- C++-*------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Queries that provide a list of symbols matching a string.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FINDSYMBOLS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FINDSYMBOLS_H
+
+#include "Protocol.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace clangd {
+class ParsedAST;
+class SymbolIndex;
+
+/// Searches for the symbols matching \p Query. The syntax of \p Query can be
+/// the non-qualified name or fully qualified of a symbol. For example, "vector"
+/// will match the symbol std::vector and "std::vector" would also match it.
+/// Direct children of scopes (namepaces, etc) can be listed with a trailing
+/// "::". For example, "std::" will list all children of the std namespace and
+/// "::" alone will list all children of the global namespace.
+/// \p Limit limits the number of results returned (0 means no limit).
+/// \p HintPath This is used when resolving URIs. If empty, URI resolution can
+/// fail if a hint path is required for the scheme of a specific URI.
+llvm::Expected<std::vector<SymbolInformation>>
+getWorkspaceSymbols(llvm::StringRef Query, int Limit,
+                    const SymbolIndex *const Index, llvm::StringRef HintPath);
+
+/// Retrieves the symbols contained in the "main file" section of an AST in the
+/// same order that they appear.
+llvm::Expected<std::vector<SymbolInformation>>
+getDocumentSymbols(ParsedAST &AST);
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Function.h b/src/third_party/llvm-project/clang-tools-extra/clangd/Function.h
new file mode 100644
index 0000000..88a5bc0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Function.h
@@ -0,0 +1,89 @@
+//===--- 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 utilities for callable objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUNCTION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUNCTION_H
+
+#include "llvm/ADT/FunctionExtras.h"
+#include "llvm/Support/Error.h"
+#include <tuple>
+#include <utility>
+
+namespace clang {
+namespace clangd {
+
+/// A Callback<T> is a void function that accepts Expected<T>.
+/// This is accepted by ClangdServer functions that logically return T.
+template <typename T>
+using Callback = llvm::unique_function<void(llvm::Expected<T>)>;
+
+/// 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 Bind 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...> Bind(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/src/third_party/llvm-project/clang-tools-extra/clangd/FuzzyMatch.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/FuzzyMatch.cpp
new file mode 100644
index 0000000..b81020a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/FuzzyMatch.cpp
@@ -0,0 +1,395 @@
+//===--- FuzzyMatch.h - Approximate identifier matching  ---------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// To check for a match between a Pattern ('u_p') and a Word ('unique_ptr'),
+// we consider the possible partial match states:
+//
+//     u n i q u e _ p t r
+//   +---------------------
+//   |A . . . . . . . . . .
+//  u|
+//   |. . . . . . . . . . .
+//  _|
+//   |. . . . . . . O . . .
+//  p|
+//   |. . . . . . . . . . B
+//
+// Each dot represents some prefix of the pattern being matched against some
+// prefix of the word.
+//   - A is the initial state: '' matched against ''
+//   - O is an intermediate state: 'u_' matched against 'unique_'
+//   - B is the target state: 'u_p' matched against 'unique_ptr'
+//
+// We aim to find the best path from A->B.
+//  - Moving right (consuming a word character)
+//    Always legal: not all word characters must match.
+//  - Moving diagonally (consuming both a word and pattern character)
+//    Legal if the characters match.
+//  - Moving down (consuming a pattern character) is never legal.
+//    Never legal: all pattern characters must match something.
+// Characters are matched case-insensitively.
+// The first pattern character may only match the start of a word segment.
+//
+// The scoring is based on heuristics:
+//  - when matching a character, apply a bonus or penalty depending on the
+//    match quality (does case match, do word segments align, etc)
+//  - when skipping a character, apply a penalty if it hurts the match
+//    (it starts a word segment, or splits the matched region, etc)
+//
+// These heuristics require the ability to "look backward" one character, to
+// see whether it was matched or not. Therefore the dynamic-programming matrix
+// has an extra dimension (last character matched).
+// Each entry also has an additional flag indicating whether the last-but-one
+// character matched, which is needed to trace back through the scoring table
+// and reconstruct the match.
+//
+// We treat strings as byte-sequences, so only ASCII has first-class support.
+//
+// This algorithm was inspired by VS code's client-side filtering, and aims
+// to be mostly-compatible.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FuzzyMatch.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Format.h"
+
+namespace clang {
+namespace clangd {
+using namespace llvm;
+
+constexpr int FuzzyMatcher::MaxPat;
+constexpr int FuzzyMatcher::MaxWord;
+
+static char lower(char C) { return C >= 'A' && C <= 'Z' ? C + ('a' - 'A') : C; }
+// A "negative infinity" score that won't overflow.
+// We use this to mark unreachable states and forbidden solutions.
+// Score field is 15 bits wide, min value is -2^14, we use half of that.
+static constexpr int AwfulScore = -(1 << 13);
+static bool isAwful(int S) { return S < AwfulScore / 2; }
+static constexpr int PerfectBonus = 3; // Perfect per-pattern-char score.
+
+FuzzyMatcher::FuzzyMatcher(StringRef Pattern)
+    : PatN(std::min<int>(MaxPat, Pattern.size())),
+      ScoreScale(PatN ? float{1} / (PerfectBonus * PatN) : 0), WordN(0) {
+  std::copy(Pattern.begin(), Pattern.begin() + PatN, Pat);
+  for (int I = 0; I < PatN; ++I)
+    LowPat[I] = lower(Pat[I]);
+  Scores[0][0][Miss] = {0, Miss};
+  Scores[0][0][Match] = {AwfulScore, Miss};
+  for (int P = 0; P <= PatN; ++P)
+    for (int W = 0; W < P; ++W)
+      for (Action A : {Miss, Match})
+        Scores[P][W][A] = {AwfulScore, Miss};
+  PatTypeSet =
+      calculateRoles(StringRef(Pat, PatN), makeMutableArrayRef(PatRole, PatN));
+}
+
+Optional<float> FuzzyMatcher::match(StringRef Word) {
+  if (!(WordContainsPattern = init(Word)))
+    return None;
+  if (!PatN)
+    return 1;
+  buildGraph();
+  auto Best = std::max(Scores[PatN][WordN][Miss].Score,
+                       Scores[PatN][WordN][Match].Score);
+  if (isAwful(Best))
+    return None;
+  float Score =
+      ScoreScale * std::min(PerfectBonus * PatN, std::max<int>(0, Best));
+  // If the pattern is as long as the word, we have an exact string match,
+  // since every pattern character must match something.
+  if (WordN == PatN)
+    Score *= 2; // May not be perfect 2 if case differs in a significant way.
+  return Score;
+}
+
+// We get CharTypes from a lookup table. Each is 2 bits, 4 fit in each byte.
+// The top 6 bits of the char select the byte, the bottom 2 select the offset.
+// e.g. 'q' = 010100 01 = byte 28 (55), bits 3-2 (01) -> Lower.
+constexpr static uint8_t CharTypes[] = {
+    0x00, 0x00, 0x00, 0x00, // Control characters
+    0x00, 0x00, 0x00, 0x00, // Control characters
+    0xff, 0xff, 0xff, 0xff, // Punctuation
+    0x55, 0x55, 0xf5, 0xff, // Numbers->Lower, more Punctuation.
+    0xab, 0xaa, 0xaa, 0xaa, // @ and A-O
+    0xaa, 0xaa, 0xea, 0xff, // P-Z, more Punctuation.
+    0x57, 0x55, 0x55, 0x55, // ` and a-o
+    0x55, 0x55, 0xd5, 0x3f, // p-z, Punctuation, DEL.
+    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, // Bytes over 127 -> Lower.
+    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, // (probably UTF-8).
+    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+};
+
+// The Role can be determined from the Type of a character and its neighbors:
+//
+//   Example  | Chars | Type | Role
+//   ---------+--------------+-----
+//   F(o)oBar | Foo   | Ull  | Tail
+//   Foo(B)ar | oBa   | lUl  | Head
+//   (f)oo    | ^fo   | Ell  | Head
+//   H(T)TP   | HTT   | UUU  | Tail
+//
+// Our lookup table maps a 6 bit key (Prev, Curr, Next) to a 2-bit Role.
+// A byte packs 4 Roles. (Prev, Curr) selects a byte, Next selects the offset.
+// e.g. Lower, Upper, Lower -> 01 10 01 -> byte 6 (aa), bits 3-2 (10) -> Head.
+constexpr static uint8_t CharRoles[] = {
+    // clang-format off
+    //         Curr= Empty Lower Upper Separ
+    /* Prev=Empty */ 0x00, 0xaa, 0xaa, 0xff, // At start, Lower|Upper->Head
+    /* Prev=Lower */ 0x00, 0x55, 0xaa, 0xff, // In word, Upper->Head;Lower->Tail
+    /* Prev=Upper */ 0x00, 0x55, 0x59, 0xff, // Ditto, but U(U)U->Tail
+    /* Prev=Separ */ 0x00, 0xaa, 0xaa, 0xff, // After separator, like at start
+    // clang-format on
+};
+
+template <typename T> static T packedLookup(const uint8_t *Data, int I) {
+  return static_cast<T>((Data[I >> 2] >> ((I & 3) * 2)) & 3);
+}
+CharTypeSet calculateRoles(StringRef Text, MutableArrayRef<CharRole> Roles) {
+  assert(Text.size() == Roles.size());
+  if (Text.size() == 0)
+    return 0;
+  CharType Type = packedLookup<CharType>(CharTypes, Text[0]);
+  CharTypeSet TypeSet = 1 << Type;
+  // Types holds a sliding window of (Prev, Curr, Next) types.
+  // Initial value is (Empty, Empty, type of Text[0]).
+  int Types = Type;
+  // Rotate slides in the type of the next character.
+  auto Rotate = [&](CharType T) { Types = ((Types << 2) | T) & 0x3f; };
+  for (unsigned I = 0; I < Text.size() - 1; ++I) {
+    // For each character, rotate in the next, and look up the role.
+    Type = packedLookup<CharType>(CharTypes, Text[I + 1]);
+    TypeSet |= 1 << Type;
+    Rotate(Type);
+    Roles[I] = packedLookup<CharRole>(CharRoles, Types);
+  }
+  // For the last character, the "next character" is Empty.
+  Rotate(Empty);
+  Roles[Text.size() - 1] = packedLookup<CharRole>(CharRoles, Types);
+  return TypeSet;
+}
+
+// Sets up the data structures matching Word.
+// Returns false if we can cheaply determine that no match is possible.
+bool FuzzyMatcher::init(StringRef NewWord) {
+  WordN = std::min<int>(MaxWord, NewWord.size());
+  if (PatN > WordN)
+    return false;
+  std::copy(NewWord.begin(), NewWord.begin() + WordN, Word);
+  if (PatN == 0)
+    return true;
+  for (int I = 0; I < WordN; ++I)
+    LowWord[I] = lower(Word[I]);
+
+  // Cheap subsequence check.
+  for (int W = 0, P = 0; P != PatN; ++W) {
+    if (W == WordN)
+      return false;
+    if (LowWord[W] == LowPat[P])
+      ++P;
+  }
+
+  // FIXME: some words are hard to tokenize algorithmically.
+  // e.g. vsprintf is V S Print F, and should match [pri] but not [int].
+  // We could add a tokenization dictionary for common stdlib names.
+  WordTypeSet = calculateRoles(StringRef(Word, WordN),
+                               makeMutableArrayRef(WordRole, WordN));
+  return true;
+}
+
+// The forwards pass finds the mappings of Pattern onto Word.
+// Score = best score achieved matching Word[..W] against Pat[..P].
+// Unlike other tables, indices range from 0 to N *inclusive*
+// Matched = whether we chose to match Word[W] with Pat[P] or not.
+//
+// Points are mostly assigned to matched characters, with 1 being a good score
+// and 3 being a great one. So we treat the score range as [0, 3 * PatN].
+// This range is not strict: we can apply larger bonuses/penalties, or penalize
+// non-matched characters.
+void FuzzyMatcher::buildGraph() {
+  for (int W = 0; W < WordN; ++W) {
+    Scores[0][W + 1][Miss] = {Scores[0][W][Miss].Score - skipPenalty(W, Miss),
+                              Miss};
+    Scores[0][W + 1][Match] = {AwfulScore, Miss};
+  }
+  for (int P = 0; P < PatN; ++P) {
+    for (int W = P; W < WordN; ++W) {
+      auto &Score = Scores[P + 1][W + 1], &PreMiss = Scores[P + 1][W];
+
+      auto MatchMissScore = PreMiss[Match].Score;
+      auto MissMissScore = PreMiss[Miss].Score;
+      if (P < PatN - 1) { // Skipping trailing characters is always free.
+        MatchMissScore -= skipPenalty(W, Match);
+        MissMissScore -= skipPenalty(W, Miss);
+      }
+      Score[Miss] = (MatchMissScore > MissMissScore)
+                        ? ScoreInfo{MatchMissScore, Match}
+                        : ScoreInfo{MissMissScore, Miss};
+
+      auto &PreMatch = Scores[P][W];
+      auto MatchMatchScore =
+          allowMatch(P, W, Match)
+              ? PreMatch[Match].Score + matchBonus(P, W, Match)
+              : AwfulScore;
+      auto MissMatchScore = allowMatch(P, W, Miss)
+                                ? PreMatch[Miss].Score + matchBonus(P, W, Miss)
+                                : AwfulScore;
+      Score[Match] = (MatchMatchScore > MissMatchScore)
+                         ? ScoreInfo{MatchMatchScore, Match}
+                         : ScoreInfo{MissMatchScore, Miss};
+    }
+  }
+}
+
+bool FuzzyMatcher::allowMatch(int P, int W, Action Last) const {
+  if (LowPat[P] != LowWord[W])
+    return false;
+  // We require a "strong" match:
+  // - for the first pattern character.  [foo] !~ "barefoot"
+  // - after a gap.                      [pat] !~ "patnther"
+  if (Last == Miss) {
+    // We're banning matches outright, so conservatively accept some other cases
+    // where our segmentation might be wrong:
+    //  - allow matching B in ABCDef (but not in NDEBUG)
+    //  - we'd like to accept print in sprintf, but too many false positives
+    if (WordRole[W] == Tail &&
+        (Word[W] == LowWord[W] || !(WordTypeSet & 1 << Lower)))
+      return false;
+  }
+  return true;
+}
+
+int FuzzyMatcher::skipPenalty(int W, Action Last) const {
+  int S = 0;
+  if (WordRole[W] == Head) // Skipping a segment.
+    S += 1;
+  if (Last == Match) // Non-consecutive match.
+    S += 2;          // We'd rather skip a segment than split our match.
+  return S;
+}
+
+int FuzzyMatcher::matchBonus(int P, int W, Action Last) const {
+  assert(LowPat[P] == LowWord[W]);
+  int S = 1;
+  // Bonus: pattern so far is a (case-insensitive) prefix of the word.
+  if (P == W) // We can't skip pattern characters, so we must have matched all.
+    ++S;
+  // Bonus: case matches, or a Head in the pattern aligns with one in the word.
+  if ((Pat[P] == Word[W] && ((PatTypeSet & 1 << Upper) || P == W)) ||
+      (PatRole[P] == Head && WordRole[W] == Head))
+    ++S;
+  // Penalty: matching inside a segment (and previous char wasn't matched).
+  if (WordRole[W] == Tail && P && Last == Miss)
+    S -= 3;
+  // Penalty: a Head in the pattern matches in the middle of a word segment.
+  if (PatRole[P] == Head && WordRole[W] == Tail)
+    --S;
+  // Penalty: matching the first pattern character in the middle of a segment.
+  if (P == 0 && WordRole[W] == Tail)
+    S -= 4;
+  assert(S <= PerfectBonus);
+  return S;
+}
+
+llvm::SmallString<256> FuzzyMatcher::dumpLast(llvm::raw_ostream &OS) const {
+  llvm::SmallString<256> Result;
+  OS << "=== Match \"" << StringRef(Word, WordN) << "\" against ["
+     << StringRef(Pat, PatN) << "] ===\n";
+  if (PatN == 0) {
+    OS << "Pattern is empty: perfect match.\n";
+    return Result = StringRef(Word, WordN);
+  }
+  if (WordN == 0) {
+    OS << "Word is empty: no match.\n";
+    return Result;
+  }
+  if (!WordContainsPattern) {
+    OS << "Substring check failed.\n";
+    return Result;
+  } else if (isAwful(std::max(Scores[PatN][WordN][Match].Score,
+                              Scores[PatN][WordN][Miss].Score))) {
+    OS << "Substring check passed, but all matches are forbidden\n";
+  }
+  if (!(PatTypeSet & 1 << Upper))
+    OS << "Lowercase query, so scoring ignores case\n";
+
+  // Traverse Matched table backwards to reconstruct the Pattern/Word mapping.
+  // The Score table has cumulative scores, subtracting along this path gives
+  // us the per-letter scores.
+  Action Last =
+      (Scores[PatN][WordN][Match].Score > Scores[PatN][WordN][Miss].Score)
+          ? Match
+          : Miss;
+  int S[MaxWord];
+  Action A[MaxWord];
+  for (int W = WordN - 1, P = PatN - 1; W >= 0; --W) {
+    A[W] = Last;
+    const auto &Cell = Scores[P + 1][W + 1][Last];
+    if (Last == Match)
+      --P;
+    const auto &Prev = Scores[P + 1][W][Cell.Prev];
+    S[W] = Cell.Score - Prev.Score;
+    Last = Cell.Prev;
+  }
+  for (int I = 0; I < WordN; ++I) {
+    if (A[I] == Match && (I == 0 || A[I - 1] == Miss))
+      Result.push_back('[');
+    if (A[I] == Miss && I > 0 && A[I - 1] == Match)
+      Result.push_back(']');
+    Result.push_back(Word[I]);
+  }
+  if (A[WordN - 1] == Match)
+    Result.push_back(']');
+
+  for (char C : StringRef(Word, WordN))
+    OS << " " << C << " ";
+  OS << "\n";
+  for (int I = 0, J = 0; I < WordN; I++)
+    OS << " " << (A[I] == Match ? Pat[J++] : ' ') << " ";
+  OS << "\n";
+  for (int I = 0; I < WordN; I++)
+    OS << format("%2d ", S[I]);
+  OS << "\n";
+
+  OS << "\nSegmentation:";
+  OS << "\n'" << StringRef(Word, WordN) << "'\n ";
+  for (int I = 0; I < WordN; ++I)
+    OS << "?-+ "[static_cast<int>(WordRole[I])];
+  OS << "\n[" << StringRef(Pat, PatN) << "]\n ";
+  for (int I = 0; I < PatN; ++I)
+    OS << "?-+ "[static_cast<int>(PatRole[I])];
+  OS << "\n";
+
+  OS << "\nScoring table (last-Miss, last-Match):\n";
+  OS << " |    ";
+  for (char C : StringRef(Word, WordN))
+    OS << "  " << C << " ";
+  OS << "\n";
+  OS << "-+----" << std::string(WordN * 4, '-') << "\n";
+  for (int I = 0; I <= PatN; ++I) {
+    for (Action A : {Miss, Match}) {
+      OS << ((I && A == Miss) ? Pat[I - 1] : ' ') << "|";
+      for (int J = 0; J <= WordN; ++J) {
+        if (!isAwful(Scores[I][J][A].Score))
+          OS << format("%3d%c", Scores[I][J][A].Score,
+                       Scores[I][J][A].Prev == Match ? '*' : ' ');
+        else
+          OS << "    ";
+      }
+      OS << "\n";
+    }
+  }
+
+  return Result;
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/FuzzyMatch.h b/src/third_party/llvm-project/clang-tools-extra/clangd/FuzzyMatch.h
new file mode 100644
index 0000000..f0c7e72
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/FuzzyMatch.h
@@ -0,0 +1,137 @@
+//===--- FuzzyMatch.h - Approximate identifier matching  ---------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements fuzzy-matching of strings against identifiers.
+// It indicates both the existence and quality of a match:
+// 'eb' matches both 'emplace_back' and 'embed', the former has a better score.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUZZYMATCH_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUZZYMATCH_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace clangd {
+
+// Utilities for word segmentation.
+// FuzzyMatcher already incorporates this logic, so most users don't need this.
+//
+// A name like "fooBar_baz" consists of several parts foo, bar, baz.
+// Aligning segmentation of word and pattern improves the fuzzy-match.
+// For example: [lol] matches "LaughingOutLoud" better than "LionPopulation"
+//
+// First we classify each character into types (uppercase, lowercase, etc).
+// Then we look at the sequence: e.g. [upper, lower] is the start of a segment.
+
+// We distinguish the types of characters that affect segmentation.
+// It's not obvious how to segment digits, we treat them as lowercase letters.
+// As we don't decode UTF-8, we treat bytes over 127 as lowercase too.
+// This means we require exact (case-sensitive) match for those characters.
+enum CharType : unsigned char {
+  Empty = 0,       // Before-the-start and after-the-end (and control chars).
+  Lower = 1,       // Lowercase letters, digits, and non-ASCII bytes.
+  Upper = 2,       // Uppercase letters.
+  Punctuation = 3, // ASCII punctuation (including Space)
+};
+// A CharTypeSet is a bitfield representing all the character types in a word.
+// Its bits are 1<<Empty, 1<<Lower, etc.
+using CharTypeSet = unsigned char;
+
+// Each character's Role is the Head or Tail of a segment, or a Separator.
+// e.g. XMLHttpRequest_Async
+//      +--+---+------ +----
+//      ^Head   ^Tail ^Separator
+enum CharRole : unsigned char {
+  Unknown = 0,   // Stray control characters or impossible states.
+  Tail = 1,      // Part of a word segment, but not the first character.
+  Head = 2,      // The first character of a word segment.
+  Separator = 3, // Punctuation characters that separate word segments.
+};
+
+// Compute segmentation of Text.
+// Character roles are stored in Roles (Roles.size() must equal Text.size()).
+// The set of character types encountered is returned, this may inform
+// heuristics for dealing with poorly-segmented identifiers like "strndup".
+CharTypeSet calculateRoles(llvm::StringRef Text,
+                           llvm::MutableArrayRef<CharRole> Roles);
+
+// A matcher capable of matching and scoring strings against a single pattern.
+// It's optimized for matching against many strings - match() does not allocate.
+class FuzzyMatcher {
+public:
+  // Characters beyond MaxPat are ignored.
+  FuzzyMatcher(llvm::StringRef Pattern);
+
+  // If Word matches the pattern, return a score indicating the quality match.
+  // Scores usually fall in a [0,1] range, with 1 being a very good score.
+  // "Super" scores in (1,2] are possible if the pattern is the full word.
+  // Characters beyond MaxWord are ignored.
+  llvm::Optional<float> match(llvm::StringRef Word);
+
+  llvm::StringRef pattern() const { return llvm::StringRef(Pat, PatN); }
+  bool empty() const { return PatN == 0; }
+
+  // Dump internal state from the last match() to the stream, for debugging.
+  // Returns the pattern with [] around matched characters, e.g.
+  //   [u_p] + "unique_ptr" --> "[u]nique[_p]tr"
+  llvm::SmallString<256> dumpLast(llvm::raw_ostream &) const;
+
+private:
+  // We truncate the pattern and the word to bound the cost of matching.
+  constexpr static int MaxPat = 63, MaxWord = 127;
+  // Action describes how a word character was matched to the pattern.
+  // It should be an enum, but this causes bitfield problems:
+  //   - for MSVC the enum type must be explicitly unsigned for correctness
+  //   - GCC 4.8 complains not all values fit if the type is unsigned
+  using Action = bool;
+  constexpr static Action Miss = false; // Word character was skipped.
+  constexpr static Action Match = true; // Matched against a pattern character.
+
+  bool init(llvm::StringRef Word);
+  void buildGraph();
+  bool allowMatch(int P, int W, Action Last) const;
+  int skipPenalty(int W, Action Last) const;
+  int matchBonus(int P, int W, Action Last) const;
+
+  // Pattern data is initialized by the constructor, then constant.
+  char Pat[MaxPat];         // Pattern data
+  int PatN;                 // Length
+  char LowPat[MaxPat];      // Pattern in lowercase
+  CharRole PatRole[MaxPat]; // Pattern segmentation info
+  CharTypeSet PatTypeSet;   // Bitmask of 1<<CharType for all Pattern characters
+  float ScoreScale;         // Normalizes scores for the pattern length.
+
+  // Word data is initialized on each call to match(), mostly by init().
+  char Word[MaxWord];         // Word data
+  int WordN;                  // Length
+  char LowWord[MaxWord];      // Word in lowercase
+  CharRole WordRole[MaxWord]; // Word segmentation info
+  CharTypeSet WordTypeSet;    // Bitmask of 1<<CharType for all Word characters
+  bool WordContainsPattern;   // Simple substring check
+
+  // Cumulative best-match score table.
+  // Boundary conditions are filled in by the constructor.
+  // The rest is repopulated for each match(), by buildGraph().
+  struct ScoreInfo {
+    signed int Score : 15;
+    Action Prev : 1;
+  };
+  ScoreInfo Scores[MaxPat + 1][MaxWord + 1][/* Last Action */ 2];
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
new file mode 100644
index 0000000..be03e4c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -0,0 +1,156 @@
+//===--- GlobalCompilationDatabase.cpp --------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "GlobalCompilationDatabase.h"
+#include "Logger.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+namespace clang {
+namespace clangd {
+
+tooling::CompileCommand
+GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+  std::vector<std::string> Argv = {"clang"};
+  // Clang treats .h files as C by default, resulting in unhelpful diagnostics.
+  // Parsing as Objective C++ is friendly to more cases.
+  if (llvm::sys::path::extension(File) == ".h")
+    Argv.push_back("-xobjective-c++-header");
+  Argv.push_back(File);
+  return tooling::CompileCommand(llvm::sys::path::parent_path(File),
+                                 llvm::sys::path::filename(File),
+                                 std::move(Argv),
+                                 /*Output=*/"");
+}
+
+DirectoryBasedGlobalCompilationDatabase::
+    DirectoryBasedGlobalCompilationDatabase(
+        llvm::Optional<Path> CompileCommandsDir)
+    : CompileCommandsDir(std::move(CompileCommandsDir)) {}
+
+DirectoryBasedGlobalCompilationDatabase::
+    ~DirectoryBasedGlobalCompilationDatabase() = default;
+
+llvm::Optional<tooling::CompileCommand>
+DirectoryBasedGlobalCompilationDatabase::getCompileCommand(PathRef File) const {
+  if (auto CDB = getCDBForFile(File)) {
+    auto Candidates = CDB->getCompileCommands(File);
+    if (!Candidates.empty()) {
+      addExtraFlags(File, Candidates.front());
+      return std::move(Candidates.front());
+    }
+  } else {
+    log("Failed to find compilation database for {0}", File);
+  }
+  return llvm::None;
+}
+
+tooling::CompileCommand
+DirectoryBasedGlobalCompilationDatabase::getFallbackCommand(
+    PathRef File) const {
+  auto C = GlobalCompilationDatabase::getFallbackCommand(File);
+  addExtraFlags(File, C);
+  return C;
+}
+
+void DirectoryBasedGlobalCompilationDatabase::setCompileCommandsDir(Path P) {
+  std::lock_guard<std::mutex> Lock(Mutex);
+  CompileCommandsDir = P;
+  CompilationDatabases.clear();
+}
+
+void DirectoryBasedGlobalCompilationDatabase::setExtraFlagsForFile(
+    PathRef File, std::vector<std::string> ExtraFlags) {
+  std::lock_guard<std::mutex> Lock(Mutex);
+  ExtraFlagsForFile[File] = std::move(ExtraFlags);
+}
+
+void DirectoryBasedGlobalCompilationDatabase::addExtraFlags(
+    PathRef File, tooling::CompileCommand &C) const {
+  std::lock_guard<std::mutex> Lock(Mutex);
+
+  auto It = ExtraFlagsForFile.find(File);
+  if (It == ExtraFlagsForFile.end())
+    return;
+
+  auto &Args = C.CommandLine;
+  assert(Args.size() >= 2 && "Expected at least [compiler, source file]");
+  // The last argument of CommandLine is the name of the input file.
+  // Add ExtraFlags before it.
+  Args.insert(Args.end() - 1, It->second.begin(), It->second.end());
+}
+
+tooling::CompilationDatabase *
+DirectoryBasedGlobalCompilationDatabase::getCDBInDirLocked(PathRef Dir) const {
+  // FIXME(ibiryukov): Invalidate cached compilation databases on changes
+  auto CachedIt = CompilationDatabases.find(Dir);
+  if (CachedIt != CompilationDatabases.end())
+    return CachedIt->second.get();
+  std::string Error = "";
+  auto CDB = tooling::CompilationDatabase::loadFromDirectory(Dir, Error);
+  if (CDB)
+    CDB = tooling::inferMissingCompileCommands(std::move(CDB));
+  auto Result = CDB.get();
+  CompilationDatabases.insert(std::make_pair(Dir, std::move(CDB)));
+  return Result;
+}
+
+tooling::CompilationDatabase *
+DirectoryBasedGlobalCompilationDatabase::getCDBForFile(PathRef File) const {
+  namespace path = llvm::sys::path;
+  assert((path::is_absolute(File, path::Style::posix) ||
+          path::is_absolute(File, path::Style::windows)) &&
+         "path must be absolute");
+
+  std::lock_guard<std::mutex> Lock(Mutex);
+  if (CompileCommandsDir)
+    return getCDBInDirLocked(*CompileCommandsDir);
+  for (auto Path = path::parent_path(File); !Path.empty();
+       Path = path::parent_path(Path))
+    if (auto CDB = getCDBInDirLocked(Path))
+      return CDB;
+  return nullptr;
+}
+
+CachingCompilationDb::CachingCompilationDb(
+    const GlobalCompilationDatabase &InnerCDB)
+    : InnerCDB(InnerCDB) {}
+
+llvm::Optional<tooling::CompileCommand>
+CachingCompilationDb::getCompileCommand(PathRef File) const {
+  std::unique_lock<std::mutex> Lock(Mut);
+  auto It = Cached.find(File);
+  if (It != Cached.end())
+    return It->second;
+
+  Lock.unlock();
+  llvm::Optional<tooling::CompileCommand> Command =
+      InnerCDB.getCompileCommand(File);
+  Lock.lock();
+  return Cached.try_emplace(File, std::move(Command)).first->getValue();
+}
+
+tooling::CompileCommand
+CachingCompilationDb::getFallbackCommand(PathRef File) const {
+  return InnerCDB.getFallbackCommand(File);
+}
+
+void CachingCompilationDb::invalidate(PathRef File) {
+  std::unique_lock<std::mutex> Lock(Mut);
+  Cached.erase(File);
+}
+
+void CachingCompilationDb::clear() {
+  std::unique_lock<std::mutex> Lock(Mut);
+  Cached.clear();
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/GlobalCompilationDatabase.h b/src/third_party/llvm-project/clang-tools-extra/clangd/GlobalCompilationDatabase.h
new file mode 100644
index 0000000..ab89a18
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -0,0 +1,119 @@
+//===--- GlobalCompilationDatabase.h ----------------------------*- 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_GLOBALCOMPILATIONDATABASE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H
+
+#include "Path.h"
+#include "llvm/ADT/StringMap.h"
+#include <memory>
+#include <mutex>
+#include <vector>
+
+namespace clang {
+
+namespace tooling {
+class CompilationDatabase;
+struct CompileCommand;
+} // namespace tooling
+
+namespace clangd {
+
+class Logger;
+
+/// Provides compilation arguments used for parsing C and C++ files.
+class GlobalCompilationDatabase {
+public:
+  virtual ~GlobalCompilationDatabase() = default;
+
+  /// If there are any known-good commands for building this file, returns one.
+  virtual llvm::Optional<tooling::CompileCommand>
+  getCompileCommand(PathRef File) const = 0;
+
+  /// Makes a guess at how to build a file.
+  /// The default implementation just runs clang on the file.
+  /// Clangd should treat the results as unreliable.
+  virtual tooling::CompileCommand getFallbackCommand(PathRef File) const;
+
+  /// FIXME(ibiryukov): add facilities to track changes to compilation flags of
+  /// existing targets.
+};
+
+/// Gets compile args from tooling::CompilationDatabases built for parent
+/// directories.
+class DirectoryBasedGlobalCompilationDatabase
+    : public GlobalCompilationDatabase {
+public:
+  DirectoryBasedGlobalCompilationDatabase(
+      llvm::Optional<Path> CompileCommandsDir);
+  ~DirectoryBasedGlobalCompilationDatabase() override;
+
+  /// Scans File's parents looking for compilation databases.
+  /// Any extra flags will be added.
+  llvm::Optional<tooling::CompileCommand>
+  getCompileCommand(PathRef File) const override;
+
+  /// Uses the default fallback command, adding any extra flags.
+  tooling::CompileCommand getFallbackCommand(PathRef File) const override;
+
+  /// Set the compile commands directory to \p P.
+  void setCompileCommandsDir(Path P);
+
+  /// Sets the extra flags that should be added to a file.
+  void setExtraFlagsForFile(PathRef File, std::vector<std::string> ExtraFlags);
+
+private:
+  tooling::CompilationDatabase *getCDBForFile(PathRef File) const;
+  tooling::CompilationDatabase *getCDBInDirLocked(PathRef File) const;
+  void addExtraFlags(PathRef File, tooling::CompileCommand &C) const;
+
+  mutable std::mutex Mutex;
+  /// Caches compilation databases loaded from directories(keys are
+  /// directories).
+  mutable llvm::StringMap<std::unique_ptr<clang::tooling::CompilationDatabase>>
+      CompilationDatabases;
+
+  /// Stores extra flags per file.
+  llvm::StringMap<std::vector<std::string>> ExtraFlagsForFile;
+  /// Used for command argument pointing to folder where compile_commands.json
+  /// is located.
+  llvm::Optional<Path> CompileCommandsDir;
+};
+
+/// A wrapper around GlobalCompilationDatabase that caches the compile commands.
+/// Note that only results of getCompileCommand are cached.
+class CachingCompilationDb : public GlobalCompilationDatabase {
+public:
+  explicit CachingCompilationDb(const GlobalCompilationDatabase &InnerCDB);
+
+  /// Gets compile command for \p File from cache or CDB if it's not in the
+  /// cache.
+  llvm::Optional<tooling::CompileCommand>
+  getCompileCommand(PathRef File) const override;
+
+  /// Forwards to the inner CDB. Results of this function are not cached.
+  tooling::CompileCommand getFallbackCommand(PathRef File) const override;
+
+  /// Removes an entry for \p File if it's present in the cache.
+  void invalidate(PathRef File);
+
+  /// Removes all cached compile commands.
+  void clear();
+
+private:
+  const GlobalCompilationDatabase &InnerCDB;
+  mutable std::mutex Mut;
+  mutable llvm::StringMap<llvm::Optional<tooling::CompileCommand>>
+      Cached; /* GUARDED_BY(Mut) */
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Headers.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/Headers.cpp
new file mode 100644
index 0000000..137b29a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Headers.cpp
@@ -0,0 +1,173 @@
+//===--- Headers.cpp - Include headers ---------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Headers.h"
+#include "Compiler.h"
+#include "Logger.h"
+#include "SourceCode.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "llvm/Support/Path.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+class RecordHeaders : public PPCallbacks {
+public:
+  RecordHeaders(const SourceManager &SM, IncludeStructure *Out)
+      : SM(SM), Out(Out) {}
+
+  // Record existing #includes - both written and resolved paths. Only #includes
+  // in the main file are collected.
+  void InclusionDirective(SourceLocation HashLoc, const Token & /*IncludeTok*/,
+                          llvm::StringRef FileName, bool IsAngled,
+                          CharSourceRange FilenameRange, const FileEntry *File,
+                          llvm::StringRef /*SearchPath*/,
+                          llvm::StringRef /*RelativePath*/,
+                          const Module * /*Imported*/,
+                          SrcMgr::CharacteristicKind /*FileType*/) override {
+    if (SM.isInMainFile(HashLoc))
+      Out->MainFileIncludes.push_back({
+          halfOpenToRange(SM, FilenameRange),
+          (IsAngled ? "<" + FileName + ">" : "\"" + FileName + "\"").str(),
+          File ? File->tryGetRealPathName() : "",
+      });
+    if (File) {
+      auto *IncludingFileEntry = SM.getFileEntryForID(SM.getFileID(HashLoc));
+      if (!IncludingFileEntry) {
+        assert(SM.getBufferName(HashLoc).startswith("<") &&
+               "Expected #include location to be a file or <built-in>");
+        // Treat as if included from the main file.
+        IncludingFileEntry = SM.getFileEntryForID(SM.getMainFileID());
+      }
+      Out->recordInclude(IncludingFileEntry->getName(), File->getName(),
+                         File->tryGetRealPathName());
+    }
+  }
+
+private:
+  const SourceManager &SM;
+  IncludeStructure *Out;
+};
+
+} // namespace
+
+bool isLiteralInclude(llvm::StringRef Include) {
+  return Include.startswith("<") || Include.startswith("\"");
+}
+
+bool HeaderFile::valid() const {
+  return (Verbatim && isLiteralInclude(File)) ||
+         (!Verbatim && llvm::sys::path::is_absolute(File));
+}
+
+std::unique_ptr<PPCallbacks>
+collectIncludeStructureCallback(const SourceManager &SM,
+                                IncludeStructure *Out) {
+  return llvm::make_unique<RecordHeaders>(SM, Out);
+}
+
+void IncludeStructure::recordInclude(llvm::StringRef IncludingName,
+                                     llvm::StringRef IncludedName,
+                                     llvm::StringRef IncludedRealName) {
+  auto Child = fileIndex(IncludedName);
+  if (!IncludedRealName.empty() && RealPathNames[Child].empty())
+    RealPathNames[Child] = IncludedRealName;
+  auto Parent = fileIndex(IncludingName);
+  IncludeChildren[Parent].push_back(Child);
+}
+
+unsigned IncludeStructure::fileIndex(llvm::StringRef Name) {
+  auto R = NameToIndex.try_emplace(Name, RealPathNames.size());
+  if (R.second)
+    RealPathNames.emplace_back();
+  return R.first->getValue();
+}
+
+llvm::StringMap<unsigned>
+IncludeStructure::includeDepth(llvm::StringRef Root) const {
+  // Include depth 0 is the main file only.
+  llvm::StringMap<unsigned> Result;
+  Result[Root] = 0;
+  std::vector<unsigned> CurrentLevel;
+  llvm::DenseSet<unsigned> Seen;
+  auto It = NameToIndex.find(Root);
+  if (It != NameToIndex.end()) {
+    CurrentLevel.push_back(It->second);
+    Seen.insert(It->second);
+  }
+
+  // Each round of BFS traversal finds the next depth level.
+  std::vector<unsigned> PreviousLevel;
+  for (unsigned Level = 1; !CurrentLevel.empty(); ++Level) {
+    PreviousLevel.clear();
+    PreviousLevel.swap(CurrentLevel);
+    for (const auto &Parent : PreviousLevel) {
+      for (const auto &Child : IncludeChildren.lookup(Parent)) {
+        if (Seen.insert(Child).second) {
+          CurrentLevel.push_back(Child);
+          const auto &Name = RealPathNames[Child];
+          // Can't include files if we don't have their real path.
+          if (!Name.empty())
+            Result[Name] = Level;
+        }
+      }
+    }
+  }
+  return Result;
+}
+
+/// FIXME(ioeric): we might not want to insert an absolute include path if the
+/// path is not shortened.
+bool IncludeInserter::shouldInsertInclude(
+    const HeaderFile &DeclaringHeader, const HeaderFile &InsertedHeader) const {
+  assert(DeclaringHeader.valid() && InsertedHeader.valid());
+  if (FileName == DeclaringHeader.File || FileName == InsertedHeader.File)
+    return false;
+  llvm::StringSet<> IncludedHeaders;
+  for (const auto &Inc : Inclusions) {
+    IncludedHeaders.insert(Inc.Written);
+    if (!Inc.Resolved.empty())
+      IncludedHeaders.insert(Inc.Resolved);
+  }
+  auto Included = [&](llvm::StringRef Header) {
+    return IncludedHeaders.find(Header) != IncludedHeaders.end();
+  };
+  return !Included(DeclaringHeader.File) && !Included(InsertedHeader.File);
+}
+
+std::string
+IncludeInserter::calculateIncludePath(const HeaderFile &DeclaringHeader,
+                                      const HeaderFile &InsertedHeader) const {
+  assert(DeclaringHeader.valid() && InsertedHeader.valid());
+  if (InsertedHeader.Verbatim)
+    return InsertedHeader.File;
+  bool IsSystem = false;
+  std::string Suggested = HeaderSearchInfo.suggestPathToFileForDiagnostics(
+      InsertedHeader.File, BuildDir, &IsSystem);
+  if (IsSystem)
+    Suggested = "<" + Suggested + ">";
+  else
+    Suggested = "\"" + Suggested + "\"";
+  return Suggested;
+}
+
+Optional<TextEdit> IncludeInserter::insert(StringRef VerbatimHeader) const {
+  Optional<TextEdit> Edit = None;
+  if (auto Insertion = Inserter.insert(VerbatimHeader.trim("\"<>"),
+                                       VerbatimHeader.startswith("<")))
+    Edit = replacementToEdit(Code, *Insertion);
+  return Edit;
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Headers.h b/src/third_party/llvm-project/clang-tools-extra/clangd/Headers.h
new file mode 100644
index 0000000..2abf27c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Headers.h
@@ -0,0 +1,144 @@
+//===--- Headers.h - Include headers -----------------------------*- 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_HEADERS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEADERS_H
+
+#include "Path.h"
+#include "Protocol.h"
+#include "SourceCode.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Format/Format.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Tooling/Inclusions/HeaderIncludes.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace clangd {
+
+/// Returns true if \p Include is literal include like "path" or <path>.
+bool isLiteralInclude(llvm::StringRef Include);
+
+/// Represents a header file to be #include'd.
+struct HeaderFile {
+  std::string File;
+  /// If this is true, `File` is a literal string quoted with <> or "" that
+  /// can be #included directly; otherwise, `File` is an absolute file path.
+  bool Verbatim;
+
+  bool valid() const;
+};
+
+// An #include directive that we found in the main file.
+struct Inclusion {
+  Range R;             // Inclusion range.
+  std::string Written; // Inclusion name as written e.g. <vector>.
+  Path Resolved;       // Resolved path of included file. Empty if not resolved.
+};
+
+// Information captured about the inclusion graph in a translation unit.
+// This includes detailed information about the direct #includes, and summary
+// information about all transitive includes.
+//
+// It should be built incrementally with collectIncludeStructureCallback().
+// When we build the preamble, we capture and store its include structure along
+// with the preamble data. When we use the preamble, we can copy its
+// IncludeStructure and use another collectIncludeStructureCallback() to fill
+// in any non-preamble inclusions.
+class IncludeStructure {
+public:
+  std::vector<Inclusion> MainFileIncludes;
+
+  // Return all transitively reachable files, and their minimum include depth.
+  // All transitive includes (absolute paths), with their minimum include depth.
+  // Root --> 0, #included file --> 1, etc.
+  // Root is clang's name for a file, which may not be absolute.
+  // Usually it should be SM.getFileEntryForID(SM.getMainFileID())->getName().
+  llvm::StringMap<unsigned> includeDepth(llvm::StringRef Root) const;
+
+  // This updates IncludeDepth(), but not MainFileIncludes.
+  void recordInclude(llvm::StringRef IncludingName,
+                     llvm::StringRef IncludedName,
+                     llvm::StringRef IncludedRealName);
+
+private:
+  // Identifying files in a way that persists from preamble build to subsequent
+  // builds is surprisingly hard. FileID is unavailable in InclusionDirective(),
+  // and RealPathName and UniqueID are not preseved in the preamble.
+  // We use the FileEntry::Name, which is stable, interned into a "file index".
+  // The paths we want to expose are the RealPathName, so store those too.
+  std::vector<std::string> RealPathNames; // In file index order.
+  unsigned fileIndex(llvm::StringRef Name);
+  llvm::StringMap<unsigned> NameToIndex; // Values are file indexes.
+  // Maps a file's index to that of the files it includes.
+  llvm::DenseMap<unsigned, SmallVector<unsigned, 8>> IncludeChildren;
+};
+
+/// Returns a PPCallback that visits all inclusions in the main file.
+std::unique_ptr<PPCallbacks>
+collectIncludeStructureCallback(const SourceManager &SM, IncludeStructure *Out);
+
+// Calculates insertion edit for including a new header in a file.
+class IncludeInserter {
+public:
+  IncludeInserter(StringRef FileName, StringRef Code,
+                  const format::FormatStyle &Style, StringRef BuildDir,
+                  HeaderSearch &HeaderSearchInfo)
+      : FileName(FileName), Code(Code), BuildDir(BuildDir),
+        HeaderSearchInfo(HeaderSearchInfo),
+        Inserter(FileName, Code, Style.IncludeStyle) {}
+
+  void addExisting(Inclusion Inc) { Inclusions.push_back(std::move(Inc)); }
+
+  /// Checks whether to add an #include of the header into \p File.
+  /// An #include will not be added if:
+  ///   - Either \p DeclaringHeader or \p InsertedHeader is already (directly)
+  ///   in \p Inclusions (including those included via different paths).
+  ///   - \p DeclaringHeader or \p InsertedHeader is the same as \p File.
+  ///
+  /// \param DeclaringHeader is the original header corresponding to \p
+  /// InsertedHeader e.g. the header that declares a symbol.
+  /// \param InsertedHeader The preferred header to be inserted. This could be
+  /// the same as DeclaringHeader but must be provided.
+  bool shouldInsertInclude(const HeaderFile &DeclaringHeader,
+                           const HeaderFile &InsertedHeader) const;
+
+  /// Determines the preferred way to #include a file, taking into account the
+  /// search path. Usually this will prefer a shorter representation like
+  /// 'Foo/Bar.h' over a longer one like 'Baz/include/Foo/Bar.h'.
+  ///
+  /// \param DeclaringHeader is the original header corresponding to \p
+  /// InsertedHeader e.g. the header that declares a symbol.
+  /// \param InsertedHeader The preferred header to be inserted. This could be
+  /// the same as DeclaringHeader but must be provided.
+  ///
+  /// \return A quoted "path" or <path> to be included.
+  std::string calculateIncludePath(const HeaderFile &DeclaringHeader,
+                                   const HeaderFile &InsertedHeader) const;
+
+  /// Calculates an edit that inserts \p VerbatimHeader into code. If the header
+  /// is already included, this returns None.
+  llvm::Optional<TextEdit> insert(llvm::StringRef VerbatimHeader) const;
+
+private:
+  StringRef FileName;
+  StringRef Code;
+  StringRef BuildDir;
+  HeaderSearch &HeaderSearchInfo;
+  std::vector<Inclusion> Inclusions;
+  tooling::HeaderIncludes Inserter; // Computers insertion replacement.
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEADERS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/JSONRPCDispatcher.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/JSONRPCDispatcher.cpp
new file mode 100644
index 0000000..2741c66
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/JSONRPCDispatcher.cpp
@@ -0,0 +1,368 @@
+//===--- JSONRPCDispatcher.cpp - Main JSON parser entry point -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JSONRPCDispatcher.h"
+#include "ProtocolHandlers.h"
+#include "Trace.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/Errno.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/SourceMgr.h"
+#include <istream>
+
+using namespace llvm;
+using namespace clang;
+using namespace clangd;
+
+namespace {
+static Key<json::Value> RequestID;
+static Key<JSONOutput *> RequestOut;
+
+// When tracing, we trace a request and attach the repsonse in reply().
+// Because the Span isn't available, we find the current request using Context.
+class RequestSpan {
+  RequestSpan(llvm::json::Object *Args) : Args(Args) {}
+  std::mutex Mu;
+  llvm::json::Object *Args;
+  static Key<std::unique_ptr<RequestSpan>> RSKey;
+
+public:
+  // Return a context that's aware of the enclosing request, identified by Span.
+  static Context stash(const trace::Span &Span) {
+    return Context::current().derive(
+        RSKey, std::unique_ptr<RequestSpan>(new RequestSpan(Span.Args)));
+  }
+
+  // If there's an enclosing request and the tracer is interested, calls \p F
+  // with a json::Object where request info can be added.
+  template <typename Func> static void attach(Func &&F) {
+    auto *RequestArgs = Context::current().get(RSKey);
+    if (!RequestArgs || !*RequestArgs || !(*RequestArgs)->Args)
+      return;
+    std::lock_guard<std::mutex> Lock((*RequestArgs)->Mu);
+    F(*(*RequestArgs)->Args);
+  }
+};
+Key<std::unique_ptr<RequestSpan>> RequestSpan::RSKey;
+} // namespace
+
+void JSONOutput::writeMessage(const json::Value &Message) {
+  std::string S;
+  llvm::raw_string_ostream OS(S);
+  if (Pretty)
+    OS << llvm::formatv("{0:2}", Message);
+  else
+    OS << Message;
+  OS.flush();
+
+  {
+    std::lock_guard<std::mutex> Guard(StreamMutex);
+    Outs << "Content-Length: " << S.size() << "\r\n\r\n" << S;
+    Outs.flush();
+  }
+  vlog(">>> {0}\n", S);
+}
+
+void JSONOutput::log(Logger::Level Level,
+                     const llvm::formatv_object_base &Message) {
+  if (Level < MinLevel)
+    return;
+  llvm::sys::TimePoint<> Timestamp = std::chrono::system_clock::now();
+  trace::log(Message);
+  std::lock_guard<std::mutex> Guard(StreamMutex);
+  Logs << llvm::formatv("{0}[{1:%H:%M:%S.%L}] {2}\n", indicator(Level),
+                        Timestamp, Message);
+  Logs.flush();
+}
+
+void JSONOutput::mirrorInput(const Twine &Message) {
+  if (!InputMirror)
+    return;
+
+  *InputMirror << Message;
+  InputMirror->flush();
+}
+
+void clangd::reply(json::Value &&Result) {
+  auto ID = Context::current().get(RequestID);
+  if (!ID) {
+    elog("Attempted to reply to a notification!");
+    return;
+  }
+  RequestSpan::attach([&](json::Object &Args) { Args["Reply"] = Result; });
+  log("--> reply({0})", *ID);
+  Context::current()
+      .getExisting(RequestOut)
+      ->writeMessage(json::Object{
+          {"jsonrpc", "2.0"},
+          {"id", *ID},
+          {"result", std::move(Result)},
+      });
+}
+
+void clangd::replyError(ErrorCode Code, const llvm::StringRef &Message) {
+  elog("Error {0}: {1}", static_cast<int>(Code), Message);
+  RequestSpan::attach([&](json::Object &Args) {
+    Args["Error"] = json::Object{{"code", static_cast<int>(Code)},
+                                 {"message", Message.str()}};
+  });
+
+  if (auto ID = Context::current().get(RequestID)) {
+    log("--> reply({0}) error: {1}", *ID, Message);
+    Context::current()
+        .getExisting(RequestOut)
+        ->writeMessage(json::Object{
+            {"jsonrpc", "2.0"},
+            {"id", *ID},
+            {"error", json::Object{{"code", static_cast<int>(Code)},
+                                   {"message", Message}}},
+        });
+  }
+}
+
+void clangd::call(StringRef Method, json::Value &&Params) {
+  RequestSpan::attach([&](json::Object &Args) {
+    Args["Call"] = json::Object{{"method", Method.str()}, {"params", Params}};
+  });
+  // FIXME: Generate/Increment IDs for every request so that we can get proper
+  // replies once we need to.
+  auto ID = 1;
+  log("--> {0}({1})", Method, ID);
+  Context::current()
+      .getExisting(RequestOut)
+      ->writeMessage(json::Object{
+          {"jsonrpc", "2.0"},
+          {"id", ID},
+          {"method", Method},
+          {"params", std::move(Params)},
+      });
+}
+
+void JSONRPCDispatcher::registerHandler(StringRef Method, Handler H) {
+  assert(!Handlers.count(Method) && "Handler already registered!");
+  Handlers[Method] = std::move(H);
+}
+
+static void logIncomingMessage(const llvm::Optional<json::Value> &ID,
+                               llvm::Optional<StringRef> Method,
+                               const json::Object *Error) {
+  if (Method) { // incoming request
+    if (ID)     // call
+      log("<-- {0}({1})", *Method, *ID);
+    else // notification
+      log("<-- {0}", *Method);
+  } else if (ID) { // response, ID must be provided
+    if (Error)
+      log("<-- reply({0}) error: {1}", *ID,
+          Error->getString("message").getValueOr("<no message>"));
+    else
+      log("<-- reply({0})", *ID);
+  }
+}
+
+bool JSONRPCDispatcher::call(const json::Value &Message,
+                             JSONOutput &Out) const {
+  // Message must be an object with "jsonrpc":"2.0".
+  auto *Object = Message.getAsObject();
+  if (!Object || Object->getString("jsonrpc") != Optional<StringRef>("2.0"))
+    return false;
+  // ID may be any JSON value. If absent, this is a notification.
+  llvm::Optional<json::Value> ID;
+  if (auto *I = Object->get("id"))
+    ID = std::move(*I);
+  auto Method = Object->getString("method");
+  logIncomingMessage(ID, Method, Object->getObject("error"));
+  if (!Method) // We only handle incoming requests, and ignore responses.
+    return false;
+  // Params should be given, use null if not.
+  json::Value Params = nullptr;
+  if (auto *P = Object->get("params"))
+    Params = std::move(*P);
+
+  auto I = Handlers.find(*Method);
+  auto &Handler = I != Handlers.end() ? I->second : UnknownHandler;
+
+  // Create a Context that contains request information.
+  WithContextValue WithRequestOut(RequestOut, &Out);
+  llvm::Optional<WithContextValue> WithID;
+  if (ID)
+    WithID.emplace(RequestID, *ID);
+
+  // Create a tracing Span covering the whole request lifetime.
+  trace::Span Tracer(*Method);
+  if (ID)
+    SPAN_ATTACH(Tracer, "ID", *ID);
+  SPAN_ATTACH(Tracer, "Params", Params);
+
+  // Stash a reference to the span args, so later calls can add metadata.
+  WithContext WithRequestSpan(RequestSpan::stash(Tracer));
+  Handler(std::move(Params));
+  return true;
+}
+
+// Tries to read a line up to and including \n.
+// If failing, feof() or ferror() will be set.
+static bool readLine(std::FILE *In, std::string &Out) {
+  static constexpr int BufSize = 1024;
+  size_t Size = 0;
+  Out.clear();
+  for (;;) {
+    Out.resize(Size + BufSize);
+    // Handle EINTR which is sent when a debugger attaches on some platforms.
+    if (!llvm::sys::RetryAfterSignal(nullptr, ::fgets, &Out[Size], BufSize, In))
+      return false;
+    clearerr(In);
+    // If the line contained null bytes, anything after it (including \n) will
+    // be ignored. Fortunately this is not a legal header or JSON.
+    size_t Read = std::strlen(&Out[Size]);
+    if (Read > 0 && Out[Size + Read - 1] == '\n') {
+      Out.resize(Size + Read);
+      return true;
+    }
+    Size += Read;
+  }
+}
+
+// Returns None when:
+//  - ferror() or feof() are set.
+//  - Content-Length is missing or empty (protocol error)
+static llvm::Optional<std::string> readStandardMessage(std::FILE *In,
+                                                       JSONOutput &Out) {
+  // 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;
+  std::string Line;
+  while (true) {
+    if (feof(In) || ferror(In) || !readLine(In, Line))
+      return llvm::None;
+
+    Out.mirrorInput(Line);
+    llvm::StringRef LineRef(Line);
+
+    // We allow comments in headers. Technically this isn't part
+    // of the LSP specification, but makes writing tests easier.
+    if (LineRef.startswith("#"))
+      continue;
+
+    // Content-Length is a mandatory header, and the only one we handle.
+    if (LineRef.consume_front("Content-Length: ")) {
+      if (ContentLength != 0) {
+        elog("Warning: Duplicate Content-Length header received. "
+             "The previous value for this message ({0}) was ignored.",
+             ContentLength);
+      }
+      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;
+    }
+  }
+
+  // The fuzzer likes crashing us by sending "Content-Length: 9999999999999999"
+  if (ContentLength > 1 << 30) { // 1024M
+    elog("Refusing to read message with long Content-Length: {0}. "
+         "Expect protocol errors",
+         ContentLength);
+    return llvm::None;
+  }
+  if (ContentLength == 0) {
+    log("Warning: Missing Content-Length header, or zero-length message.");
+    return llvm::None;
+  }
+
+  std::string JSON(ContentLength, '\0');
+  for (size_t Pos = 0, Read; Pos < ContentLength; Pos += Read) {
+    // Handle EINTR which is sent when a debugger attaches on some platforms.
+    Read = llvm::sys::RetryAfterSignal(0u, ::fread, &JSON[Pos], 1,
+                                       ContentLength - Pos, In);
+    Out.mirrorInput(StringRef(&JSON[Pos], Read));
+    if (Read == 0) {
+      elog("Input was aborted. Read only {0} bytes of expected {1}.", Pos,
+           ContentLength);
+      return llvm::None;
+    }
+    clearerr(In); // If we're done, the error was transient. If we're not done,
+                  // either it was transient or we'll see it again on retry.
+    Pos += Read;
+  }
+  return std::move(JSON);
+}
+
+// For lit tests we support a simplified syntax:
+// - messages are delimited by '---' on a line by itself
+// - lines starting with # are ignored.
+// This is a testing path, so favor simplicity over performance here.
+// When returning None, feof() or ferror() will be set.
+static llvm::Optional<std::string> readDelimitedMessage(std::FILE *In,
+                                                        JSONOutput &Out) {
+  std::string JSON;
+  std::string Line;
+  while (readLine(In, Line)) {
+    auto LineRef = llvm::StringRef(Line).trim();
+    if (LineRef.startswith("#")) // comment
+      continue;
+
+    // found a delimiter
+    if (LineRef.rtrim() == "---")
+      break;
+
+    JSON += Line;
+  }
+
+  if (ferror(In)) {
+    elog("Input error while reading message!");
+    return llvm::None;
+  } else { // Including EOF
+    Out.mirrorInput(
+        llvm::formatv("Content-Length: {0}\r\n\r\n{1}", JSON.size(), JSON));
+    return std::move(JSON);
+  }
+}
+
+// The use of C-style std::FILE* IO deserves some explanation.
+// Previously, std::istream was used. When a debugger attached on MacOS, the
+// process received EINTR, the stream went bad, and clangd exited.
+// A retry-on-EINTR loop around reads solved this problem, but caused clangd to
+// sometimes hang rather than exit on other OSes. The interaction between
+// istreams and signals isn't well-specified, so it's hard to get this right.
+// The C APIs seem to be clearer in this respect.
+void clangd::runLanguageServerLoop(std::FILE *In, JSONOutput &Out,
+                                   JSONStreamStyle InputStyle,
+                                   JSONRPCDispatcher &Dispatcher,
+                                   bool &IsDone) {
+  auto &ReadMessage =
+      (InputStyle == Delimited) ? readDelimitedMessage : readStandardMessage;
+  while (!IsDone && !feof(In)) {
+    if (ferror(In)) {
+      elog("IO error: {0}", llvm::sys::StrError());
+      return;
+    }
+    if (auto JSON = ReadMessage(In, Out)) {
+      if (auto Doc = json::parse(*JSON)) {
+        // Log the formatted message.
+        vlog(Out.Pretty ? "<<< {0:2}\n" : "<<< {0}\n", *Doc);
+        // Finally, execute the action for this JSON message.
+        if (!Dispatcher.call(*Doc, Out))
+          elog("JSON dispatch failed!");
+      } else {
+        // Parse error. Log the raw message.
+        vlog("<<< {0}\n", *JSON);
+        elog("JSON parse error: {0}", llvm::toString(Doc.takeError()));
+      }
+    }
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/JSONRPCDispatcher.h b/src/third_party/llvm-project/clang-tools-extra/clangd/JSONRPCDispatcher.h
new file mode 100644
index 0000000..e8c96fc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/JSONRPCDispatcher.h
@@ -0,0 +1,117 @@
+//===--- JSONRPCDispatcher.h - Main JSON parser entry point -----*- 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_JSONRPCDISPATCHER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSONRPCDISPATCHER_H
+
+#include "Logger.h"
+#include "Protocol.h"
+#include "Trace.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/JSON.h"
+#include <iosfwd>
+#include <mutex>
+
+namespace clang {
+namespace clangd {
+
+/// Encapsulates output and logs streams and provides thread-safe access to
+/// them.
+class JSONOutput : public Logger {
+  // FIXME(ibiryukov): figure out if we can shrink the public interface of
+  // JSONOutput now that we pass Context everywhere.
+public:
+  JSONOutput(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs,
+             Logger::Level MinLevel, llvm::raw_ostream *InputMirror = nullptr,
+             bool Pretty = false)
+      : Pretty(Pretty), MinLevel(MinLevel), Outs(Outs), Logs(Logs),
+        InputMirror(InputMirror) {}
+
+  /// Emit a JSONRPC message.
+  void writeMessage(const llvm::json::Value &Result);
+
+  /// Write a line to the logging stream.
+  void log(Level, const llvm::formatv_object_base &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);
+
+  // Whether output should be pretty-printed.
+  const bool Pretty;
+
+private:
+  Logger::Level MinLevel;
+  llvm::raw_ostream &Outs;
+  llvm::raw_ostream &Logs;
+  llvm::raw_ostream *InputMirror;
+
+  std::mutex StreamMutex;
+};
+
+/// Sends a successful reply.
+/// Current context must derive from JSONRPCDispatcher::Handler.
+void reply(llvm::json::Value &&Result);
+/// Sends an error response to the client, and logs it.
+/// Current context must derive from JSONRPCDispatcher::Handler.
+void replyError(ErrorCode Code, const llvm::StringRef &Message);
+/// Sends a request to the client.
+/// Current context must derive from JSONRPCDispatcher::Handler.
+void call(llvm::StringRef Method, llvm::json::Value &&Params);
+
+/// 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(const llvm::json::Value &)>;
+
+  /// Create a new JSONRPCDispatcher. UnknownHandler is called when an unknown
+  /// method is received.
+  JSONRPCDispatcher(Handler UnknownHandler)
+      : UnknownHandler(std::move(UnknownHandler)) {}
+
+  /// Registers a Handler for the specified Method.
+  void registerHandler(StringRef Method, Handler H);
+
+  /// Parses a JSONRPC message and calls the Handler for it.
+  bool call(const llvm::json::Value &Message, JSONOutput &Out) const;
+
+private:
+  llvm::StringMap<Handler> Handlers;
+  Handler UnknownHandler;
+};
+
+/// Controls the way JSON-RPC messages are encoded (both input and output).
+enum JSONStreamStyle {
+  /// Encoding per the LSP specification, with mandatory Content-Length header.
+  Standard,
+  /// Messages are delimited by a '---' line. Comment lines start with #.
+  Delimited
+};
+
+/// Parses input queries from LSP client (coming from \p In) and runs call
+/// method of \p Dispatcher for each query.
+/// After handling each query checks if \p IsDone is set true and exits the loop
+/// if it is.
+/// Input stream(\p In) must be opened in binary mode to avoid preliminary
+/// replacements of \r\n with \n.
+/// We use C-style FILE* for reading as std::istream has unclear interaction
+/// with signals, which are sent by debuggers on some OSs.
+void runLanguageServerLoop(std::FILE *In, JSONOutput &Out,
+                           JSONStreamStyle InputStyle,
+                           JSONRPCDispatcher &Dispatcher, bool &IsDone);
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Logger.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/Logger.cpp
new file mode 100644
index 0000000..5ce3351
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Logger.cpp
@@ -0,0 +1,48 @@
+//===--- 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"
+#include "llvm/Support/raw_ostream.h"
+#include <mutex>
+
+namespace clang {
+namespace clangd {
+
+namespace {
+Logger *L = nullptr;
+} // namespace
+
+LoggingSession::LoggingSession(clangd::Logger &Instance) {
+  assert(!L);
+  L = &Instance;
+}
+
+LoggingSession::~LoggingSession() { L = nullptr; }
+
+void detail::log(Logger::Level Level,
+                 const llvm::formatv_object_base &Message) {
+  if (L)
+    L->log(Level, Message);
+  else {
+    static std::mutex Mu;
+    std::lock_guard<std::mutex> Guard(Mu);
+    llvm::errs() << Message << "\n";
+  }
+}
+
+const char *detail::debugType(const char *Filename) {
+  if (const char *Slash = strrchr(Filename, '/'))
+    return Slash + 1;
+  if (const char *Backslash = strrchr(Filename, '\\'))
+    return Backslash + 1;
+  return Filename;
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Logger.h b/src/third_party/llvm-project/clang-tools-extra/clangd/Logger.h
new file mode 100644
index 0000000..cc6e3a0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Logger.h
@@ -0,0 +1,92 @@
+//===--- 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"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatVariadic.h"
+
+namespace clang {
+namespace clangd {
+
+/// Interface to allow custom logging in clangd.
+class Logger {
+public:
+  virtual ~Logger() = default;
+
+  enum Level { Debug, Verbose, Info, Error };
+  static char indicator(Level L) { return "DVIE"[L]; }
+
+  /// Implementations of this method must be thread-safe.
+  virtual void log(Level, const llvm::formatv_object_base &Message) = 0;
+};
+
+namespace detail {
+const char *debugType(const char *Filename);
+void log(Logger::Level, const llvm::formatv_object_base &);
+
+// We often want to consume llvm::Errors by value when passing them to log().
+// We automatically wrap them in llvm::fmt_consume() as formatv requires.
+template <typename T> T &&wrap(T &&V) { return std::forward<T>(V); }
+inline decltype(fmt_consume(llvm::Error::success())) wrap(llvm::Error &&V) {
+  return fmt_consume(std::move(V));
+}
+template <typename... Ts>
+void log(Logger::Level L, const char *Fmt, Ts &&... Vals) {
+  detail::log(L, llvm::formatv(Fmt, detail::wrap(std::forward<Ts>(Vals))...));
+}
+} // namespace detail
+
+// Clangd logging functions write to a global logger set by LoggingSession.
+// If no logger is registered, writes to llvm::errs().
+// All accept llvm::formatv()-style arguments, e.g. log("Text={0}", Text).
+
+// elog() is used for "loud" errors and warnings.
+// This level is often visible to users.
+template <typename... Ts> void elog(const char *Fmt, Ts &&... Vals) {
+  detail::log(Logger::Error, Fmt, std::forward<Ts>(Vals)...);
+}
+// log() is used for information important to understanding a clangd session.
+// e.g. the names of LSP messages sent are logged at this level.
+// This level could be enabled in production builds to allow later inspection.
+template <typename... Ts> void log(const char *Fmt, Ts &&... Vals) {
+  detail::log(Logger::Info, Fmt, std::forward<Ts>(Vals)...);
+}
+// vlog() is used for details often needed for debugging clangd sessions.
+// This level would typically be enabled for clangd developers.
+template <typename... Ts> void vlog(const char *Fmt, Ts &&... Vals) {
+  detail::log(Logger::Verbose, Fmt, std::forward<Ts>(Vals)...);
+}
+// dlog only logs if --debug was passed, or --debug_only=Basename.
+// This level would be enabled in a targeted way when debugging.
+#define dlog(...)                                                              \
+  DEBUG_WITH_TYPE(::clang::clangd::detail::debugType(__FILE__),                \
+                  ::clang::clangd::detail::log(Logger::Debug, __VA_ARGS__))
+
+/// Only one LoggingSession can be active at a time.
+class LoggingSession {
+public:
+  LoggingSession(clangd::Logger &Instance);
+  ~LoggingSession();
+
+  LoggingSession(LoggingSession &&) = delete;
+  LoggingSession &operator=(LoggingSession &&) = delete;
+
+  LoggingSession(LoggingSession const &) = delete;
+  LoggingSession &operator=(LoggingSession const &) = delete;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Path.h b/src/third_party/llvm-project/clang-tools-extra/clangd/Path.h
new file mode 100644
index 0000000..b4c9335
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Path.h
@@ -0,0 +1,29 @@
+//===--- Path.h - Helper typedefs --------------------------------*- 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_PATH_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PATH_H
+
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+namespace clang {
+namespace clangd {
+
+/// A typedef to represent a file path. Used solely for more descriptive
+/// signatures.
+using Path = std::string;
+/// A typedef to represent a ref to file path. Used solely for more descriptive
+/// signatures.
+using PathRef = llvm::StringRef;
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Protocol.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/Protocol.cpp
new file mode 100644
index 0000000..5ecd719
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Protocol.cpp
@@ -0,0 +1,601 @@
+//===--- Protocol.cpp - Language Server Protocol Implementation -----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the serialization code for the LSP structs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Protocol.h"
+#include "Logger.h"
+#include "URI.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace clangd {
+using namespace llvm;
+
+URIForFile::URIForFile(std::string AbsPath) {
+  assert(llvm::sys::path::is_absolute(AbsPath) && "the path is relative");
+  File = std::move(AbsPath);
+}
+
+bool fromJSON(const json::Value &E, URIForFile &R) {
+  if (auto S = E.getAsString()) {
+    auto U = URI::parse(*S);
+    if (!U) {
+      elog("Failed to parse URI {0}: {1}", *S, U.takeError());
+      return false;
+    }
+    if (U->scheme() != "file" && U->scheme() != "test") {
+      elog("Clangd only supports 'file' URI scheme for workspace files: {0}",
+           *S);
+      return false;
+    }
+    auto Path = URI::resolve(*U);
+    if (!Path) {
+      log("{0}", Path.takeError());
+      return false;
+    }
+    R = URIForFile(*Path);
+    return true;
+  }
+  return false;
+}
+
+json::Value toJSON(const URIForFile &U) { return U.uri(); }
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const URIForFile &U) {
+  return OS << U.uri();
+}
+
+json::Value toJSON(const TextDocumentIdentifier &R) {
+  return json::Object{{"uri", R.uri}};
+}
+
+bool fromJSON(const json::Value &Params, TextDocumentIdentifier &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("uri", R.uri);
+}
+
+bool fromJSON(const json::Value &Params, Position &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("line", R.line) && O.map("character", R.character);
+}
+
+json::Value toJSON(const Position &P) {
+  return json::Object{
+      {"line", P.line},
+      {"character", P.character},
+  };
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Position &P) {
+  return OS << P.line << ':' << P.character;
+}
+
+bool fromJSON(const json::Value &Params, Range &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("start", R.start) && O.map("end", R.end);
+}
+
+json::Value toJSON(const Range &P) {
+  return json::Object{
+      {"start", P.start},
+      {"end", P.end},
+  };
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Range &R) {
+  return OS << R.start << '-' << R.end;
+}
+
+json::Value toJSON(const Location &P) {
+  return json::Object{
+      {"uri", P.uri},
+      {"range", P.range},
+  };
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Location &L) {
+  return OS << L.range << '@' << L.uri;
+}
+
+bool fromJSON(const json::Value &Params, TextDocumentItem &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("uri", R.uri) && O.map("languageId", R.languageId) &&
+         O.map("version", R.version) && O.map("text", R.text);
+}
+
+bool fromJSON(const json::Value &Params, Metadata &R) {
+  json::ObjectMapper O(Params);
+  if (!O)
+    return false;
+  O.map("extraFlags", R.extraFlags);
+  return true;
+}
+
+bool fromJSON(const json::Value &Params, TextEdit &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("range", R.range) && O.map("newText", R.newText);
+}
+
+json::Value toJSON(const TextEdit &P) {
+  return json::Object{
+      {"range", P.range},
+      {"newText", P.newText},
+  };
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TextEdit &TE) {
+  OS << TE.range << " => \"";
+  printEscapedString(TE.newText, OS);
+  return OS << '"';
+}
+
+bool fromJSON(const json::Value &E, TraceLevel &Out) {
+  if (auto S = E.getAsString()) {
+    if (*S == "off") {
+      Out = TraceLevel::Off;
+      return true;
+    } else if (*S == "messages") {
+      Out = TraceLevel::Messages;
+      return true;
+    } else if (*S == "verbose") {
+      Out = TraceLevel::Verbose;
+      return true;
+    }
+  }
+  return false;
+}
+
+bool fromJSON(const json::Value &Params, CompletionItemClientCapabilities &R) {
+  json::ObjectMapper O(Params);
+  if (!O)
+    return false;
+  O.map("snippetSupport", R.snippetSupport);
+  O.map("commitCharacterSupport", R.commitCharacterSupport);
+  return true;
+}
+
+bool fromJSON(const json::Value &Params, CompletionClientCapabilities &R) {
+  json::ObjectMapper O(Params);
+  if (!O)
+    return false;
+  O.map("dynamicRegistration", R.dynamicRegistration);
+  O.map("completionItem", R.completionItem);
+  O.map("contextSupport", R.contextSupport);
+  return true;
+}
+
+bool fromJSON(const json::Value &E, SymbolKind &Out) {
+  if (auto T = E.getAsInteger()) {
+    if (*T < static_cast<int>(SymbolKind::File) ||
+        *T > static_cast<int>(SymbolKind::TypeParameter))
+      return false;
+    Out = static_cast<SymbolKind>(*T);
+    return true;
+  }
+  return false;
+}
+
+bool fromJSON(const json::Value &E, std::vector<SymbolKind> &Out) {
+  if (auto *A = E.getAsArray()) {
+    Out.clear();
+    for (size_t I = 0; I < A->size(); ++I) {
+      SymbolKind KindOut;
+      if (fromJSON((*A)[I], KindOut))
+        Out.push_back(KindOut);
+    }
+    return true;
+  }
+  return false;
+}
+
+bool fromJSON(const json::Value &Params, SymbolKindCapabilities &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("valueSet", R.valueSet);
+}
+
+SymbolKind adjustKindToCapability(SymbolKind Kind,
+                                  SymbolKindBitset &SupportedSymbolKinds) {
+  auto KindVal = static_cast<size_t>(Kind);
+  if (KindVal >= SymbolKindMin && KindVal <= SupportedSymbolKinds.size() &&
+      SupportedSymbolKinds[KindVal])
+    return Kind;
+
+  switch (Kind) {
+  // Provide some fall backs for common kinds that are close enough.
+  case SymbolKind::Struct:
+    return SymbolKind::Class;
+  case SymbolKind::EnumMember:
+    return SymbolKind::Enum;
+  default:
+    return SymbolKind::String;
+  }
+}
+
+bool fromJSON(const json::Value &Params, WorkspaceSymbolCapabilities &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("symbolKind", R.symbolKind);
+}
+
+bool fromJSON(const json::Value &Params, WorkspaceClientCapabilities &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("symbol", R.symbol);
+}
+
+bool fromJSON(const json::Value &Params, TextDocumentClientCapabilities &R) {
+  json::ObjectMapper O(Params);
+  if (!O)
+    return false;
+  O.map("completion", R.completion);
+  return true;
+}
+
+bool fromJSON(const json::Value &Params, ClientCapabilities &R) {
+  json::ObjectMapper O(Params);
+  if (!O)
+    return false;
+  O.map("textDocument", R.textDocument);
+  O.map("workspace", R.workspace);
+  return true;
+}
+
+bool fromJSON(const json::Value &Params, InitializeParams &R) {
+  json::ObjectMapper O(Params);
+  if (!O)
+    return false;
+  // We deliberately don't fail if we can't parse individual fields.
+  // Failing to handle a slightly malformed initialize would be a disaster.
+  O.map("processId", R.processId);
+  O.map("rootUri", R.rootUri);
+  O.map("rootPath", R.rootPath);
+  O.map("capabilities", R.capabilities);
+  O.map("trace", R.trace);
+  O.map("initializationOptions", R.initializationOptions);
+  return true;
+}
+
+bool fromJSON(const json::Value &Params, DidOpenTextDocumentParams &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("textDocument", R.textDocument) &&
+         O.map("metadata", R.metadata);
+}
+
+bool fromJSON(const json::Value &Params, DidCloseTextDocumentParams &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("textDocument", R.textDocument);
+}
+
+bool fromJSON(const json::Value &Params, DidChangeTextDocumentParams &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("textDocument", R.textDocument) &&
+         O.map("contentChanges", R.contentChanges) &&
+         O.map("wantDiagnostics", R.wantDiagnostics);
+}
+
+bool fromJSON(const json::Value &E, FileChangeType &Out) {
+  if (auto T = E.getAsInteger()) {
+    if (*T < static_cast<int>(FileChangeType::Created) ||
+        *T > static_cast<int>(FileChangeType::Deleted))
+      return false;
+    Out = static_cast<FileChangeType>(*T);
+    return true;
+  }
+  return false;
+}
+
+bool fromJSON(const json::Value &Params, FileEvent &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("uri", R.uri) && O.map("type", R.type);
+}
+
+bool fromJSON(const json::Value &Params, DidChangeWatchedFilesParams &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("changes", R.changes);
+}
+
+bool fromJSON(const json::Value &Params, TextDocumentContentChangeEvent &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("range", R.range) && O.map("rangeLength", R.rangeLength) &&
+         O.map("text", R.text);
+}
+
+bool fromJSON(const json::Value &Params, FormattingOptions &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("tabSize", R.tabSize) &&
+         O.map("insertSpaces", R.insertSpaces);
+}
+
+json::Value toJSON(const FormattingOptions &P) {
+  return json::Object{
+      {"tabSize", P.tabSize},
+      {"insertSpaces", P.insertSpaces},
+  };
+}
+
+bool fromJSON(const json::Value &Params, DocumentRangeFormattingParams &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("textDocument", R.textDocument) &&
+         O.map("range", R.range) && O.map("options", R.options);
+}
+
+bool fromJSON(const json::Value &Params, DocumentOnTypeFormattingParams &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("textDocument", R.textDocument) &&
+         O.map("position", R.position) && O.map("ch", R.ch) &&
+         O.map("options", R.options);
+}
+
+bool fromJSON(const json::Value &Params, DocumentFormattingParams &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("textDocument", R.textDocument) &&
+         O.map("options", R.options);
+}
+
+bool fromJSON(const json::Value &Params, DocumentSymbolParams &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("textDocument", R.textDocument);
+}
+
+bool fromJSON(const json::Value &Params, Diagnostic &R) {
+  json::ObjectMapper O(Params);
+  if (!O || !O.map("range", R.range) || !O.map("message", R.message))
+    return false;
+  O.map("severity", R.severity);
+  return true;
+}
+
+bool fromJSON(const json::Value &Params, CodeActionContext &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("diagnostics", R.diagnostics);
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diagnostic &D) {
+  OS << D.range << " [";
+  switch (D.severity) {
+    case 1:
+      OS << "error";
+      break;
+    case 2:
+      OS << "warning";
+      break;
+    case 3:
+      OS << "note";
+      break;
+    case 4:
+      OS << "remark";
+      break;
+    default:
+      OS << "diagnostic";
+      break;
+  }
+  return OS << '(' << D.severity << "): " << D.message << "]";
+}
+
+bool fromJSON(const json::Value &Params, CodeActionParams &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("textDocument", R.textDocument) &&
+         O.map("range", R.range) && O.map("context", R.context);
+}
+
+bool fromJSON(const json::Value &Params, WorkspaceEdit &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("changes", R.changes);
+}
+
+const llvm::StringLiteral ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND =
+    "clangd.applyFix";
+bool fromJSON(const json::Value &Params, ExecuteCommandParams &R) {
+  json::ObjectMapper O(Params);
+  if (!O || !O.map("command", R.command))
+    return false;
+
+  auto Args = Params.getAsObject()->getArray("arguments");
+  if (R.command == ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND) {
+    return Args && Args->size() == 1 &&
+           fromJSON(Args->front(), R.workspaceEdit);
+  }
+  return false; // Unrecognized command.
+}
+
+json::Value toJSON(const SymbolInformation &P) {
+  return json::Object{
+      {"name", P.name},
+      {"kind", static_cast<int>(P.kind)},
+      {"location", P.location},
+      {"containerName", P.containerName},
+  };
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
+                              const SymbolInformation &SI) {
+  O << SI.containerName << "::" << SI.name << " - " << toJSON(SI);
+  return O;
+}
+
+bool fromJSON(const json::Value &Params, WorkspaceSymbolParams &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("query", R.query);
+}
+
+json::Value toJSON(const Command &C) {
+  auto Cmd = json::Object{{"title", C.title}, {"command", C.command}};
+  if (C.workspaceEdit)
+    Cmd["arguments"] = {*C.workspaceEdit};
+  return std::move(Cmd);
+}
+
+json::Value toJSON(const WorkspaceEdit &WE) {
+  if (!WE.changes)
+    return json::Object{};
+  json::Object FileChanges;
+  for (auto &Change : *WE.changes)
+    FileChanges[Change.first] = json::Array(Change.second);
+  return json::Object{{"changes", std::move(FileChanges)}};
+}
+
+json::Value toJSON(const ApplyWorkspaceEditParams &Params) {
+  return json::Object{{"edit", Params.edit}};
+}
+
+bool fromJSON(const json::Value &Params, TextDocumentPositionParams &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("textDocument", R.textDocument) &&
+         O.map("position", R.position);
+}
+
+static StringRef toTextKind(MarkupKind Kind) {
+  switch (Kind) {
+  case MarkupKind::PlainText:
+    return "plaintext";
+  case MarkupKind::Markdown:
+    return "markdown";
+  }
+  llvm_unreachable("Invalid MarkupKind");
+}
+
+json::Value toJSON(const MarkupContent &MC) {
+  if (MC.value.empty())
+    return nullptr;
+
+  return json::Object{
+      {"kind", toTextKind(MC.kind)},
+      {"value", MC.value},
+  };
+}
+
+json::Value toJSON(const Hover &H) {
+  json::Object Result{{"contents", toJSON(H.contents)}};
+
+  if (H.range.hasValue())
+    Result["range"] = toJSON(*H.range);
+
+  return std::move(Result);
+}
+
+json::Value toJSON(const CompletionItem &CI) {
+  assert(!CI.label.empty() && "completion item label is required");
+  json::Object Result{{"label", CI.label}};
+  if (CI.kind != CompletionItemKind::Missing)
+    Result["kind"] = static_cast<int>(CI.kind);
+  if (!CI.detail.empty())
+    Result["detail"] = CI.detail;
+  if (!CI.documentation.empty())
+    Result["documentation"] = CI.documentation;
+  if (!CI.sortText.empty())
+    Result["sortText"] = CI.sortText;
+  if (!CI.filterText.empty())
+    Result["filterText"] = CI.filterText;
+  if (!CI.insertText.empty())
+    Result["insertText"] = CI.insertText;
+  if (CI.insertTextFormat != InsertTextFormat::Missing)
+    Result["insertTextFormat"] = static_cast<int>(CI.insertTextFormat);
+  if (CI.textEdit)
+    Result["textEdit"] = *CI.textEdit;
+  if (!CI.additionalTextEdits.empty())
+    Result["additionalTextEdits"] = json::Array(CI.additionalTextEdits);
+  return std::move(Result);
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const CompletionItem &I) {
+  O << I.label << " - " << toJSON(I);
+  return O;
+}
+
+bool operator<(const CompletionItem &L, const CompletionItem &R) {
+  return (L.sortText.empty() ? L.label : L.sortText) <
+         (R.sortText.empty() ? R.label : R.sortText);
+}
+
+json::Value toJSON(const CompletionList &L) {
+  return json::Object{
+      {"isIncomplete", L.isIncomplete},
+      {"items", json::Array(L.items)},
+  };
+}
+
+json::Value toJSON(const ParameterInformation &PI) {
+  assert(!PI.label.empty() && "parameter information label is required");
+  json::Object Result{{"label", PI.label}};
+  if (!PI.documentation.empty())
+    Result["documentation"] = PI.documentation;
+  return std::move(Result);
+}
+
+json::Value toJSON(const SignatureInformation &SI) {
+  assert(!SI.label.empty() && "signature information label is required");
+  json::Object Result{
+      {"label", SI.label},
+      {"parameters", json::Array(SI.parameters)},
+  };
+  if (!SI.documentation.empty())
+    Result["documentation"] = SI.documentation;
+  return std::move(Result);
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
+                              const SignatureInformation &I) {
+  O << I.label << " - " << toJSON(I);
+  return O;
+}
+
+json::Value toJSON(const SignatureHelp &SH) {
+  assert(SH.activeSignature >= 0 &&
+         "Unexpected negative value for number of active signatures.");
+  assert(SH.activeParameter >= 0 &&
+         "Unexpected negative value for active parameter index");
+  return json::Object{
+      {"activeSignature", SH.activeSignature},
+      {"activeParameter", SH.activeParameter},
+      {"signatures", json::Array(SH.signatures)},
+  };
+}
+
+bool fromJSON(const json::Value &Params, RenameParams &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("textDocument", R.textDocument) &&
+         O.map("position", R.position) && O.map("newName", R.newName);
+}
+
+json::Value toJSON(const DocumentHighlight &DH) {
+  return json::Object{
+      {"range", toJSON(DH.range)},
+      {"kind", static_cast<int>(DH.kind)},
+  };
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
+                              const DocumentHighlight &V) {
+  O << V.range;
+  if (V.kind == DocumentHighlightKind::Read)
+    O << "(r)";
+  if (V.kind == DocumentHighlightKind::Write)
+    O << "(w)";
+  return O;
+}
+
+bool fromJSON(const json::Value &Params, DidChangeConfigurationParams &CCP) {
+  json::ObjectMapper O(Params);
+  return O && O.map("settings", CCP.settings);
+}
+
+bool fromJSON(const json::Value &Params,
+              ClangdConfigurationParamsChange &CCPC) {
+  json::ObjectMapper O(Params);
+  return O && O.map("compilationDatabasePath", CCPC.compilationDatabasePath);
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Protocol.h b/src/third_party/llvm-project/clang-tools-extra/clangd/Protocol.h
new file mode 100644
index 0000000..7f33976
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Protocol.h
@@ -0,0 +1,844 @@
+//===--- Protocol.h - Language Server Protocol Implementation ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains structs based on the LSP specification at
+// https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md
+//
+// This is not meant to be a complete implementation, new interfaces are added
+// when they're needed.
+//
+// Each struct has a toJSON and fromJSON function, that converts between
+// the struct and a JSON representation. (See JSON.h)
+//
+// Some structs also have operator<< serialization. This is for debugging and
+// tests, and is not generally machine-readable.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H
+
+#include "URI.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/JSON.h"
+#include <bitset>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace clangd {
+
+enum class ErrorCode {
+  // Defined by JSON RPC.
+  ParseError = -32700,
+  InvalidRequest = -32600,
+  MethodNotFound = -32601,
+  InvalidParams = -32602,
+  InternalError = -32603,
+
+  ServerNotInitialized = -32002,
+  UnknownErrorCode = -32001,
+
+  // Defined by the protocol.
+  RequestCancelled = -32800,
+};
+
+struct URIForFile {
+  URIForFile() = default;
+  explicit URIForFile(std::string AbsPath);
+
+  /// Retrieves absolute path to the file.
+  llvm::StringRef file() const { return File; }
+
+  explicit operator bool() const { return !File.empty(); }
+  std::string uri() const { return URI::createFile(File).toString(); }
+
+  friend bool operator==(const URIForFile &LHS, const URIForFile &RHS) {
+    return LHS.File == RHS.File;
+  }
+
+  friend bool operator!=(const URIForFile &LHS, const URIForFile &RHS) {
+    return !(LHS == RHS);
+  }
+
+  friend bool operator<(const URIForFile &LHS, const URIForFile &RHS) {
+    return LHS.File < RHS.File;
+  }
+
+private:
+  std::string File;
+};
+
+/// Serialize/deserialize \p URIForFile to/from a string URI.
+llvm::json::Value toJSON(const URIForFile &U);
+bool fromJSON(const llvm::json::Value &, URIForFile &);
+
+struct TextDocumentIdentifier {
+  /// The text document's URI.
+  URIForFile uri;
+};
+llvm::json::Value toJSON(const TextDocumentIdentifier &);
+bool fromJSON(const llvm::json::Value &, TextDocumentIdentifier &);
+
+struct Position {
+  /// Line position in a document (zero-based).
+  int line = 0;
+
+  /// Character offset on a line in a document (zero-based).
+  /// WARNING: this is in UTF-16 codepoints, not bytes or characters!
+  /// Use the functions in SourceCode.h to construct/interpret Positions.
+  int character = 0;
+
+  friend bool operator==(const Position &LHS, const Position &RHS) {
+    return std::tie(LHS.line, LHS.character) ==
+           std::tie(RHS.line, RHS.character);
+  }
+  friend bool operator!=(const Position &LHS, const Position &RHS) {
+    return !(LHS == RHS);
+  }
+  friend bool operator<(const Position &LHS, const Position &RHS) {
+    return std::tie(LHS.line, LHS.character) <
+           std::tie(RHS.line, RHS.character);
+  }
+  friend bool operator<=(const Position &LHS, const Position &RHS) {
+    return std::tie(LHS.line, LHS.character) <=
+           std::tie(RHS.line, RHS.character);
+  }
+};
+bool fromJSON(const llvm::json::Value &, Position &);
+llvm::json::Value toJSON(const Position &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Position &);
+
+struct Range {
+  /// The range's start position.
+  Position start;
+
+  /// The range's end position.
+  Position end;
+
+  friend bool operator==(const Range &LHS, const Range &RHS) {
+    return std::tie(LHS.start, LHS.end) == std::tie(RHS.start, RHS.end);
+  }
+  friend bool operator!=(const Range &LHS, const Range &RHS) {
+    return !(LHS == RHS);
+  }
+  friend bool operator<(const Range &LHS, const Range &RHS) {
+    return std::tie(LHS.start, LHS.end) < std::tie(RHS.start, RHS.end);
+  }
+
+  bool contains(Position Pos) const { return start <= Pos && Pos < end; }
+};
+bool fromJSON(const llvm::json::Value &, Range &);
+llvm::json::Value toJSON(const Range &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Range &);
+
+struct Location {
+  /// The text document's URI.
+  URIForFile 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);
+  }
+};
+llvm::json::Value toJSON(const Location &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Location &);
+
+struct Metadata {
+  std::vector<std::string> extraFlags;
+};
+bool fromJSON(const llvm::json::Value &, Metadata &);
+
+struct TextEdit {
+  /// The range of the text document to be manipulated. To insert
+  /// text into a document create a range where start === end.
+  Range range;
+
+  /// The string to be inserted. For delete operations use an
+  /// empty string.
+  std::string newText;
+};
+bool fromJSON(const llvm::json::Value &, TextEdit &);
+llvm::json::Value toJSON(const TextEdit &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const TextEdit &);
+
+struct TextDocumentItem {
+  /// The text document's URI.
+  URIForFile uri;
+
+  /// The text document's language identifier.
+  std::string languageId;
+
+  /// The version number of this document (it will strictly increase after each
+  int version = 0;
+
+  /// The content of the opened text document.
+  std::string text;
+};
+bool fromJSON(const llvm::json::Value &, TextDocumentItem &);
+
+enum class TraceLevel {
+  Off = 0,
+  Messages = 1,
+  Verbose = 2,
+};
+bool fromJSON(const llvm::json::Value &E, TraceLevel &Out);
+
+struct NoParams {};
+inline bool fromJSON(const llvm::json::Value &, NoParams &) { return true; }
+using ShutdownParams = NoParams;
+using ExitParams = NoParams;
+
+/// Defines how the host (editor) should sync document changes to the language
+/// server.
+enum class TextDocumentSyncKind {
+  /// Documents should not be synced at all.
+  None = 0,
+
+  /// Documents are synced by always sending the full content of the document.
+  Full = 1,
+
+  /// Documents are synced by sending the full content on open.  After that
+  /// only incremental updates to the document are send.
+  Incremental = 2,
+};
+
+struct CompletionItemClientCapabilities {
+  /// Client supports snippets as insert text.
+  bool snippetSupport = false;
+  /// Client supports commit characters on a completion item.
+  bool commitCharacterSupport = false;
+  // Client supports the follow content formats for the documentation property.
+  // The order describes the preferred format of the client.
+  // NOTE: not used by clangd at the moment.
+  // std::vector<MarkupKind> documentationFormat;
+};
+bool fromJSON(const llvm::json::Value &, CompletionItemClientCapabilities &);
+
+struct CompletionClientCapabilities {
+  /// Whether completion supports dynamic registration.
+  bool dynamicRegistration = false;
+  /// The client supports the following `CompletionItem` specific capabilities.
+  CompletionItemClientCapabilities completionItem;
+  // NOTE: not used by clangd at the moment.
+  // llvm::Optional<CompletionItemKindCapabilities> completionItemKind;
+
+  /// The client supports to send additional context information for a
+  /// `textDocument/completion` request.
+  bool contextSupport = false;
+};
+bool fromJSON(const llvm::json::Value &, CompletionClientCapabilities &);
+
+/// A symbol kind.
+enum class SymbolKind {
+  File = 1,
+  Module = 2,
+  Namespace = 3,
+  Package = 4,
+  Class = 5,
+  Method = 6,
+  Property = 7,
+  Field = 8,
+  Constructor = 9,
+  Enum = 10,
+  Interface = 11,
+  Function = 12,
+  Variable = 13,
+  Constant = 14,
+  String = 15,
+  Number = 16,
+  Boolean = 17,
+  Array = 18,
+  Object = 19,
+  Key = 20,
+  Null = 21,
+  EnumMember = 22,
+  Struct = 23,
+  Event = 24,
+  Operator = 25,
+  TypeParameter = 26
+};
+
+constexpr auto SymbolKindMin = static_cast<size_t>(SymbolKind::File);
+constexpr auto SymbolKindMax = static_cast<size_t>(SymbolKind::TypeParameter);
+using SymbolKindBitset = std::bitset<SymbolKindMax + 1>;
+
+bool fromJSON(const llvm::json::Value &, SymbolKind &);
+
+struct SymbolKindCapabilities {
+  /// The SymbolKinds that the client supports. If not set, the client only
+  /// supports <= SymbolKind::Array and will not fall back to a valid default
+  /// value.
+  llvm::Optional<std::vector<SymbolKind>> valueSet;
+};
+bool fromJSON(const llvm::json::Value &, std::vector<SymbolKind> &);
+bool fromJSON(const llvm::json::Value &, SymbolKindCapabilities &);
+SymbolKind adjustKindToCapability(SymbolKind Kind,
+                                  SymbolKindBitset &supportedSymbolKinds);
+
+struct WorkspaceSymbolCapabilities {
+  /// Capabilities SymbolKind.
+  llvm::Optional<SymbolKindCapabilities> symbolKind;
+};
+bool fromJSON(const llvm::json::Value &, WorkspaceSymbolCapabilities &);
+
+// FIXME: most of the capabilities are missing from this struct. Only the ones
+// used by clangd are currently there.
+struct WorkspaceClientCapabilities {
+  /// Capabilities specific to `workspace/symbol`.
+  llvm::Optional<WorkspaceSymbolCapabilities> symbol;
+};
+bool fromJSON(const llvm::json::Value &, WorkspaceClientCapabilities &);
+
+// FIXME: most of the capabilities are missing from this struct. Only the ones
+// used by clangd are currently there.
+struct TextDocumentClientCapabilities {
+  /// Capabilities specific to the `textDocument/completion`
+  CompletionClientCapabilities completion;
+};
+bool fromJSON(const llvm::json::Value &, TextDocumentClientCapabilities &);
+
+struct ClientCapabilities {
+  // Workspace specific client capabilities.
+  llvm::Optional<WorkspaceClientCapabilities> workspace;
+
+  // Text document specific client capabilities.
+  TextDocumentClientCapabilities textDocument;
+};
+
+bool fromJSON(const llvm::json::Value &, ClientCapabilities &);
+
+/// Clangd extension to set clangd-specific "initializationOptions" in the
+/// "initialize" request and for the "workspace/didChangeConfiguration"
+/// notification since the data received is described as 'any' type in LSP.
+struct ClangdConfigurationParamsChange {
+  llvm::Optional<std::string> compilationDatabasePath;
+};
+bool fromJSON(const llvm::json::Value &, ClangdConfigurationParamsChange &);
+
+struct ClangdInitializationOptions : public ClangdConfigurationParamsChange {};
+
+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<URIForFile> rootUri;
+
+  // User provided initialization options.
+  // initializationOptions?: any;
+
+  /// The capabilities provided by the client (editor or tool)
+  ClientCapabilities capabilities;
+
+  /// The initial trace setting. If omitted trace is disabled ('off').
+  llvm::Optional<TraceLevel> trace;
+
+  // We use this predefined struct because it is easier to use
+  // than the protocol specified type of 'any'.
+  llvm::Optional<ClangdInitializationOptions> initializationOptions;
+};
+bool fromJSON(const llvm::json::Value &, InitializeParams &);
+
+struct DidOpenTextDocumentParams {
+  /// The document that was opened.
+  TextDocumentItem textDocument;
+
+  /// Extension storing per-file metadata, such as compilation flags.
+  llvm::Optional<Metadata> metadata;
+};
+bool fromJSON(const llvm::json::Value &, DidOpenTextDocumentParams &);
+
+struct DidCloseTextDocumentParams {
+  /// The document that was closed.
+  TextDocumentIdentifier textDocument;
+};
+bool fromJSON(const llvm::json::Value &, DidCloseTextDocumentParams &);
+
+struct TextDocumentContentChangeEvent {
+  /// The range of the document that changed.
+  llvm::Optional<Range> range;
+
+  /// The length of the range that got replaced.
+  llvm::Optional<int> rangeLength;
+
+  /// The new text of the range/document.
+  std::string text;
+};
+bool fromJSON(const llvm::json::Value &, TextDocumentContentChangeEvent &);
+
+struct DidChangeTextDocumentParams {
+  /// The document that did change. The version number points
+  /// to the version after all provided content changes have
+  /// been applied.
+  TextDocumentIdentifier textDocument;
+
+  /// The actual content changes.
+  std::vector<TextDocumentContentChangeEvent> contentChanges;
+
+  /// Forces diagnostics to be generated, or to not be generated, for this
+  /// version of the file. If not set, diagnostics are eventually consistent:
+  /// either they will be provided for this version or some subsequent one.
+  /// This is a clangd extension.
+  llvm::Optional<bool> wantDiagnostics;
+};
+bool fromJSON(const llvm::json::Value &, DidChangeTextDocumentParams &);
+
+enum class FileChangeType {
+  /// The file got created.
+  Created = 1,
+  /// The file got changed.
+  Changed = 2,
+  /// The file got deleted.
+  Deleted = 3
+};
+bool fromJSON(const llvm::json::Value &E, FileChangeType &Out);
+
+struct FileEvent {
+  /// The file's URI.
+  URIForFile uri;
+  /// The change type.
+  FileChangeType type = FileChangeType::Created;
+};
+bool fromJSON(const llvm::json::Value &, FileEvent &);
+
+struct DidChangeWatchedFilesParams {
+  /// The actual file events.
+  std::vector<FileEvent> changes;
+};
+bool fromJSON(const llvm::json::Value &, DidChangeWatchedFilesParams &);
+
+struct DidChangeConfigurationParams {
+  // We use this predefined struct because it is easier to use
+  // than the protocol specified type of 'any'.
+  ClangdConfigurationParamsChange settings;
+};
+bool fromJSON(const llvm::json::Value &, DidChangeConfigurationParams &);
+
+struct FormattingOptions {
+  /// Size of a tab in spaces.
+  int tabSize = 0;
+
+  /// Prefer spaces over tabs.
+  bool insertSpaces = false;
+};
+bool fromJSON(const llvm::json::Value &, FormattingOptions &);
+llvm::json::Value toJSON(const FormattingOptions &);
+
+struct DocumentRangeFormattingParams {
+  /// The document to format.
+  TextDocumentIdentifier textDocument;
+
+  /// The range to format
+  Range range;
+
+  /// The format options
+  FormattingOptions options;
+};
+bool fromJSON(const llvm::json::Value &, DocumentRangeFormattingParams &);
+
+struct DocumentOnTypeFormattingParams {
+  /// The document to format.
+  TextDocumentIdentifier textDocument;
+
+  /// The position at which this request was sent.
+  Position position;
+
+  /// The character that has been typed.
+  std::string ch;
+
+  /// The format options.
+  FormattingOptions options;
+};
+bool fromJSON(const llvm::json::Value &, DocumentOnTypeFormattingParams &);
+
+struct DocumentFormattingParams {
+  /// The document to format.
+  TextDocumentIdentifier textDocument;
+
+  /// The format options
+  FormattingOptions options;
+};
+bool fromJSON(const llvm::json::Value &, DocumentFormattingParams &);
+
+struct DocumentSymbolParams {
+  // The text document to find symbols in.
+  TextDocumentIdentifier textDocument;
+};
+bool fromJSON(const llvm::json::Value &, DocumentSymbolParams &);
+
+struct Diagnostic {
+  /// The range at which the message applies.
+  Range range;
+
+  /// The diagnostic's severity. Can be omitted. If omitted it is up to the
+  /// client to interpret diagnostics as error, warning, info or hint.
+  int severity = 0;
+
+  /// 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;
+};
+
+/// A LSP-specific comparator used to find diagnostic in a container like
+/// std:map.
+/// We only use the required fields of Diagnostic to do the comparsion to avoid
+/// any regression issues from LSP clients (e.g. VScode), see
+/// https://git.io/vbr29
+struct LSPDiagnosticCompare {
+  bool operator()(const Diagnostic &LHS, const Diagnostic &RHS) const {
+    return std::tie(LHS.range, LHS.message) < std::tie(RHS.range, RHS.message);
+  }
+};
+bool fromJSON(const llvm::json::Value &, Diagnostic &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Diagnostic &);
+
+struct CodeActionContext {
+  /// An array of diagnostics.
+  std::vector<Diagnostic> diagnostics;
+};
+bool fromJSON(const llvm::json::Value &, CodeActionContext &);
+
+struct CodeActionParams {
+  /// The document in which the command was invoked.
+  TextDocumentIdentifier textDocument;
+
+  /// The range for which the command was invoked.
+  Range range;
+
+  /// Context carrying additional information.
+  CodeActionContext context;
+};
+bool fromJSON(const llvm::json::Value &, CodeActionParams &);
+
+struct WorkspaceEdit {
+  /// Holds changes to existing resources.
+  llvm::Optional<std::map<std::string, std::vector<TextEdit>>> changes;
+
+  /// Note: "documentChanges" is not currently used because currently there is
+  /// no support for versioned edits.
+};
+bool fromJSON(const llvm::json::Value &, WorkspaceEdit &);
+llvm::json::Value toJSON(const WorkspaceEdit &WE);
+
+/// Exact commands are not specified in the protocol so we define the
+/// ones supported by Clangd here. The protocol specifies the command arguments
+/// to be "any[]" but to make this safer and more manageable, each command we
+/// handle maps to a certain llvm::Optional of some struct to contain its
+/// arguments. Different commands could reuse the same llvm::Optional as
+/// arguments but a command that needs different arguments would simply add a
+/// new llvm::Optional and not use any other ones. In practice this means only
+/// one argument type will be parsed and set.
+struct ExecuteCommandParams {
+  // Command to apply fix-its. Uses WorkspaceEdit as argument.
+  const static llvm::StringLiteral CLANGD_APPLY_FIX_COMMAND;
+
+  /// The command identifier, e.g. CLANGD_APPLY_FIX_COMMAND
+  std::string command;
+
+  // Arguments
+  llvm::Optional<WorkspaceEdit> workspaceEdit;
+};
+bool fromJSON(const llvm::json::Value &, ExecuteCommandParams &);
+
+struct Command : public ExecuteCommandParams {
+  std::string title;
+};
+
+llvm::json::Value toJSON(const Command &C);
+
+/// Represents information about programming constructs like variables, classes,
+/// interfaces etc.
+struct SymbolInformation {
+  /// The name of this symbol.
+  std::string name;
+
+  /// The kind of this symbol.
+  SymbolKind kind;
+
+  /// The location of this symbol.
+  Location location;
+
+  /// The name of the symbol containing this symbol.
+  std::string containerName;
+};
+llvm::json::Value toJSON(const SymbolInformation &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const SymbolInformation &);
+
+/// The parameters of a Workspace Symbol Request.
+struct WorkspaceSymbolParams {
+  /// A non-empty query string
+  std::string query;
+};
+bool fromJSON(const llvm::json::Value &, WorkspaceSymbolParams &);
+
+struct ApplyWorkspaceEditParams {
+  WorkspaceEdit edit;
+};
+llvm::json::Value toJSON(const ApplyWorkspaceEditParams &);
+
+struct TextDocumentPositionParams {
+  /// The text document.
+  TextDocumentIdentifier textDocument;
+
+  /// The position inside the text document.
+  Position position;
+};
+bool fromJSON(const llvm::json::Value &, TextDocumentPositionParams &);
+
+enum class MarkupKind {
+  PlainText,
+  Markdown,
+};
+
+struct MarkupContent {
+  MarkupKind kind = MarkupKind::PlainText;
+  std::string value;
+};
+llvm::json::Value toJSON(const MarkupContent &MC);
+
+struct Hover {
+  /// The hover's content
+  MarkupContent contents;
+
+  /// An optional range is a range inside a text document
+  /// that is used to visualize a hover, e.g. by changing the background color.
+  llvm::Optional<Range> range;
+};
+llvm::json::Value toJSON(const Hover &H);
+
+/// The kind of a completion entry.
+enum class CompletionItemKind {
+  Missing = 0,
+  Text = 1,
+  Method = 2,
+  Function = 3,
+  Constructor = 4,
+  Field = 5,
+  Variable = 6,
+  Class = 7,
+  Interface = 8,
+  Module = 9,
+  Property = 10,
+  Unit = 11,
+  Value = 12,
+  Enum = 13,
+  Keyword = 14,
+  Snippet = 15,
+  Color = 16,
+  File = 17,
+  Reference = 18,
+};
+
+/// Defines whether the insert text in a completion item should be interpreted
+/// as plain text or a snippet.
+enum class InsertTextFormat {
+  Missing = 0,
+  /// The primary text to be inserted is treated as a plain string.
+  PlainText = 1,
+  /// The primary text to be inserted is treated as a snippet.
+  ///
+  /// A snippet can define tab stops and placeholders with `$1`, `$2`
+  /// and `${3:foo}`. `$0` defines the final tab stop, it defaults to the end
+  /// of the snippet. Placeholders with equal identifiers are linked, that is
+  /// typing in one will update others too.
+  ///
+  /// See also:
+  /// https//github.com/Microsoft/vscode/blob/master/src/vs/editor/contrib/snippet/common/snippet.md
+  Snippet = 2,
+};
+
+struct CompletionItem {
+  /// The label of this completion item. By default also the text that is
+  /// inserted when selecting this completion.
+  std::string label;
+
+  /// The kind of this completion item. Based of the kind an icon is chosen by
+  /// the editor.
+  CompletionItemKind kind = CompletionItemKind::Missing;
+
+  /// A human-readable string with additional information about this item, like
+  /// type or symbol information.
+  std::string detail;
+
+  /// A human-readable string that represents a doc-comment.
+  std::string documentation;
+
+  /// A string that should be used when comparing this item with other items.
+  /// When `falsy` the label is used.
+  std::string sortText;
+
+  /// A string that should be used when filtering a set of completion items.
+  /// When `falsy` the label is used.
+  std::string filterText;
+
+  /// A string that should be inserted to a document when selecting this
+  /// completion. When `falsy` the label is used.
+  std::string insertText;
+
+  /// The format of the insert text. The format applies to both the `insertText`
+  /// property and the `newText` property of a provided `textEdit`.
+  InsertTextFormat insertTextFormat = InsertTextFormat::Missing;
+
+  /// An edit which is applied to a document when selecting this completion.
+  /// When an edit is provided `insertText` is ignored.
+  ///
+  /// Note: The range of the edit must be a single line range and it must
+  /// contain the position at which completion has been requested.
+  llvm::Optional<TextEdit> textEdit;
+
+  /// An optional array of additional text edits that are applied when selecting
+  /// this completion. Edits must not overlap with the main edit nor with
+  /// themselves.
+  std::vector<TextEdit> additionalTextEdits;
+
+  // TODO(krasimir): The following optional fields defined by the language
+  // server protocol are unsupported:
+  //
+  // data?: any - A data entry field that is preserved on a completion item
+  //              between a completion and a completion resolve request.
+};
+llvm::json::Value toJSON(const CompletionItem &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const CompletionItem &);
+
+bool operator<(const CompletionItem &, const CompletionItem &);
+
+/// Represents a collection of completion items to be presented in the editor.
+struct CompletionList {
+  /// The list is not complete. Further typing should result in recomputing the
+  /// list.
+  bool isIncomplete = false;
+
+  /// The completion items.
+  std::vector<CompletionItem> items;
+};
+llvm::json::Value toJSON(const CompletionList &);
+
+/// 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;
+};
+llvm::json::Value toJSON(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;
+};
+llvm::json::Value toJSON(const SignatureInformation &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &,
+                              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;
+};
+llvm::json::Value toJSON(const SignatureHelp &);
+
+struct RenameParams {
+  /// The document that was opened.
+  TextDocumentIdentifier textDocument;
+
+  /// The position at which this request was sent.
+  Position position;
+
+  /// The new name of the symbol.
+  std::string newName;
+};
+bool fromJSON(const llvm::json::Value &, RenameParams &);
+
+enum class DocumentHighlightKind { Text = 1, Read = 2, Write = 3 };
+
+/// A document highlight is a range inside a text document which deserves
+/// special attention. Usually a document highlight is visualized by changing
+/// the background color of its range.
+
+struct DocumentHighlight {
+  /// The range this highlight applies to.
+  Range range;
+
+  /// The highlight kind, default is DocumentHighlightKind.Text.
+  DocumentHighlightKind kind = DocumentHighlightKind::Text;
+
+  friend bool operator<(const DocumentHighlight &LHS,
+                        const DocumentHighlight &RHS) {
+    int LHSKind = static_cast<int>(LHS.kind);
+    int RHSKind = static_cast<int>(RHS.kind);
+    return std::tie(LHS.range, LHSKind) < std::tie(RHS.range, RHSKind);
+  }
+
+  friend bool operator==(const DocumentHighlight &LHS,
+                         const DocumentHighlight &RHS) {
+    return LHS.kind == RHS.kind && LHS.range == RHS.range;
+  }
+};
+llvm::json::Value toJSON(const DocumentHighlight &DH);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const DocumentHighlight &);
+
+} // namespace clangd
+} // namespace clang
+
+namespace llvm {
+template <> struct format_provider<clang::clangd::Position> {
+  static void format(const clang::clangd::Position &Pos, raw_ostream &OS,
+                     StringRef Style) {
+    assert(Style.empty() && "style modifiers for this type are not supported");
+    OS << Pos;
+  }
+};
+} // namespace llvm
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/ProtocolHandlers.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/ProtocolHandlers.cpp
new file mode 100644
index 0000000..deb5b9d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/ProtocolHandlers.cpp
@@ -0,0 +1,78 @@
+//===--- ProtocolHandlers.cpp - LSP callbacks -----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ProtocolHandlers.h"
+#include "ClangdLSPServer.h"
+#include "ClangdServer.h"
+#include "DraftStore.h"
+#include "Trace.h"
+
+using namespace clang;
+using namespace clang::clangd;
+using namespace llvm;
+
+namespace {
+
+// 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 fromJSON function.
+struct HandlerRegisterer {
+  template <typename Param>
+  void operator()(StringRef Method, void (ProtocolCallbacks::*Handler)(Param)) {
+    // Capture pointers by value, as the lambda will outlive this object.
+    auto *Callbacks = this->Callbacks;
+    Dispatcher.registerHandler(Method, [=](const json::Value &RawParams) {
+      typename std::remove_reference<Param>::type P;
+      if (fromJSON(RawParams, P)) {
+        (Callbacks->*Handler)(P);
+      } else {
+        elog("Failed to decode {0} request.", Method);
+      }
+    });
+  }
+
+  JSONRPCDispatcher &Dispatcher;
+  ProtocolCallbacks *Callbacks;
+};
+
+} // namespace
+
+void clangd::registerCallbackHandlers(JSONRPCDispatcher &Dispatcher,
+                                      ProtocolCallbacks &Callbacks) {
+  HandlerRegisterer Register{Dispatcher, &Callbacks};
+
+  Register("initialize", &ProtocolCallbacks::onInitialize);
+  Register("shutdown", &ProtocolCallbacks::onShutdown);
+  Register("exit", &ProtocolCallbacks::onExit);
+  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("textDocument/rename", &ProtocolCallbacks::onRename);
+  Register("textDocument/hover", &ProtocolCallbacks::onHover);
+  Register("textDocument/documentSymbol", &ProtocolCallbacks::onDocumentSymbol);
+  Register("workspace/didChangeWatchedFiles", &ProtocolCallbacks::onFileEvent);
+  Register("workspace/executeCommand", &ProtocolCallbacks::onCommand);
+  Register("textDocument/documentHighlight",
+           &ProtocolCallbacks::onDocumentHighlight);
+  Register("workspace/didChangeConfiguration",
+           &ProtocolCallbacks::onChangeConfiguration);
+  Register("workspace/symbol", &ProtocolCallbacks::onWorkspaceSymbol);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/ProtocolHandlers.h b/src/third_party/llvm-project/clang-tools-extra/clangd/ProtocolHandlers.h
new file mode 100644
index 0000000..63fd99d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/ProtocolHandlers.h
@@ -0,0 +1,66 @@
+//===--- ProtocolHandlers.h - LSP callbacks ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOLHANDLERS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOLHANDLERS_H
+
+#include "JSONRPCDispatcher.h"
+#include "Protocol.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace clangd {
+
+// The interface implemented by ClangLSPServer to handle incoming requests.
+class ProtocolCallbacks {
+public:
+  virtual ~ProtocolCallbacks() = default;
+
+  virtual void onInitialize(InitializeParams &Params) = 0;
+  virtual void onShutdown(ShutdownParams &Params) = 0;
+  virtual void onExit(ExitParams &Params) = 0;
+  virtual void onDocumentDidOpen(DidOpenTextDocumentParams &Params) = 0;
+  virtual void onDocumentDidChange(DidChangeTextDocumentParams &Params) = 0;
+  virtual void onDocumentDidClose(DidCloseTextDocumentParams &Params) = 0;
+  virtual void onDocumentFormatting(DocumentFormattingParams &Params) = 0;
+  virtual void onDocumentSymbol(DocumentSymbolParams &Params) = 0;
+  virtual void
+  onDocumentOnTypeFormatting(DocumentOnTypeFormattingParams &Params) = 0;
+  virtual void
+  onDocumentRangeFormatting(DocumentRangeFormattingParams &Params) = 0;
+  virtual void onCodeAction(CodeActionParams &Params) = 0;
+  virtual void onCompletion(TextDocumentPositionParams &Params) = 0;
+  virtual void onSignatureHelp(TextDocumentPositionParams &Params) = 0;
+  virtual void onGoToDefinition(TextDocumentPositionParams &Params) = 0;
+  virtual void onSwitchSourceHeader(TextDocumentIdentifier &Params) = 0;
+  virtual void onFileEvent(DidChangeWatchedFilesParams &Params) = 0;
+  virtual void onCommand(ExecuteCommandParams &Params) = 0;
+  virtual void onWorkspaceSymbol(WorkspaceSymbolParams &Params) = 0;
+  virtual void onRename(RenameParams &Parames) = 0;
+  virtual void onDocumentHighlight(TextDocumentPositionParams &Params) = 0;
+  virtual void onHover(TextDocumentPositionParams &Params) = 0;
+  virtual void onChangeConfiguration(DidChangeConfigurationParams &Params) = 0;
+};
+
+void registerCallbackHandlers(JSONRPCDispatcher &Dispatcher,
+                              ProtocolCallbacks &Callbacks);
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Quality.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/Quality.cpp
new file mode 100644
index 0000000..61195b5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Quality.cpp
@@ -0,0 +1,398 @@
+//===--- Quality.cpp --------------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+#include "Quality.h"
+#include "FileDistance.h"
+#include "URI.h"
+#include "index/Index.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cmath>
+
+namespace clang {
+namespace clangd {
+using namespace llvm;
+static bool isReserved(StringRef Name) {
+  // FIXME: Should we exclude _Bool and others recognized by the standard?
+  return Name.size() >= 2 && Name[0] == '_' &&
+         (isUppercase(Name[1]) || Name[1] == '_');
+}
+
+static bool hasDeclInMainFile(const Decl &D) {
+  auto &SourceMgr = D.getASTContext().getSourceManager();
+  for (auto *Redecl : D.redecls()) {
+    auto Loc = SourceMgr.getSpellingLoc(Redecl->getLocation());
+    if (SourceMgr.isWrittenInMainFile(Loc))
+      return true;
+  }
+  return false;
+}
+
+static bool hasUsingDeclInMainFile(const CodeCompletionResult &R) {
+  const auto &Context = R.Declaration->getASTContext();
+  const auto &SourceMgr = Context.getSourceManager();
+  if (R.ShadowDecl) {
+    const auto Loc = SourceMgr.getExpansionLoc(R.ShadowDecl->getLocation());
+    if (SourceMgr.isWrittenInMainFile(Loc))
+      return true;
+  }
+  return false;
+}
+
+static SymbolQualitySignals::SymbolCategory categorize(const NamedDecl &ND) {
+  class Switch
+      : public ConstDeclVisitor<Switch, SymbolQualitySignals::SymbolCategory> {
+  public:
+#define MAP(DeclType, Category)                                                \
+  SymbolQualitySignals::SymbolCategory Visit##DeclType(const DeclType *) {     \
+    return SymbolQualitySignals::Category;                                     \
+  }
+    MAP(NamespaceDecl, Namespace);
+    MAP(NamespaceAliasDecl, Namespace);
+    MAP(TypeDecl, Type);
+    MAP(TypeAliasTemplateDecl, Type);
+    MAP(ClassTemplateDecl, Type);
+    MAP(CXXConstructorDecl, Constructor);
+    MAP(ValueDecl, Variable);
+    MAP(VarTemplateDecl, Variable);
+    MAP(FunctionDecl, Function);
+    MAP(FunctionTemplateDecl, Function);
+    MAP(Decl, Unknown);
+#undef MAP
+  };
+  return Switch().Visit(&ND);
+}
+
+static SymbolQualitySignals::SymbolCategory
+categorize(const CodeCompletionResult &R) {
+  if (R.Declaration)
+    return categorize(*R.Declaration);
+  if (R.Kind == CodeCompletionResult::RK_Macro)
+    return SymbolQualitySignals::Macro;
+  // Everything else is a keyword or a pattern. Patterns are mostly keywords
+  // too, except a few which we recognize by cursor kind.
+  switch (R.CursorKind) {
+  case CXCursor_CXXMethod:
+    return SymbolQualitySignals::Function;
+  case CXCursor_ModuleImportDecl:
+    return SymbolQualitySignals::Namespace;
+  case CXCursor_MacroDefinition:
+    return SymbolQualitySignals::Macro;
+  case CXCursor_TypeRef:
+    return SymbolQualitySignals::Type;
+  case CXCursor_MemberRef:
+    return SymbolQualitySignals::Variable;
+  case CXCursor_Constructor:
+    return SymbolQualitySignals::Constructor;
+  default:
+    return SymbolQualitySignals::Keyword;
+  }
+}
+
+static SymbolQualitySignals::SymbolCategory
+categorize(const index::SymbolInfo &D) {
+  switch (D.Kind) {
+  case index::SymbolKind::Namespace:
+  case index::SymbolKind::NamespaceAlias:
+    return SymbolQualitySignals::Namespace;
+  case index::SymbolKind::Macro:
+    return SymbolQualitySignals::Macro;
+  case index::SymbolKind::Enum:
+  case index::SymbolKind::Struct:
+  case index::SymbolKind::Class:
+  case index::SymbolKind::Protocol:
+  case index::SymbolKind::Extension:
+  case index::SymbolKind::Union:
+  case index::SymbolKind::TypeAlias:
+    return SymbolQualitySignals::Type;
+  case index::SymbolKind::Function:
+  case index::SymbolKind::ClassMethod:
+  case index::SymbolKind::InstanceMethod:
+  case index::SymbolKind::StaticMethod:
+  case index::SymbolKind::InstanceProperty:
+  case index::SymbolKind::ClassProperty:
+  case index::SymbolKind::StaticProperty:
+  case index::SymbolKind::Destructor:
+  case index::SymbolKind::ConversionFunction:
+    return SymbolQualitySignals::Function;
+  case index::SymbolKind::Constructor:
+    return SymbolQualitySignals::Constructor;
+  case index::SymbolKind::Variable:
+  case index::SymbolKind::Field:
+  case index::SymbolKind::EnumConstant:
+  case index::SymbolKind::Parameter:
+    return SymbolQualitySignals::Variable;
+  case index::SymbolKind::Using:
+  case index::SymbolKind::Module:
+  case index::SymbolKind::Unknown:
+    return SymbolQualitySignals::Unknown;
+  }
+  llvm_unreachable("Unknown index::SymbolKind");
+}
+
+static bool isInstanceMember(const NamedDecl *ND) {
+  if (!ND)
+    return false;
+  if (const auto *TP = dyn_cast<FunctionTemplateDecl>(ND))
+    ND = TP->TemplateDecl::getTemplatedDecl();
+  if (const auto *CM = dyn_cast<CXXMethodDecl>(ND))
+    return !CM->isStatic();
+  return isa<FieldDecl>(ND); // Note that static fields are VarDecl.
+}
+
+static bool isInstanceMember(const index::SymbolInfo &D) {
+  switch (D.Kind) {
+  case index::SymbolKind::InstanceMethod:
+  case index::SymbolKind::InstanceProperty:
+  case index::SymbolKind::Field:
+    return true;
+  default:
+    return false;
+  }
+}
+
+void SymbolQualitySignals::merge(const CodeCompletionResult &SemaCCResult) {
+  if (SemaCCResult.Availability == CXAvailability_Deprecated)
+    Deprecated = true;
+
+  Category = categorize(SemaCCResult);
+
+  if (SemaCCResult.Declaration) {
+    if (auto *ID = SemaCCResult.Declaration->getIdentifier())
+      ReservedName = ReservedName || isReserved(ID->getName());
+  } else if (SemaCCResult.Kind == CodeCompletionResult::RK_Macro)
+    ReservedName = ReservedName || isReserved(SemaCCResult.Macro->getName());
+}
+
+void SymbolQualitySignals::merge(const Symbol &IndexResult) {
+  References = std::max(IndexResult.References, References);
+  Category = categorize(IndexResult.SymInfo);
+  ReservedName = ReservedName || isReserved(IndexResult.Name);
+}
+
+float SymbolQualitySignals::evaluate() const {
+  float Score = 1;
+
+  // This avoids a sharp gradient for tail symbols, and also neatly avoids the
+  // question of whether 0 references means a bad symbol or missing data.
+  if (References >= 10) {
+    // Use a sigmoid style boosting function, which flats out nicely for large
+    // numbers (e.g. 2.58 for 1M refererences).
+    // The following boosting function is equivalent to:
+    //   m = 0.06
+    //   f = 12.0
+    //   boost = f * sigmoid(m * std::log(References)) - 0.5 * f + 0.59
+    // Sample data points: (10, 1.00), (100, 1.41), (1000, 1.82),
+    //                     (10K, 2.21), (100K, 2.58), (1M, 2.94)
+    float S = std::pow(References, -0.06);
+    Score *= 6.0 * (1 - S) / (1 + S) + 0.59;
+  }
+
+  if (Deprecated)
+    Score *= 0.1f;
+  if (ReservedName)
+    Score *= 0.1f;
+
+  switch (Category) {
+  case Keyword: // Often relevant, but misses most signals.
+    Score *= 4; // FIXME: important keywords should have specific boosts.
+    break;
+  case Type:
+  case Function:
+  case Variable:
+    Score *= 1.1f;
+    break;
+  case Namespace:
+    Score *= 0.8f;
+    break;
+  case Macro:
+    Score *= 0.2f;
+    break;
+  case Unknown:
+  case Constructor: // No boost constructors so they are after class types.
+    break;
+  }
+
+  return Score;
+}
+
+raw_ostream &operator<<(raw_ostream &OS, const SymbolQualitySignals &S) {
+  OS << formatv("=== Symbol quality: {0}\n", S.evaluate());
+  OS << formatv("\tReferences: {0}\n", S.References);
+  OS << formatv("\tDeprecated: {0}\n", S.Deprecated);
+  OS << formatv("\tReserved name: {0}\n", S.ReservedName);
+  OS << formatv("\tCategory: {0}\n", static_cast<int>(S.Category));
+  return OS;
+}
+
+static SymbolRelevanceSignals::AccessibleScope
+computeScope(const NamedDecl *D) {
+  // Injected "Foo" within the class "Foo" has file scope, not class scope.
+  const DeclContext *DC = D->getDeclContext();
+  if (auto *R = dyn_cast_or_null<RecordDecl>(D))
+    if (R->isInjectedClassName())
+      DC = DC->getParent();
+  // Class constructor should have the same scope as the class.
+  if (isa<CXXConstructorDecl>(D))
+    DC = DC->getParent();
+  bool InClass = false;
+  for (; !DC->isFileContext(); DC = DC->getParent()) {
+    if (DC->isFunctionOrMethod())
+      return SymbolRelevanceSignals::FunctionScope;
+    InClass = InClass || DC->isRecord();
+  }
+  if (InClass)
+    return SymbolRelevanceSignals::ClassScope;
+  // This threshold could be tweaked, e.g. to treat module-visible as global.
+  if (D->getLinkageInternal() < ExternalLinkage)
+    return SymbolRelevanceSignals::FileScope;
+  return SymbolRelevanceSignals::GlobalScope;
+}
+
+void SymbolRelevanceSignals::merge(const Symbol &IndexResult) {
+  // FIXME: Index results always assumed to be at global scope. If Scope becomes
+  // relevant to non-completion requests, we should recognize class members etc.
+
+  SymbolURI = IndexResult.CanonicalDeclaration.FileURI;
+  IsInstanceMember |= isInstanceMember(IndexResult.SymInfo);
+}
+
+void SymbolRelevanceSignals::merge(const CodeCompletionResult &SemaCCResult) {
+  if (SemaCCResult.Availability == CXAvailability_NotAvailable ||
+      SemaCCResult.Availability == CXAvailability_NotAccessible)
+    Forbidden = true;
+
+  if (SemaCCResult.Declaration) {
+    // We boost things that have decls in the main file. We give a fixed score
+    // for all other declarations in sema as they are already included in the
+    // translation unit.
+    float DeclProximity = (hasDeclInMainFile(*SemaCCResult.Declaration) ||
+                           hasUsingDeclInMainFile(SemaCCResult))
+                              ? 1.0
+                              : 0.6;
+    SemaProximityScore = std::max(DeclProximity, SemaProximityScore);
+    IsInstanceMember |= isInstanceMember(SemaCCResult.Declaration);
+  }
+
+  // Declarations are scoped, others (like macros) are assumed global.
+  if (SemaCCResult.Declaration)
+    Scope = std::min(Scope, computeScope(SemaCCResult.Declaration));
+}
+
+static std::pair<float, unsigned> proximityScore(llvm::StringRef SymbolURI,
+                                                 URIDistance *D) {
+  if (!D || SymbolURI.empty())
+    return {0.f, 0u};
+  unsigned Distance = D->distance(SymbolURI);
+  // Assume approximately default options are used for sensible scoring.
+  return {std::exp(Distance * -0.4f / FileDistanceOptions().UpCost), Distance};
+}
+
+float SymbolRelevanceSignals::evaluate() const {
+  float Score = 1;
+
+  if (Forbidden)
+    return 0;
+
+  Score *= NameMatch;
+
+  // Proximity scores are [0,1] and we translate them into a multiplier in the
+  // range from 1 to 3.
+  Score *= 1 + 2 * std::max(proximityScore(SymbolURI, FileProximityMatch).first,
+                            SemaProximityScore);
+
+  // Symbols like local variables may only be referenced within their scope.
+  // Conversely if we're in that scope, it's likely we'll reference them.
+  if (Query == CodeComplete) {
+    // The narrower the scope where a symbol is visible, the more likely it is
+    // to be relevant when it is available.
+    switch (Scope) {
+    case GlobalScope:
+      break;
+    case FileScope:
+      Score *= 1.5;
+      break;
+    case ClassScope:
+      Score *= 2;
+      break;
+    case FunctionScope:
+      Score *= 4;
+      break;
+    }
+  }
+
+  // Penalize non-instance members when they are accessed via a class instance.
+  if (!IsInstanceMember &&
+      (Context == CodeCompletionContext::CCC_DotMemberAccess ||
+       Context == CodeCompletionContext::CCC_ArrowMemberAccess)) {
+    Score *= 0.5;
+  }
+
+  return Score;
+}
+
+raw_ostream &operator<<(raw_ostream &OS, const SymbolRelevanceSignals &S) {
+  OS << formatv("=== Symbol relevance: {0}\n", S.evaluate());
+  OS << formatv("\tName match: {0}\n", S.NameMatch);
+  OS << formatv("\tForbidden: {0}\n", S.Forbidden);
+  OS << formatv("\tIsInstanceMember: {0}\n", S.IsInstanceMember);
+  OS << formatv("\tContext: {0}\n", getCompletionKindString(S.Context));
+  OS << formatv("\tSymbol URI: {0}\n", S.SymbolURI);
+  if (S.FileProximityMatch) {
+    auto Score = proximityScore(S.SymbolURI, S.FileProximityMatch);
+    OS << formatv("\tIndex proximity: {0} (distance={1})\n", Score.first,
+                  Score.second);
+  }
+  OS << formatv("\tSema proximity: {0}\n", S.SemaProximityScore);
+  OS << formatv("\tQuery type: {0}\n", static_cast<int>(S.Query));
+  OS << formatv("\tScope: {0}\n", static_cast<int>(S.Scope));
+  return OS;
+}
+
+float evaluateSymbolAndRelevance(float SymbolQuality, float SymbolRelevance) {
+  return SymbolQuality * SymbolRelevance;
+}
+
+// Produces an integer that sorts in the same order as F.
+// That is: a < b <==> encodeFloat(a) < encodeFloat(b).
+static uint32_t encodeFloat(float F) {
+  static_assert(std::numeric_limits<float>::is_iec559, "");
+  constexpr uint32_t TopBit = ~(~uint32_t{0} >> 1);
+
+  // Get the bits of the float. Endianness is the same as for integers.
+  uint32_t U = FloatToBits(F);
+  // IEEE 754 floats compare like sign-magnitude integers.
+  if (U & TopBit)    // Negative float.
+    return 0 - U;    // Map onto the low half of integers, order reversed.
+  return U + TopBit; // Positive floats map onto the high half of integers.
+}
+
+std::string sortText(float Score, llvm::StringRef Name) {
+  // We convert -Score to an integer, and hex-encode for readability.
+  // Example: [0.5, "foo"] -> "41000000foo"
+  std::string S;
+  llvm::raw_string_ostream OS(S);
+  write_hex(OS, encodeFloat(-Score), llvm::HexPrintStyle::Lower,
+            /*Width=*/2 * sizeof(Score));
+  OS << Name;
+  OS.flush();
+  return S;
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Quality.h b/src/third_party/llvm-project/clang-tools-extra/clangd/Quality.h
new file mode 100644
index 0000000..0aed496
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Quality.h
@@ -0,0 +1,167 @@
+//===--- Quality.h - Ranking alternatives for ambiguous queries -*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+///
+/// Some operations such as code completion produce a set of candidates.
+/// Usually the user can choose between them, but we should put the best options
+/// at the top (they're easier to select, and more likely to be seen).
+///
+/// This file defines building blocks for ranking candidates.
+/// It's used by the features directly and also in the implementation of
+/// indexes, as indexes also need to heuristically limit their results.
+///
+/// The facilities here are:
+///   - retrieving scoring signals from e.g. indexes, AST, CodeCompletionString
+///     These are structured in a way that they can be debugged, and are fairly
+///     consistent regardless of the source.
+///   - compute scores from scoring signals. These are suitable for sorting.
+///   - sorting utilities like the TopN container.
+/// These could be split up further to isolate dependencies if we care.
+///
+//===---------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_QUALITY_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_QUALITY_H
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include <algorithm>
+#include <functional>
+#include <vector>
+namespace llvm {
+class raw_ostream;
+}
+namespace clang {
+class CodeCompletionResult;
+namespace clangd {
+struct Symbol;
+class URIDistance;
+
+// Signals structs are designed to be aggregated from 0 or more sources.
+// A default instance has neutral signals, and sources are merged into it.
+// They can be dumped for debugging, and evaluate()d into a score.
+
+/// Attributes of a symbol that affect how much we like it.
+struct SymbolQualitySignals {
+  bool Deprecated = false;
+  bool ReservedName = false; // __foo, _Foo are usually implementation details.
+                             // FIXME: make these findable once user types _.
+  unsigned References = 0;
+
+  enum SymbolCategory {
+    Unknown = 0,
+    Variable,
+    Macro,
+    Type,
+    Function,
+    Constructor,
+    Namespace,
+    Keyword,
+  } Category = Unknown;
+
+  void merge(const CodeCompletionResult &SemaCCResult);
+  void merge(const Symbol &IndexResult);
+
+  // Condense these signals down to a single number, higher is better.
+  float evaluate() const;
+};
+llvm::raw_ostream &operator<<(llvm::raw_ostream &,
+                              const SymbolQualitySignals &);
+
+/// Attributes of a symbol-query pair that affect how much we like it.
+struct SymbolRelevanceSignals {
+  /// 0-1+ fuzzy-match score for unqualified name. Must be explicitly assigned.
+  float NameMatch = 1;
+  bool Forbidden = false; // Unavailable (e.g const) or inaccessible (private).
+
+  URIDistance *FileProximityMatch = nullptr;
+  /// This is used to calculate proximity between the index symbol and the
+  /// query.
+  llvm::StringRef SymbolURI;
+  /// Proximity between best declaration and the query. [0-1], 1 is closest.
+  /// FIXME: unify with index proximity score - signals should be
+  /// source-independent.
+  float SemaProximityScore = 0;
+
+  // An approximate measure of where we expect the symbol to be used.
+  enum AccessibleScope {
+    FunctionScope,
+    ClassScope,
+    FileScope,
+    GlobalScope,
+  } Scope = GlobalScope;
+
+  enum QueryType {
+    CodeComplete,
+    Generic,
+  } Query = Generic;
+
+  CodeCompletionContext::Kind Context = CodeCompletionContext::CCC_Other;
+
+  // Whether symbol is an instance member of a class.
+  bool IsInstanceMember = false;
+
+  void merge(const CodeCompletionResult &SemaResult);
+  void merge(const Symbol &IndexResult);
+
+  // Condense these signals down to a single number, higher is better.
+  float evaluate() const;
+};
+llvm::raw_ostream &operator<<(llvm::raw_ostream &,
+                              const SymbolRelevanceSignals &);
+
+/// Combine symbol quality and relevance into a single score.
+float evaluateSymbolAndRelevance(float SymbolQuality, float SymbolRelevance);
+
+/// TopN<T> is a lossy container that preserves only the "best" N elements.
+template <typename T, typename Compare = std::greater<T>> class TopN {
+public:
+  using value_type = T;
+  TopN(size_t N, Compare Greater = Compare())
+      : N(N), Greater(std::move(Greater)) {}
+
+  // Adds a candidate to the set.
+  // Returns true if a candidate was dropped to get back under N.
+  bool push(value_type &&V) {
+    bool Dropped = false;
+    if (Heap.size() >= N) {
+      Dropped = true;
+      if (N > 0 && Greater(V, Heap.front())) {
+        std::pop_heap(Heap.begin(), Heap.end(), Greater);
+        Heap.back() = std::move(V);
+        std::push_heap(Heap.begin(), Heap.end(), Greater);
+      }
+    } else {
+      Heap.push_back(std::move(V));
+      std::push_heap(Heap.begin(), Heap.end(), Greater);
+    }
+    assert(Heap.size() <= N);
+    assert(std::is_heap(Heap.begin(), Heap.end(), Greater));
+    return Dropped;
+  }
+
+  // Returns candidates from best to worst.
+  std::vector<value_type> items() && {
+    std::sort_heap(Heap.begin(), Heap.end(), Greater);
+    assert(Heap.size() <= N);
+    return std::move(Heap);
+  }
+
+private:
+  const size_t N;
+  std::vector<value_type> Heap; // Min-heap, comparator is Greater.
+  Compare Greater;
+};
+
+/// Returns a string that sorts in the same order as (-Score, Tiebreak), for
+/// LSP. (The highest score compares smallest so it sorts at the top).
+std::string sortText(float Score, llvm::StringRef Tiebreak = "");
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/SourceCode.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/SourceCode.cpp
new file mode 100644
index 0000000..d302518
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/SourceCode.cpp
@@ -0,0 +1,203 @@
+//===--- SourceCode.h - Manipulating source code as strings -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "SourceCode.h"
+
+#include "Logger.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Path.h"
+
+namespace clang {
+namespace clangd {
+using namespace llvm;
+
+// Here be dragons. LSP positions use columns measured in *UTF-16 code units*!
+// Clangd uses UTF-8 and byte-offsets internally, so conversion is nontrivial.
+
+// Iterates over unicode codepoints in the (UTF-8) string. For each,
+// invokes CB(UTF-8 length, UTF-16 length), and breaks if it returns true.
+// Returns true if CB returned true, false if we hit the end of string.
+template <typename Callback>
+static bool iterateCodepoints(StringRef U8, const Callback &CB) {
+  for (size_t I = 0; I < U8.size();) {
+    unsigned char C = static_cast<unsigned char>(U8[I]);
+    if (LLVM_LIKELY(!(C & 0x80))) { // ASCII character.
+      if (CB(1, 1))
+        return true;
+      ++I;
+      continue;
+    }
+    // This convenient property of UTF-8 holds for all non-ASCII characters.
+    size_t UTF8Length = countLeadingOnes(C);
+    // 0xxx is ASCII, handled above. 10xxx is a trailing byte, invalid here.
+    // 11111xxx is not valid UTF-8 at all. Assert because it's probably our bug.
+    assert((UTF8Length >= 2 && UTF8Length <= 4) &&
+           "Invalid UTF-8, or transcoding bug?");
+    I += UTF8Length; // Skip over all trailing bytes.
+    // A codepoint takes two UTF-16 code unit if it's astral (outside BMP).
+    // Astral codepoints are encoded as 4 bytes in UTF-8 (11110xxx ...)
+    if (CB(UTF8Length, UTF8Length == 4 ? 2 : 1))
+      return true;
+  }
+  return false;
+}
+
+// Returns the offset into the string that matches \p Units UTF-16 code units.
+// Conceptually, this converts to UTF-16, truncates to CodeUnits, converts back
+// to UTF-8, and returns the length in bytes.
+static size_t measureUTF16(StringRef U8, int U16Units, bool &Valid) {
+  size_t Result = 0;
+  Valid = U16Units == 0 || iterateCodepoints(U8, [&](int U8Len, int U16Len) {
+            Result += U8Len;
+            U16Units -= U16Len;
+            return U16Units <= 0;
+          });
+  if (U16Units < 0) // Offset was into the middle of a surrogate pair.
+    Valid = false;
+  // Don't return an out-of-range index if we overran.
+  return std::min(Result, U8.size());
+}
+
+// Counts the number of UTF-16 code units needed to represent a string.
+// Like most strings in clangd, the input is UTF-8 encoded.
+static size_t utf16Len(StringRef U8) {
+  // A codepoint takes two UTF-16 code unit if it's astral (outside BMP).
+  // Astral codepoints are encoded as 4 bytes in UTF-8, starting with 11110xxx.
+  size_t Count = 0;
+  iterateCodepoints(U8, [&](int U8Len, int U16Len) {
+    Count += U16Len;
+    return false;
+  });
+  return Count;
+}
+
+llvm::Expected<size_t> positionToOffset(StringRef Code, Position P,
+                                        bool AllowColumnsBeyondLineLength) {
+  if (P.line < 0)
+    return llvm::make_error<llvm::StringError>(
+        llvm::formatv("Line value can't be negative ({0})", P.line),
+        llvm::errc::invalid_argument);
+  if (P.character < 0)
+    return llvm::make_error<llvm::StringError>(
+        llvm::formatv("Character value can't be negative ({0})", P.character),
+        llvm::errc::invalid_argument);
+  size_t StartOfLine = 0;
+  for (int I = 0; I != P.line; ++I) {
+    size_t NextNL = Code.find('\n', StartOfLine);
+    if (NextNL == StringRef::npos)
+      return llvm::make_error<llvm::StringError>(
+          llvm::formatv("Line value is out of range ({0})", P.line),
+          llvm::errc::invalid_argument);
+    StartOfLine = NextNL + 1;
+  }
+
+  size_t NextNL = Code.find('\n', StartOfLine);
+  if (NextNL == StringRef::npos)
+    NextNL = Code.size();
+
+  bool Valid;
+  size_t ByteOffsetInLine = measureUTF16(
+      Code.substr(StartOfLine, NextNL - StartOfLine), P.character, Valid);
+  if (!Valid && !AllowColumnsBeyondLineLength)
+    return llvm::make_error<llvm::StringError>(
+        llvm::formatv("UTF-16 offset {0} is invalid for line {1}", P.character,
+                      P.line),
+        llvm::errc::invalid_argument);
+  return StartOfLine + ByteOffsetInLine;
+}
+
+Position offsetToPosition(StringRef Code, size_t Offset) {
+  Offset = std::min(Code.size(), Offset);
+  StringRef Before = Code.substr(0, Offset);
+  int Lines = Before.count('\n');
+  size_t PrevNL = Before.rfind('\n');
+  size_t StartOfLine = (PrevNL == StringRef::npos) ? 0 : (PrevNL + 1);
+  Position Pos;
+  Pos.line = Lines;
+  Pos.character = utf16Len(Before.substr(StartOfLine));
+  return Pos;
+}
+
+Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc) {
+  // We use the SourceManager's line tables, but its column number is in bytes.
+  FileID FID;
+  unsigned Offset;
+  std::tie(FID, Offset) = SM.getDecomposedSpellingLoc(Loc);
+  Position P;
+  P.line = static_cast<int>(SM.getLineNumber(FID, Offset)) - 1;
+  bool Invalid = false;
+  StringRef Code = SM.getBufferData(FID, &Invalid);
+  if (!Invalid) {
+    auto ColumnInBytes = SM.getColumnNumber(FID, Offset) - 1;
+    auto LineSoFar = Code.substr(Offset - ColumnInBytes, ColumnInBytes);
+    P.character = utf16Len(LineSoFar);
+  }
+  return P;
+}
+
+Range halfOpenToRange(const SourceManager &SM, CharSourceRange R) {
+  // Clang is 1-based, LSP uses 0-based indexes.
+  Position Begin = sourceLocToPosition(SM, R.getBegin());
+  Position End = sourceLocToPosition(SM, R.getEnd());
+
+  return {Begin, End};
+}
+
+std::pair<size_t, size_t> offsetToClangLineColumn(StringRef Code,
+                                                  size_t Offset) {
+  Offset = std::min(Code.size(), Offset);
+  StringRef Before = Code.substr(0, Offset);
+  int Lines = Before.count('\n');
+  size_t PrevNL = Before.rfind('\n');
+  size_t StartOfLine = (PrevNL == StringRef::npos) ? 0 : (PrevNL + 1);
+  return {Lines + 1, Offset - StartOfLine + 1};
+}
+
+std::pair<llvm::StringRef, llvm::StringRef>
+splitQualifiedName(llvm::StringRef QName) {
+  size_t Pos = QName.rfind("::");
+  if (Pos == llvm::StringRef::npos)
+    return {StringRef(), QName};
+  return {QName.substr(0, Pos + 2), QName.substr(Pos + 2)};
+}
+
+TextEdit replacementToEdit(StringRef Code, const tooling::Replacement &R) {
+  Range ReplacementRange = {
+      offsetToPosition(Code, R.getOffset()),
+      offsetToPosition(Code, R.getOffset() + R.getLength())};
+  return {ReplacementRange, R.getReplacementText()};
+}
+
+std::vector<TextEdit> replacementsToEdits(StringRef Code,
+                                          const tooling::Replacements &Repls) {
+  std::vector<TextEdit> Edits;
+  for (const auto &R : Repls)
+    Edits.push_back(replacementToEdit(Code, R));
+  return Edits;
+}
+
+llvm::Optional<std::string>
+getAbsoluteFilePath(const FileEntry *F, const SourceManager &SourceMgr) {
+  SmallString<64> FilePath = F->tryGetRealPathName();
+  if (FilePath.empty())
+    FilePath = F->getName();
+  if (!llvm::sys::path::is_absolute(FilePath)) {
+    if (!SourceMgr.getFileManager().makeAbsolutePath(FilePath)) {
+      log("Could not turn relative path to absolute: {0}", FilePath);
+      return llvm::None;
+    }
+  }
+  return FilePath.str().str();
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/SourceCode.h b/src/third_party/llvm-project/clang-tools-extra/clangd/SourceCode.h
new file mode 100644
index 0000000..b67fe6e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/SourceCode.h
@@ -0,0 +1,69 @@
+//===--- SourceCode.h - Manipulating source code as strings -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Various code that examines C++ source code without using heavy AST machinery
+// (and often not even the lexer). To be used sparingly!
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SOURCECODE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SOURCECODE_H
+#include "Protocol.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Tooling/Core/Replacement.h"
+
+namespace clang {
+class SourceManager;
+
+namespace clangd {
+
+/// Turn a [line, column] pair into an offset in Code.
+///
+/// If P.character exceeds the line length, returns the offset at end-of-line.
+/// (If !AllowColumnsBeyondLineLength, then returns an error instead).
+/// If the line number is out of range, returns an error.
+///
+/// The returned value is in the range [0, Code.size()].
+llvm::Expected<size_t>
+positionToOffset(llvm::StringRef Code, Position P,
+                 bool AllowColumnsBeyondLineLength = true);
+
+/// Turn an offset in Code into a [line, column] pair.
+/// The offset must be in range [0, Code.size()].
+Position offsetToPosition(llvm::StringRef Code, size_t Offset);
+
+/// Turn a SourceLocation into a [line, column] pair.
+/// FIXME: This should return an error if the location is invalid.
+Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc);
+
+// Converts a half-open clang source range to an LSP range.
+// Note that clang also uses closed source ranges, which this can't handle!
+Range halfOpenToRange(const SourceManager &SM, CharSourceRange R);
+
+// Converts an offset to a clang line/column (1-based, columns are bytes).
+// The offset must be in range [0, Code.size()].
+// Prefer to use SourceManager if one is available.
+std::pair<size_t, size_t> offsetToClangLineColumn(llvm::StringRef Code,
+                                                  size_t Offset);
+
+/// From "a::b::c", return {"a::b::", "c"}. Scope is empty if there's no
+/// qualifier.
+std::pair<llvm::StringRef, llvm::StringRef>
+splitQualifiedName(llvm::StringRef QName);
+
+TextEdit replacementToEdit(StringRef Code, const tooling::Replacement &R);
+
+std::vector<TextEdit> replacementsToEdits(StringRef Code,
+                                          const tooling::Replacements &Repls);
+
+/// Get the absolute file path of a given file entry.
+llvm::Optional<std::string> getAbsoluteFilePath(const FileEntry *F,
+                                                const SourceManager &SourceMgr);
+} // namespace clangd
+} // namespace clang
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/TUScheduler.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/TUScheduler.cpp
new file mode 100644
index 0000000..81a75bb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/TUScheduler.cpp
@@ -0,0 +1,764 @@
+//===--- TUScheduler.cpp -----------------------------------------*-C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// For each file, managed by TUScheduler, we create a single ASTWorker that
+// manages an AST for that file. All operations that modify or read the AST are
+// run on a separate dedicated thread asynchronously in FIFO order.
+//
+// We start processing each update immediately after we receive it. If two or
+// more updates come subsequently without reads in-between, we attempt to drop
+// an older one to not waste time building the ASTs we don't need.
+//
+// The processing thread of the ASTWorker is also responsible for building the
+// preamble. However, unlike AST, the same preamble can be read concurrently, so
+// we run each of async preamble reads on its own thread.
+//
+// To limit the concurrent load that clangd produces we mantain a semaphore that
+// keeps more than a fixed number of threads from running concurrently.
+//
+// Rationale for cancelling updates.
+// LSP clients can send updates to clangd on each keystroke. Some files take
+// significant time to parse (e.g. a few seconds) and clangd can get starved by
+// the updates to those files. Therefore we try to process only the last update,
+// if possible.
+// Our current strategy to do that is the following:
+// - For each update we immediately schedule rebuild of the AST.
+// - Rebuild of the AST checks if it was cancelled before doing any actual work.
+//   If it was, it does not do an actual rebuild, only reports llvm::None to the
+//   callback
+// - When adding an update, we cancel the last update in the queue if it didn't
+//   have any reads.
+// There is probably a optimal ways to do that. One approach we might take is
+// the following:
+// - For each update we remember the pending inputs, but delay rebuild of the
+//   AST for some timeout.
+// - If subsequent updates come before rebuild was started, we replace the
+//   pending inputs and reset the timer.
+// - If any reads of the AST are scheduled, we start building the AST
+//   immediately.
+
+#include "TUScheduler.h"
+#include "Logger.h"
+#include "Trace.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "llvm/ADT/ScopeExit.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Path.h"
+#include <algorithm>
+#include <memory>
+#include <queue>
+#include <thread>
+
+namespace clang {
+namespace clangd {
+using std::chrono::steady_clock;
+
+namespace {
+class ASTWorker;
+}
+
+/// An LRU cache of idle ASTs.
+/// Because we want to limit the overall number of these we retain, the cache
+/// owns ASTs (and may evict them) while their workers are idle.
+/// Workers borrow ASTs when active, and return them when done.
+class TUScheduler::ASTCache {
+public:
+  using Key = const ASTWorker *;
+
+  ASTCache(unsigned MaxRetainedASTs) : MaxRetainedASTs(MaxRetainedASTs) {}
+
+  /// Returns result of getUsedBytes() for the AST cached by \p K.
+  /// If no AST is cached, 0 is returned.
+  std::size_t getUsedBytes(Key K) {
+    std::lock_guard<std::mutex> Lock(Mut);
+    auto It = findByKey(K);
+    if (It == LRU.end() || !It->second)
+      return 0;
+    return It->second->getUsedBytes();
+  }
+
+  /// Store the value in the pool, possibly removing the last used AST.
+  /// The value should not be in the pool when this function is called.
+  void put(Key K, std::unique_ptr<ParsedAST> V) {
+    std::unique_lock<std::mutex> Lock(Mut);
+    assert(findByKey(K) == LRU.end());
+
+    LRU.insert(LRU.begin(), {K, std::move(V)});
+    if (LRU.size() <= MaxRetainedASTs)
+      return;
+    // We're past the limit, remove the last element.
+    std::unique_ptr<ParsedAST> ForCleanup = std::move(LRU.back().second);
+    LRU.pop_back();
+    // Run the expensive destructor outside the lock.
+    Lock.unlock();
+    ForCleanup.reset();
+  }
+
+  /// Returns the cached value for \p K, or llvm::None if the value is not in
+  /// the cache anymore. If nullptr was cached for \p K, this function will
+  /// return a null unique_ptr wrapped into an optional.
+  llvm::Optional<std::unique_ptr<ParsedAST>> take(Key K) {
+    std::unique_lock<std::mutex> Lock(Mut);
+    auto Existing = findByKey(K);
+    if (Existing == LRU.end())
+      return llvm::None;
+    std::unique_ptr<ParsedAST> V = std::move(Existing->second);
+    LRU.erase(Existing);
+    // GCC 4.8 fails to compile `return V;`, as it tries to call the copy
+    // constructor of unique_ptr, so we call the move ctor explicitly to avoid
+    // this miscompile.
+    return llvm::Optional<std::unique_ptr<ParsedAST>>(std::move(V));
+  }
+
+private:
+  using KVPair = std::pair<Key, std::unique_ptr<ParsedAST>>;
+
+  std::vector<KVPair>::iterator findByKey(Key K) {
+    return std::find_if(LRU.begin(), LRU.end(),
+                        [K](const KVPair &P) { return P.first == K; });
+  }
+
+  std::mutex Mut;
+  unsigned MaxRetainedASTs;
+  /// Items sorted in LRU order, i.e. first item is the most recently accessed
+  /// one.
+  std::vector<KVPair> LRU; /* GUARDED_BY(Mut) */
+};
+
+namespace {
+class ASTWorkerHandle;
+
+/// Owns one instance of the AST, schedules updates and reads of it.
+/// Also responsible for building and providing access to the preamble.
+/// Each ASTWorker processes the async requests sent to it on a separate
+/// dedicated thread.
+/// The ASTWorker that manages the AST is shared by both the processing thread
+/// and the TUScheduler. The TUScheduler should discard an ASTWorker when
+/// remove() is called, but its thread may be busy and we don't want to block.
+/// So the workers are accessed via an ASTWorkerHandle. Destroying the handle
+/// signals the worker to exit its run loop and gives up shared ownership of the
+/// worker.
+class ASTWorker {
+  friend class ASTWorkerHandle;
+  ASTWorker(PathRef FileName, TUScheduler::ASTCache &LRUCache,
+            Semaphore &Barrier, bool RunSync,
+            steady_clock::duration UpdateDebounce,
+            std::shared_ptr<PCHContainerOperations> PCHs,
+            bool StorePreamblesInMemory,
+            PreambleParsedCallback PreambleCallback);
+
+public:
+  /// Create a new ASTWorker and return a handle to it.
+  /// The processing thread is spawned using \p Tasks. However, when \p Tasks
+  /// is null, all requests will be processed on the calling thread
+  /// synchronously instead. \p Barrier is acquired when processing each
+  /// request, it is be used to limit the number of actively running threads.
+  static ASTWorkerHandle create(PathRef FileName,
+                                TUScheduler::ASTCache &IdleASTs,
+                                AsyncTaskRunner *Tasks, Semaphore &Barrier,
+                                steady_clock::duration UpdateDebounce,
+                                std::shared_ptr<PCHContainerOperations> PCHs,
+                                bool StorePreamblesInMemory,
+                                PreambleParsedCallback PreambleCallback);
+  ~ASTWorker();
+
+  void update(ParseInputs Inputs, WantDiagnostics,
+              llvm::unique_function<void(std::vector<Diag>)> OnUpdated);
+  void
+  runWithAST(llvm::StringRef Name,
+             llvm::unique_function<void(llvm::Expected<InputsAndAST>)> Action);
+  bool blockUntilIdle(Deadline Timeout) const;
+
+  std::shared_ptr<const PreambleData> getPossiblyStalePreamble() const;
+  /// Wait for the first build of preamble to finish. Preamble itself can be
+  /// accessed via getPossibleStalePreamble(). Note that this function will
+  /// return after an unsuccessful build of the preamble too, i.e. result of
+  /// getPossiblyStalePreamble() can be null even after this function returns.
+  void waitForFirstPreamble() const;
+
+  std::size_t getUsedBytes() const;
+  bool isASTCached() const;
+
+private:
+  // Must be called exactly once on processing thread. Will return after
+  // stop() is called on a separate thread and all pending requests are
+  // processed.
+  void run();
+  /// Signal that run() should finish processing pending requests and exit.
+  void stop();
+  /// Adds a new task to the end of the request queue.
+  void startTask(llvm::StringRef Name, llvm::unique_function<void()> Task,
+                 llvm::Optional<WantDiagnostics> UpdateType);
+  /// Determines the next action to perform.
+  /// All actions that should never run are disarded.
+  /// Returns a deadline for the next action. If it's expired, run now.
+  /// scheduleLocked() is called again at the deadline, or if requests arrive.
+  Deadline scheduleLocked();
+  /// Should the first task in the queue be skipped instead of run?
+  bool shouldSkipHeadLocked() const;
+
+  struct Request {
+    llvm::unique_function<void()> Action;
+    std::string Name;
+    steady_clock::time_point AddTime;
+    Context Ctx;
+    llvm::Optional<WantDiagnostics> UpdateType;
+  };
+
+  /// Handles retention of ASTs.
+  TUScheduler::ASTCache &IdleASTs;
+  const bool RunSync;
+  /// Time to wait after an update to see whether another update obsoletes it.
+  const steady_clock::duration UpdateDebounce;
+  /// File that ASTWorker is reponsible for.
+  const Path FileName;
+  /// Whether to keep the built preambles in memory or on disk.
+  const bool StorePreambleInMemory;
+  /// Callback, passed to the preamble builder.
+  const PreambleParsedCallback PreambleCallback;
+  /// Helper class required to build the ASTs.
+  const std::shared_ptr<PCHContainerOperations> PCHs;
+
+  Semaphore &Barrier;
+  /// Inputs, corresponding to the current state of AST.
+  ParseInputs FileInputs;
+  /// Whether the diagnostics for the current FileInputs were reported to the
+  /// users before.
+  bool DiagsWereReported = false;
+  /// Size of the last AST
+  /// Guards members used by both TUScheduler and the worker thread.
+  mutable std::mutex Mutex;
+  std::shared_ptr<const PreambleData> LastBuiltPreamble; /* GUARDED_BY(Mutex) */
+  /// Becomes ready when the first preamble build finishes.
+  Notification PreambleWasBuilt;
+  /// Set to true to signal run() to finish processing.
+  bool Done;                    /* GUARDED_BY(Mutex) */
+  std::deque<Request> Requests; /* GUARDED_BY(Mutex) */
+  mutable std::condition_variable RequestsCV;
+};
+
+/// A smart-pointer-like class that points to an active ASTWorker.
+/// In destructor, signals to the underlying ASTWorker that no new requests will
+/// be sent and the processing loop may exit (after running all pending
+/// requests).
+class ASTWorkerHandle {
+  friend class ASTWorker;
+  ASTWorkerHandle(std::shared_ptr<ASTWorker> Worker)
+      : Worker(std::move(Worker)) {
+    assert(this->Worker);
+  }
+
+public:
+  ASTWorkerHandle(const ASTWorkerHandle &) = delete;
+  ASTWorkerHandle &operator=(const ASTWorkerHandle &) = delete;
+  ASTWorkerHandle(ASTWorkerHandle &&) = default;
+  ASTWorkerHandle &operator=(ASTWorkerHandle &&) = default;
+
+  ~ASTWorkerHandle() {
+    if (Worker)
+      Worker->stop();
+  }
+
+  ASTWorker &operator*() {
+    assert(Worker && "Handle was moved from");
+    return *Worker;
+  }
+
+  ASTWorker *operator->() {
+    assert(Worker && "Handle was moved from");
+    return Worker.get();
+  }
+
+  /// Returns an owning reference to the underlying ASTWorker that can outlive
+  /// the ASTWorkerHandle. However, no new requests to an active ASTWorker can
+  /// be schedule via the returned reference, i.e. only reads of the preamble
+  /// are possible.
+  std::shared_ptr<const ASTWorker> lock() { return Worker; }
+
+private:
+  std::shared_ptr<ASTWorker> Worker;
+};
+
+ASTWorkerHandle ASTWorker::create(PathRef FileName,
+                                  TUScheduler::ASTCache &IdleASTs,
+                                  AsyncTaskRunner *Tasks, Semaphore &Barrier,
+                                  steady_clock::duration UpdateDebounce,
+                                  std::shared_ptr<PCHContainerOperations> PCHs,
+                                  bool StorePreamblesInMemory,
+                                  PreambleParsedCallback PreambleCallback) {
+  std::shared_ptr<ASTWorker> Worker(new ASTWorker(
+      FileName, IdleASTs, Barrier, /*RunSync=*/!Tasks, UpdateDebounce,
+      std::move(PCHs), StorePreamblesInMemory, std::move(PreambleCallback)));
+  if (Tasks)
+    Tasks->runAsync("worker:" + llvm::sys::path::filename(FileName),
+                    [Worker]() { Worker->run(); });
+
+  return ASTWorkerHandle(std::move(Worker));
+}
+
+ASTWorker::ASTWorker(PathRef FileName, TUScheduler::ASTCache &LRUCache,
+                     Semaphore &Barrier, bool RunSync,
+                     steady_clock::duration UpdateDebounce,
+                     std::shared_ptr<PCHContainerOperations> PCHs,
+                     bool StorePreamblesInMemory,
+                     PreambleParsedCallback PreambleCallback)
+    : IdleASTs(LRUCache), RunSync(RunSync), UpdateDebounce(UpdateDebounce),
+      FileName(FileName), StorePreambleInMemory(StorePreamblesInMemory),
+      PreambleCallback(std::move(PreambleCallback)), PCHs(std::move(PCHs)),
+      Barrier(Barrier), Done(false) {}
+
+ASTWorker::~ASTWorker() {
+  // Make sure we remove the cached AST, if any.
+  IdleASTs.take(this);
+#ifndef NDEBUG
+  std::lock_guard<std::mutex> Lock(Mutex);
+  assert(Done && "handle was not destroyed");
+  assert(Requests.empty() && "unprocessed requests when destroying ASTWorker");
+#endif
+}
+
+void ASTWorker::update(
+    ParseInputs Inputs, WantDiagnostics WantDiags,
+    llvm::unique_function<void(std::vector<Diag>)> OnUpdated) {
+  auto Task = [=](decltype(OnUpdated) OnUpdated) mutable {
+    // Will be used to check if we can avoid rebuilding the AST.
+    bool InputsAreTheSame =
+        std::tie(FileInputs.CompileCommand, FileInputs.Contents) ==
+        std::tie(Inputs.CompileCommand, Inputs.Contents);
+
+    tooling::CompileCommand OldCommand = std::move(FileInputs.CompileCommand);
+    bool PrevDiagsWereReported = DiagsWereReported;
+    FileInputs = Inputs;
+    DiagsWereReported = false;
+
+    log("Updating file {0} with command [{1}] {2}", FileName,
+        Inputs.CompileCommand.Directory,
+        llvm::join(Inputs.CompileCommand.CommandLine, " "));
+    // Rebuild the preamble and the AST.
+    std::unique_ptr<CompilerInvocation> Invocation =
+        buildCompilerInvocation(Inputs);
+    if (!Invocation) {
+      elog("Could not build CompilerInvocation for file {0}", FileName);
+      // Remove the old AST if it's still in cache.
+      IdleASTs.take(this);
+      // Make sure anyone waiting for the preamble gets notified it could not
+      // be built.
+      PreambleWasBuilt.notify();
+      return;
+    }
+
+    std::shared_ptr<const PreambleData> OldPreamble =
+        getPossiblyStalePreamble();
+    std::shared_ptr<const PreambleData> NewPreamble =
+        buildPreamble(FileName, *Invocation, OldPreamble, OldCommand, Inputs,
+                      PCHs, StorePreambleInMemory, PreambleCallback);
+
+    bool CanReuseAST = InputsAreTheSame && (OldPreamble == NewPreamble);
+    {
+      std::lock_guard<std::mutex> Lock(Mutex);
+      if (NewPreamble)
+        LastBuiltPreamble = NewPreamble;
+    }
+    // Before doing the expensive AST reparse, we want to release our reference
+    // to the old preamble, so it can be freed if there are no other references
+    // to it.
+    OldPreamble.reset();
+    PreambleWasBuilt.notify();
+
+    if (!CanReuseAST) {
+      IdleASTs.take(this); // Remove the old AST if it's still in cache.
+    } else {
+      // Since we don't need to rebuild the AST, we might've already reported
+      // the diagnostics for it.
+      if (PrevDiagsWereReported) {
+        DiagsWereReported = true;
+        // Take a shortcut and don't report the diagnostics, since they should
+        // not changed. All the clients should handle the lack of OnUpdated()
+        // call anyway to handle empty result from buildAST.
+        // FIXME(ibiryukov): the AST could actually change if non-preamble
+        // includes changed, but we choose to ignore it.
+        // FIXME(ibiryukov): should we refresh the cache in IdleASTs for the
+        // current file at this point?
+        log("Skipping rebuild of the AST for {0}, inputs are the same.",
+            FileName);
+        return;
+      }
+    }
+
+    // We only need to build the AST if diagnostics were requested.
+    if (WantDiags == WantDiagnostics::No)
+      return;
+
+    // Get the AST for diagnostics.
+    llvm::Optional<std::unique_ptr<ParsedAST>> AST = IdleASTs.take(this);
+    if (!AST) {
+      llvm::Optional<ParsedAST> NewAST =
+          buildAST(FileName, std::move(Invocation), Inputs, NewPreamble, PCHs);
+      AST = NewAST ? llvm::make_unique<ParsedAST>(std::move(*NewAST)) : nullptr;
+    }
+    // We want to report the diagnostics even if this update was cancelled.
+    // It seems more useful than making the clients wait indefinitely if they
+    // spam us with updates.
+    // Note *AST can be still be null if buildAST fails.
+    if (*AST) {
+      OnUpdated((*AST)->getDiagnostics());
+      DiagsWereReported = true;
+    }
+    // Stash the AST in the cache for further use.
+    IdleASTs.put(this, std::move(*AST));
+  };
+
+  startTask("Update", Bind(Task, std::move(OnUpdated)), WantDiags);
+}
+
+void ASTWorker::runWithAST(
+    llvm::StringRef Name,
+    llvm::unique_function<void(llvm::Expected<InputsAndAST>)> Action) {
+  auto Task = [=](decltype(Action) Action) {
+    llvm::Optional<std::unique_ptr<ParsedAST>> AST = IdleASTs.take(this);
+    if (!AST) {
+      std::unique_ptr<CompilerInvocation> Invocation =
+          buildCompilerInvocation(FileInputs);
+      // Try rebuilding the AST.
+      llvm::Optional<ParsedAST> NewAST =
+          Invocation
+              ? buildAST(FileName,
+                         llvm::make_unique<CompilerInvocation>(*Invocation),
+                         FileInputs, getPossiblyStalePreamble(), PCHs)
+              : llvm::None;
+      AST = NewAST ? llvm::make_unique<ParsedAST>(std::move(*NewAST)) : nullptr;
+    }
+    // Make sure we put the AST back into the LRU cache.
+    auto _ = llvm::make_scope_exit(
+        [&AST, this]() { IdleASTs.put(this, std::move(*AST)); });
+    // Run the user-provided action.
+    if (!*AST)
+      return Action(llvm::make_error<llvm::StringError>(
+          "invalid AST", llvm::errc::invalid_argument));
+    Action(InputsAndAST{FileInputs, **AST});
+  };
+  startTask(Name, Bind(Task, std::move(Action)),
+            /*UpdateType=*/llvm::None);
+}
+
+std::shared_ptr<const PreambleData>
+ASTWorker::getPossiblyStalePreamble() const {
+  std::lock_guard<std::mutex> Lock(Mutex);
+  return LastBuiltPreamble;
+}
+
+void ASTWorker::waitForFirstPreamble() const {
+  PreambleWasBuilt.wait();
+}
+
+std::size_t ASTWorker::getUsedBytes() const {
+  // Note that we don't report the size of ASTs currently used for processing
+  // the in-flight requests. We used this information for debugging purposes
+  // only, so this should be fine.
+  std::size_t Result = IdleASTs.getUsedBytes(this);
+  if (auto Preamble = getPossiblyStalePreamble())
+    Result += Preamble->Preamble.getSize();
+  return Result;
+}
+
+bool ASTWorker::isASTCached() const { return IdleASTs.getUsedBytes(this) != 0; }
+
+void ASTWorker::stop() {
+  {
+    std::lock_guard<std::mutex> Lock(Mutex);
+    assert(!Done && "stop() called twice");
+    Done = true;
+  }
+  RequestsCV.notify_all();
+}
+
+void ASTWorker::startTask(llvm::StringRef Name,
+                          llvm::unique_function<void()> Task,
+                          llvm::Optional<WantDiagnostics> UpdateType) {
+  if (RunSync) {
+    assert(!Done && "running a task after stop()");
+    trace::Span Tracer(Name + ":" + llvm::sys::path::filename(FileName));
+    Task();
+    return;
+  }
+
+  {
+    std::lock_guard<std::mutex> Lock(Mutex);
+    assert(!Done && "running a task after stop()");
+    Requests.push_back({std::move(Task), Name, steady_clock::now(),
+                        Context::current().clone(), UpdateType});
+  }
+  RequestsCV.notify_all();
+}
+
+void ASTWorker::run() {
+  while (true) {
+    Request Req;
+    {
+      std::unique_lock<std::mutex> Lock(Mutex);
+      for (auto Wait = scheduleLocked(); !Wait.expired();
+           Wait = scheduleLocked()) {
+        if (Done) {
+          if (Requests.empty())
+            return;
+          else     // Even though Done is set, finish pending requests.
+            break; // However, skip delays to shutdown fast.
+        }
+
+        // Tracing: we have a next request, attribute this sleep to it.
+        Optional<WithContext> Ctx;
+        Optional<trace::Span> Tracer;
+        if (!Requests.empty()) {
+          Ctx.emplace(Requests.front().Ctx.clone());
+          Tracer.emplace("Debounce");
+          SPAN_ATTACH(*Tracer, "next_request", Requests.front().Name);
+          if (!(Wait == Deadline::infinity()))
+            SPAN_ATTACH(*Tracer, "sleep_ms",
+                        std::chrono::duration_cast<std::chrono::milliseconds>(
+                            Wait.time() - steady_clock::now())
+                            .count());
+        }
+
+        wait(Lock, RequestsCV, Wait);
+      }
+      Req = std::move(Requests.front());
+      // Leave it on the queue for now, so waiters don't see an empty queue.
+    } // unlock Mutex
+
+    {
+      std::lock_guard<Semaphore> BarrierLock(Barrier);
+      WithContext Guard(std::move(Req.Ctx));
+      trace::Span Tracer(Req.Name);
+      Req.Action();
+    }
+
+    {
+      std::lock_guard<std::mutex> Lock(Mutex);
+      Requests.pop_front();
+    }
+    RequestsCV.notify_all();
+  }
+}
+
+Deadline ASTWorker::scheduleLocked() {
+  if (Requests.empty())
+    return Deadline::infinity(); // Wait for new requests.
+  while (shouldSkipHeadLocked())
+    Requests.pop_front();
+  assert(!Requests.empty() && "skipped the whole queue");
+  // Some updates aren't dead yet, but never end up being used.
+  // e.g. the first keystroke is live until obsoleted by the second.
+  // We debounce "maybe-unused" writes, sleeping 500ms in case they become dead.
+  // But don't delay reads (including updates where diagnostics are needed).
+  for (const auto &R : Requests)
+    if (R.UpdateType == None || R.UpdateType == WantDiagnostics::Yes)
+      return Deadline::zero();
+  // Front request needs to be debounced, so determine when we're ready.
+  Deadline D(Requests.front().AddTime + UpdateDebounce);
+  return D;
+}
+
+// Returns true if Requests.front() is a dead update that can be skipped.
+bool ASTWorker::shouldSkipHeadLocked() const {
+  assert(!Requests.empty());
+  auto Next = Requests.begin();
+  auto UpdateType = Next->UpdateType;
+  if (!UpdateType) // Only skip updates.
+    return false;
+  ++Next;
+  // An update is live if its AST might still be read.
+  // That is, if it's not immediately followed by another update.
+  if (Next == Requests.end() || !Next->UpdateType)
+    return false;
+  // The other way an update can be live is if its diagnostics might be used.
+  switch (*UpdateType) {
+  case WantDiagnostics::Yes:
+    return false; // Always used.
+  case WantDiagnostics::No:
+    return true; // Always dead.
+  case WantDiagnostics::Auto:
+    // Used unless followed by an update that generates diagnostics.
+    for (; Next != Requests.end(); ++Next)
+      if (Next->UpdateType == WantDiagnostics::Yes ||
+          Next->UpdateType == WantDiagnostics::Auto)
+        return true; // Prefer later diagnostics.
+    return false;
+  }
+  llvm_unreachable("Unknown WantDiagnostics");
+}
+
+bool ASTWorker::blockUntilIdle(Deadline Timeout) const {
+  std::unique_lock<std::mutex> Lock(Mutex);
+  return wait(Lock, RequestsCV, Timeout, [&] { return Requests.empty(); });
+}
+
+} // namespace
+
+unsigned 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;
+}
+
+struct TUScheduler::FileData {
+  /// Latest inputs, passed to TUScheduler::update().
+  std::string Contents;
+  tooling::CompileCommand Command;
+  ASTWorkerHandle Worker;
+};
+
+TUScheduler::TUScheduler(unsigned AsyncThreadsCount,
+                         bool StorePreamblesInMemory,
+                         PreambleParsedCallback PreambleCallback,
+                         std::chrono::steady_clock::duration UpdateDebounce,
+                         ASTRetentionPolicy RetentionPolicy)
+    : StorePreamblesInMemory(StorePreamblesInMemory),
+      PCHOps(std::make_shared<PCHContainerOperations>()),
+      PreambleCallback(std::move(PreambleCallback)), Barrier(AsyncThreadsCount),
+      IdleASTs(llvm::make_unique<ASTCache>(RetentionPolicy.MaxRetainedASTs)),
+      UpdateDebounce(UpdateDebounce) {
+  if (0 < AsyncThreadsCount) {
+    PreambleTasks.emplace();
+    WorkerThreads.emplace();
+  }
+}
+
+TUScheduler::~TUScheduler() {
+  // Notify all workers that they need to stop.
+  Files.clear();
+
+  // Wait for all in-flight tasks to finish.
+  if (PreambleTasks)
+    PreambleTasks->wait();
+  if (WorkerThreads)
+    WorkerThreads->wait();
+}
+
+bool TUScheduler::blockUntilIdle(Deadline D) const {
+  for (auto &File : Files)
+    if (!File.getValue()->Worker->blockUntilIdle(D))
+      return false;
+  if (PreambleTasks)
+    if (!PreambleTasks->wait(D))
+      return false;
+  return true;
+}
+
+void TUScheduler::update(
+    PathRef File, ParseInputs Inputs, WantDiagnostics WantDiags,
+    llvm::unique_function<void(std::vector<Diag>)> OnUpdated) {
+  std::unique_ptr<FileData> &FD = Files[File];
+  if (!FD) {
+    // Create a new worker to process the AST-related tasks.
+    ASTWorkerHandle Worker = ASTWorker::create(
+        File, *IdleASTs, WorkerThreads ? WorkerThreads.getPointer() : nullptr,
+        Barrier, UpdateDebounce, PCHOps, StorePreamblesInMemory,
+        PreambleCallback);
+    FD = std::unique_ptr<FileData>(new FileData{
+        Inputs.Contents, Inputs.CompileCommand, std::move(Worker)});
+  } else {
+    FD->Contents = Inputs.Contents;
+    FD->Command = Inputs.CompileCommand;
+  }
+  FD->Worker->update(std::move(Inputs), WantDiags, std::move(OnUpdated));
+}
+
+void TUScheduler::remove(PathRef File) {
+  bool Removed = Files.erase(File);
+  if (!Removed)
+    elog("Trying to remove file from TUScheduler that is not tracked: {0}",
+         File);
+}
+
+void TUScheduler::runWithAST(
+    llvm::StringRef Name, PathRef File,
+    llvm::unique_function<void(llvm::Expected<InputsAndAST>)> Action) {
+  auto It = Files.find(File);
+  if (It == Files.end()) {
+    Action(llvm::make_error<llvm::StringError>(
+        "trying to get AST for non-added document",
+        llvm::errc::invalid_argument));
+    return;
+  }
+
+  It->second->Worker->runWithAST(Name, std::move(Action));
+}
+
+void TUScheduler::runWithPreamble(
+    llvm::StringRef Name, PathRef File,
+    llvm::unique_function<void(llvm::Expected<InputsAndPreamble>)> Action) {
+  auto It = Files.find(File);
+  if (It == Files.end()) {
+    Action(llvm::make_error<llvm::StringError>(
+        "trying to get preamble for non-added document",
+        llvm::errc::invalid_argument));
+    return;
+  }
+
+  if (!PreambleTasks) {
+    trace::Span Tracer(Name);
+    SPAN_ATTACH(Tracer, "file", File);
+    std::shared_ptr<const PreambleData> Preamble =
+        It->second->Worker->getPossiblyStalePreamble();
+    Action(InputsAndPreamble{It->second->Contents, It->second->Command,
+                             Preamble.get()});
+    return;
+  }
+
+  std::shared_ptr<const ASTWorker> Worker = It->second->Worker.lock();
+  auto Task = [Worker, this](std::string Name, std::string File,
+                             std::string Contents,
+                             tooling::CompileCommand Command, Context Ctx,
+                             decltype(Action) Action) mutable {
+    // We don't want to be running preamble actions before the preamble was
+    // built for the first time. This avoids extra work of processing the
+    // preamble headers in parallel multiple times.
+    Worker->waitForFirstPreamble();
+
+    std::lock_guard<Semaphore> BarrierLock(Barrier);
+    WithContext Guard(std::move(Ctx));
+    trace::Span Tracer(Name);
+    SPAN_ATTACH(Tracer, "file", File);
+    std::shared_ptr<const PreambleData> Preamble =
+        Worker->getPossiblyStalePreamble();
+    Action(InputsAndPreamble{Contents, Command, Preamble.get()});
+  };
+
+  PreambleTasks->runAsync("task:" + llvm::sys::path::filename(File),
+                          Bind(Task, std::string(Name), std::string(File),
+                               It->second->Contents, It->second->Command,
+                               Context::current().clone(), std::move(Action)));
+}
+
+std::vector<std::pair<Path, std::size_t>>
+TUScheduler::getUsedBytesPerFile() const {
+  std::vector<std::pair<Path, std::size_t>> Result;
+  Result.reserve(Files.size());
+  for (auto &&PathAndFile : Files)
+    Result.push_back(
+        {PathAndFile.first(), PathAndFile.second->Worker->getUsedBytes()});
+  return Result;
+}
+
+std::vector<Path> TUScheduler::getFilesWithCachedAST() const {
+  std::vector<Path> Result;
+  for (auto &&PathAndFile : Files) {
+    if (!PathAndFile.second->Worker->isASTCached())
+      continue;
+    Result.push_back(PathAndFile.first());
+  }
+  return Result;
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/TUScheduler.h b/src/third_party/llvm-project/clang-tools-extra/clangd/TUScheduler.h
new file mode 100644
index 0000000..af1ff36
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/TUScheduler.h
@@ -0,0 +1,141 @@
+//===--- TUScheduler.h -------------------------------------------*-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_TUSCHEDULER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_TUSCHEDULER_H
+
+#include "ClangdUnit.h"
+#include "Function.h"
+#include "Threading.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace clang {
+namespace clangd {
+
+/// Returns a number of a default async threads to use for TUScheduler.
+/// Returned value is always >= 1 (i.e. will not cause requests to be processed
+/// synchronously).
+unsigned getDefaultAsyncThreadsCount();
+
+struct InputsAndAST {
+  const ParseInputs &Inputs;
+  ParsedAST &AST;
+};
+
+struct InputsAndPreamble {
+  llvm::StringRef Contents;
+  const tooling::CompileCommand &Command;
+  const PreambleData *Preamble;
+};
+
+/// Determines whether diagnostics should be generated for a file snapshot.
+enum class WantDiagnostics {
+  Yes,  /// Diagnostics must be generated for this snapshot.
+  No,   /// Diagnostics must not be generated for this snapshot.
+  Auto, /// Diagnostics must be generated for this snapshot or a subsequent one,
+        /// within a bounded amount of time.
+};
+
+/// Configuration of the AST retention policy. This only covers retention of
+/// *idle* ASTs. If queue has operations requiring the AST, they might be
+/// kept in memory.
+struct ASTRetentionPolicy {
+  /// Maximum number of ASTs to be retained in memory when there are no pending
+  /// requests for them.
+  unsigned MaxRetainedASTs = 3;
+};
+
+/// Handles running tasks for ClangdServer and managing the resources (e.g.,
+/// preambles and ASTs) for opened files.
+/// TUScheduler is not thread-safe, only one thread should be providing updates
+/// and scheduling tasks.
+/// Callbacks are run on a threadpool and it's appropriate to do slow work in
+/// them. Each task has a name, used for tracing (should be UpperCamelCase).
+/// FIXME(sammccall): pull out a scheduler options struct.
+class TUScheduler {
+public:
+  TUScheduler(unsigned AsyncThreadsCount, bool StorePreamblesInMemory,
+              PreambleParsedCallback PreambleCallback,
+              std::chrono::steady_clock::duration UpdateDebounce,
+              ASTRetentionPolicy RetentionPolicy);
+  ~TUScheduler();
+
+  /// Returns estimated memory usage for each of the currently open files.
+  /// The order of results is unspecified.
+  std::vector<std::pair<Path, std::size_t>> getUsedBytesPerFile() const;
+
+  /// Returns a list of files with ASTs currently stored in memory. This method
+  /// is not very reliable and is only used for test. E.g., the results will not
+  /// contain files that currently run something over their AST.
+  std::vector<Path> getFilesWithCachedAST() const;
+
+  /// Schedule an update for \p File. Adds \p File to a list of tracked files if
+  /// \p File was not part of it before.
+  /// FIXME(ibiryukov): remove the callback from this function.
+  void update(PathRef File, ParseInputs Inputs, WantDiagnostics WD,
+              llvm::unique_function<void(std::vector<Diag>)> OnUpdated);
+
+  /// Remove \p File from the list of tracked files and schedule removal of its
+  /// resources.
+  void remove(PathRef File);
+
+  /// Schedule an async read of the AST. \p Action will be called when AST is
+  /// ready. The AST passed to \p Action refers to the version of \p File
+  /// tracked at the time of the call, even if new updates are received before
+  /// \p Action is executed.
+  /// If an error occurs during processing, it is forwarded to the \p Action
+  /// callback.
+  void runWithAST(llvm::StringRef Name, PathRef File,
+                  Callback<InputsAndAST> Action);
+
+  /// Schedule an async read of the Preamble.
+  /// The preamble may be stale, generated from an older version of the file.
+  /// Reading from locations in the preamble may cause the files to be re-read.
+  /// This gives callers two options:
+  /// - validate that the preamble is still valid, and only use it in this case
+  /// - accept that preamble contents may be outdated, and try to avoid reading
+  ///   source code from headers.
+  /// If there's no preamble yet (because the file was just opened), we'll wait
+  /// for it to build. The preamble may still be null if it fails to build or is
+  /// empty.
+  /// If an error occurs during processing, it is forwarded to the \p Action
+  /// callback.
+  void runWithPreamble(llvm::StringRef Name, PathRef File,
+                       Callback<InputsAndPreamble> Action);
+
+  /// Wait until there are no scheduled or running tasks.
+  /// Mostly useful for synchronizing tests.
+  bool blockUntilIdle(Deadline D) const;
+
+private:
+  /// This class stores per-file data in the Files map.
+  struct FileData;
+
+public:
+  /// Responsible for retaining and rebuilding idle ASTs. An implementation is
+  /// an LRU cache.
+  class ASTCache;
+
+private:
+  const bool StorePreamblesInMemory;
+  const std::shared_ptr<PCHContainerOperations> PCHOps;
+  const PreambleParsedCallback PreambleCallback;
+  Semaphore Barrier;
+  llvm::StringMap<std::unique_ptr<FileData>> Files;
+  std::unique_ptr<ASTCache> IdleASTs;
+  // None when running tasks synchronously and non-None when running tasks
+  // asynchronously.
+  llvm::Optional<AsyncTaskRunner> PreambleTasks;
+  llvm::Optional<AsyncTaskRunner> WorkerThreads;
+  std::chrono::steady_clock::duration UpdateDebounce;
+};
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Threading.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/Threading.cpp
new file mode 100644
index 0000000..aa9dd8f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Threading.cpp
@@ -0,0 +1,100 @@
+#include "Threading.h"
+#include "Trace.h"
+#include "llvm/ADT/ScopeExit.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Threading.h"
+#include <thread>
+
+namespace clang {
+namespace clangd {
+
+void Notification::notify() {
+  {
+    std::lock_guard<std::mutex> Lock(Mu);
+    Notified = true;
+  }
+  CV.notify_all();
+}
+
+void Notification::wait() const {
+  std::unique_lock<std::mutex> Lock(Mu);
+  CV.wait(Lock, [this] { return Notified; });
+}
+
+Semaphore::Semaphore(std::size_t MaxLocks) : FreeSlots(MaxLocks) {}
+
+void Semaphore::lock() {
+  trace::Span Span("WaitForFreeSemaphoreSlot");
+  // trace::Span can also acquire locks in ctor and dtor, we make sure it
+  // happens when Semaphore's own lock is not held.
+  {
+    std::unique_lock<std::mutex> Lock(Mutex);
+    SlotsChanged.wait(Lock, [&]() { return FreeSlots > 0; });
+    --FreeSlots;
+  }
+}
+
+void Semaphore::unlock() {
+  std::unique_lock<std::mutex> Lock(Mutex);
+  ++FreeSlots;
+  Lock.unlock();
+
+  SlotsChanged.notify_one();
+}
+
+AsyncTaskRunner::~AsyncTaskRunner() { wait(); }
+
+bool AsyncTaskRunner::wait(Deadline D) const {
+  std::unique_lock<std::mutex> Lock(Mutex);
+  return clangd::wait(Lock, TasksReachedZero, D,
+                      [&] { return InFlightTasks == 0; });
+}
+
+void AsyncTaskRunner::runAsync(const llvm::Twine &Name,
+                               llvm::unique_function<void()> Action) {
+  {
+    std::lock_guard<std::mutex> Lock(Mutex);
+    ++InFlightTasks;
+  }
+
+  auto CleanupTask = llvm::make_scope_exit([this]() {
+    std::lock_guard<std::mutex> Lock(Mutex);
+    int NewTasksCnt = --InFlightTasks;
+    if (NewTasksCnt == 0) {
+      // Note: we can't unlock here because we don't want the object to be
+      // destroyed before we notify.
+      TasksReachedZero.notify_one();
+    }
+  });
+
+  std::thread(
+      [](std::string Name, decltype(Action) Action, decltype(CleanupTask)) {
+        llvm::set_thread_name(Name);
+        Action();
+        // Make sure function stored by Action is destroyed before CleanupTask
+        // is run.
+        Action = nullptr;
+      },
+      Name.str(), std::move(Action), std::move(CleanupTask))
+      .detach();
+}
+
+Deadline timeoutSeconds(llvm::Optional<double> Seconds) {
+  using namespace std::chrono;
+  if (!Seconds)
+    return Deadline::infinity();
+  return steady_clock::now() +
+         duration_cast<steady_clock::duration>(duration<double>(*Seconds));
+}
+
+void wait(std::unique_lock<std::mutex> &Lock, std::condition_variable &CV,
+          Deadline D) {
+  if (D == Deadline::zero())
+    return;
+  if (D == Deadline::infinity())
+    return CV.wait(Lock);
+  CV.wait_until(Lock, D.time());
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Threading.h b/src/third_party/llvm-project/clang-tools-extra/clangd/Threading.h
new file mode 100644
index 0000000..6dad841
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Threading.h
@@ -0,0 +1,120 @@
+//===--- ThreadPool.h --------------------------------------------*- 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_THREADING_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_THREADING_H
+
+#include "Context.h"
+#include "Function.h"
+#include "llvm/ADT/Twine.h"
+#include <cassert>
+#include <condition_variable>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+namespace clang {
+namespace clangd {
+
+/// A threadsafe flag that is initially clear.
+class Notification {
+public:
+  // Sets the flag. No-op if already set.
+  void notify();
+  // Blocks until flag is set.
+  void wait() const;
+
+private:
+  bool Notified = false;
+  mutable std::condition_variable CV;
+  mutable std::mutex Mu;
+};
+
+/// Limits the number of threads that can acquire the lock at the same time.
+class Semaphore {
+public:
+  Semaphore(std::size_t MaxLocks);
+
+  void lock();
+  void unlock();
+
+private:
+  std::mutex Mutex;
+  std::condition_variable SlotsChanged;
+  std::size_t FreeSlots;
+};
+
+/// A point in time we can wait for.
+/// Can be zero (don't wait) or infinity (wait forever).
+/// (Not time_point::max(), because many std::chrono implementations overflow).
+class Deadline {
+public:
+  Deadline(std::chrono::steady_clock::time_point Time)
+      : Type(Finite), Time(Time) {}
+  static Deadline zero() { return Deadline(Zero); }
+  static Deadline infinity() { return Deadline(Infinite); }
+
+  std::chrono::steady_clock::time_point time() const {
+    assert(Type == Finite);
+    return Time;
+  }
+  bool expired() const {
+    return (Type == Zero) ||
+           (Type == Finite && Time < std::chrono::steady_clock::now());
+  }
+  bool operator==(const Deadline &Other) const {
+    return (Type == Other.Type) && (Type != Finite || Time == Other.Time);
+  }
+
+private:
+  enum Type { Zero, Infinite, Finite };
+
+  Deadline(enum Type Type) : Type(Type) {}
+  enum Type Type;
+  std::chrono::steady_clock::time_point Time;
+};
+
+/// Makes a deadline from a timeout in seconds. None means wait forever.
+Deadline timeoutSeconds(llvm::Optional<double> Seconds);
+/// Wait once on CV for the specified duration.
+void wait(std::unique_lock<std::mutex> &Lock, std::condition_variable &CV,
+          Deadline D);
+/// Waits on a condition variable until F() is true or D expires.
+template <typename Func>
+LLVM_NODISCARD bool wait(std::unique_lock<std::mutex> &Lock,
+                         std::condition_variable &CV, Deadline D, Func F) {
+  while (!F()) {
+    if (D.expired())
+      return false;
+    wait(Lock, CV, D);
+  }
+  return true;
+}
+
+/// Runs tasks on separate (detached) threads and wait for all tasks to finish.
+/// Objects that need to spawn threads can own an AsyncTaskRunner to ensure they
+/// all complete on destruction.
+class AsyncTaskRunner {
+public:
+  /// Destructor waits for all pending tasks to finish.
+  ~AsyncTaskRunner();
+
+  void wait() const { (void)wait(Deadline::infinity()); }
+  LLVM_NODISCARD bool wait(Deadline D) const;
+  // The name is used for tracing and debugging (e.g. to name a spawned thread).
+  void runAsync(const llvm::Twine &Name, llvm::unique_function<void()> Action);
+
+private:
+  mutable std::mutex Mutex;
+  mutable std::condition_variable TasksReachedZero;
+  std::size_t InFlightTasks = 0;
+};
+} // namespace clangd
+} // namespace clang
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Trace.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/Trace.cpp
new file mode 100644
index 0000000..24c1fdd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Trace.cpp
@@ -0,0 +1,233 @@
+//===--- Trace.cpp - Performance tracing facilities -----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Trace.h"
+#include "Context.h"
+#include "Function.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/ScopeExit.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/FormatProviders.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Threading.h"
+#include <atomic>
+#include <mutex>
+
+namespace clang {
+namespace clangd {
+namespace trace {
+using namespace llvm;
+
+namespace {
+// The current implementation is naive: each thread writes to Out guarded by Mu.
+// Perhaps we should replace this by something that disturbs performance less.
+class JSONTracer : public EventTracer {
+public:
+  JSONTracer(raw_ostream &Out, bool Pretty)
+      : Out(Out), Sep(""), Start(std::chrono::system_clock::now()),
+        JSONFormat(Pretty ? "{0:2}" : "{0}") {
+    // The displayTimeUnit must be ns to avoid low-precision overlap
+    // calculations!
+    Out << R"({"displayTimeUnit":"ns","traceEvents":[)"
+        << "\n";
+    rawEvent("M", json::Object{
+                      {"name", "process_name"},
+                      {"args", json::Object{{"name", "clangd"}}},
+                  });
+  }
+
+  ~JSONTracer() {
+    Out << "\n]}";
+    Out.flush();
+  }
+
+  // We stash a Span object in the context. It will record the start/end,
+  // and this also allows us to look up the parent Span's information.
+  Context beginSpan(llvm::StringRef Name, json::Object *Args) override {
+    return Context::current().derive(
+        SpanKey, llvm::make_unique<JSONSpan>(this, Name, Args));
+  }
+
+  // Trace viewer requires each thread to properly stack events.
+  // So we need to mark only duration that the span was active on the thread.
+  // (Hopefully any off-thread activity will be connected by a flow event).
+  // Record the end time here, but don't write the event: Args aren't ready yet.
+  void endSpan() override {
+    Context::current().getExisting(SpanKey)->markEnded();
+  }
+
+  void instant(llvm::StringRef Name, json::Object &&Args) override {
+    captureThreadMetadata();
+    jsonEvent("i", json::Object{{"name", Name}, {"args", std::move(Args)}});
+  }
+
+  // Record an event on the current thread. ph, pid, tid, ts are set.
+  // Contents must be a list of the other JSON key/values.
+  void jsonEvent(StringRef Phase, json::Object &&Contents,
+                 uint64_t TID = get_threadid(), double Timestamp = 0) {
+    Contents["ts"] = Timestamp ? Timestamp : timestamp();
+    Contents["tid"] = int64_t(TID);
+    std::lock_guard<std::mutex> Lock(Mu);
+    rawEvent(Phase, std::move(Contents));
+  }
+
+private:
+  class JSONSpan {
+  public:
+    JSONSpan(JSONTracer *Tracer, llvm::StringRef Name, json::Object *Args)
+        : StartTime(Tracer->timestamp()), EndTime(0), Name(Name),
+          TID(get_threadid()), Tracer(Tracer), Args(Args) {
+      // ~JSONSpan() may run in a different thread, so we need to capture now.
+      Tracer->captureThreadMetadata();
+
+      // We don't record begin events here (and end events in the destructor)
+      // because B/E pairs have to appear in the right order, which is awkward.
+      // Instead we send the complete (X) event in the destructor.
+
+      // If our parent was on a different thread, add an arrow to this span.
+      auto *Parent = Context::current().get(SpanKey);
+      if (Parent && *Parent && (*Parent)->TID != TID) {
+        // If the parent span ended already, then show this as "following" it.
+        // Otherwise show us as "parallel".
+        double OriginTime = (*Parent)->EndTime;
+        if (!OriginTime)
+          OriginTime = (*Parent)->StartTime;
+
+        auto FlowID = nextID();
+        Tracer->jsonEvent("s",
+                          json::Object{{"id", FlowID},
+                                       {"name", "Context crosses threads"},
+                                       {"cat", "dummy"}},
+                          (*Parent)->TID, (*Parent)->StartTime);
+        Tracer->jsonEvent("f",
+                          json::Object{{"id", FlowID},
+                                       {"bp", "e"},
+                                       {"name", "Context crosses threads"},
+                                       {"cat", "dummy"}},
+                          TID);
+      }
+    }
+
+    ~JSONSpan() {
+      // Finally, record the event (ending at EndTime, not timestamp())!
+      Tracer->jsonEvent("X",
+                        json::Object{{"name", std::move(Name)},
+                                     {"args", std::move(*Args)},
+                                     {"dur", EndTime - StartTime}},
+                        TID, StartTime);
+    }
+
+    // May be called by any thread.
+    void markEnded() {
+      EndTime = Tracer->timestamp();
+    }
+
+  private:
+    static int64_t nextID() {
+      static std::atomic<int64_t> Next = {0};
+      return Next++;
+    }
+
+    double StartTime;
+    std::atomic<double> EndTime; // Filled in by markEnded().
+    std::string Name;
+    uint64_t TID;
+    JSONTracer *Tracer;
+    json::Object *Args;
+  };
+  static Key<std::unique_ptr<JSONSpan>> SpanKey;
+
+  // Record an event. ph and pid are set.
+  // Contents must be a list of the other JSON key/values.
+  void rawEvent(StringRef Phase, json::Object &&Event) /*REQUIRES(Mu)*/ {
+    // PID 0 represents the clangd process.
+    Event["pid"] = 0;
+    Event["ph"] = Phase;
+    Out << Sep << formatv(JSONFormat, json::Value(std::move(Event)));
+    Sep = ",\n";
+  }
+
+  // If we haven't already, emit metadata describing this thread.
+  void captureThreadMetadata() {
+    uint64_t TID = get_threadid();
+    std::lock_guard<std::mutex> Lock(Mu);
+    if (ThreadsWithMD.insert(TID).second) {
+      SmallString<32> Name;
+      get_thread_name(Name);
+      if (!Name.empty()) {
+        rawEvent("M", json::Object{
+                          {"tid", int64_t(TID)},
+                          {"name", "thread_name"},
+                          {"args", json::Object{{"name", Name}}},
+                      });
+      }
+    }
+  }
+
+  double timestamp() {
+    using namespace std::chrono;
+    return duration<double, std::micro>(system_clock::now() - Start).count();
+  }
+
+  std::mutex Mu;
+  raw_ostream &Out /*GUARDED_BY(Mu)*/;
+  const char *Sep /*GUARDED_BY(Mu)*/;
+  DenseSet<uint64_t> ThreadsWithMD /*GUARDED_BY(Mu)*/;
+  const sys::TimePoint<> Start;
+  const char *JSONFormat;
+};
+
+Key<std::unique_ptr<JSONTracer::JSONSpan>> JSONTracer::SpanKey;
+
+EventTracer *T = nullptr;
+} // namespace
+
+Session::Session(EventTracer &Tracer) {
+  assert(!T && "Resetting global tracer is not allowed.");
+  T = &Tracer;
+}
+
+Session::~Session() { T = nullptr; }
+
+std::unique_ptr<EventTracer> createJSONTracer(llvm::raw_ostream &OS,
+                                              bool Pretty) {
+  return llvm::make_unique<JSONTracer>(OS, Pretty);
+}
+
+void log(const Twine &Message) {
+  if (!T)
+    return;
+  T->instant("Log", json::Object{{"Message", Message.str()}});
+}
+
+// Returned context owns Args.
+static Context makeSpanContext(llvm::Twine Name, json::Object *Args) {
+  if (!T)
+    return Context::current().clone();
+  WithContextValue WithArgs{std::unique_ptr<json::Object>(Args)};
+  return T->beginSpan(Name.isSingleStringRef() ? Name.getSingleStringRef()
+                                               : llvm::StringRef(Name.str()),
+                      Args);
+}
+
+// Span keeps a non-owning pointer to the args, which is how users access them.
+// The args are owned by the context though. They stick around until the
+// beginSpan() context is destroyed, when the tracing engine will consume them.
+Span::Span(llvm::Twine Name)
+    : Args(T ? new json::Object() : nullptr),
+      RestoreCtx(makeSpanContext(Name, Args)) {}
+
+Span::~Span() {
+  if (T)
+    T->endSpan();
+}
+
+} // namespace trace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/Trace.h b/src/third_party/llvm-project/clang-tools-extra/clangd/Trace.h
new file mode 100644
index 0000000..0c4c461
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/Trace.h
@@ -0,0 +1,108 @@
+//===--- Trace.h - Performance tracing facilities ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Supports writing performance traces describing clangd's behavior.
+// Traces are consumed by implementations of the EventTracer interface.
+//
+//
+// All APIs are no-ops unless a Session is active (created by ClangdMain).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_TRACE_H_
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_TRACE_H_
+
+#include "Context.h"
+#include "Function.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace clangd {
+namespace trace {
+
+/// A consumer of trace events. The events are produced by Spans and trace::log.
+/// Implmentations of this interface must be thread-safe.
+class EventTracer {
+public:
+  virtual ~EventTracer() = default;
+
+  /// Called when event that has a duration starts. \p Name describes the event.
+  /// Returns a derived context that will be destroyed when the event ends.
+  /// Usually implementations will store an object in the returned context
+  /// whose destructor records the end of the event.
+  /// The args are *Args, only complete when the event ends.
+  virtual Context beginSpan(llvm::StringRef Name, llvm::json::Object *Args) = 0;
+  // Called when a Span is destroyed (it may still be active on other threads).
+  // beginSpan() and endSpan() will always form a proper stack on each thread.
+  // The Context returned by beginSpan is active, but Args is not ready.
+  // Tracers should not override this unless they need to observe strict
+  // per-thread nesting. Instead they should observe context destruction.
+  virtual void endSpan(){};
+
+  /// Called for instant events.
+  virtual void instant(llvm::StringRef Name, llvm::json::Object &&Args) = 0;
+};
+
+/// Sets up a global EventTracer that consumes events produced by Span and
+/// trace::log. Only one TracingSession can be active at a time and it should be
+/// set up before calling any clangd-specific functions.
+class Session {
+public:
+  Session(EventTracer &Tracer);
+  ~Session();
+};
+
+/// Create an instance of EventTracer that produces an output in the Trace Event
+/// format supported by Chrome's trace viewer (chrome://tracing).
+///
+/// The format is documented here:
+/// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
+std::unique_ptr<EventTracer> createJSONTracer(llvm::raw_ostream &OS,
+                                              bool Pretty = false);
+
+/// Records a single instant event, associated with the current thread.
+void log(const llvm::Twine &Name);
+
+/// Records an event whose duration is the lifetime of the Span object.
+/// This lifetime is extended when the span's context is reused.
+///
+/// This is the main public interface for producing tracing events.
+///
+/// Arbitrary JSON metadata can be attached while this span is active:
+///   SPAN_ATTACH(MySpan, "Payload", SomeJSONExpr);
+///
+/// SomeJSONExpr is evaluated and copied only if actually needed.
+class Span {
+public:
+  Span(llvm::Twine Name);
+  ~Span();
+
+  /// Mutable metadata, if this span is interested.
+  /// Prefer to use SPAN_ATTACH rather than accessing this directly.
+  llvm::json::Object *const Args;
+
+private:
+  WithContext RestoreCtx;
+};
+
+/// Attach a key-value pair to a Span event.
+/// This is not threadsafe when used with the same Span.
+#define SPAN_ATTACH(S, Name, Expr)                                             \
+  do {                                                                         \
+    if (auto *Args = (S).Args)                                                 \
+      (*Args)[Name] = Expr;                                                    \
+  } while (0)
+
+} // namespace trace
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_TRACE_H_
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/URI.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/URI.cpp
new file mode 100644
index 0000000..a722640
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/URI.cpp
@@ -0,0 +1,207 @@
+//===---- URI.h - File URIs with schemes -------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "URI.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/Path.h"
+#include <iomanip>
+#include <sstream>
+
+LLVM_INSTANTIATE_REGISTRY(clang::clangd::URISchemeRegistry)
+
+namespace clang {
+namespace clangd {
+namespace {
+
+inline llvm::Error make_string_error(const llvm::Twine &Message) {
+  return llvm::make_error<llvm::StringError>(Message,
+                                             llvm::inconvertibleErrorCode());
+}
+
+/// \brief This manages file paths in the file system. All paths in the scheme
+/// are absolute (with leading '/').
+class FileSystemScheme : public URIScheme {
+public:
+  static const char *Scheme;
+
+  llvm::Expected<std::string>
+  getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body,
+                  llvm::StringRef /*HintPath*/) const override {
+    if (!Body.startswith("/"))
+      return make_string_error("File scheme: expect body to be an absolute "
+                               "path starting with '/': " +
+                               Body);
+    // For Windows paths e.g. /X:
+    if (Body.size() > 2 && Body[0] == '/' && Body[2] == ':')
+      Body.consume_front("/");
+    llvm::SmallVector<char, 16> Path(Body.begin(), Body.end());
+    llvm::sys::path::native(Path);
+    return std::string(Path.begin(), Path.end());
+  }
+
+  llvm::Expected<URI>
+  uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override {
+    using namespace llvm::sys;
+
+    std::string Body;
+    // For Windows paths e.g. X:
+    if (AbsolutePath.size() > 1 && AbsolutePath[1] == ':')
+      Body = "/";
+    Body += path::convert_to_slash(AbsolutePath);
+    return URI(Scheme, /*Authority=*/"", Body);
+  }
+};
+
+const char *FileSystemScheme::Scheme = "file";
+
+static URISchemeRegistry::Add<FileSystemScheme>
+    X(FileSystemScheme::Scheme,
+      "URI scheme for absolute paths in the file system.");
+
+llvm::Expected<std::unique_ptr<URIScheme>>
+findSchemeByName(llvm::StringRef Scheme) {
+  for (auto I = URISchemeRegistry::begin(), E = URISchemeRegistry::end();
+       I != E; ++I) {
+    if (I->getName() != Scheme)
+      continue;
+    return I->instantiate();
+  }
+  return make_string_error("Can't find scheme: " + Scheme);
+}
+
+bool shouldEscape(unsigned char C) {
+  // Unreserved characters.
+  if ((C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z') ||
+      (C >= '0' && C <= '9'))
+    return false;
+  switch (C) {
+  case '-':
+  case '_':
+  case '.':
+  case '~':
+  case '/': // '/' is only reserved when parsing.
+    return false;
+  }
+  return true;
+}
+
+/// Encodes a string according to percent-encoding.
+/// - Unreserved characters are not escaped.
+/// - Reserved characters always escaped with exceptions like '/'.
+/// - All other characters are escaped.
+std::string percentEncode(llvm::StringRef Content) {
+  std::string Result;
+  llvm::raw_string_ostream OS(Result);
+  for (unsigned char C : Content)
+    if (shouldEscape(C))
+      OS << '%' << llvm::format_hex_no_prefix(C, 2);
+    else
+      OS << C;
+
+  OS.flush();
+  return Result;
+}
+
+/// Decodes a string according to percent-encoding.
+std::string percentDecode(llvm::StringRef Content) {
+  std::string Result;
+  for (auto I = Content.begin(), E = Content.end(); I != E; ++I) {
+    if (*I != '%') {
+      Result += *I;
+      continue;
+    }
+    if (*I == '%' && I + 2 < Content.end() && llvm::isHexDigit(*(I + 1)) &&
+        llvm::isHexDigit(*(I + 2))) {
+      Result.push_back(llvm::hexFromNibbles(*(I + 1), *(I + 2)));
+      I += 2;
+    } else
+      Result.push_back(*I);
+  }
+  return Result;
+}
+
+} // namespace
+
+URI::URI(llvm::StringRef Scheme, llvm::StringRef Authority,
+         llvm::StringRef Body)
+    : Scheme(Scheme), Authority(Authority), Body(Body) {
+  assert(!Scheme.empty());
+  assert((Authority.empty() || Body.startswith("/")) &&
+         "URI body must start with '/' when authority is present.");
+}
+
+std::string URI::toString() const {
+  std::string Result;
+  llvm::raw_string_ostream OS(Result);
+  OS << percentEncode(Scheme) << ":";
+  if (Authority.empty() && Body.empty())
+    return OS.str();
+  // If authority if empty, we only print body if it starts with "/"; otherwise,
+  // the URI is invalid.
+  if (!Authority.empty() || llvm::StringRef(Body).startswith("/"))
+    OS << "//" << percentEncode(Authority);
+  OS << percentEncode(Body);
+  OS.flush();
+  return Result;
+}
+
+llvm::Expected<URI> URI::parse(llvm::StringRef OrigUri) {
+  URI U;
+  llvm::StringRef Uri = OrigUri;
+
+  auto Pos = Uri.find(':');
+  if (Pos == 0 || Pos == llvm::StringRef::npos)
+    return make_string_error("Scheme must be provided in URI: " + OrigUri);
+  U.Scheme = percentDecode(Uri.substr(0, Pos));
+  Uri = Uri.substr(Pos + 1);
+  if (Uri.consume_front("//")) {
+    Pos = Uri.find('/');
+    U.Authority = percentDecode(Uri.substr(0, Pos));
+    Uri = Uri.substr(Pos);
+  }
+  U.Body = percentDecode(Uri);
+  return U;
+}
+
+llvm::Expected<URI> URI::create(llvm::StringRef AbsolutePath,
+                                llvm::StringRef Scheme) {
+  if (!llvm::sys::path::is_absolute(AbsolutePath))
+    return make_string_error("Not a valid absolute path: " + AbsolutePath);
+  auto S = findSchemeByName(Scheme);
+  if (!S)
+    return S.takeError();
+  return S->get()->uriFromAbsolutePath(AbsolutePath);
+}
+
+URI URI::createFile(llvm::StringRef AbsolutePath) {
+  auto U = create(AbsolutePath, "file");
+  if (!U)
+    llvm_unreachable(llvm::toString(U.takeError()).c_str());
+  return std::move(*U);
+}
+
+llvm::Expected<std::string> URI::resolve(const URI &Uri,
+                                         llvm::StringRef HintPath) {
+  auto S = findSchemeByName(Uri.Scheme);
+  if (!S)
+    return S.takeError();
+  return S->get()->getAbsolutePath(Uri.Authority, Uri.Body, HintPath);
+}
+
+llvm::Expected<std::string> URI::includeSpelling(const URI &Uri) {
+  auto S = findSchemeByName(Uri.Scheme);
+  if (!S)
+    return S.takeError();
+  return S->get()->getIncludeSpelling(Uri);
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/URI.h b/src/third_party/llvm-project/clang-tools-extra/clangd/URI.h
new file mode 100644
index 0000000..112264f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/URI.h
@@ -0,0 +1,122 @@
+//===--- URI.h - File URIs with schemes --------------------------*- 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_PATHURI_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PATHURI_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Registry.h"
+
+namespace clang {
+namespace clangd {
+
+/// A URI describes the location of a source file.
+/// In the simplest case, this is a "file" URI that directly encodes the
+/// absolute path to a file. More abstract cases are possible: a shared index
+/// service might expose repo:// URIs that are relative to the source control
+/// root.
+///
+/// Clangd handles URIs of the form <scheme>:[//<authority>]<body>. It doesn't
+/// further split the authority or body into constituent parts (e.g. query
+/// strings is included in the body).
+class URI {
+public:
+  URI(llvm::StringRef Scheme, llvm::StringRef Authority, llvm::StringRef Body);
+
+  /// Returns decoded scheme e.g. "https"
+  llvm::StringRef scheme() const { return Scheme; }
+  /// Returns decoded authority e.g. "reviews.lvm.org"
+  llvm::StringRef authority() const { return Authority; }
+  /// Returns decoded body e.g. "/D41946"
+  llvm::StringRef body() const { return Body; }
+
+  /// Returns a string URI with all components percent-encoded.
+  std::string toString() const;
+
+  /// Creates a URI for a file in the given scheme. \p Scheme must be
+  /// registered. The URI is percent-encoded.
+  static llvm::Expected<URI> create(llvm::StringRef AbsolutePath,
+                                    llvm::StringRef Scheme);
+
+  /// This creates a file:// URI for \p AbsolutePath. The path must be absolute.
+  static URI createFile(llvm::StringRef AbsolutePath);
+
+  /// Parse a URI string "<scheme>:[//<authority>/]<path>". Percent-encoded
+  /// characters in the URI will be decoded.
+  static llvm::Expected<URI> parse(llvm::StringRef Uri);
+
+  /// Resolves the absolute path of \p U. If there is no matching scheme, or the
+  /// URI is invalid in the scheme, this returns an error.
+  ///
+  /// \p HintPath A related path, such as the current file or working directory,
+  /// which can help disambiguate when the same file exists in many workspaces.
+  static llvm::Expected<std::string> resolve(const URI &U,
+                                             llvm::StringRef HintPath = "");
+
+  /// Gets the preferred spelling of this file for #include, if there is one,
+  /// e.g. <system_header.h>, "path/to/x.h".
+  ///
+  /// This allows URI schemas to provide their customized include paths.
+  ///
+  /// Returns an empty string if normal include-shortening based on the absolute
+  /// path should be used.
+  /// Fails if the URI is not valid in the schema.
+  static llvm::Expected<std::string> includeSpelling(const URI &U);
+
+  friend bool operator==(const URI &LHS, const URI &RHS) {
+    return std::tie(LHS.Scheme, LHS.Authority, LHS.Body) ==
+           std::tie(RHS.Scheme, RHS.Authority, RHS.Body);
+  }
+
+  friend bool operator<(const URI &LHS, const URI &RHS) {
+    return std::tie(LHS.Scheme, LHS.Authority, LHS.Body) <
+           std::tie(RHS.Scheme, RHS.Authority, RHS.Body);
+  }
+
+private:
+  URI() = default;
+
+  std::string Scheme;
+  std::string Authority;
+  std::string Body;
+};
+
+/// URIScheme is an extension point for teaching clangd to recognize a custom
+/// URI scheme. This is expected to be implemented and exposed via the
+/// URISchemeRegistry.
+class URIScheme {
+public:
+  virtual ~URIScheme() = default;
+
+  /// Returns the absolute path of the file corresponding to the URI
+  /// authority+body in the file system. See URI::resolve for semantics of
+  /// \p HintPath.
+  virtual llvm::Expected<std::string>
+  getAbsolutePath(llvm::StringRef Authority, llvm::StringRef Body,
+                  llvm::StringRef HintPath) const = 0;
+
+  virtual llvm::Expected<URI>
+  uriFromAbsolutePath(llvm::StringRef AbsolutePath) const = 0;
+
+  /// Returns the include path of the file (e.g. <path>, "path"), which can be
+  /// #included directly. See URI::includeSpelling for details.
+  virtual llvm::Expected<std::string> getIncludeSpelling(const URI &U) const {
+    return ""; // no customized include path for this scheme.
+  }
+};
+
+/// By default, a "file" scheme is supported where URI paths are always absolute
+/// in the file system.
+typedef llvm::Registry<URIScheme> URISchemeRegistry;
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_PATHURI_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/XRefs.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/XRefs.cpp
new file mode 100644
index 0000000..99ccd21
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/XRefs.cpp
@@ -0,0 +1,673 @@
+//===--- XRefs.cpp ----------------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+#include "XRefs.h"
+#include "AST.h"
+#include "Logger.h"
+#include "SourceCode.h"
+#include "URI.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Index/IndexDataConsumer.h"
+#include "clang/Index/IndexingAction.h"
+#include "clang/Index/USRGeneration.h"
+#include "llvm/Support/Path.h"
+namespace clang {
+namespace clangd {
+using namespace llvm;
+namespace {
+
+// Get the definition from a given declaration `D`.
+// Return nullptr if no definition is found, or the declaration type of `D` is
+// not supported.
+const Decl *getDefinition(const Decl *D) {
+  assert(D);
+  if (const auto *TD = dyn_cast<TagDecl>(D))
+    return TD->getDefinition();
+  else if (const auto *VD = dyn_cast<VarDecl>(D))
+    return VD->getDefinition();
+  else if (const auto *FD = dyn_cast<FunctionDecl>(D))
+    return FD->getDefinition();
+  return nullptr;
+}
+
+// Convert a SymbolLocation to LSP's Location.
+// HintPath is used to resolve the path of URI.
+// FIXME: figure out a good home for it, and share the implementation with
+// FindSymbols.
+llvm::Optional<Location> toLSPLocation(const SymbolLocation &Loc,
+                                       llvm::StringRef HintPath) {
+  if (!Loc)
+    return llvm::None;
+  auto Uri = URI::parse(Loc.FileURI);
+  if (!Uri) {
+    log("Could not parse URI: {0}", Loc.FileURI);
+    return llvm::None;
+  }
+  auto Path = URI::resolve(*Uri, HintPath);
+  if (!Path) {
+    log("Could not resolve URI: {0}", Loc.FileURI);
+    return llvm::None;
+  }
+  Location LSPLoc;
+  LSPLoc.uri = URIForFile(*Path);
+  LSPLoc.range.start.line = Loc.Start.Line;
+  LSPLoc.range.start.character = Loc.Start.Column;
+  LSPLoc.range.end.line = Loc.End.Line;
+  LSPLoc.range.end.character = Loc.End.Column;
+  return LSPLoc;
+}
+
+struct MacroDecl {
+  StringRef Name;
+  const MacroInfo *Info;
+};
+
+/// Finds declarations locations that a given source location refers to.
+class DeclarationAndMacrosFinder : public index::IndexDataConsumer {
+  std::vector<const Decl *> Decls;
+  std::vector<MacroDecl> MacroInfos;
+  const SourceLocation &SearchedLocation;
+  const ASTContext &AST;
+  Preprocessor &PP;
+
+public:
+  DeclarationAndMacrosFinder(raw_ostream &OS,
+                             const SourceLocation &SearchedLocation,
+                             ASTContext &AST, Preprocessor &PP)
+      : SearchedLocation(SearchedLocation), AST(AST), PP(PP) {}
+
+  std::vector<const Decl *> takeDecls() {
+    // Don't keep the same declaration multiple times.
+    // This can happen when nodes in the AST are visited twice.
+    std::sort(Decls.begin(), Decls.end());
+    auto Last = std::unique(Decls.begin(), Decls.end());
+    Decls.erase(Last, Decls.end());
+    return std::move(Decls);
+  }
+
+  std::vector<MacroDecl> takeMacroInfos() {
+    // Don't keep the same Macro info multiple times.
+    std::sort(MacroInfos.begin(), MacroInfos.end(),
+              [](const MacroDecl &Left, const MacroDecl &Right) {
+                return Left.Info < Right.Info;
+              });
+
+    auto Last = std::unique(MacroInfos.begin(), MacroInfos.end(),
+                            [](const MacroDecl &Left, const MacroDecl &Right) {
+                              return Left.Info == Right.Info;
+                            });
+    MacroInfos.erase(Last, MacroInfos.end());
+    return std::move(MacroInfos);
+  }
+
+  bool
+  handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
+                      ArrayRef<index::SymbolRelation> Relations,
+                      SourceLocation Loc,
+                      index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
+    if (Loc == SearchedLocation) {
+      // Find and add definition declarations (for GoToDefinition).
+      // We don't use parameter `D`, as Parameter `D` is the canonical
+      // declaration, which is the first declaration of a redeclarable
+      // declaration, and it could be a forward declaration.
+      if (const auto *Def = getDefinition(D)) {
+        Decls.push_back(Def);
+      } else {
+        // Couldn't find a definition, fall back to use `D`.
+        Decls.push_back(D);
+      }
+    }
+    return true;
+  }
+
+private:
+  void finish() override {
+    // Also handle possible macro at the searched location.
+    Token Result;
+    auto &Mgr = AST.getSourceManager();
+    if (!Lexer::getRawToken(Mgr.getSpellingLoc(SearchedLocation), Result, Mgr,
+                            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 =
+            Mgr.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 = Mgr.getMacroArgExpandedLocation(
+            Mgr.getLocForStartOfFile(DecLoc.first)
+                .getLocWithOffset(DecLoc.second - 1));
+        MacroDefinition MacroDef =
+            PP.getMacroDefinitionAtLoc(IdentifierInfo, BeforeSearchedLocation);
+        MacroInfo *MacroInf = MacroDef.getMacroInfo();
+        if (MacroInf) {
+          MacroInfos.push_back(MacroDecl{IdentifierInfo->getName(), MacroInf});
+          assert(Decls.empty());
+        }
+      }
+    }
+  }
+};
+
+struct IdentifiedSymbol {
+  std::vector<const Decl *> Decls;
+  std::vector<MacroDecl> Macros;
+};
+
+IdentifiedSymbol getSymbolAtPosition(ParsedAST &AST, SourceLocation Pos) {
+  auto DeclMacrosFinder = DeclarationAndMacrosFinder(
+      llvm::errs(), Pos, AST.getASTContext(), AST.getPreprocessor());
+  index::IndexingOptions IndexOpts;
+  IndexOpts.SystemSymbolFilter =
+      index::IndexingOptions::SystemSymbolFilterKind::All;
+  IndexOpts.IndexFunctionLocals = true;
+  indexTopLevelDecls(AST.getASTContext(), AST.getLocalTopLevelDecls(),
+                     DeclMacrosFinder, IndexOpts);
+
+  return {DeclMacrosFinder.takeDecls(), DeclMacrosFinder.takeMacroInfos()};
+}
+
+llvm::Optional<Location>
+makeLocation(ParsedAST &AST, const SourceRange &ValSourceRange) {
+  const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
+  const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
+  SourceLocation LocStart = ValSourceRange.getBegin();
+
+  const FileEntry *F =
+      SourceMgr.getFileEntryForID(SourceMgr.getFileID(LocStart));
+  if (!F)
+    return llvm::None;
+  SourceLocation LocEnd = Lexer::getLocForEndOfToken(ValSourceRange.getEnd(), 0,
+                                                     SourceMgr, LangOpts);
+  Position Begin = sourceLocToPosition(SourceMgr, LocStart);
+  Position End = sourceLocToPosition(SourceMgr, LocEnd);
+  Range R = {Begin, End};
+  Location L;
+
+  auto FilePath = getAbsoluteFilePath(F, SourceMgr);
+  if (!FilePath) {
+    log("failed to get path!");
+    return llvm::None;
+  }
+  L.uri = URIForFile(*FilePath);
+  L.range = R;
+  return L;
+}
+
+// Get the symbol ID for a declaration, if possible.
+llvm::Optional<SymbolID> getSymbolID(const Decl *D) {
+  llvm::SmallString<128> USR;
+  if (index::generateUSRForDecl(D, USR)) {
+    return None;
+  }
+  return SymbolID(USR);
+}
+
+} // namespace
+
+std::vector<Location> findDefinitions(ParsedAST &AST, Position Pos,
+                                      const SymbolIndex *Index) {
+  const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
+
+  std::vector<Location> Result;
+  // Handle goto definition for #include.
+  for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) {
+    if (!Inc.Resolved.empty() && Inc.R.contains(Pos))
+      Result.push_back(Location{URIForFile{Inc.Resolved}, {}});
+  }
+  if (!Result.empty())
+    return Result;
+
+  // Identified symbols at a specific position.
+  SourceLocation SourceLocationBeg =
+      getBeginningOfIdentifier(AST, Pos, SourceMgr.getMainFileID());
+  auto Symbols = getSymbolAtPosition(AST, SourceLocationBeg);
+
+  for (auto Item : Symbols.Macros) {
+    auto Loc = Item.Info->getDefinitionLoc();
+    auto L = makeLocation(AST, SourceRange(Loc, Loc));
+    if (L)
+      Result.push_back(*L);
+  }
+
+  // Declaration and definition are different terms in C-family languages, and
+  // LSP only defines the "GoToDefinition" specification, so we try to perform
+  // the "most sensible" GoTo operation:
+  //
+  //  - We use the location from AST and index (if available) to provide the
+  //    final results. When there are duplicate results, we prefer AST over
+  //    index because AST is more up-to-date.
+  //
+  //  - For each symbol, we will return a location of the canonical declaration
+  //    (e.g. function declaration in header), and a location of definition if
+  //    they are available.
+  //
+  // So the work flow:
+  //
+  //   1. Identify the symbols being search for by traversing the AST.
+  //   2. Populate one of the locations with the AST location.
+  //   3. Use the AST information to query the index, and populate the index
+  //      location (if available).
+  //   4. Return all populated locations for all symbols, definition first (
+  //      which  we think is the users wants most often).
+  struct CandidateLocation {
+    llvm::Optional<Location> Def;
+    llvm::Optional<Location> Decl;
+  };
+  llvm::DenseMap<SymbolID, CandidateLocation> ResultCandidates;
+
+  // Emit all symbol locations (declaration or definition) from AST.
+  for (const auto *D : Symbols.Decls) {
+    // Fake key for symbols don't have USR (no SymbolID).
+    // Ideally, there should be a USR for each identified symbols. Symbols
+    // without USR are rare and unimportant cases, we use the a fake holder to
+    // minimize the invasiveness of these cases.
+    SymbolID Key("");
+    if (auto ID = getSymbolID(D))
+      Key = *ID;
+
+    auto &Candidate = ResultCandidates[Key];
+    auto Loc = findNameLoc(D);
+    auto L = makeLocation(AST, SourceRange(Loc, Loc));
+    // The declaration in the identified symbols is a definition if possible
+    // otherwise it is declaration.
+    bool IsDef = getDefinition(D) == D;
+    // Populate one of the slots with location for the AST.
+    if (!IsDef)
+      Candidate.Decl = L;
+    else
+      Candidate.Def = L;
+  }
+
+  if (Index) {
+    LookupRequest QueryRequest;
+    // Build request for index query, using SymbolID.
+    for (auto It : ResultCandidates)
+      QueryRequest.IDs.insert(It.first);
+    std::string HintPath;
+    const FileEntry *FE =
+        SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
+    if (auto Path = getAbsoluteFilePath(FE, SourceMgr))
+      HintPath = *Path;
+    // Query the index and populate the empty slot.
+    Index->lookup(
+        QueryRequest, [&HintPath, &ResultCandidates](const Symbol &Sym) {
+          auto It = ResultCandidates.find(Sym.ID);
+          assert(It != ResultCandidates.end());
+          auto &Value = It->second;
+
+          if (!Value.Def)
+            Value.Def = toLSPLocation(Sym.Definition, HintPath);
+          if (!Value.Decl)
+            Value.Decl = toLSPLocation(Sym.CanonicalDeclaration, HintPath);
+        });
+  }
+
+  // Populate the results, definition first.
+  for (auto It : ResultCandidates) {
+    const auto &Candidate = It.second;
+    if (Candidate.Def)
+      Result.push_back(*Candidate.Def);
+    if (Candidate.Decl &&
+        Candidate.Decl != Candidate.Def) // Decl and Def might be the same
+      Result.push_back(*Candidate.Decl);
+  }
+
+  return Result;
+}
+
+namespace {
+
+/// Finds document highlights that a given list of declarations refers to.
+class DocumentHighlightsFinder : public index::IndexDataConsumer {
+  std::vector<const Decl *> &Decls;
+  std::vector<DocumentHighlight> DocumentHighlights;
+  const ASTContext &AST;
+
+public:
+  DocumentHighlightsFinder(raw_ostream &OS, ASTContext &AST, Preprocessor &PP,
+                           std::vector<const Decl *> &Decls)
+      : Decls(Decls), AST(AST) {}
+  std::vector<DocumentHighlight> takeHighlights() {
+    // Don't keep the same highlight multiple times.
+    // This can happen when nodes in the AST are visited twice.
+    std::sort(DocumentHighlights.begin(), DocumentHighlights.end());
+    auto Last =
+        std::unique(DocumentHighlights.begin(), DocumentHighlights.end());
+    DocumentHighlights.erase(Last, DocumentHighlights.end());
+    return std::move(DocumentHighlights);
+  }
+
+  bool
+  handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
+                      ArrayRef<index::SymbolRelation> Relations,
+                      SourceLocation Loc,
+                      index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
+    const SourceManager &SourceMgr = AST.getSourceManager();
+    SourceLocation HighlightStartLoc = SourceMgr.getFileLoc(Loc);
+    if (SourceMgr.getMainFileID() != SourceMgr.getFileID(HighlightStartLoc) ||
+        std::find(Decls.begin(), Decls.end(), D) == Decls.end()) {
+      return true;
+    }
+    SourceLocation End;
+    const LangOptions &LangOpts = AST.getLangOpts();
+    End = Lexer::getLocForEndOfToken(HighlightStartLoc, 0, SourceMgr, LangOpts);
+    SourceRange SR(HighlightStartLoc, End);
+
+    DocumentHighlightKind Kind = DocumentHighlightKind::Text;
+    if (static_cast<index::SymbolRoleSet>(index::SymbolRole::Write) & Roles)
+      Kind = DocumentHighlightKind::Write;
+    else if (static_cast<index::SymbolRoleSet>(index::SymbolRole::Read) & Roles)
+      Kind = DocumentHighlightKind::Read;
+
+    DocumentHighlights.push_back(getDocumentHighlight(SR, Kind));
+    return true;
+  }
+
+private:
+  DocumentHighlight getDocumentHighlight(SourceRange SR,
+                                         DocumentHighlightKind Kind) {
+    const SourceManager &SourceMgr = AST.getSourceManager();
+    Position Begin = sourceLocToPosition(SourceMgr, SR.getBegin());
+    Position End = sourceLocToPosition(SourceMgr, SR.getEnd());
+    Range R = {Begin, End};
+    DocumentHighlight DH;
+    DH.range = R;
+    DH.kind = Kind;
+    return DH;
+  }
+};
+
+} // namespace
+
+std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST,
+                                                      Position Pos) {
+  const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
+  SourceLocation SourceLocationBeg =
+      getBeginningOfIdentifier(AST, Pos, SourceMgr.getMainFileID());
+
+  auto Symbols = getSymbolAtPosition(AST, SourceLocationBeg);
+  std::vector<const Decl *> SelectedDecls = Symbols.Decls;
+
+  DocumentHighlightsFinder DocHighlightsFinder(
+      llvm::errs(), AST.getASTContext(), AST.getPreprocessor(), SelectedDecls);
+
+  index::IndexingOptions IndexOpts;
+  IndexOpts.SystemSymbolFilter =
+      index::IndexingOptions::SystemSymbolFilterKind::All;
+  IndexOpts.IndexFunctionLocals = true;
+  indexTopLevelDecls(AST.getASTContext(), AST.getLocalTopLevelDecls(),
+                     DocHighlightsFinder, IndexOpts);
+
+  return DocHighlightsFinder.takeHighlights();
+}
+
+static PrintingPolicy printingPolicyForDecls(PrintingPolicy Base) {
+  PrintingPolicy Policy(Base);
+
+  Policy.AnonymousTagLocations = false;
+  Policy.TerseOutput = true;
+  Policy.PolishForDeclaration = true;
+  Policy.ConstantsAsWritten = true;
+  Policy.SuppressTagKeyword = false;
+
+  return Policy;
+}
+
+/// Return a string representation (e.g. "class MyNamespace::MyClass") of
+/// the type declaration \p TD.
+static std::string typeDeclToString(const TypeDecl *TD) {
+  QualType Type = TD->getASTContext().getTypeDeclType(TD);
+
+  PrintingPolicy Policy =
+      printingPolicyForDecls(TD->getASTContext().getPrintingPolicy());
+
+  std::string Name;
+  llvm::raw_string_ostream Stream(Name);
+  Type.print(Stream, Policy);
+
+  return Stream.str();
+}
+
+/// Return a string representation (e.g. "namespace ns1::ns2") of
+/// the named declaration \p ND.
+static std::string namedDeclQualifiedName(const NamedDecl *ND,
+                                          StringRef Prefix) {
+  PrintingPolicy Policy =
+      printingPolicyForDecls(ND->getASTContext().getPrintingPolicy());
+
+  std::string Name;
+  llvm::raw_string_ostream Stream(Name);
+  Stream << Prefix << ' ';
+  ND->printQualifiedName(Stream, Policy);
+
+  return Stream.str();
+}
+
+/// Given a declaration \p D, return a human-readable string representing the
+/// scope in which it is declared.  If the declaration is in the global scope,
+/// return the string "global namespace".
+static llvm::Optional<std::string> getScopeName(const Decl *D) {
+  const DeclContext *DC = D->getDeclContext();
+
+  if (isa<TranslationUnitDecl>(DC))
+    return std::string("global namespace");
+  if (const TypeDecl *TD = dyn_cast<TypeDecl>(DC))
+    return typeDeclToString(TD);
+  else if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC))
+    return namedDeclQualifiedName(ND, "namespace");
+  else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
+    return namedDeclQualifiedName(FD, "function");
+
+  return llvm::None;
+}
+
+/// Generate a \p Hover object given the declaration \p D.
+static Hover getHoverContents(const Decl *D) {
+  Hover H;
+  llvm::Optional<std::string> NamedScope = getScopeName(D);
+
+  // Generate the "Declared in" section.
+  if (NamedScope) {
+    assert(!NamedScope->empty());
+
+    H.contents.value += "Declared in ";
+    H.contents.value += *NamedScope;
+    H.contents.value += "\n\n";
+  }
+
+  // We want to include the template in the Hover.
+  if (TemplateDecl *TD = D->getDescribedTemplate())
+    D = TD;
+
+  std::string DeclText;
+  llvm::raw_string_ostream OS(DeclText);
+
+  PrintingPolicy Policy =
+      printingPolicyForDecls(D->getASTContext().getPrintingPolicy());
+
+  D->print(OS, Policy);
+
+  OS.flush();
+
+  H.contents.value += DeclText;
+  return H;
+}
+
+/// Generate a \p Hover object given the type \p T.
+static Hover getHoverContents(QualType T, ASTContext &ASTCtx) {
+  Hover H;
+  std::string TypeText;
+  llvm::raw_string_ostream OS(TypeText);
+  PrintingPolicy Policy = printingPolicyForDecls(ASTCtx.getPrintingPolicy());
+  T.print(OS, Policy);
+  OS.flush();
+  H.contents.value += TypeText;
+  return H;
+}
+
+/// Generate a \p Hover object given the macro \p MacroInf.
+static Hover getHoverContents(StringRef MacroName) {
+  Hover H;
+
+  H.contents.value = "#define ";
+  H.contents.value += MacroName;
+
+  return H;
+}
+
+namespace {
+/// Computes the deduced type at a given location by visiting the relevant
+/// nodes. We use this to display the actual type when hovering over an "auto"
+/// keyword or "decltype()" expression.
+/// FIXME: This could have been a lot simpler by visiting AutoTypeLocs but it
+/// seems that the AutoTypeLocs that can be visited along with their AutoType do
+/// not have the deduced type set. Instead, we have to go to the appropriate
+/// DeclaratorDecl/FunctionDecl and work our back to the AutoType that does have
+/// a deduced type set. The AST should be improved to simplify this scenario.
+class DeducedTypeVisitor : public RecursiveASTVisitor<DeducedTypeVisitor> {
+  SourceLocation SearchedLocation;
+  llvm::Optional<QualType> DeducedType;
+
+public:
+  DeducedTypeVisitor(SourceLocation SearchedLocation)
+      : SearchedLocation(SearchedLocation) {}
+
+  llvm::Optional<QualType> getDeducedType() { return DeducedType; }
+
+  // Handle auto initializers:
+  //- auto i = 1;
+  //- decltype(auto) i = 1;
+  //- auto& i = 1;
+  bool VisitDeclaratorDecl(DeclaratorDecl *D) {
+    if (!D->getTypeSourceInfo() ||
+        D->getTypeSourceInfo()->getTypeLoc().getLocStart() != SearchedLocation)
+      return true;
+
+    auto DeclT = D->getType();
+    // "auto &" is represented as a ReferenceType containing an AutoType
+    if (const ReferenceType *RT = dyn_cast<ReferenceType>(DeclT.getTypePtr()))
+      DeclT = RT->getPointeeType();
+
+    const AutoType *AT = dyn_cast<AutoType>(DeclT.getTypePtr());
+    if (AT && !AT->getDeducedType().isNull()) {
+      // For auto, use the underlying type because the const& would be
+      // represented twice: written in the code and in the hover.
+      // Example: "const auto I = 1", we only want "int" when hovering on auto,
+      // not "const int".
+      //
+      // For decltype(auto), take the type as is because it cannot be written
+      // with qualifiers or references but its decuded type can be const-ref.
+      DeducedType = AT->isDecltypeAuto() ? DeclT : DeclT.getUnqualifiedType();
+    }
+    return true;
+  }
+
+  // Handle auto return types:
+  //- auto foo() {}
+  //- auto& foo() {}
+  //- auto foo() -> decltype(1+1) {}
+  //- operator auto() const { return 10; }
+  bool VisitFunctionDecl(FunctionDecl *D) {
+    if (!D->getTypeSourceInfo())
+      return true;
+    // Loc of auto in return type (c++14).
+    auto CurLoc = D->getReturnTypeSourceRange().getBegin();
+    // Loc of "auto" in operator auto()
+    if (CurLoc.isInvalid() && dyn_cast<CXXConversionDecl>(D))
+      CurLoc = D->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
+    // Loc of "auto" in function with traling return type (c++11).
+    if (CurLoc.isInvalid())
+      CurLoc = D->getSourceRange().getBegin();
+    if (CurLoc != SearchedLocation)
+      return true;
+
+    auto T = D->getReturnType();
+    // "auto &" is represented as a ReferenceType containing an AutoType.
+    if (const ReferenceType *RT = dyn_cast<ReferenceType>(T.getTypePtr()))
+      T = RT->getPointeeType();
+
+    const AutoType *AT = dyn_cast<AutoType>(T.getTypePtr());
+    if (AT && !AT->getDeducedType().isNull()) {
+      DeducedType = T.getUnqualifiedType();
+    } else { // auto in a trailing return type just points to a DecltypeType.
+      const DecltypeType *DT = dyn_cast<DecltypeType>(T.getTypePtr());
+      if (!DT->getUnderlyingType().isNull())
+        DeducedType = DT->getUnderlyingType();
+    }
+    return true;
+  }
+
+  // Handle non-auto decltype, e.g.:
+  // - auto foo() -> decltype(expr) {}
+  // - decltype(expr);
+  bool VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
+    if (TL.getBeginLoc() != SearchedLocation)
+      return true;
+
+    // A DecltypeType's underlying type can be another DecltypeType! E.g.
+    //  int I = 0;
+    //  decltype(I) J = I;
+    //  decltype(J) K = J;
+    const DecltypeType *DT = dyn_cast<DecltypeType>(TL.getTypePtr());
+    while (DT && !DT->getUnderlyingType().isNull()) {
+      DeducedType = DT->getUnderlyingType();
+      DT = dyn_cast<DecltypeType>(DeducedType->getTypePtr());
+    }
+    return true;
+  }
+};
+} // namespace
+
+/// Retrieves the deduced type at a given location (auto, decltype).
+llvm::Optional<QualType> getDeducedType(ParsedAST &AST,
+                                        SourceLocation SourceLocationBeg) {
+  Token Tok;
+  auto &ASTCtx = AST.getASTContext();
+  // Only try to find a deduced type if the token is auto or decltype.
+  if (!SourceLocationBeg.isValid() ||
+      Lexer::getRawToken(SourceLocationBeg, Tok, ASTCtx.getSourceManager(),
+                         ASTCtx.getLangOpts(), false) ||
+      !Tok.is(tok::raw_identifier)) {
+    return {};
+  }
+  AST.getPreprocessor().LookUpIdentifierInfo(Tok);
+  if (!(Tok.is(tok::kw_auto) || Tok.is(tok::kw_decltype)))
+    return {};
+
+  DeducedTypeVisitor V(SourceLocationBeg);
+  for (Decl *D : AST.getLocalTopLevelDecls())
+    V.TraverseDecl(D);
+  return V.getDeducedType();
+}
+
+Optional<Hover> getHover(ParsedAST &AST, Position Pos) {
+  const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
+  SourceLocation SourceLocationBeg =
+      getBeginningOfIdentifier(AST, Pos, SourceMgr.getMainFileID());
+  // Identified symbols at a specific position.
+  auto Symbols = getSymbolAtPosition(AST, SourceLocationBeg);
+
+  if (!Symbols.Macros.empty())
+    return getHoverContents(Symbols.Macros[0].Name);
+
+  if (!Symbols.Decls.empty())
+    return getHoverContents(Symbols.Decls[0]);
+
+  auto DeducedType = getDeducedType(AST, SourceLocationBeg);
+  if (DeducedType && !DeducedType->isNull())
+    return getHoverContents(*DeducedType, AST.getASTContext());
+
+  return None;
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/XRefs.h b/src/third_party/llvm-project/clang-tools-extra/clangd/XRefs.h
new file mode 100644
index 0000000..d698a61
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/XRefs.h
@@ -0,0 +1,38 @@
+//===--- XRefs.h ------------------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// Features that traverse references between symbols.
+//
+//===---------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_XREFS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_XREFS_H
+
+#include "ClangdUnit.h"
+#include "Protocol.h"
+#include "index/Index.h"
+#include "llvm/ADT/Optional.h"
+#include <vector>
+
+namespace clang {
+namespace clangd {
+
+/// Get definition of symbol at a specified \p Pos.
+std::vector<Location> findDefinitions(ParsedAST &AST, Position Pos,
+                                      const SymbolIndex *Index = nullptr);
+
+/// Returns highlights for all usages of a symbol at \p Pos.
+std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST,
+                                                      Position Pos);
+
+/// Get the hover information when hovering at \p Pos.
+llvm::Optional<Hover> getHover(ParsedAST &AST, Position Pos);
+
+} // namespace clangd
+} // namespace clang
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/launch.json b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/launch.json
new file mode 100644
index 0000000..cd6b87b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/launch.json
@@ -0,0 +1,28 @@
+// A launch configuration that compiles the extension and then opens it inside a new window
+{
+    "version": "0.1.0",
+    "configurations": [
+        {
+            "name": "Launch Extension",
+            "type": "extensionHost",
+            "request": "launch",
+            "runtimeExecutable": "${execPath}",
+            "args": ["--extensionDevelopmentPath=${workspaceRoot}" ],
+            "stopOnEntry": false,
+            "sourceMaps": true,
+            "outFiles": [ "${workspaceRoot}/out/src/**/*.js" ],
+            "preLaunchTask": "npm"
+        },
+        {
+            "name": "Launch Tests",
+            "type": "extensionHost",
+            "request": "launch",
+            "runtimeExecutable": "${execPath}",
+            "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ],
+            "stopOnEntry": false,
+            "sourceMaps": true,
+            "outFiles": [ "${workspaceRoot}/out/test/**/*.js" ],
+            "preLaunchTask": "npm"
+        }
+    ]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/settings.json b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/settings.json
new file mode 100644
index 0000000..d137133
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/settings.json
@@ -0,0 +1,9 @@
+// Place your settings in this file to overwrite default and user settings.
+{
+    "files.exclude": {
+        "out": false // set this to true to hide the "out" folder with the compiled JS files
+    },
+    "search.exclude": {
+        "out": true // set this to false to include "out" folder in search results
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/tasks.json b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/tasks.json
new file mode 100644
index 0000000..fb7f662
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/tasks.json
@@ -0,0 +1,30 @@
+// Available variables which can be used inside of strings.
+// ${workspaceRoot}: the root folder of the team
+// ${file}: the current opened file
+// ${fileBasename}: the current opened file's basename
+// ${fileDirname}: the current opened file's dirname
+// ${fileExtname}: the current opened file's extension
+// ${cwd}: the current working directory of the spawned process
+
+// A task runner that calls a custom npm script that compiles the extension.
+{
+    "version": "0.1.0",
+
+    // we want to run npm
+    "command": "npm",
+
+    // the command is a shell script
+    "isShellCommand": true,
+
+    // show the output window only if unrecognized errors occur.
+    "showOutput": "silent",
+
+    // we run the custom script "compile" as defined in package.json
+    "args": ["run", "compile", "--loglevel", "silent"],
+
+    // The tsc compiler is started in watching mode
+    "isWatching": true,
+
+    // use the standard tsc in watch mode problem matcher to find compile problems in the output.
+    "problemMatcher": "$tsc-watch"
+}
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.vscodeignore b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.vscodeignore
new file mode 100644
index 0000000..5ff3c19
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.vscodeignore
@@ -0,0 +1,9 @@
+.vscode/**
+.vscode-test/**
+out/test/**
+test/**
+src/**
+**/*.map
+.gitignore
+tsconfig.json
+vsc-extension-quickstart.md
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/LICENSE b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/LICENSE
new file mode 100644
index 0000000..c558158
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2017 The LLVM Developers
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/README.md b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/README.md
new file mode 100644
index 0000000..f950cb6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/README.md
@@ -0,0 +1,76 @@
+# vscode-clangd
+
+Provides C/C++ language IDE features for VS Code using [clangd](https://clang.llvm.org/extra/clangd.html).
+
+## Usage
+
+`vscode-clangd` provides the features designated by the [Language Server
+Protocol](https://github.com/Microsoft/language-server-protocol), such as
+code completion, code formatting and goto definition.
+
+**Note**: `clangd` is under heavy development, not all LSP features are
+implemented. See [Current Status](https://clang.llvm.org/extra/clangd.html#current-status)
+for details.
+
+To use `vscode-clangd` extension in VS Code, you need to install `vscode-clangd`
+from VS Code extension marketplace.
+
+`vscode-clangd` will attempt to find the `clangd` binary on your `PATH`.
+Alternatively, the `clangd` executable can be specified in your VS Code
+`settings.json` file:
+
+```json
+{
+    "clangd.path": "/absolute/path/to/clangd"
+}
+```
+
+To obtain `clangd` binary, please see the [installing Clangd](https://clang.llvm.org/extra/clangd.html#installing-clangd).
+
+## Development
+
+A guide of developing `vscode-clangd` extension.
+
+### Requirements
+
+* VS Code
+* node.js and npm
+
+### Steps
+
+1. Make sure you disable the installed `vscode-clangd` extension in VS Code.
+2. Make sure you have clangd in /usr/bin/clangd or edit src/extension.ts to
+point to the binary.
+3. In order to start a development instance of VS code extended with this, run:
+
+```bash
+   $ cd /path/to/clang-tools-extra/clangd/clients/clangd-vscode/
+   $ npm install
+   $ code .
+   # When VS Code starts, press <F5>.
+```
+
+## Publish to VS Code Marketplace
+
+New changes to `clangd-vscode` are not released until a new version is published
+to the marketplace.
+
+### Requirements
+
+* Make sure install the `vsce` command (`npm install -g vsce`)
+* `llvm-vs-code-extensions` account
+* Bump the version in `package.json`, and commit the change to upstream
+
+The extension is published under `llvm-vs-code-extensions` account, which is
+currently maintained by clangd developers. If you want to make a new release,
+please contact cfe-dev@lists.llvm.org.
+
+### Steps
+
+```bash
+  $ cd /path/to/clang-tools-extra/clangd/clients/clangd-vscode/
+  # For the first time, you need to login in the account. vsce will ask you for
+    the Personal Access Token, and remember it for future commands.
+  $ vsce login llvm-vs-code-extensions
+  $ vsce publish
+```
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/package.json b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/package.json
new file mode 100644
index 0000000..eeb5112
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/package.json
@@ -0,0 +1,79 @@
+{
+    "name": "vscode-clangd",
+    "displayName": "vscode-clangd",
+    "description": "Clang Language Server",
+    "version": "0.0.6",
+    "publisher": "llvm-vs-code-extensions",
+    "homepage": "https://clang.llvm.org/extra/clangd.html",
+    "engines": {
+        "vscode": "^1.18.0"
+    },
+    "categories": [
+        "Programming Languages",
+        "Linters",
+        "Snippets"
+    ],
+    "keywords": [
+        "C",
+        "C++",
+        "LSP",
+        "Clangd",
+        "LLVM"
+    ],
+    "activationEvents": [
+        "onLanguage:cpp",
+        "onLanguage:c"
+    ],
+    "main": "./out/src/extension",
+    "scripts": {
+        "vscode:prepublish": "tsc -p ./",
+        "compile": "tsc -watch -p ./",
+        "postinstall": "node ./node_modules/vscode/bin/install",
+        "test": "node ./node_modules/vscode/bin/test"
+    },
+    "dependencies": {
+        "vscode-languageclient": "^4.0.0",
+        "vscode-languageserver": "^4.0.0"
+    },
+    "devDependencies": {
+        "typescript": "^2.0.3",
+        "vscode": "^1.1.0",
+        "mocha": "^2.3.3",
+        "@types/node": "^6.0.40",
+        "@types/mocha": "^2.2.32"
+    },
+    "repository": {
+        "type": "svn",
+        "url": "http://llvm.org/svn/llvm-project/clang-tools-extra/trunk/clangd/clients/clangd-vscode/"
+    },
+    "contributes": {
+        "configuration": {
+            "type": "object",
+            "title": "clangd configuration",
+            "properties": {
+                "clangd.path": {
+                    "type": "string",
+                    "default": "clangd",
+                    "description": "The path to clangd executable, e.g.: /usr/bin/clangd"
+                },
+                "clangd.arguments": {
+                    "type": "array",
+                    "default": [],
+                    "items": {
+                        "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."
+                },
+                "clangd.trace": {
+                    "type": "string",
+                    "description": "Names a file that clangd should log a performance trace to, in chrome trace-viewer JSON format."
+                }
+            }
+        }
+    }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts
new file mode 100644
index 0000000..a126a19
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts
@@ -0,0 +1,58 @@
+import * as vscode from 'vscode';
+import * as vscodelc from 'vscode-languageclient';
+import { realpathSync } from 'fs';
+
+/**
+ * Method to get workspace configuration option
+ * @param option name of the option (e.g. for clangd.path should be path)
+ * @param defaultValue default value to return if option is not set
+ */
+function getConfig<T>(option: string, defaultValue?: any): T {
+    const config = vscode.workspace.getConfiguration('clangd');
+    return config.get<T>(option, defaultValue);
+}
+
+/**
+ *  this method is called when your extension is activate
+ *  your extension is activated the very first time the command is executed
+ */
+export function activate(context: vscode.ExtensionContext) {
+    const syncFileEvents = getConfig<boolean>('syncFileEvents', true);
+
+    const clangd: vscodelc.Executable = {
+        command: getConfig<string>('path'),
+        args: getConfig<string[]>('arguments')
+    };
+    const traceFile = getConfig<string>('trace');
+    if (!!traceFile) {
+        const trace = { CLANGD_TRACE: traceFile };
+        clangd.options = { env: { ...process.env, ...trace } };
+    }
+    const serverOptions: vscodelc.ServerOptions = clangd;
+
+    const filePattern: string = '**/*.{' +
+        ['cpp', 'c', 'cc', 'cxx', 'c++', 'm', 'mm', 'h', 'hh', 'hpp', 'hxx', 'inc'].join() + '}';
+    const clientOptions: vscodelc.LanguageClientOptions = {
+        // Register the server for C/C++ files
+        documentSelector: [{ scheme: 'file', pattern: filePattern }],
+        synchronize: !syncFileEvents ? undefined : {
+            fileEvents: vscode.workspace.createFileSystemWatcher(filePattern)
+        },
+        // Resolve symlinks for all files provided by clangd.
+        // This is a workaround for a bazel + clangd issue - bazel produces a symlink tree to build in,
+        // and when navigating to the included file, clangd passes its path inside the symlink tree
+        // rather than its filesystem path.
+        // FIXME: remove this once clangd knows enough about bazel to resolve the
+        // symlinks where needed (or if this causes problems for other workflows).
+        uriConverters: {
+            code2Protocol: (value: vscode.Uri) => value.toString(),
+            protocol2Code: (value: string) =>
+                vscode.Uri.file(realpathSync(vscode.Uri.parse(value).fsPath))
+        }
+    };
+
+    const clangdClient = new vscodelc.LanguageClient('Clang Language Server', serverOptions, clientOptions);
+    console.log('Clang Language Server is now active!');
+
+    const disposable = clangdClient.start();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/test/extension.test.ts b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/test/extension.test.ts
new file mode 100644
index 0000000..de4e068
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/test/extension.test.ts
@@ -0,0 +1,15 @@
+/** The module 'assert' provides assertion methods from node */
+import * as assert from 'assert';
+
+import * as vscode from 'vscode';
+import * as myExtension from '../src/extension';
+
+// TODO: add tests
+suite("Extension Tests", () => {
+
+    // Defines a Mocha unit test
+    test("Something 1", () => {
+        assert.equal(-1, [1, 2, 3].indexOf(5));
+        assert.equal(-1, [1, 2, 3].indexOf(0));
+    });
+});
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/test/index.ts b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/test/index.ts
new file mode 100644
index 0000000..50bae45
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/test/index.ts
@@ -0,0 +1,22 @@
+//
+// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
+//
+// This file is providing the test runner to use when running extension tests.
+// By default the test runner in use is Mocha based.
+//
+// You can provide your own test runner if you want to override it by exporting
+// a function run(testRoot: string, clb: (error:Error) => void) that the extension
+// host can call to run the tests. The test runner is expected to use console.log
+// to report the results back to the caller. When the tests are finished, return
+// a possible error to the callback or null if none.
+
+var testRunner = require('vscode/lib/testrunner');
+
+// You can directly control Mocha options by uncommenting the following lines
+// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
+testRunner.configure({
+    ui: 'tdd', 		// the TDD UI is being used in extension.test.ts (suite, test, etc.)
+    useColors: true // colored output from test results
+});
+
+module.exports = testRunner;
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/tsconfig.json b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/tsconfig.json
new file mode 100644
index 0000000..0b05f30
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/tsconfig.json
@@ -0,0 +1,29 @@
+{
+    "compilerOptions": {
+        "module": "commonjs",
+        "target": "es6",
+        "outDir": "out",
+        "lib": [
+            "es6",
+            "es2015.core",
+            "es2015.collection",
+            "es2015.generator",
+            "es2015.iterable",
+            "es2015.promise",
+            "es2015.symbol",
+            "es2016.array.include"
+        ],
+        "sourceMap": true,
+        "rootDir": ".",
+        "alwaysStrict": true,
+        "noEmitOnError": true,
+        "noFallthroughCasesInSwitch": true,
+        "noImplicitAny": true,
+        "noImplicitReturns": true,
+        "noImplicitThis": true
+    },
+    "exclude": [
+        "node_modules",
+        ".vscode-test"
+    ]
+}
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/vsc-extension-quickstart.md b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/vsc-extension-quickstart.md
new file mode 100644
index 0000000..24675ec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/vsc-extension-quickstart.md
@@ -0,0 +1,33 @@
+# Toy VS Code Extension for clangd
+
+## What's in the folder
+* This folder contains all of the files necessary for your extension
+* `package.json` - this is the manifest file in which you declare your extension and command.
+The sample plugin registers a command and defines its title and command name. With this information
+VS Code can show the command in the command palette. It doesn’t yet need to load the plugin.
+* `src/extension.ts` - this is the main file where you will provide the implementation of your command.
+The file exports one function, `activate`, which is called the very first time your extension is
+activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`.
+We pass the function containing the implementation of the command as the second parameter to
+`registerCommand`.
+
+## Get up and running straight away
+* press `F5` to open a new window with your extension loaded
+* run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`
+* set breakpoints in your code inside `src/extension.ts` to debug your extension
+* find output from your extension in the debug console
+
+## Make changes
+* you can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`
+* you can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes
+
+## Explore the API
+* you can open the full set of our API when you open the file `node_modules/vscode/vscode.d.ts`
+
+## Run tests
+* open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Launch Tests`
+* press `F5` to run the tests in a new window with your extension loaded
+* see the output of the test result in the debug console
+* make changes to `test/extension.test.ts` or create new test files inside the `test` folder
+    * by convention, the test runner will only consider files matching the name pattern `**.test.ts`
+    * you can create folders inside the `test` folder to structure your tests any way you want
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/fuzzer/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clangd/fuzzer/CMakeLists.txt
new file mode 100644
index 0000000..ca76c97
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/fuzzer/CMakeLists.txt
@@ -0,0 +1,24 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
+
+set(LLVM_LINK_COMPONENTS support)
+
+if(LLVM_USE_SANITIZE_COVERAGE)
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=fuzzer")
+endif()
+
+add_clang_executable(clangd-fuzzer
+  EXCLUDE_FROM_ALL
+  ClangdFuzzer.cpp
+  )
+
+target_link_libraries(clangd-fuzzer
+  PRIVATE
+  clangBasic
+  clangDaemon
+  clangFormat
+  clangFrontend
+  clangSema
+  clangTooling
+  clangToolingCore
+  ${LLVM_LIB_FUZZING_ENGINE}
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/fuzzer/ClangdFuzzer.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/fuzzer/ClangdFuzzer.cpp
new file mode 100644
index 0000000..86f6107
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/fuzzer/ClangdFuzzer.cpp
@@ -0,0 +1,37 @@
+//===-- ClangdFuzzer.cpp - Fuzz clangd ------------------------------------===//
+//
+//                     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 function that runs clangd on a single input.
+/// This function is then linked into the Fuzzer library.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ClangdLSPServer.h"
+#include "ClangdServer.h"
+#include "CodeComplete.h"
+#include <sstream>
+#include <stdio.h>
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
+  if (size == 0)
+    return 0;
+
+  clang::clangd::JSONOutput Out(llvm::nulls(), llvm::nulls(),
+                                clang::clangd::Logger::Error, nullptr);
+  clang::clangd::CodeCompleteOptions CCOpts;
+  CCOpts.EnableSnippets = false;
+  clang::clangd::ClangdServer::Options Opts;
+
+  // Initialize and run ClangdLSPServer.
+  clang::clangd::ClangdLSPServer LSPServer(Out, CCOpts, llvm::None, Opts);
+  // fmemopen isn't portable, but I think we only run the fuzzer on Linux.
+  LSPServer.run(fmemopen(data, size, "r"));
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/global-symbol-builder/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clangd/global-symbol-builder/CMakeLists.txt
new file mode 100644
index 0000000..c81da16
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/global-symbol-builder/CMakeLists.txt
@@ -0,0 +1,20 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../)
+
+set(LLVM_LINK_COMPONENTS
+    Support
+    )
+
+add_clang_executable(global-symbol-builder
+  GlobalSymbolBuilderMain.cpp
+  )
+
+target_link_libraries(global-symbol-builder
+  PRIVATE
+  clangAST
+  clangIndex
+  clangDaemon
+  clangBasic
+  clangFrontend
+  clangLex
+  clangTooling
+)
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/global-symbol-builder/GlobalSymbolBuilderMain.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/global-symbol-builder/GlobalSymbolBuilderMain.cpp
new file mode 100644
index 0000000..0cc0480
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/global-symbol-builder/GlobalSymbolBuilderMain.cpp
@@ -0,0 +1,199 @@
+//===--- GlobalSymbolBuilderMain.cpp -----------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// GlobalSymbolBuilder is a tool to generate YAML-format symbols across the
+// whole project. This tools is for **experimental** only. Don't use it in
+// production code.
+//
+//===---------------------------------------------------------------------===//
+
+#include "index/CanonicalIncludes.h"
+#include "index/Index.h"
+#include "index/Merge.h"
+#include "index/SymbolCollector.h"
+#include "index/SymbolYAML.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Index/IndexDataConsumer.h"
+#include "clang/Index/IndexingAction.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Execution.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/ThreadPool.h"
+#include "llvm/Support/YAMLTraits.h"
+
+using namespace llvm;
+using namespace clang::tooling;
+using clang::clangd::SymbolSlab;
+
+namespace clang {
+namespace clangd {
+namespace {
+
+static llvm::cl::opt<std::string> AssumedHeaderDir(
+    "assume-header-dir",
+    llvm::cl::desc("The index includes header that a symbol is defined in. "
+                   "If the absolute path cannot be determined (e.g. an "
+                   "in-memory VFS) then the relative path is resolved against "
+                   "this directory, which must be absolute. If this flag is "
+                   "not given, such headers will have relative paths."),
+    llvm::cl::init(""));
+
+class SymbolIndexActionFactory : public tooling::FrontendActionFactory {
+public:
+  SymbolIndexActionFactory(tooling::ExecutionContext *Ctx) : Ctx(Ctx) {}
+
+  clang::FrontendAction *create() override {
+    // Wraps the index action and reports collected symbols to the execution
+    // context at the end of each translation unit.
+    class WrappedIndexAction : public WrapperFrontendAction {
+    public:
+      WrappedIndexAction(std::shared_ptr<SymbolCollector> C,
+                         std::unique_ptr<CanonicalIncludes> Includes,
+                         const index::IndexingOptions &Opts,
+                         tooling::ExecutionContext *Ctx)
+          : WrapperFrontendAction(
+                index::createIndexingAction(C, Opts, nullptr)),
+            Ctx(Ctx), Collector(C), Includes(std::move(Includes)),
+            PragmaHandler(collectIWYUHeaderMaps(this->Includes.get())) {}
+
+      std::unique_ptr<ASTConsumer>
+      CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override {
+        CI.getPreprocessor().addCommentHandler(PragmaHandler.get());
+        return WrapperFrontendAction::CreateASTConsumer(CI, InFile);
+      }
+
+      bool BeginInvocation(CompilerInstance &CI) override {
+        // We want all comments, not just the doxygen ones.
+        CI.getLangOpts().CommentOpts.ParseAllComments = true;
+        return WrapperFrontendAction::BeginInvocation(CI);
+      }
+
+      void EndSourceFileAction() override {
+        WrapperFrontendAction::EndSourceFileAction();
+
+        const auto &CI = getCompilerInstance();
+        if (CI.hasDiagnostics() &&
+            CI.getDiagnostics().hasUncompilableErrorOccurred()) {
+          llvm::errs()
+              << "Found uncompilable errors in the translation unit. Igoring "
+                 "collected symbols...\n";
+          return;
+        }
+
+        auto Symbols = Collector->takeSymbols();
+        for (const auto &Sym : Symbols) {
+          Ctx->reportResult(Sym.ID.str(), SymbolToYAML(Sym));
+        }
+      }
+
+    private:
+      tooling::ExecutionContext *Ctx;
+      std::shared_ptr<SymbolCollector> Collector;
+      std::unique_ptr<CanonicalIncludes> Includes;
+      std::unique_ptr<CommentHandler> PragmaHandler;
+    };
+
+    index::IndexingOptions IndexOpts;
+    IndexOpts.SystemSymbolFilter =
+        index::IndexingOptions::SystemSymbolFilterKind::All;
+    IndexOpts.IndexFunctionLocals = false;
+    auto CollectorOpts = SymbolCollector::Options();
+    CollectorOpts.FallbackDir = AssumedHeaderDir;
+    CollectorOpts.CollectIncludePath = true;
+    CollectorOpts.CountReferences = true;
+    CollectorOpts.Origin = SymbolOrigin::Static;
+    auto Includes = llvm::make_unique<CanonicalIncludes>();
+    addSystemHeadersMapping(Includes.get());
+    CollectorOpts.Includes = Includes.get();
+    return new WrappedIndexAction(
+        std::make_shared<SymbolCollector>(std::move(CollectorOpts)),
+        std::move(Includes), IndexOpts, Ctx);
+  }
+
+  tooling::ExecutionContext *Ctx;
+};
+
+// Combine occurrences of the same symbol across translation units.
+SymbolSlab mergeSymbols(tooling::ToolResults *Results) {
+  SymbolSlab::Builder UniqueSymbols;
+  llvm::BumpPtrAllocator Arena;
+  Symbol::Details Scratch;
+  Results->forEachResult([&](llvm::StringRef Key, llvm::StringRef Value) {
+    Arena.Reset();
+    llvm::yaml::Input Yin(Value, &Arena);
+    auto Sym = clang::clangd::SymbolFromYAML(Yin, Arena);
+    clang::clangd::SymbolID ID;
+    Key >> ID;
+    if (const auto *Existing = UniqueSymbols.find(ID))
+      UniqueSymbols.insert(mergeSymbol(*Existing, Sym, &Scratch));
+    else
+      UniqueSymbols.insert(Sym);
+  });
+  return std::move(UniqueSymbols).build();
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
+
+int main(int argc, const char **argv) {
+  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+
+  const char *Overview = R"(
+  This is an **experimental** tool to generate YAML-format project-wide symbols
+  for clangd (global code completion). It would be changed and deprecated
+  eventually. Don't use it in production code!
+
+  Example usage for building index for the whole project using CMake compile
+  commands:
+
+  $ global-symbol-builder --executor=all-TUs compile_commands.json > index.yaml
+
+  Example usage for file sequence index without flags:
+
+  $ global-symbol-builder File1.cpp File2.cpp ... FileN.cpp > index.yaml
+
+  Note: only symbols from header files will be collected.
+  )";
+
+  auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
+      argc, argv, cl::GeneralCategory, Overview);
+
+  if (!Executor) {
+    llvm::errs() << llvm::toString(Executor.takeError()) << "\n";
+    return 1;
+  }
+
+  if (!clang::clangd::AssumedHeaderDir.empty() &&
+      !llvm::sys::path::is_absolute(clang::clangd::AssumedHeaderDir)) {
+    llvm::errs() << "--assume-header-dir must be an absolute path.\n";
+    return 1;
+  }
+
+  // Map phase: emit symbols found in each translation unit.
+  auto Err = Executor->get()->execute(
+      llvm::make_unique<clang::clangd::SymbolIndexActionFactory>(
+          Executor->get()->getExecutionContext()));
+  if (Err) {
+    llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+  }
+
+  // Reduce phase: combine symbols using the ID as a key.
+  auto UniqueSymbols =
+      clang::clangd::mergeSymbols(Executor->get()->getToolResults());
+
+  // Output phase: emit YAML for result symbols.
+  SymbolsToYAML(UniqueSymbols, llvm::outs());
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/CanonicalIncludes.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/index/CanonicalIncludes.cpp
new file mode 100644
index 0000000..a3493e3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/CanonicalIncludes.cpp
@@ -0,0 +1,813 @@
+//===-- CanonicalIncludes.h - remap #inclue headers--------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CanonicalIncludes.h"
+#include "../Headers.h"
+#include "clang/Driver/Types.h"
+#include "llvm/Support/Regex.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+const char IWYUPragma[] = "// IWYU pragma: private, include ";
+} // namespace
+
+void CanonicalIncludes::addMapping(llvm::StringRef Path,
+                                   llvm::StringRef CanonicalPath) {
+  addRegexMapping((llvm::Twine("^") + llvm::Regex::escape(Path) + "$").str(),
+                  CanonicalPath);
+}
+
+void CanonicalIncludes::addRegexMapping(llvm::StringRef RE,
+                                        llvm::StringRef CanonicalPath) {
+  this->RegexHeaderMappingTable.emplace_back(llvm::Regex(RE), CanonicalPath);
+}
+
+void CanonicalIncludes::addSymbolMapping(llvm::StringRef QualifiedName,
+                                         llvm::StringRef CanonicalPath) {
+  this->SymbolMapping[QualifiedName] = CanonicalPath;
+}
+
+llvm::StringRef
+CanonicalIncludes::mapHeader(llvm::ArrayRef<std::string> Headers,
+                             llvm::StringRef QualifiedName) const {
+  assert(!Headers.empty());
+  auto SE = SymbolMapping.find(QualifiedName);
+  if (SE != SymbolMapping.end())
+    return SE->second;
+  std::lock_guard<std::mutex> Lock(RegexMutex);
+  // Find the first header such that the extension is not '.inc', and isn't a
+  // recognized non-header file
+  auto I =
+      std::find_if(Headers.begin(), Headers.end(), [](llvm::StringRef Include) {
+        // Skip .inc file whose including header file should
+        // be #included instead.
+        return !Include.endswith(".inc");
+      });
+  if (I == Headers.end())
+    return Headers[0]; // Fallback to the declaring header.
+  StringRef Header = *I;
+  // If Header is not expected be included (e.g. .cc file), we fall back to
+  // the declaring header.
+  StringRef Ext = llvm::sys::path::extension(Header).trim('.');
+  // Include-able headers must have precompile type. Treat files with
+  // non-recognized extenstions (TY_INVALID) as headers.
+  auto ExtType = driver::types::lookupTypeForExtension(Ext);
+  if ((ExtType != driver::types::TY_INVALID) &&
+      !driver::types::onlyPrecompileType(ExtType))
+    return Headers[0];
+  for (auto &Entry : RegexHeaderMappingTable) {
+#ifndef NDEBUG
+    std::string Dummy;
+    assert(Entry.first.isValid(Dummy) && "Regex should never be invalid!");
+#endif
+    if (Entry.first.match(Header))
+      return Entry.second;
+  }
+  return Header;
+}
+
+std::unique_ptr<CommentHandler>
+collectIWYUHeaderMaps(CanonicalIncludes *Includes) {
+  class PragmaCommentHandler : public clang::CommentHandler {
+  public:
+    PragmaCommentHandler(CanonicalIncludes *Includes) : Includes(Includes) {}
+
+    bool HandleComment(Preprocessor &PP, SourceRange Range) override {
+      StringRef Text =
+          Lexer::getSourceText(CharSourceRange::getCharRange(Range),
+                               PP.getSourceManager(), PP.getLangOpts());
+      if (!Text.consume_front(IWYUPragma))
+        return false;
+      // FIXME(ioeric): resolve the header and store actual file path. For now,
+      // we simply assume the written header is suitable to be #included.
+      Includes->addMapping(PP.getSourceManager().getFilename(Range.getBegin()),
+                           isLiteralInclude(Text) ? Text.str()
+                                                  : ("\"" + Text + "\"").str());
+      return false;
+    }
+
+  private:
+    CanonicalIncludes *const Includes;
+  };
+  return llvm::make_unique<PragmaCommentHandler>(Includes);
+}
+
+void addSystemHeadersMapping(CanonicalIncludes *Includes) {
+  static const std::vector<std::pair<const char *, const char *>> SymbolMap = {
+      {"std::addressof", "<memory>"},
+      // Map symbols in <iosfwd> to their preferred includes.
+      {"std::basic_filebuf", "<fstream>"},
+      {"std::basic_fstream", "<fstream>"},
+      {"std::basic_ifstream", "<fstream>"},
+      {"std::basic_ofstream", "<fstream>"},
+      {"std::filebuf", "<fstream>"},
+      {"std::fstream", "<fstream>"},
+      {"std::ifstream", "<fstream>"},
+      {"std::ofstream", "<fstream>"},
+      {"std::wfilebuf", "<fstream>"},
+      {"std::wfstream", "<fstream>"},
+      {"std::wifstream", "<fstream>"},
+      {"std::wofstream", "<fstream>"},
+      {"std::basic_ios", "<ios>"},
+      {"std::ios", "<ios>"},
+      {"std::wios", "<ios>"},
+      {"std::basic_iostream", "<iostream>"},
+      {"std::iostream", "<iostream>"},
+      {"std::wiostream", "<iostream>"},
+      {"std::basic_istream", "<istream>"},
+      {"std::istream", "<istream>"},
+      {"std::wistream", "<istream>"},
+      {"std::istreambuf_iterator", "<iterator>"},
+      {"std::ostreambuf_iterator", "<iterator>"},
+      {"std::basic_ostream", "<ostream>"},
+      {"std::ostream", "<ostream>"},
+      {"std::wostream", "<ostream>"},
+      {"std::basic_istringstream", "<sstream>"},
+      {"std::basic_ostringstream", "<sstream>"},
+      {"std::basic_stringbuf", "<sstream>"},
+      {"std::basic_stringstream", "<sstream>"},
+      {"std::istringstream", "<sstream>"},
+      {"std::ostringstream", "<sstream>"},
+      {"std::stringbuf", "<sstream>"},
+      {"std::stringstream", "<sstream>"},
+      {"std::wistringstream", "<sstream>"},
+      {"std::wostringstream", "<sstream>"},
+      {"std::wstringbuf", "<sstream>"},
+      {"std::wstringstream", "<sstream>"},
+      {"std::basic_streambuf", "<streambuf>"},
+      {"std::streambuf", "<streambuf>"},
+      {"std::wstreambuf", "<streambuf>"},
+      {"std::uint_least16_t", "<cstdint>"}, // <type_traits> redeclares these
+      {"std::uint_least32_t", "<cstdint>"},
+      {"std::declval", "<utility>"},
+  };
+  for (const auto &Pair : SymbolMap)
+    Includes->addSymbolMapping(Pair.first, Pair.second);
+
+  static const std::vector<std::pair<const char *, const char *>>
+      SystemHeaderMap = {
+          {"include/__stddef_max_align_t.h$", "<cstddef>"},
+          {"include/__wmmintrin_aes.h$", "<wmmintrin.h>"},
+          {"include/__wmmintrin_pclmul.h$", "<wmmintrin.h>"},
+          {"include/adxintrin.h$", "<immintrin.h>"},
+          {"include/ammintrin.h$", "<ammintrin.h>"},
+          {"include/avx2intrin.h$", "<immintrin.h>"},
+          {"include/avx512bwintrin.h$", "<immintrin.h>"},
+          {"include/avx512cdintrin.h$", "<immintrin.h>"},
+          {"include/avx512dqintrin.h$", "<immintrin.h>"},
+          {"include/avx512erintrin.h$", "<immintrin.h>"},
+          {"include/avx512fintrin.h$", "<immintrin.h>"},
+          {"include/avx512ifmaintrin.h$", "<immintrin.h>"},
+          {"include/avx512ifmavlintrin.h$", "<immintrin.h>"},
+          {"include/avx512pfintrin.h$", "<immintrin.h>"},
+          {"include/avx512vbmiintrin.h$", "<immintrin.h>"},
+          {"include/avx512vbmivlintrin.h$", "<immintrin.h>"},
+          {"include/avx512vlbwintrin.h$", "<immintrin.h>"},
+          {"include/avx512vlcdintrin.h$", "<immintrin.h>"},
+          {"include/avx512vldqintrin.h$", "<immintrin.h>"},
+          {"include/avx512vlintrin.h$", "<immintrin.h>"},
+          {"include/avxintrin.h$", "<immintrin.h>"},
+          {"include/bmi2intrin.h$", "<x86intrin.h>"},
+          {"include/bmiintrin.h$", "<x86intrin.h>"},
+          {"include/emmintrin.h$", "<emmintrin.h>"},
+          {"include/f16cintrin.h$", "<emmintrin.h>"},
+          {"include/float.h$", "<cfloat>"},
+          {"include/fma4intrin.h$", "<x86intrin.h>"},
+          {"include/fmaintrin.h$", "<immintrin.h>"},
+          {"include/fxsrintrin.h$", "<immintrin.h>"},
+          {"include/ia32intrin.h$", "<x86intrin.h>"},
+          {"include/immintrin.h$", "<immintrin.h>"},
+          {"include/inttypes.h$", "<cinttypes>"},
+          {"include/limits.h$", "<climits>"},
+          {"include/lzcntintrin.h$", "<x86intrin.h>"},
+          {"include/mm3dnow.h$", "<mm3dnow.h>"},
+          {"include/mm_malloc.h$", "<mm_malloc.h>"},
+          {"include/mmintrin.h$", "<mmintrin>"},
+          {"include/mwaitxintrin.h$", "<x86intrin.h>"},
+          {"include/pkuintrin.h$", "<immintrin.h>"},
+          {"include/pmmintrin.h$", "<pmmintrin.h>"},
+          {"include/popcntintrin.h$", "<popcntintrin.h>"},
+          {"include/prfchwintrin.h$", "<x86intrin.h>"},
+          {"include/rdseedintrin.h$", "<x86intrin.h>"},
+          {"include/rtmintrin.h$", "<immintrin.h>"},
+          {"include/shaintrin.h$", "<immintrin.h>"},
+          {"include/smmintrin.h$", "<smmintrin.h>"},
+          {"include/stdalign.h$", "<cstdalign>"},
+          {"include/stdarg.h$", "<cstdarg>"},
+          {"include/stdbool.h$", "<cstdbool>"},
+          {"include/stddef.h$", "<cstddef>"},
+          {"include/stdint.h$", "<cstdint>"},
+          {"include/tbmintrin.h$", "<x86intrin.h>"},
+          {"include/tmmintrin.h$", "<tmmintrin.h>"},
+          {"include/wmmintrin.h$", "<wmmintrin.h>"},
+          {"include/x86intrin.h$", "<x86intrin.h>"},
+          {"include/xmmintrin.h$", "<xmmintrin.h>"},
+          {"include/xopintrin.h$", "<x86intrin.h>"},
+          {"include/xsavecintrin.h$", "<immintrin.h>"},
+          {"include/xsaveintrin.h$", "<immintrin.h>"},
+          {"include/xsaveoptintrin.h$", "<immintrin.h>"},
+          {"include/xsavesintrin.h$", "<immintrin.h>"},
+          {"include/xtestintrin.h$", "<immintrin.h>"},
+          {"include/_G_config.h$", "<cstdio>"},
+          {"include/assert.h$", "<cassert>"},
+          {"algorithm$", "<algorithm>"},
+          {"valarray$", "<valarray>"},
+          {"array$", "<array>"},
+          {"atomic$", "<atomic>"},
+          {"backward/auto_ptr.h$", "<memory>"},
+          {"backward/binders.h$", "<string>"},
+          {"bits/algorithmfwd.h$", "<algorithm>"},
+          {"bits/alloc_traits.h$", "<memory>"},
+          {"bits/allocated_ptr.h$", "<memory>"},
+          {"bits/allocator.h$", "<allocator>"},
+          {"bits/atomic_base.h$", "<atomic>"},
+          {"bits/atomic_lockfree_defines.h$", "<exception>"},
+          {"bits/atomic_futex.h$", "<atomic>"},
+          {"bits/basic_ios.h$", "<ios>"},
+          {"bits/basic_ios.tcc$", "<ios>"},
+          {"bits/basic_string.h$", "<string>"},
+          {"bits/basic_string.tcc$", "<string>"},
+          {"bits/char_traits.h$", "<string>"},
+          {"bits/codecvt.h$", "<locale>"},
+          {"bits/concept_check.h$", "<numeric>"},
+          {"bits/cpp_type_traits.h$", "<cmath>"},
+          {"bits/cxxabi_forced.h$", "<cxxabi.h>"},
+          {"bits/deque.tcc$", "<deque>"},
+          {"bits/exception.h$", "<exception>"},
+          {"bits/exception_defines.h$", "<exception>"},
+          {"bits/exception_ptr.h$", "<exception>"},
+          {"bits/forward_list.h$", "<forward_list>"},
+          {"bits/forward_list.tcc$", "<forward_list>"},
+          {"bits/fstream.tcc$", "<fstream>"},
+          {"bits/functexcept.h$", "<list>"},
+          {"bits/functional_hash.h$", "<functional>"},
+          {"bits/gslice.h$", "<valarray>"},
+          {"bits/gslice_array.h$", "<valarray>"},
+          {"bits/hash_bytes.h$", "<typeinfo>"},
+          {"bits/hashtable.h$", "<unordered_set>"},
+          {"bits/hashtable_policy.h$", "<unordered_set>"},
+          {"bits/indirect_array.h$", "<valarray>"},
+          {"bits/invoke.h$", "<functional>"},
+          {"bits/ios_base.h$", "<ios>"},
+          {"bits/istream.tcc$", "<istream>"},
+          {"bits/list.tcc$", "<list>"},
+          {"bits/locale_classes.h$", "<locale>"},
+          {"bits/locale_classes.tcc$", "<locale>"},
+          {"bits/locale_conv.h$", "<locale>"},
+          {"bits/locale_facets.h$", "<locale>"},
+          {"bits/locale_facets.tcc$", "<locale>"},
+          {"bits/locale_facets_nonio.h$", "<locale>"},
+          {"bits/locale_facets_nonio.tcc$", "<locale>"},
+          {"bits/localefwd.h$", "<locale>"},
+          {"bits/mask_array.h$", "<valarray>"},
+          {"bits/memoryfwd.h$", "<memory>"},
+          {"bits/move.h$", "<utility>"},
+          {"bits/nested_exception.h$", "<exception>"},
+          {"bits/ostream.tcc$", "<ostream>"},
+          {"bits/ostream_insert.h$", "<ostream>"},
+          {"bits/parse_numbers.h$", "<chrono>"},
+          {"bits/postypes.h$", "<ios>"},
+          {"bits/predefined_ops.h$", "<algorithm>"},
+          {"bits/ptr_traits.h$", "<memory>"},
+          {"bits/quoted_string.h$", "<iomanip>"},
+          {"bits/random.h$", "<random>"},
+          {"bits/random.tcc$", "<random>"},
+          {"bits/range_access.h$", "<iterator>"},
+          {"bits/refwrap.h$", "<functional>"},
+          {"bits/regex.h$", "<regex>"},
+          {"bits/regex_automaton.h$", "<regex>"},
+          {"bits/regex_compiler.h$", "<regex>"},
+          {"bits/regex_constants.h$", "<regex>"},
+          {"bits/regex_cursor.h$", "<regex>"},
+          {"bits/regex_error.h$", "<regex>"},
+          {"bits/regex_executor.h$", "<regex>"},
+          {"bits/regex_grep_matcher.h$", "<regex>"},
+          {"bits/regex_grep_matcher.tcc$", "<regex>"},
+          {"bits/regex_nfa.h$", "<regex>"},
+          {"bits/regex_scanner.h$", "<regex>"},
+          {"bits/shared_ptr.h$", "<memory>"},
+          {"bits/shared_ptr_base.h$", "<memory>"},
+          {"bits/shared_ptr_atomic.h$", "<atomic>"},
+          {"bits/slice_array.h$", "<valarray>"},
+          {"bits/sstream.tcc$", "<sstream>"},
+          {"bits/std_abs.h$", "<cmath>"},
+          {"bits/std_function.h$", "<functional>"},
+          {"bits/std_mutex.h$", "<mutex>"},
+          {"bits/stl_algo.h$", "<algorithm>"},
+          {"bits/stl_algobase.h$", "<algorithm>"},
+          {"bits/stl_bvector.h$", "<vector>"},
+          {"bits/stl_construct.h$", "<deque>"},
+          {"bits/stl_deque.h$", "<deque>"},
+          {"bits/stl_function.h$", "<functional>"},
+          {"bits/stl_heap.h$", "<heap>"},
+          {"bits/stl_iterator.h$", "<iterator>"},
+          {"bits/stl_iterator_base_funcs.h$", "<iterator>"},
+          {"bits/stl_iterator_base_types.h$", "<iterator>"},
+          {"bits/stl_list.h$", "<list>"},
+          {"bits/stl_map.h$", "<map>"},
+          {"bits/stl_multimap.h$", "<map>"},
+          {"bits/stl_multiset.h$", "<set>"},
+          {"bits/stl_numeric.h$", "<numeric>"},
+          {"bits/stl_pair.h$", "<utility>"},
+          {"bits/stl_queue.h$", "<queue>"},
+          {"bits/stl_raw_storage_iter.h$", "<memory>"},
+          {"bits/stl_relops.h$", "<utility>"},
+          {"bits/stl_set.h$", "<set>"},
+          {"bits/stl_stack.h$", "<stack>"},
+          {"bits/stl_tempbuf.h$", "<memory>"},
+          {"bits/stl_tree.h$", "<map>"},
+          {"bits/stl_uninitialized.h$", "<memory>"},
+          {"bits/stl_vector.h$", "<vector>"},
+          {"bits/stream_iterator.h$", "<iterator>"},
+          {"bits/streambuf.tcc$", "<streambuf>"},
+          {"bits/streambuf_iterator.h$", "<iterator>"},
+          {"bits/stringfwd.h$", "<string>"},
+          {"bits/uniform_int_dist.h$", "<random>"},
+          {"bits/unique_ptr.h$", "<memory>"},
+          {"bits/unordered_map.h$", "<unordered_map>"},
+          {"bits/unordered_set.h$", "<unordered_set>"},
+          {"bits/uses_allocator.h$", "<memory>"},
+          {"bits/valarray_after.h$", "<valarray>"},
+          {"bits/valarray_array.h$", "<valarray>"},
+          {"bits/valarray_array.tcc$", "<valarray>"},
+          {"bits/valarray_before.h$", "<valarray>"},
+          {"bits/vector.tcc$", "<vector>"},
+          {"bitset$", "<bitset>"},
+          {"ccomplex$", "<ccomplex>"},
+          {"cctype$", "<cctype>"},
+          {"cerrno$", "<cerrno>"},
+          {"cfenv$", "<cfenv>"},
+          {"cfloat$", "<cfloat>"},
+          {"chrono$", "<chrono>"},
+          {"cinttypes$", "<cinttypes>"},
+          {"climits$", "<climits>"},
+          {"clocale$", "<clocale>"},
+          {"cmath$", "<cmath>"},
+          {"complex$", "<complex>"},
+          {"complex.h$", "<complex.h>"},
+          {"condition_variable$", "<condition_variable>"},
+          {"csetjmp$", "<csetjmp>"},
+          {"csignal$", "<csignal>"},
+          {"cstdalign$", "<cstdalign>"},
+          {"cstdarg$", "<cstdarg>"},
+          {"cstdbool$", "<cstdbool>"},
+          {"cstdint$", "<cstdint>"},
+          {"cstdio$", "<cstdio>"},
+          {"cstdlib$", "<cstdlib>"},
+          {"cstring$", "<cstring>"},
+          {"ctgmath$", "<ctgmath>"},
+          {"ctime$", "<ctime>"},
+          {"cwchar$", "<cwchar>"},
+          {"cwctype$", "<cwctype>"},
+          {"cxxabi.h$", "<cxxabi.h>"},
+          {"debug/debug.h$", "<numeric>"},
+          {"debug/map.h$", "<map>"},
+          {"debug/multimap.h$", "<multimap>"},
+          {"debug/multiset.h$", "<multiset>"},
+          {"debug/set.h$", "<set>"},
+          {"deque$", "<deque>"},
+          {"exception$", "<exception>"},
+          {"ext/alloc_traits.h$", "<deque>"},
+          {"ext/atomicity.h$", "<memory>"},
+          {"ext/concurrence.h$", "<memory>"},
+          {"ext/new_allocator.h$", "<string>"},
+          {"ext/numeric_traits.h$", "<list>"},
+          {"ext/string_conversions.h$", "<string>"},
+          {"ext/type_traits.h$", "<cmath>"},
+          {"fenv.h$", "<fenv.h>"},
+          {"forward_list$", "<forward_list>"},
+          {"fstream$", "<fstream>"},
+          {"functional$", "<functional>"},
+          {"future$", "<future>"},
+          {"initializer_list$", "<initializer_list>"},
+          {"iomanip$", "<iomanip>"},
+          {"ios$", "<ios>"},
+          {"iosfwd$", "<iosfwd>"},
+          {"iostream$", "<iostream>"},
+          {"istream$", "<istream>"},
+          {"iterator$", "<iterator>"},
+          {"limits$", "<limits>"},
+          {"list$", "<list>"},
+          {"locale$", "<locale>"},
+          {"map$", "<map>"},
+          {"memory$", "<memory>"},
+          {"shared_mutex$", "<shared_mutex>"},
+          {"mutex$", "<mutex>"},
+          {"new$", "<new>"},
+          {"numeric$", "<numeric>"},
+          {"ostream$", "<ostream>"},
+          {"queue$", "<queue>"},
+          {"random$", "<random>"},
+          {"ratio$", "<ratio>"},
+          {"regex$", "<regex>"},
+          {"scoped_allocator$", "<scoped_allocator>"},
+          {"set$", "<set>"},
+          {"sstream$", "<sstream>"},
+          {"stack$", "<stack>"},
+          {"stdexcept$", "<stdexcept>"},
+          {"streambuf$", "<streambuf>"},
+          {"string$", "<string>"},
+          {"system_error$", "<system_error>"},
+          {"tgmath.h$", "<tgmath.h>"},
+          {"thread$", "<thread>"},
+          {"tuple$", "<tuple>"},
+          {"type_traits$", "<type_traits>"},
+          {"typeindex$", "<typeindex>"},
+          {"typeinfo$", "<typeinfo>"},
+          {"unordered_map$", "<unordered_map>"},
+          {"unordered_set$", "<unordered_set>"},
+          {"utility$", "<utility>"},
+          {"valarray$", "<valarray>"},
+          {"vector$", "<vector>"},
+          {"include/complex.h$", "<complex.h>"},
+          {"include/ctype.h$", "<cctype>"},
+          {"include/errno.h$", "<cerrno>"},
+          {"include/fenv.h$", "<fenv.h>"},
+          {"include/inttypes.h$", "<cinttypes>"},
+          {"include/libio.h$", "<cstdio>"},
+          {"include/limits.h$", "<climits>"},
+          {"include/locale.h$", "<clocale>"},
+          {"include/math.h$", "<cmath>"},
+          {"include/setjmp.h$", "<csetjmp>"},
+          {"include/signal.h$", "<csignal>"},
+          {"include/stdint.h$", "<cstdint>"},
+          {"include/stdio.h$", "<cstdio>"},
+          {"include/stdlib.h$", "<cstdlib>"},
+          {"include/string.h$", "<cstring>"},
+          {"include/time.h$", "<ctime>"},
+          {"include/wchar.h$", "<cwchar>"},
+          {"include/wctype.h$", "<cwctype>"},
+          {"bits/cmathcalls.h$", "<complex.h>"},
+          {"bits/errno.h$", "<cerrno>"},
+          {"bits/fenv.h$", "<fenv.h>"},
+          {"bits/huge_val.h$", "<cmath>"},
+          {"bits/huge_valf.h$", "<cmath>"},
+          {"bits/huge_vall.h$", "<cmath>"},
+          {"bits/inf.h$", "<cmath>"},
+          {"bits/local_lim.h$", "<climits>"},
+          {"bits/locale.h$", "<clocale>"},
+          {"bits/mathcalls.h$", "<math.h>"},
+          {"bits/mathdef.h$", "<cmath>"},
+          {"bits/nan.h$", "<cmath>"},
+          {"bits/posix1_lim.h$", "<climits>"},
+          {"bits/posix2_lim.h$", "<climits>"},
+          {"bits/setjmp.h$", "<csetjmp>"},
+          {"bits/sigaction.h$", "<csignal>"},
+          {"bits/sigcontext.h$", "<csignal>"},
+          {"bits/siginfo.h$", "<csignal>"},
+          {"bits/signum.h$", "<csignal>"},
+          {"bits/sigset.h$", "<csignal>"},
+          {"bits/sigstack.h$", "<csignal>"},
+          {"bits/stdio_lim.h$", "<cstdio>"},
+          {"bits/sys_errlist.h$", "<cstdio>"},
+          {"bits/time.h$", "<ctime>"},
+          {"bits/timex.h$", "<ctime>"},
+          {"bits/typesizes.h$", "<cstdio>"},
+          {"bits/wchar.h$", "<cwchar>"},
+          {"bits/wordsize.h$", "<csetjmp>"},
+          {"bits/xopen_lim.h$", "<climits>"},
+          {"include/xlocale.h$", "<cstring>"},
+          {"bits/atomic_word.h$", "<memory>"},
+          {"bits/basic_file.h$", "<fstream>"},
+          {"bits/c\\+\\+allocator.h$", "<string>"},
+          {"bits/c\\+\\+config.h$", "<cstddef>"},
+          {"bits/c\\+\\+io.h$", "<ios>"},
+          {"bits/c\\+\\+locale.h$", "<locale>"},
+          {"bits/cpu_defines.h$", "<iosfwd>"},
+          {"bits/ctype_base.h$", "<locale>"},
+          {"bits/cxxabi_tweaks.h$", "<cxxabi.h>"},
+          {"bits/error_constants.h$", "<system_error>"},
+          {"bits/gthr-default.h$", "<memory>"},
+          {"bits/gthr.h$", "<memory>"},
+          {"bits/opt_random.h$", "<random>"},
+          {"bits/os_defines.h$", "<iosfwd>"},
+          // GNU C headers
+          {"include/aio.h$", "<aio.h>"},
+          {"include/aliases.h$", "<aliases.h>"},
+          {"include/alloca.h$", "<alloca.h>"},
+          {"include/ar.h$", "<ar.h>"},
+          {"include/argp.h$", "<argp.h>"},
+          {"include/argz.h$", "<argz.h>"},
+          {"include/arpa/nameser.h$", "<resolv.h>"},
+          {"include/arpa/nameser_compat.h$", "<resolv.h>"},
+          {"include/byteswap.h$", "<byteswap.h>"},
+          {"include/cpio.h$", "<cpio.h>"},
+          {"include/crypt.h$", "<crypt.h>"},
+          {"include/dirent.h$", "<dirent.h>"},
+          {"include/dlfcn.h$", "<dlfcn.h>"},
+          {"include/elf.h$", "<elf.h>"},
+          {"include/endian.h$", "<endian.h>"},
+          {"include/envz.h$", "<envz.h>"},
+          {"include/err.h$", "<err.h>"},
+          {"include/error.h$", "<error.h>"},
+          {"include/execinfo.h$", "<execinfo.h>"},
+          {"include/fcntl.h$", "<fcntl.h>"},
+          {"include/features.h$", "<features.h>"},
+          {"include/fenv.h$", "<fenv.h>"},
+          {"include/fmtmsg.h$", "<fmtmsg.h>"},
+          {"include/fnmatch.h$", "<fnmatch.h>"},
+          {"include/fstab.h$", "<fstab.h>"},
+          {"include/fts.h$", "<fts.h>"},
+          {"include/ftw.h$", "<ftw.h>"},
+          {"include/gconv.h$", "<gconv.h>"},
+          {"include/getopt.h$", "<getopt.h>"},
+          {"include/glob.h$", "<glob.h>"},
+          {"include/grp.h$", "<grp.h>"},
+          {"include/gshadow.h$", "<gshadow.h>"},
+          {"include/iconv.h$", "<iconv.h>"},
+          {"include/ifaddrs.h$", "<ifaddrs.h>"},
+          {"include/kdb.h$", "<kdb.h>"},
+          {"include/langinfo.h$", "<langinfo.h>"},
+          {"include/libgen.h$", "<libgen.h>"},
+          {"include/libintl.h$", "<libintl.h>"},
+          {"include/link.h$", "<link.h>"},
+          {"include/malloc.h$", "<malloc.h>"},
+          {"include/mcheck.h$", "<mcheck.h>"},
+          {"include/memory.h$", "<memory.h>"},
+          {"include/mntent.h$", "<mntent.h>"},
+          {"include/monetary.h$", "<monetary.h>"},
+          {"include/mqueue.h$", "<mqueue.h>"},
+          {"include/netdb.h$", "<netdb.h>"},
+          {"include/netinet/in.h$", "<netinet/in.h>"},
+          {"include/nl_types.h$", "<nl_types.h>"},
+          {"include/nss.h$", "<nss.h>"},
+          {"include/obstack.h$", "<obstack.h>"},
+          {"include/panel.h$", "<panel.h>"},
+          {"include/paths.h$", "<paths.h>"},
+          {"include/printf.h$", "<printf.h>"},
+          {"include/profile.h$", "<profile.h>"},
+          {"include/pthread.h$", "<pthread.h>"},
+          {"include/pty.h$", "<pty.h>"},
+          {"include/pwd.h$", "<pwd.h>"},
+          {"include/re_comp.h$", "<re_comp.h>"},
+          {"include/regex.h$", "<regex.h>"},
+          {"include/regexp.h$", "<regexp.h>"},
+          {"include/resolv.h$", "<resolv.h>"},
+          {"include/rpc/netdb.h$", "<netdb.h>"},
+          {"include/sched.h$", "<sched.h>"},
+          {"include/search.h$", "<search.h>"},
+          {"include/semaphore.h$", "<semaphore.h>"},
+          {"include/sgtty.h$", "<sgtty.h>"},
+          {"include/shadow.h$", "<shadow.h>"},
+          {"include/spawn.h$", "<spawn.h>"},
+          {"include/stab.h$", "<stab.h>"},
+          {"include/stdc-predef.h$", "<stdc-predef.h>"},
+          {"include/stdio_ext.h$", "<stdio_ext.h>"},
+          {"include/strings.h$", "<strings.h>"},
+          {"include/stropts.h$", "<stropts.h>"},
+          {"include/sudo_plugin.h$", "<sudo_plugin.h>"},
+          {"include/sysexits.h$", "<sysexits.h>"},
+          {"include/tar.h$", "<tar.h>"},
+          {"include/tcpd.h$", "<tcpd.h>"},
+          {"include/term.h$", "<term.h>"},
+          {"include/term_entry.h$", "<term_entry.h>"},
+          {"include/termcap.h$", "<termcap.h>"},
+          {"include/termios.h$", "<termios.h>"},
+          {"include/thread_db.h$", "<thread_db.h>"},
+          {"include/tic.h$", "<tic.h>"},
+          {"include/ttyent.h$", "<ttyent.h>"},
+          {"include/uchar.h$", "<uchar.h>"},
+          {"include/ucontext.h$", "<ucontext.h>"},
+          {"include/ulimit.h$", "<ulimit.h>"},
+          {"include/unctrl.h$", "<unctrl.h>"},
+          {"include/unistd.h$", "<unistd.h>"},
+          {"include/utime.h$", "<utime.h>"},
+          {"include/utmp.h$", "<utmp.h>"},
+          {"include/utmpx.h$", "<utmpx.h>"},
+          {"include/values.h$", "<values.h>"},
+          {"include/wordexp.h$", "<wordexp.h>"},
+          {"fpu_control.h$", "<fpu_control.h>"},
+          {"ieee754.h$", "<ieee754.h>"},
+          {"include/xlocale.h$", "<xlocale.h>"},
+          {"gnu/lib-names.h$", "<gnu/lib-names.h>"},
+          {"gnu/libc-version.h$", "<gnu/libc-version.h>"},
+          {"gnu/option-groups.h$", "<gnu/option-groups.h>"},
+          {"gnu/stubs-32.h$", "<gnu/stubs-32.h>"},
+          {"gnu/stubs-64.h$", "<gnu/stubs-64.h>"},
+          {"gnu/stubs-x32.h$", "<gnu/stubs-x32.h>"},
+          {"include/rpc/auth_des.h$", "<rpc/auth_des.h>"},
+          {"include/rpc/rpc_msg.h$", "<rpc/rpc_msg.h>"},
+          {"include/rpc/pmap_clnt.h$", "<rpc/pmap_clnt.h>"},
+          {"include/rpc/rpc.h$", "<rpc/rpc.h>"},
+          {"include/rpc/types.h$", "<rpc/types.h>"},
+          {"include/rpc/auth_unix.h$", "<rpc/auth_unix.h>"},
+          {"include/rpc/key_prot.h$", "<rpc/key_prot.h>"},
+          {"include/rpc/pmap_prot.h$", "<rpc/pmap_prot.h>"},
+          {"include/rpc/auth.h$", "<rpc/auth.h>"},
+          {"include/rpc/svc_auth.h$", "<rpc/svc_auth.h>"},
+          {"include/rpc/xdr.h$", "<rpc/xdr.h>"},
+          {"include/rpc/pmap_rmt.h$", "<rpc/pmap_rmt.h>"},
+          {"include/rpc/des_crypt.h$", "<rpc/des_crypt.h>"},
+          {"include/rpc/svc.h$", "<rpc/svc.h>"},
+          {"include/rpc/rpc_des.h$", "<rpc/rpc_des.h>"},
+          {"include/rpc/clnt.h$", "<rpc/clnt.h>"},
+          {"include/scsi/scsi.h$", "<scsi/scsi.h>"},
+          {"include/scsi/sg.h$", "<scsi/sg.h>"},
+          {"include/scsi/scsi_ioctl.h$", "<scsi/scsi_ioctl>"},
+          {"include/netrose/rose.h$", "<netrose/rose.h>"},
+          {"include/nfs/nfs.h$", "<nfs/nfs.h>"},
+          {"include/netatalk/at.h$", "<netatalk/at.h>"},
+          {"include/netinet/ether.h$", "<netinet/ether.h>"},
+          {"include/netinet/icmp6.h$", "<netinet/icmp6.h>"},
+          {"include/netinet/if_ether.h$", "<netinet/if_ether.h>"},
+          {"include/netinet/if_fddi.h$", "<netinet/if_fddi.h>"},
+          {"include/netinet/if_tr.h$", "<netinet/if_tr.h>"},
+          {"include/netinet/igmp.h$", "<netinet/igmp.h>"},
+          {"include/netinet/in.h$", "<netinet/in.h>"},
+          {"include/netinet/in_systm.h$", "<netinet/in_systm.h>"},
+          {"include/netinet/ip.h$", "<netinet/ip.h>"},
+          {"include/netinet/ip6.h$", "<netinet/ip6.h>"},
+          {"include/netinet/ip_icmp.h$", "<netinet/ip_icmp.h>"},
+          {"include/netinet/tcp.h$", "<netinet/tcp.h>"},
+          {"include/netinet/udp.h$", "<netinet/udp.h>"},
+          {"include/netrom/netrom.h$", "<netrom/netrom.h>"},
+          {"include/protocols/routed.h$", "<protocols/routed.h>"},
+          {"include/protocols/rwhod.h$", "<protocols/rwhod.h>"},
+          {"include/protocols/talkd.h$", "<protocols/talkd.h>"},
+          {"include/protocols/timed.h$", "<protocols/timed.h>"},
+          {"include/rpcsvc/klm_prot.x$", "<rpcsvc/klm_prot.x>"},
+          {"include/rpcsvc/rstat.h$", "<rpcsvc/rstat.h>"},
+          {"include/rpcsvc/spray.x$", "<rpcsvc/spray.x>"},
+          {"include/rpcsvc/nlm_prot.x$", "<rpcsvc/nlm_prot.x>"},
+          {"include/rpcsvc/nis_callback.x$", "<rpcsvc/nis_callback.x>"},
+          {"include/rpcsvc/yp.h$", "<rpcsvc/yp.h>"},
+          {"include/rpcsvc/yp.x$", "<rpcsvc/yp.x>"},
+          {"include/rpcsvc/nfs_prot.h$", "<rpcsvc/nfs_prot.h>"},
+          {"include/rpcsvc/rex.h$", "<rpcsvc/rex.h>"},
+          {"include/rpcsvc/yppasswd.h$", "<rpcsvc/yppasswd.h>"},
+          {"include/rpcsvc/rex.x$", "<rpcsvc/rex.x>"},
+          {"include/rpcsvc/nis_tags.h$", "<rpcsvc/nis_tags.h>"},
+          {"include/rpcsvc/nis_callback.h$", "<rpcsvc/nis_callback.h>"},
+          {"include/rpcsvc/nfs_prot.x$", "<rpcsvc/nfs_prot.x>"},
+          {"include/rpcsvc/bootparam_prot.x$", "<rpcsvc/bootparam_prot.x>"},
+          {"include/rpcsvc/rusers.x$", "<rpcsvc/rusers.x>"},
+          {"include/rpcsvc/rquota.x$", "<rpcsvc/rquota.x>"},
+          {"include/rpcsvc/nis.h$", "<rpcsvc/nis.h>"},
+          {"include/rpcsvc/nislib.h$", "<rpcsvc/nislib.h>"},
+          {"include/rpcsvc/ypupd.h$", "<rpcsvc/ypupd.h>"},
+          {"include/rpcsvc/bootparam.h$", "<rpcsvc/bootparam.h>"},
+          {"include/rpcsvc/spray.h$", "<rpcsvc/spray.h>"},
+          {"include/rpcsvc/key_prot.h$", "<rpcsvc/key_prot.h>"},
+          {"include/rpcsvc/klm_prot.h$", "<rpcsvc/klm_prot.h>"},
+          {"include/rpcsvc/sm_inter.h$", "<rpcsvc/sm_inter.h>"},
+          {"include/rpcsvc/nlm_prot.h$", "<rpcsvc/nlm_prot.h>"},
+          {"include/rpcsvc/yp_prot.h$", "<rpcsvc/yp_prot.h>"},
+          {"include/rpcsvc/ypclnt.h$", "<rpcsvc/ypclnt.h>"},
+          {"include/rpcsvc/rstat.x$", "<rpcsvc/rstat.x>"},
+          {"include/rpcsvc/rusers.h$", "<rpcsvc/rusers.h>"},
+          {"include/rpcsvc/key_prot.x$", "<rpcsvc/key_prot.x>"},
+          {"include/rpcsvc/sm_inter.x$", "<rpcsvc/sm_inter.x>"},
+          {"include/rpcsvc/rquota.h$", "<rpcsvc/rquota.h>"},
+          {"include/rpcsvc/nis.x$", "<rpcsvc/nis.x>"},
+          {"include/rpcsvc/bootparam_prot.h$", "<rpcsvc/bootparam_prot.h>"},
+          {"include/rpcsvc/mount.h$", "<rpcsvc/mount.h>"},
+          {"include/rpcsvc/mount.x$", "<rpcsvc/mount.x>"},
+          {"include/rpcsvc/nis_object.x$", "<rpcsvc/nis_object.x>"},
+          {"include/rpcsvc/yppasswd.x$", "<rpcsvc/yppasswd.x>"},
+          {"sys/acct.h$", "<sys/acct.h>"},
+          {"sys/auxv.h$", "<sys/auxv.h>"},
+          {"sys/cdefs.h$", "<sys/cdefs.h>"},
+          {"sys/debugreg.h$", "<sys/debugreg.h>"},
+          {"sys/dir.h$", "<sys/dir.h>"},
+          {"sys/elf.h$", "<sys/elf.h>"},
+          {"sys/epoll.h$", "<sys/epoll.h>"},
+          {"sys/eventfd.h$", "<sys/eventfd.h>"},
+          {"sys/fanotify.h$", "<sys/fanotify.h>"},
+          {"sys/file.h$", "<sys/file.h>"},
+          {"sys/fsuid.h$", "<sys/fsuid.h>"},
+          {"sys/gmon.h$", "<sys/gmon.h>"},
+          {"sys/gmon_out.h$", "<sys/gmon_out.h>"},
+          {"sys/inotify.h$", "<sys/inotify.h>"},
+          {"sys/io.h$", "<sys/io.h>"},
+          {"sys/ioctl.h$", "<sys/ioctl.h>"},
+          {"sys/ipc.h$", "<sys/ipc.h>"},
+          {"sys/kd.h$", "<sys/kd.h>"},
+          {"sys/kdaemon.h$", "<sys/kdaemon.h>"},
+          {"sys/klog.h$", "<sys/klog.h>"},
+          {"sys/mman.h$", "<sys/mman.h>"},
+          {"sys/mount.h$", "<sys/mount.h>"},
+          {"sys/msg.h$", "<sys/msg.h>"},
+          {"sys/mtio.h$", "<sys/mtio.h>"},
+          {"sys/param.h$", "<sys/param.h>"},
+          {"sys/pci.h$", "<sys/pci.h>"},
+          {"sys/perm.h$", "<sys/perm.h>"},
+          {"sys/personality.h$", "<sys/personality.h>"},
+          {"sys/poll.h$", "<sys/poll.h>"},
+          {"sys/prctl.h$", "<sys/prctl.h>"},
+          {"sys/procfs.h$", "<sys/procfs.h>"},
+          {"sys/profil.h$", "<sys/profil.h>"},
+          {"sys/ptrace.h$", "<sys/ptrace.h>"},
+          {"sys/queue.h$", "<sys/queue.h>"},
+          {"sys/quota.h$", "<sys/quota.h>"},
+          {"sys/raw.h$", "<sys/raw.h>"},
+          {"sys/reboot.h$", "<sys/reboot.h>"},
+          {"sys/reg.h$", "<sys/reg.h>"},
+          {"sys/resource.h$", "<sys/resource.h>"},
+          {"sys/select.h$", "<sys/select.h>"},
+          {"sys/sem.h$", "<sys/sem.h>"},
+          {"sys/sendfile.h$", "<sys/sendfile.h>"},
+          {"sys/shm.h$", "<sys/shm.h>"},
+          {"sys/signalfd.h$", "<sys/signalfd.h>"},
+          {"sys/socket.h$", "<sys/socket.h>"},
+          {"sys/stat.h$", "<sys/stat.h>"},
+          {"sys/statfs.h$", "<sys/statfs.h>"},
+          {"sys/statvfs.h$", "<sys/statvfs.h>"},
+          {"sys/swap.h$", "<sys/swap.h>"},
+          {"sys/syscall.h$", "<sys/syscall.h>"},
+          {"sys/sysctl.h$", "<sys/sysctl.h>"},
+          {"sys/sysinfo.h$", "<sys/sysinfo.h>"},
+          {"sys/syslog.h$", "<sys/syslog.h>"},
+          {"sys/sysmacros.h$", "<sys/sysmacros.h>"},
+          {"sys/termios.h$", "<sys/termios.h>"},
+          {"sys/time.h$", "<sys/select.h>"},
+          {"sys/timeb.h$", "<sys/timeb.h>"},
+          {"sys/timerfd.h$", "<sys/timerfd.h>"},
+          {"sys/times.h$", "<sys/times.h>"},
+          {"sys/timex.h$", "<sys/timex.h>"},
+          {"sys/ttychars.h$", "<sys/ttychars.h>"},
+          {"sys/ttydefaults.h$", "<sys/ttydefaults.h>"},
+          {"sys/types.h$", "<sys/types.h>"},
+          {"sys/ucontext.h$", "<sys/ucontext.h>"},
+          {"sys/uio.h$", "<sys/uio.h>"},
+          {"sys/un.h$", "<sys/un.h>"},
+          {"sys/user.h$", "<sys/user.h>"},
+          {"sys/ustat.h$", "<sys/ustat.h>"},
+          {"sys/utsname.h$", "<sys/utsname.h>"},
+          {"sys/vlimit.h$", "<sys/vlimit.h>"},
+          {"sys/vm86.h$", "<sys/vm86.h>"},
+          {"sys/vtimes.h$", "<sys/vtimes.h>"},
+          {"sys/wait.h$", "<sys/wait.h>"},
+          {"sys/xattr.h$", "<sys/xattr.h>"},
+          {"bits/epoll.h$", "<sys/epoll.h>"},
+          {"bits/eventfd.h$", "<sys/eventfd.h>"},
+          {"bits/inotify.h$", "<sys/inotify.h>"},
+          {"bits/ipc.h$", "<sys/ipc.h>"},
+          {"bits/ipctypes.h$", "<sys/ipc.h>"},
+          {"bits/mman-linux.h$", "<sys/mman.h>"},
+          {"bits/mman.h$", "<sys/mman.h>"},
+          {"bits/msq.h$", "<sys/msg.h>"},
+          {"bits/resource.h$", "<sys/resource.h>"},
+          {"bits/sem.h$", "<sys/sem.h>"},
+          {"bits/shm.h$", "<sys/shm.h>"},
+          {"bits/signalfd.h$", "<sys/signalfd.h>"},
+          {"bits/statfs.h$", "<sys/statfs.h>"},
+          {"bits/statvfs.h$", "<sys/statvfs.h>"},
+          {"bits/timerfd.h$", "<sys/timerfd.h>"},
+          {"bits/utsname.h$", "<sys/utsname.h>"},
+          {"bits/auxv.h$", "<sys/auxv.h>"},
+          {"bits/byteswap-16.h$", "<byteswap.h>"},
+          {"bits/byteswap.h$", "<byteswap.h>"},
+          {"bits/confname.h$", "<unistd.h>"},
+          {"bits/dirent.h$", "<dirent.h>"},
+          {"bits/dlfcn.h$", "<dlfcn.h>"},
+          {"bits/elfclass.h$", "<link.h>"},
+          {"bits/endian.h$", "<endian.h>"},
+          {"bits/environments.h$", "<unistd.h>"},
+          {"bits/fcntl-linux.h$", "<fcntl.h>"},
+          {"bits/fcntl.h$", "<fcntl.h>"},
+          {"bits/in.h$", "<netinet/in.h>"},
+          {"bits/ioctl-types.h$", "<sys/ioctl.h>"},
+          {"bits/ioctls.h$", "<sys/ioctl.h>"},
+          {"bits/link.h$", "<link.h>"},
+          {"bits/mqueue.h$", "<mqueue.h>"},
+          {"bits/netdb.h$", "<netdb.h>"},
+          {"bits/param.h$", "<sys/param.h>"},
+          {"bits/poll.h$", "<sys/poll.h>"},
+          {"bits/posix_opt.h$", "<bits/posix_opt.h>"},
+          {"bits/pthreadtypes.h$", "<pthread.h>"},
+          {"bits/sched.h$", "<sched.h>"},
+          {"bits/select.h$", "<sys/select.h>"},
+          {"bits/semaphore.h$", "<semaphore.h>"},
+          {"bits/sigthread.h$", "<pthread.h>"},
+          {"bits/sockaddr.h$", "<sys/socket.h>"},
+          {"bits/socket.h$", "<sys/socket.h>"},
+          {"bits/socket_type.h$", "<sys/socket.h>"},
+          {"bits/stab.def$", "<stab.h>"},
+          {"bits/stat.h$", "<sys/stat.h>"},
+          {"bits/stropts.h$", "<stropts.h>"},
+          {"bits/syscall.h$", "<sys/syscall.h>"},
+          {"bits/syslog-path.h$", "<sys/syslog.h>"},
+          {"bits/termios.h$", "<termios.h>"},
+          {"bits/types.h$", "<sys/types.h>"},
+          {"bits/typesizes.h$", "<sys/types.h>"},
+          {"bits/uio.h$", "<sys/uio.h>"},
+          {"bits/ustat.h$", "<sys/ustat.h>"},
+          {"bits/utmp.h$", "<utmp.h>"},
+          {"bits/utmpx.h$", "<utmpx.h>"},
+          {"bits/waitflags.h$", "<sys/wait.h>"},
+          {"bits/waitstatus.h$", "<sys/wait.h>"},
+          {"bits/xtitypes.h$", "<stropts.h>"},
+      };
+  for (const auto &Pair : SystemHeaderMap)
+    Includes->addRegexMapping(Pair.first, Pair.second);
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/CanonicalIncludes.h b/src/third_party/llvm-project/clang-tools-extra/clangd/index/CanonicalIncludes.h
new file mode 100644
index 0000000..a2fdb04
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/CanonicalIncludes.h
@@ -0,0 +1,93 @@
+//===-- CanonicalIncludes.h - remap #include header -------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// At indexing time, we decide which file to #included for a symbol.
+// Usually this is the file with the canonical decl, but there are exceptions:
+// - private headers may have pragmas pointing to the matching public header.
+//   (These are "IWYU" pragmas, named after the include-what-you-use tool).
+// - the standard library is implemented in many files, without any pragmas.
+//   We have a lookup table for common standard library implementations.
+//   libstdc++ puts char_traits in bits/char_traits.h, but we #include <string>.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_CANONICALINCLUDES_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_CANONICALINCLUDES_H
+
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Regex.h"
+#include <mutex>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace clangd {
+
+/// Maps a definition location onto an #include file, based on a set of filename
+/// rules.
+/// Only const methods (i.e. mapHeader) in this class are thread safe.
+class CanonicalIncludes {
+public:
+  CanonicalIncludes() = default;
+
+  /// Adds a string-to-string mapping from \p Path to \p CanonicalPath.
+  void addMapping(llvm::StringRef Path, llvm::StringRef CanonicalPath);
+
+  /// Maps all files matching \p RE to \p CanonicalPath
+  void addRegexMapping(llvm::StringRef RE, llvm::StringRef CanonicalPath);
+
+  /// Sets the canonical include for any symbol with \p QualifiedName.
+  /// Symbol mappings take precedence over header mappings.
+  void addSymbolMapping(llvm::StringRef QualifiedName,
+                        llvm::StringRef CanonicalPath);
+
+  /// Returns the canonical include for symbol with \p QualifiedName.
+  /// \p Headers is the include stack: Headers.front() is the file declaring the
+  /// symbol, and Headers.back() is the main file.
+  llvm::StringRef mapHeader(llvm::ArrayRef<std::string> Headers,
+                            llvm::StringRef QualifiedName) const;
+
+private:
+  // A map from header patterns to header names. This needs to be mutable so
+  // that we can match again a Regex in a const function member.
+  // FIXME(ioeric): All the regexes we have so far are suffix matches. The
+  // performance could be improved by allowing only suffix matches instead of
+  // arbitrary regexes.
+  mutable std::vector<std::pair<llvm::Regex, std::string>>
+      RegexHeaderMappingTable;
+  // A map from fully qualified symbol names to header names.
+  llvm::StringMap<std::string> SymbolMapping;
+  // Guards Regex matching as it's not thread-safe.
+  mutable std::mutex RegexMutex;
+};
+
+/// Returns a CommentHandler that parses pragma comment on include files to
+/// determine when we should include a different header from the header that
+/// directly defines a symbol. Mappinps are registered with \p Includes.
+///
+/// Currently it only supports IWYU private pragma:
+/// https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/IWYUPragmas.md#iwyu-pragma-private
+std::unique_ptr<CommentHandler>
+collectIWYUHeaderMaps(CanonicalIncludes *Includes);
+
+/// Adds mapping for system headers and some special symbols (e.g. STL symbols
+/// in <iosfwd> need to be mapped individually). Approximately, the following
+/// system headers are handled:
+///   - C++ standard library e.g. bits/basic_string.h$ -> <string>
+///   - Posix library e.g. bits/pthreadtypes.h$ -> <pthread.h>
+///   - Compiler extensions, e.g. include/avx512bwintrin.h$ -> <immintrin.h>
+/// The mapping is hardcoded and hand-maintained, so it might not cover all
+/// headers.
+void addSystemHeadersMapping(CanonicalIncludes *Includes);
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_HEADERMAPCOLLECTOR_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/FileIndex.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/index/FileIndex.cpp
new file mode 100644
index 0000000..407e86a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/FileIndex.cpp
@@ -0,0 +1,109 @@
+//===--- FileIndex.cpp - Indexes for files. ------------------------ C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FileIndex.h"
+#include "SymbolCollector.h"
+#include "clang/Index/IndexingAction.h"
+#include "clang/Lex/Preprocessor.h"
+
+namespace clang {
+namespace clangd {
+
+SymbolSlab indexAST(ASTContext &AST, std::shared_ptr<Preprocessor> PP,
+                    llvm::ArrayRef<std::string> URISchemes) {
+  SymbolCollector::Options CollectorOpts;
+  // FIXME(ioeric): we might also want to collect include headers. We would need
+  // to make sure all includes are canonicalized (with CanonicalIncludes), which
+  // is not trivial given the current way of collecting symbols: we only have
+  // AST at this point, but we also need preprocessor callbacks (e.g.
+  // CommentHandler for IWYU pragma) to canonicalize includes.
+  CollectorOpts.CollectIncludePath = false;
+  CollectorOpts.CountReferences = false;
+  if (!URISchemes.empty())
+    CollectorOpts.URISchemes = URISchemes;
+  CollectorOpts.Origin = SymbolOrigin::Dynamic;
+
+  SymbolCollector Collector(std::move(CollectorOpts));
+  Collector.setPreprocessor(PP);
+  index::IndexingOptions IndexOpts;
+  // We only need declarations, because we don't count references.
+  IndexOpts.SystemSymbolFilter =
+      index::IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly;
+  IndexOpts.IndexFunctionLocals = false;
+
+  std::vector<const Decl *> TopLevelDecls(
+      AST.getTranslationUnitDecl()->decls().begin(),
+      AST.getTranslationUnitDecl()->decls().end());
+  index::indexTopLevelDecls(AST, TopLevelDecls, Collector, IndexOpts);
+
+  return Collector.takeSymbols();
+}
+
+FileIndex::FileIndex(std::vector<std::string> URISchemes)
+    : URISchemes(std::move(URISchemes)) {}
+
+void FileSymbols::update(PathRef Path, std::unique_ptr<SymbolSlab> Slab) {
+  std::lock_guard<std::mutex> Lock(Mutex);
+  if (!Slab)
+    FileToSlabs.erase(Path);
+  else
+    FileToSlabs[Path] = std::move(Slab);
+}
+
+std::shared_ptr<std::vector<const Symbol *>> FileSymbols::allSymbols() {
+  // The snapshot manages life time of symbol slabs and provides pointers of all
+  // symbols in all slabs.
+  struct Snapshot {
+    std::vector<const Symbol *> Pointers;
+    std::vector<std::shared_ptr<SymbolSlab>> KeepAlive;
+  };
+  auto Snap = std::make_shared<Snapshot>();
+  {
+    std::lock_guard<std::mutex> Lock(Mutex);
+
+    for (const auto &FileAndSlab : FileToSlabs) {
+      Snap->KeepAlive.push_back(FileAndSlab.second);
+      for (const auto &Iter : *FileAndSlab.second)
+        Snap->Pointers.push_back(&Iter);
+    }
+  }
+  auto *Pointers = &Snap->Pointers;
+  // Use aliasing constructor to keep the snapshot alive along with the
+  // pointers.
+  return {std::move(Snap), Pointers};
+}
+
+void FileIndex::update(PathRef Path, ASTContext *AST,
+                       std::shared_ptr<Preprocessor> PP) {
+  if (!AST) {
+    FSymbols.update(Path, nullptr);
+  } else {
+    assert(PP);
+    auto Slab = llvm::make_unique<SymbolSlab>();
+    *Slab = indexAST(*AST, PP, URISchemes);
+    FSymbols.update(Path, std::move(Slab));
+  }
+  auto Symbols = FSymbols.allSymbols();
+  Index.build(std::move(Symbols));
+}
+
+bool FileIndex::fuzzyFind(
+    const FuzzyFindRequest &Req,
+    llvm::function_ref<void(const Symbol &)> Callback) const {
+  return Index.fuzzyFind(Req, Callback);
+}
+
+void FileIndex::lookup(
+    const LookupRequest &Req,
+    llvm::function_ref<void(const Symbol &)> Callback) const {
+  Index.lookup(Req, Callback);
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/FileIndex.h b/src/third_party/llvm-project/clang-tools-extra/clangd/index/FileIndex.h
new file mode 100644
index 0000000..1af37d1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/FileIndex.h
@@ -0,0 +1,91 @@
+//===--- FileIndex.h - Index for files. ---------------------------- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// FileIndex implements SymbolIndex for symbols from a set of files. Symbols are
+// maintained at source-file granuality (e.g. with ASTs), and files can be
+// updated dynamically.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_FILEINDEX_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_FILEINDEX_H
+
+#include "../ClangdUnit.h"
+#include "Index.h"
+#include "MemIndex.h"
+#include "clang/Lex/Preprocessor.h"
+
+namespace clang {
+namespace clangd {
+
+/// \brief A container of Symbols from several source files. It can be updated
+/// at source-file granularity, replacing all symbols from one file with a new
+/// set.
+///
+/// This implements a snapshot semantics for symbols in a file. Each update to a
+/// file will create a new snapshot for all symbols in the file. Snapshots are
+/// managed with shared pointers that are shared between this class and the
+/// users. For each file, this class only stores a pointer pointing to the
+/// newest snapshot, and an outdated snapshot is deleted by the last owner of
+/// the snapshot, either this class or the symbol index.
+///
+/// The snapshot semantics keeps critical sections minimal since we only need
+/// locking when we swap or obtain refereces to snapshots.
+class FileSymbols {
+public:
+  /// \brief Updates all symbols in a file. If \p Slab is nullptr, symbols for
+  /// \p Path will be removed.
+  void update(PathRef Path, std::unique_ptr<SymbolSlab> Slab);
+
+  // The shared_ptr keeps the symbols alive
+  std::shared_ptr<std::vector<const Symbol *>> allSymbols();
+
+private:
+  mutable std::mutex Mutex;
+
+  /// \brief Stores the latest snapshots for all active files.
+  llvm::StringMap<std::shared_ptr<SymbolSlab>> FileToSlabs;
+};
+
+/// \brief This manages symbls from files and an in-memory index on all symbols.
+class FileIndex : public SymbolIndex {
+public:
+  /// If URISchemes is empty, the default schemes in SymbolCollector will be
+  /// used.
+  FileIndex(std::vector<std::string> URISchemes = {});
+
+  /// \brief Update symbols in \p Path with symbols in \p AST. If \p AST is
+  /// nullptr, this removes all symbols in the file.
+  /// If \p AST is not null, \p PP cannot be null and it should be the
+  /// preprocessor that was used to build \p AST.
+  void update(PathRef Path, ASTContext *AST, std::shared_ptr<Preprocessor> PP);
+
+  bool
+  fuzzyFind(const FuzzyFindRequest &Req,
+            llvm::function_ref<void(const Symbol &)> Callback) const override;
+
+  void lookup(const LookupRequest &Req,
+              llvm::function_ref<void(const Symbol &)> Callback) const override;
+
+private:
+  FileSymbols FSymbols;
+  MemIndex Index;
+  std::vector<std::string> URISchemes;
+};
+
+/// Retrieves namespace and class level symbols in \p AST.
+/// Exposed to assist in unit tests.
+/// If URISchemes is empty, the default schemes in SymbolCollector will be used.
+SymbolSlab indexAST(ASTContext &AST, std::shared_ptr<Preprocessor> PP,
+                    llvm::ArrayRef<std::string> URISchemes = {});
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_FILEINDEX_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/Index.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/index/Index.cpp
new file mode 100644
index 0000000..1ae3d54
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/Index.cpp
@@ -0,0 +1,138 @@
+//===--- Index.cpp -----------------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Index.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/SHA1.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace clangd {
+using namespace llvm;
+
+raw_ostream &operator<<(raw_ostream &OS, const SymbolLocation &L) {
+  if (!L)
+    return OS << "(none)";
+  return OS << L.FileURI << "[" << L.Start.Line << ":" << L.Start.Column << "-"
+            << L.End.Line << ":" << L.End.Column << ")";
+}
+
+SymbolID::SymbolID(StringRef USR)
+    : HashValue(SHA1::hash(arrayRefFromStringRef(USR))) {}
+
+raw_ostream &operator<<(raw_ostream &OS, const SymbolID &ID) {
+  OS << toHex(toStringRef(ID.HashValue));
+  return OS;
+}
+
+std::string SymbolID::str() const {
+  std::string ID;
+  llvm::raw_string_ostream OS(ID);
+  OS << *this;
+  return OS.str();
+}
+
+void operator>>(StringRef Str, SymbolID &ID) {
+  std::string HexString = fromHex(Str);
+  assert(HexString.size() == ID.HashValue.size());
+  std::copy(HexString.begin(), HexString.end(), ID.HashValue.begin());
+}
+
+raw_ostream &operator<<(raw_ostream &OS, SymbolOrigin O) {
+  if (O == SymbolOrigin::Unknown)
+    return OS << "unknown";
+  constexpr static char Sigils[] = "ADSM4567";
+  for (unsigned I = 0; I < sizeof(Sigils); ++I)
+    if (static_cast<uint8_t>(O) & 1u << I)
+      OS << Sigils[I];
+  return OS;
+}
+
+raw_ostream &operator<<(raw_ostream &OS, const Symbol &S) {
+  return OS << S.Scope << S.Name;
+}
+
+double quality(const Symbol &S) {
+  // This avoids a sharp gradient for tail symbols, and also neatly avoids the
+  // question of whether 0 references means a bad symbol or missing data.
+  if (S.References < 3)
+    return 1;
+  return std::log(S.References);
+}
+
+SymbolSlab::const_iterator SymbolSlab::find(const SymbolID &ID) const {
+  auto It = std::lower_bound(Symbols.begin(), Symbols.end(), ID,
+                             [](const Symbol &S, const SymbolID &I) {
+                               return S.ID < I;
+                             });
+  if (It != Symbols.end() && It->ID == ID)
+    return It;
+  return Symbols.end();
+}
+
+// Copy the underlying data of the symbol into the owned arena.
+static void own(Symbol &S, DenseSet<StringRef> &Strings,
+                BumpPtrAllocator &Arena) {
+  // Intern replaces V with a reference to the same string owned by the arena.
+  auto Intern = [&](StringRef &V) {
+    auto R = Strings.insert(V);
+    if (R.second) { // New entry added to the table, copy the string.
+      *R.first = V.copy(Arena);
+    }
+    V = *R.first;
+  };
+
+  // We need to copy every StringRef field onto the arena.
+  Intern(S.Name);
+  Intern(S.Scope);
+  Intern(S.CanonicalDeclaration.FileURI);
+  Intern(S.Definition.FileURI);
+
+  Intern(S.Signature);
+  Intern(S.CompletionSnippetSuffix);
+
+  if (S.Detail) {
+    // Copy values of StringRefs into arena.
+    auto *Detail = Arena.Allocate<Symbol::Details>();
+    *Detail = *S.Detail;
+    // Intern the actual strings.
+    Intern(Detail->Documentation);
+    Intern(Detail->ReturnType);
+    Intern(Detail->IncludeHeader);
+    // Replace the detail pointer with our copy.
+    S.Detail = Detail;
+  }
+}
+
+void SymbolSlab::Builder::insert(const Symbol &S) {
+  auto R = SymbolIndex.try_emplace(S.ID, Symbols.size());
+  if (R.second) {
+    Symbols.push_back(S);
+    own(Symbols.back(), Strings, Arena);
+  } else {
+    auto &Copy = Symbols[R.first->second] = S;
+    own(Copy, Strings, Arena);
+  }
+}
+
+SymbolSlab SymbolSlab::Builder::build() && {
+  Symbols = {Symbols.begin(), Symbols.end()}; // Force shrink-to-fit.
+  // Sort symbols so the slab can binary search over them.
+  std::sort(Symbols.begin(), Symbols.end(),
+            [](const Symbol &L, const Symbol &R) { return L.ID < R.ID; });
+  // We may have unused strings from overwritten symbols. Build a new arena.
+  BumpPtrAllocator NewArena;
+  DenseSet<StringRef> Strings;
+  for (auto &S : Symbols)
+    own(S, Strings, NewArena);
+  return SymbolSlab(std::move(NewArena), std::move(Symbols));
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/Index.h b/src/third_party/llvm-project/clang-tools-extra/clangd/index/Index.h
new file mode 100644
index 0000000..18ed05f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/Index.h
@@ -0,0 +1,343 @@
+//===--- Index.h ------------------------------------------------*- 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_INDEX_INDEX_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_INDEX_H
+
+#include "clang/Index/IndexSymbol.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringExtras.h"
+#include <array>
+#include <string>
+
+namespace clang {
+namespace clangd {
+
+struct SymbolLocation {
+  // Specify a position (Line, Column) of symbol. Using Line/Column allows us to
+  // build LSP responses without reading the file content.
+  struct Position {
+    uint32_t Line = 0; // 0-based
+    // Using UTF-16 code units.
+    uint32_t Column = 0; // 0-based
+    bool operator==(const Position& P) const {
+      return Line == P.Line && Column == P.Column;
+    }
+  };
+
+  // The URI of the source file where a symbol occurs.
+  llvm::StringRef FileURI;
+
+  /// The symbol range, using half-open range [Start, End).
+  Position Start;
+  Position End;
+
+  explicit operator bool() const { return !FileURI.empty(); }
+  bool operator==(const SymbolLocation& Loc) const {
+    return std::tie(FileURI, Start, End) ==
+           std::tie(Loc.FileURI, Loc.Start, Loc.End);
+  }
+};
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const SymbolLocation &);
+
+// The class identifies a particular C++ symbol (class, function, method, etc).
+//
+// As USRs (Unified Symbol Resolution) could be large, especially for functions
+// with long type arguments, SymbolID is using 160-bits SHA1(USR) values to
+// guarantee the uniqueness of symbols while using a relatively small amount of
+// memory (vs storing USRs directly).
+//
+// SymbolID can be used as key in the symbol indexes to lookup the symbol.
+class SymbolID {
+public:
+  SymbolID() = default;
+  explicit SymbolID(llvm::StringRef USR);
+
+  bool operator==(const SymbolID &Sym) const {
+    return HashValue == Sym.HashValue;
+  }
+  bool operator<(const SymbolID &Sym) const {
+    return HashValue < Sym.HashValue;
+  }
+
+  // Returns a 40-bytes hex encoded string.
+  std::string str() const;
+
+private:
+  static constexpr unsigned HashByteLength = 20;
+
+  friend llvm::hash_code hash_value(const SymbolID &ID) {
+    // We already have a good hash, just return the first bytes.
+    static_assert(sizeof(size_t) <= HashByteLength, "size_t longer than SHA1!");
+    size_t Result;
+    memcpy(&Result, ID.HashValue.data(), sizeof(size_t));
+    return llvm::hash_code(Result);
+  }
+  friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+                                       const SymbolID &ID);
+  friend void operator>>(llvm::StringRef Str, SymbolID &ID);
+
+  std::array<uint8_t, HashByteLength> HashValue;
+};
+
+// Write SymbolID into the given stream. SymbolID is encoded as a 40-bytes
+// hex string.
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolID &ID);
+
+// Construct SymbolID from a hex string.
+// The HexStr is required to be a 40-bytes hex string, which is encoded from the
+// "<<" operator.
+void operator>>(llvm::StringRef HexStr, SymbolID &ID);
+
+} // namespace clangd
+} // namespace clang
+namespace llvm {
+// Support SymbolIDs as DenseMap keys.
+template <> struct DenseMapInfo<clang::clangd::SymbolID> {
+  static inline clang::clangd::SymbolID getEmptyKey() {
+    static clang::clangd::SymbolID EmptyKey("EMPTYKEY");
+    return EmptyKey;
+  }
+  static inline clang::clangd::SymbolID getTombstoneKey() {
+    static clang::clangd::SymbolID TombstoneKey("TOMBSTONEKEY");
+    return TombstoneKey;
+  }
+  static unsigned getHashValue(const clang::clangd::SymbolID &Sym) {
+    return hash_value(Sym);
+  }
+  static bool isEqual(const clang::clangd::SymbolID &LHS,
+                      const clang::clangd::SymbolID &RHS) {
+    return LHS == RHS;
+  }
+};
+} // namespace llvm
+namespace clang {
+namespace clangd {
+
+// Describes the source of information about a symbol.
+// Mainly useful for debugging, e.g. understanding code completion reuslts.
+// This is a bitfield as information can be combined from several sources.
+enum class SymbolOrigin : uint8_t {
+  Unknown = 0,
+  AST = 1 << 0,     // Directly from the AST (indexes should not set this).
+  Dynamic = 1 << 1, // From the dynamic index of opened files.
+  Static = 1 << 2,  // From the static, externally-built index.
+  Merge = 1 << 3,   // A non-trivial index merge was performed.
+  // Remaining bits reserved for index implementations.
+};
+inline SymbolOrigin operator|(SymbolOrigin A, SymbolOrigin B) {
+  return static_cast<SymbolOrigin>(static_cast<uint8_t>(A) |
+                                   static_cast<uint8_t>(B));
+}
+inline SymbolOrigin &operator|=(SymbolOrigin &A, SymbolOrigin B) {
+  return A = A | B;
+}
+inline SymbolOrigin operator&(SymbolOrigin A, SymbolOrigin B) {
+  return static_cast<SymbolOrigin>(static_cast<uint8_t>(A) &
+                                   static_cast<uint8_t>(B));
+}
+raw_ostream &operator<<(raw_ostream &, SymbolOrigin);
+
+// The class presents a C++ symbol, e.g. class, function.
+//
+// WARNING: Symbols do not own much of their underlying data - typically strings
+// are owned by a SymbolSlab. They should be treated as non-owning references.
+// Copies are shallow.
+// When adding new unowned data fields to Symbol, remember to update:
+//   - SymbolSlab::Builder in Index.cpp, to copy them to the slab's storage.
+//   - mergeSymbol in Merge.cpp, to properly combine two Symbols.
+//
+// A fully documented symbol can be split as:
+// size_type std::map<k, t>::count(const K& key) const
+// | Return  |     Scope     |Name|    Signature     |
+// We split up these components to allow display flexibility later.
+struct Symbol {
+  // The ID of the symbol.
+  SymbolID ID;
+  // The symbol information, like symbol kind.
+  index::SymbolInfo SymInfo;
+  // The unqualified name of the symbol, e.g. "bar" (for ns::bar).
+  llvm::StringRef Name;
+  // The containing namespace. e.g. "" (global), "ns::" (top-level namespace).
+  llvm::StringRef Scope;
+  // The location of the symbol's definition, if one was found.
+  // This just covers the symbol name (e.g. without class/function body).
+  SymbolLocation Definition;
+  // The location of the preferred declaration of the symbol.
+  // This just covers the symbol name.
+  // This may be the same as Definition.
+  //
+  // A C++ symbol may have multiple declarations, and we pick one to prefer.
+  //   * For classes, the canonical declaration should be the definition.
+  //   * For non-inline functions, the canonical declaration typically appears
+  //     in the ".h" file corresponding to the definition.
+  SymbolLocation CanonicalDeclaration;
+  // The number of translation units that reference this symbol from their main
+  // file. This number is only meaningful if aggregated in an index.
+  unsigned References = 0;
+  /// Whether or not this symbol is meant to be used for the code completion.
+  /// See also isIndexedForCodeCompletion().
+  bool IsIndexedForCodeCompletion = false;
+  /// Where this symbol came from. Usually an index provides a constant value.
+  SymbolOrigin Origin = SymbolOrigin::Unknown;
+  /// A brief description of the symbol that can be appended in the completion
+  /// candidate list. For example, "(X x, Y y) const" is a function signature.
+  llvm::StringRef Signature;
+  /// What to insert when completing this symbol, after the symbol name.
+  /// This is in LSP snippet syntax (e.g. "({$0})" for a no-args function).
+  /// (When snippets are disabled, the symbol name alone is used).
+  llvm::StringRef CompletionSnippetSuffix;
+
+  /// Optional symbol details that are not required to be set. For example, an
+  /// index fuzzy match can return a large number of symbol candidates, and it
+  /// is preferable to send only core symbol information in the batched results
+  /// and have clients resolve full symbol information for a specific candidate
+  /// if needed.
+  struct Details {
+    /// Documentation including comment for the symbol declaration.
+    llvm::StringRef Documentation;
+    /// Type when this symbol is used in an expression. (Short display form).
+    /// e.g. return type of a function, or type of a variable.
+    llvm::StringRef ReturnType;
+    /// This can be either a URI of the header to be #include'd for this symbol,
+    /// or a literal header quoted with <> or "" that is suitable to be included
+    /// directly. When this is a URI, the exact #include path needs to be
+    /// calculated according to the URI scheme.
+    ///
+    /// This is a canonical include for the symbol and can be different from
+    /// FileURI in the CanonicalDeclaration.
+    llvm::StringRef IncludeHeader;
+  };
+
+  // Optional details of the symbol.
+  const Details *Detail = nullptr;
+
+  // FIXME: add all occurrences support.
+  // FIXME: add extra fields for index scoring signals.
+};
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S);
+
+// Computes query-independent quality score for a Symbol.
+// This currently falls in the range [1, ln(#indexed documents)].
+// FIXME: this should probably be split into symbol -> signals
+//        and signals -> score, so it can be reused for Sema completions.
+double quality(const Symbol &S);
+
+// An immutable symbol container that stores a set of symbols.
+// The container will maintain the lifetime of the symbols.
+class SymbolSlab {
+public:
+  using const_iterator = std::vector<Symbol>::const_iterator;
+  using iterator = const_iterator;
+
+  SymbolSlab() = default;
+
+  const_iterator begin() const { return Symbols.begin(); }
+  const_iterator end() const { return Symbols.end(); }
+  const_iterator find(const SymbolID &SymID) const;
+
+  size_t size() const { return Symbols.size(); }
+  // Estimates the total memory usage.
+  size_t bytes() const {
+    return sizeof(*this) + Arena.getTotalMemory() +
+           Symbols.capacity() * sizeof(Symbol);
+  }
+
+  // SymbolSlab::Builder is a mutable container that can 'freeze' to SymbolSlab.
+  // The frozen SymbolSlab will use less memory.
+  class Builder {
+  public:
+    // Adds a symbol, overwriting any existing one with the same ID.
+    // This is a deep copy: underlying strings will be owned by the slab.
+    void insert(const Symbol &S);
+
+    // Returns the symbol with an ID, if it exists. Valid until next insert().
+    const Symbol *find(const SymbolID &ID) {
+      auto I = SymbolIndex.find(ID);
+      return I == SymbolIndex.end() ? nullptr : &Symbols[I->second];
+    }
+
+    // Consumes the builder to finalize the slab.
+    SymbolSlab build() &&;
+
+  private:
+    llvm::BumpPtrAllocator Arena;
+    // Intern table for strings. Contents are on the arena.
+    llvm::DenseSet<llvm::StringRef> Strings;
+    std::vector<Symbol> Symbols;
+    // Values are indices into Symbols vector.
+    llvm::DenseMap<SymbolID, size_t> SymbolIndex;
+  };
+
+private:
+  SymbolSlab(llvm::BumpPtrAllocator Arena, std::vector<Symbol> Symbols)
+      : Arena(std::move(Arena)), Symbols(std::move(Symbols)) {}
+
+  llvm::BumpPtrAllocator Arena; // Owns Symbol data that the Symbols do not.
+  std::vector<Symbol> Symbols;  // Sorted by SymbolID to allow lookup.
+};
+
+struct FuzzyFindRequest {
+  /// \brief A query string for the fuzzy find. This is matched against symbols'
+  /// un-qualified identifiers and should not contain qualifiers like "::".
+  std::string Query;
+  /// \brief If this is non-empty, symbols must be in at least one of the scopes
+  /// (e.g. namespaces) excluding nested scopes. For example, if a scope "xyz::"
+  /// is provided, the matched symbols must be defined in namespace xyz but not
+  /// namespace xyz::abc.
+  ///
+  /// The global scope is "", a top level scope is "foo::", etc.
+  std::vector<std::string> Scopes;
+  /// \brief The number of top candidates to return. The index may choose to
+  /// return more than this, e.g. if it doesn't know which candidates are best.
+  size_t MaxCandidateCount = UINT_MAX;
+  /// If set to true, only symbols for completion support will be considered.
+  bool RestrictForCodeCompletion = false;
+  /// Contextually relevant files (e.g. the file we're code-completing in).
+  /// Paths should be absolute.
+  std::vector<std::string> ProximityPaths;
+};
+
+struct LookupRequest {
+  llvm::DenseSet<SymbolID> IDs;
+};
+
+/// \brief Interface for symbol indexes that can be used for searching or
+/// matching symbols among a set of symbols based on names or unique IDs.
+class SymbolIndex {
+public:
+  virtual ~SymbolIndex() = default;
+
+  /// \brief Matches symbols in the index fuzzily and applies \p Callback on
+  /// each matched symbol before returning.
+  /// If returned Symbols are used outside Callback, they must be deep-copied!
+  ///
+  /// Returns true if there may be more results (limited by MaxCandidateCount).
+  virtual bool
+  fuzzyFind(const FuzzyFindRequest &Req,
+            llvm::function_ref<void(const Symbol &)> Callback) const = 0;
+
+  /// Looks up symbols with any of the given symbol IDs and applies \p Callback
+  /// on each matched symbol.
+  /// The returned symbol must be deep-copied if it's used outside Callback.
+  virtual void
+  lookup(const LookupRequest &Req,
+         llvm::function_ref<void(const Symbol &)> Callback) const = 0;
+
+  // FIXME: add interfaces for more index use cases:
+  //  - getAllOccurrences(SymbolID);
+};
+
+} // namespace clangd
+} // namespace clang
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_INDEX_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/MemIndex.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/index/MemIndex.cpp
new file mode 100644
index 0000000..1a38386
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/MemIndex.cpp
@@ -0,0 +1,91 @@
+//===--- MemIndex.cpp - Dynamic in-memory symbol index. ----------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===-------------------------------------------------------------------===//
+
+#include "MemIndex.h"
+#include "../FuzzyMatch.h"
+#include "../Logger.h"
+#include <queue>
+
+namespace clang {
+namespace clangd {
+
+void MemIndex::build(std::shared_ptr<std::vector<const Symbol *>> Syms) {
+  llvm::DenseMap<SymbolID, const Symbol *> TempIndex;
+  for (const Symbol *Sym : *Syms)
+    TempIndex[Sym->ID] = Sym;
+
+  // Swap out the old symbols and index.
+  {
+    std::lock_guard<std::mutex> Lock(Mutex);
+    Index = std::move(TempIndex);
+    Symbols = std::move(Syms); // Relase old symbols.
+  }
+}
+
+bool MemIndex::fuzzyFind(
+    const FuzzyFindRequest &Req,
+    llvm::function_ref<void(const Symbol &)> Callback) const {
+  assert(!StringRef(Req.Query).contains("::") &&
+         "There must be no :: in query.");
+
+  std::priority_queue<std::pair<float, const Symbol *>> Top;
+  FuzzyMatcher Filter(Req.Query);
+  bool More = false;
+  {
+    std::lock_guard<std::mutex> Lock(Mutex);
+    for (const auto Pair : Index) {
+      const Symbol *Sym = Pair.second;
+
+      // Exact match against all possible scopes.
+      if (!Req.Scopes.empty() && !llvm::is_contained(Req.Scopes, Sym->Scope))
+        continue;
+      if (Req.RestrictForCodeCompletion && !Sym->IsIndexedForCodeCompletion)
+        continue;
+
+      if (auto Score = Filter.match(Sym->Name)) {
+        Top.emplace(-*Score * quality(*Sym), Sym);
+        if (Top.size() > Req.MaxCandidateCount) {
+          More = true;
+          Top.pop();
+        }
+      }
+    }
+    for (; !Top.empty(); Top.pop())
+      Callback(*Top.top().second);
+  }
+  return More;
+}
+
+void MemIndex::lookup(const LookupRequest &Req,
+                      llvm::function_ref<void(const Symbol &)> Callback) const {
+  for (const auto &ID : Req.IDs) {
+    auto I = Index.find(ID);
+    if (I != Index.end())
+      Callback(*I->second);
+  }
+}
+
+std::unique_ptr<SymbolIndex> MemIndex::build(SymbolSlab Slab) {
+  struct Snapshot {
+    SymbolSlab Slab;
+    std::vector<const Symbol *> Pointers;
+  };
+  auto Snap = std::make_shared<Snapshot>();
+  Snap->Slab = std::move(Slab);
+  for (auto &Sym : Snap->Slab)
+    Snap->Pointers.push_back(&Sym);
+  auto S = std::shared_ptr<std::vector<const Symbol *>>(std::move(Snap),
+                                                        &Snap->Pointers);
+  auto MemIdx = llvm::make_unique<MemIndex>();
+  MemIdx->build(std::move(S));
+  return std::move(MemIdx);
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/MemIndex.h b/src/third_party/llvm-project/clang-tools-extra/clangd/index/MemIndex.h
new file mode 100644
index 0000000..3147a6c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/MemIndex.h
@@ -0,0 +1,49 @@
+//===--- MemIndex.h - Dynamic in-memory symbol index. -------------- 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_INDEX_MEMINDEX_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_MEMINDEX_H
+
+#include "Index.h"
+#include <mutex>
+
+namespace clang {
+namespace clangd {
+
+/// \brief This implements an index for a (relatively small) set of symbols that
+/// can be easily managed in memory.
+class MemIndex : public SymbolIndex {
+public:
+  /// \brief (Re-)Build index for `Symbols`. All symbol pointers must remain
+  /// accessible as long as `Symbols` is kept alive.
+  void build(std::shared_ptr<std::vector<const Symbol *>> Symbols);
+
+  /// \brief Build index from a symbol slab.
+  static std::unique_ptr<SymbolIndex> build(SymbolSlab Slab);
+
+  bool
+  fuzzyFind(const FuzzyFindRequest &Req,
+            llvm::function_ref<void(const Symbol &)> Callback) const override;
+
+  virtual void
+  lookup(const LookupRequest &Req,
+         llvm::function_ref<void(const Symbol &)> Callback) const override;
+
+private:
+  std::shared_ptr<std::vector<const Symbol *>> Symbols;
+  // Index is a set of symbols that are deduplicated by symbol IDs.
+  // FIXME: build smarter index structure.
+  llvm::DenseMap<SymbolID, const Symbol *> Index;
+  mutable std::mutex Mutex;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_MEMINDEX_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/Merge.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/index/Merge.cpp
new file mode 100644
index 0000000..da31f8b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/Merge.cpp
@@ -0,0 +1,128 @@
+//===--- Merge.h ------------------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+#include "Merge.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/raw_ostream.h"
+namespace clang {
+namespace clangd {
+namespace {
+using namespace llvm;
+
+class MergedIndex : public SymbolIndex {
+ public:
+   MergedIndex(const SymbolIndex *Dynamic, const SymbolIndex *Static)
+       : Dynamic(Dynamic), Static(Static) {}
+
+   // FIXME: Deleted symbols in dirty files are still returned (from Static).
+   //        To identify these eliminate these, we should:
+   //          - find the generating file from each Symbol which is Static-only
+   //          - ask Dynamic if it has that file (needs new SymbolIndex method)
+   //          - if so, drop the Symbol.
+   bool fuzzyFind(const FuzzyFindRequest &Req,
+                  function_ref<void(const Symbol &)> Callback) const override {
+     // We can't step through both sources in parallel. So:
+     //  1) query all dynamic symbols, slurping results into a slab
+     //  2) query the static symbols, for each one:
+     //    a) if it's not in the dynamic slab, yield it directly
+     //    b) if it's in the dynamic slab, merge it and yield the result
+     //  3) now yield all the dynamic symbols we haven't processed.
+     bool More = false; // We'll be incomplete if either source was.
+     SymbolSlab::Builder DynB;
+     More |= Dynamic->fuzzyFind(Req, [&](const Symbol &S) { DynB.insert(S); });
+     SymbolSlab Dyn = std::move(DynB).build();
+
+     DenseSet<SymbolID> SeenDynamicSymbols;
+     Symbol::Details Scratch;
+     More |= Static->fuzzyFind(Req, [&](const Symbol &S) {
+       auto DynS = Dyn.find(S.ID);
+       if (DynS == Dyn.end())
+         return Callback(S);
+       SeenDynamicSymbols.insert(S.ID);
+       Callback(mergeSymbol(*DynS, S, &Scratch));
+     });
+     for (const Symbol &S : Dyn)
+       if (!SeenDynamicSymbols.count(S.ID))
+         Callback(S);
+     return More;
+  }
+
+  void
+  lookup(const LookupRequest &Req,
+         llvm::function_ref<void(const Symbol &)> Callback) const override {
+    SymbolSlab::Builder B;
+
+    Dynamic->lookup(Req, [&](const Symbol &S) { B.insert(S); });
+
+    auto RemainingIDs = Req.IDs;
+    Symbol::Details Scratch;
+    Static->lookup(Req, [&](const Symbol &S) {
+      const Symbol *Sym = B.find(S.ID);
+      RemainingIDs.erase(S.ID);
+      if (!Sym)
+        Callback(S);
+      else
+        Callback(mergeSymbol(*Sym, S, &Scratch));
+    });
+    for (const auto &ID : RemainingIDs)
+      if (const Symbol *Sym = B.find(ID))
+        Callback(*Sym);
+  }
+
+private:
+  const SymbolIndex *Dynamic, *Static;
+};
+} // namespace
+
+Symbol
+mergeSymbol(const Symbol &L, const Symbol &R, Symbol::Details *Scratch) {
+  assert(L.ID == R.ID);
+  // We prefer information from TUs that saw the definition.
+  // Classes: this is the def itself. Functions: hopefully the header decl.
+  // If both did (or both didn't), continue to prefer L over R.
+  bool PreferR = R.Definition && !L.Definition;
+  Symbol S = PreferR ? R : L;        // The target symbol we're merging into.
+  const Symbol &O = PreferR ? L : R; // The "other" less-preferred symbol.
+
+  // For each optional field, fill it from O if missing in S.
+  // (It might be missing in O too, but that's a no-op).
+  if (!S.Definition)
+    S.Definition = O.Definition;
+  if (!S.CanonicalDeclaration)
+    S.CanonicalDeclaration = O.CanonicalDeclaration;
+  S.References += O.References;
+  if (S.Signature == "")
+    S.Signature = O.Signature;
+  if (S.CompletionSnippetSuffix == "")
+    S.CompletionSnippetSuffix = O.CompletionSnippetSuffix;
+
+  if (O.Detail) {
+    if (S.Detail) {
+      // Copy into scratch space so we can merge.
+      *Scratch = *S.Detail;
+      if (Scratch->Documentation == "")
+        Scratch->Documentation = O.Detail->Documentation;
+      if (Scratch->ReturnType == "")
+        Scratch->ReturnType = O.Detail->ReturnType;
+      if (Scratch->IncludeHeader == "")
+        Scratch->IncludeHeader = O.Detail->IncludeHeader;
+      S.Detail = Scratch;
+    } else
+      S.Detail = O.Detail;
+  }
+
+  S.Origin |= O.Origin | SymbolOrigin::Merge;
+  return S;
+}
+
+std::unique_ptr<SymbolIndex> mergeIndex(const SymbolIndex *Dynamic,
+                                        const SymbolIndex *Static) {
+  return llvm::make_unique<MergedIndex>(Dynamic, Static);
+}
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/Merge.h b/src/third_party/llvm-project/clang-tools-extra/clangd/index/Merge.h
new file mode 100644
index 0000000..b9b58fd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/Merge.h
@@ -0,0 +1,29 @@
+//===--- Merge.h ------------------------------------------------*- 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_INDEX_MERGE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_MERGE_H
+#include "Index.h"
+namespace clang {
+namespace clangd {
+
+// Merge symbols L and R, preferring data from L in case of conflict.
+// The two symbols must have the same ID.
+// Returned symbol may contain data owned by either source.
+Symbol mergeSymbol(const Symbol &L, const Symbol &R, Symbol::Details *Scratch);
+
+// mergedIndex returns a composite index based on two provided Indexes:
+//  - the Dynamic index covers few files, but is relatively up-to-date.
+//  - the Static index covers a bigger set of files, but is relatively stale.
+// The returned index attempts to combine results, and avoid duplicates.
+std::unique_ptr<SymbolIndex> mergeIndex(const SymbolIndex *Dynamic,
+                                        const SymbolIndex *Static);
+
+} // namespace clangd
+} // namespace clang
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/SymbolCollector.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/index/SymbolCollector.cpp
new file mode 100644
index 0000000..5c80f38
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/SymbolCollector.cpp
@@ -0,0 +1,518 @@
+//===--- SymbolCollector.cpp -------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolCollector.h"
+#include "../AST.h"
+#include "../CodeComplete.h"
+#include "../CodeCompletionStrings.h"
+#include "../Logger.h"
+#include "../SourceCode.h"
+#include "../URI.h"
+#include "CanonicalIncludes.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Index/IndexSymbol.h"
+#include "clang/Index/USRGeneration.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+
+namespace clang {
+namespace clangd {
+
+namespace {
+/// If \p ND is a template specialization, returns the described template.
+/// Otherwise, returns \p ND.
+const NamedDecl &getTemplateOrThis(const NamedDecl &ND) {
+  if (auto T = ND.getDescribedTemplate())
+    return *T;
+  return ND;
+}
+
+// Returns a URI of \p Path. Firstly, this makes the \p Path absolute using the
+// current working directory of the given SourceManager if the Path is not an
+// absolute path. If failed, this resolves relative paths against \p FallbackDir
+// to get an absolute path. Then, this tries creating an URI for the absolute
+// path with schemes specified in \p Opts. This returns an URI with the first
+// working scheme, if there is any; otherwise, this returns None.
+//
+// The Path can be a path relative to the build directory, or retrieved from
+// the SourceManager.
+llvm::Optional<std::string> toURI(const SourceManager &SM, StringRef Path,
+                                  const SymbolCollector::Options &Opts) {
+  llvm::SmallString<128> AbsolutePath(Path);
+  if (std::error_code EC =
+          SM.getFileManager().getVirtualFileSystem()->makeAbsolute(
+              AbsolutePath))
+    log("Warning: could not make absolute file: {0}", EC.message());
+  if (llvm::sys::path::is_absolute(AbsolutePath)) {
+    // Handle the symbolic link path case where the current working directory
+    // (getCurrentWorkingDirectory) is a symlink./ We always want to the real
+    // file path (instead of the symlink path) for the  C++ symbols.
+    //
+    // Consider the following example:
+    //
+    //   src dir: /project/src/foo.h
+    //   current working directory (symlink): /tmp/build -> /project/src/
+    //
+    // The file path of Symbol is "/project/src/foo.h" instead of
+    // "/tmp/build/foo.h"
+    if (const DirectoryEntry *Dir = SM.getFileManager().getDirectory(
+            llvm::sys::path::parent_path(AbsolutePath.str()))) {
+      StringRef DirName = SM.getFileManager().getCanonicalName(Dir);
+      SmallString<128> AbsoluteFilename;
+      llvm::sys::path::append(AbsoluteFilename, DirName,
+                              llvm::sys::path::filename(AbsolutePath.str()));
+      AbsolutePath = AbsoluteFilename;
+    }
+  } else if (!Opts.FallbackDir.empty()) {
+    llvm::sys::fs::make_absolute(Opts.FallbackDir, AbsolutePath);
+  }
+
+  llvm::sys::path::remove_dots(AbsolutePath, /*remove_dot_dot=*/true);
+
+  std::string ErrMsg;
+  for (const auto &Scheme : Opts.URISchemes) {
+    auto U = URI::create(AbsolutePath, Scheme);
+    if (U)
+      return U->toString();
+    ErrMsg += llvm::toString(U.takeError()) + "\n";
+  }
+  log("Failed to create an URI for file {0}: {1}", AbsolutePath, ErrMsg);
+  return llvm::None;
+}
+
+// All proto generated headers should start with this line.
+static const char *PROTO_HEADER_COMMENT =
+    "// Generated by the protocol buffer compiler.  DO NOT EDIT!";
+
+// Checks whether the decl is a private symbol in a header generated by
+// protobuf compiler.
+// To identify whether a proto header is actually generated by proto compiler,
+// we check whether it starts with PROTO_HEADER_COMMENT.
+// FIXME: make filtering extensible when there are more use cases for symbol
+// filters.
+bool isPrivateProtoDecl(const NamedDecl &ND) {
+  const auto &SM = ND.getASTContext().getSourceManager();
+  auto Loc = findNameLoc(&ND);
+  auto FileName = SM.getFilename(Loc);
+  if (!FileName.endswith(".proto.h") && !FileName.endswith(".pb.h"))
+    return false;
+  auto FID = SM.getFileID(Loc);
+  // Double check that this is an actual protobuf header.
+  if (!SM.getBufferData(FID).startswith(PROTO_HEADER_COMMENT))
+    return false;
+
+  // ND without identifier can be operators.
+  if (ND.getIdentifier() == nullptr)
+    return false;
+  auto Name = ND.getIdentifier()->getName();
+  if (!Name.contains('_'))
+    return false;
+  // Nested proto entities (e.g. Message::Nested) have top-level decls
+  // that shouldn't be used (Message_Nested). Ignore them completely.
+  // The nested entities are dangling type aliases, we may want to reconsider
+  // including them in the future.
+  // For enum constants, SOME_ENUM_CONSTANT is not private and should be
+  // indexed. Outer_INNER is private. This heuristic relies on naming style, it
+  // will include OUTER_INNER and exclude some_enum_constant.
+  // FIXME: the heuristic relies on naming style (i.e. no underscore in
+  // user-defined names) and can be improved.
+  return (ND.getKind() != Decl::EnumConstant) ||
+         std::any_of(Name.begin(), Name.end(), islower);
+}
+
+// We only collect #include paths for symbols that are suitable for global code
+// completion, except for namespaces since #include path for a namespace is hard
+// to define.
+bool shouldCollectIncludePath(index::SymbolKind Kind) {
+  using SK = index::SymbolKind;
+  switch (Kind) {
+  case SK::Macro:
+  case SK::Enum:
+  case SK::Struct:
+  case SK::Class:
+  case SK::Union:
+  case SK::TypeAlias:
+  case SK::Using:
+  case SK::Function:
+  case SK::Variable:
+  case SK::EnumConstant:
+    return true;
+  default:
+    return false;
+  }
+}
+
+/// Gets a canonical include (URI of the header or <header>  or "header") for
+/// header of \p Loc.
+/// Returns None if fails to get include header for \p Loc.
+llvm::Optional<std::string>
+getIncludeHeader(llvm::StringRef QName, const SourceManager &SM,
+                 SourceLocation Loc, const SymbolCollector::Options &Opts) {
+  std::vector<std::string> Headers;
+  // Collect the #include stack.
+  while (true) {
+    if (!Loc.isValid())
+      break;
+    auto FilePath = SM.getFilename(Loc);
+    if (FilePath.empty())
+      break;
+    Headers.push_back(FilePath);
+    if (SM.isInMainFile(Loc))
+      break;
+    Loc = SM.getIncludeLoc(SM.getFileID(Loc));
+  }
+  if (Headers.empty())
+    return llvm::None;
+  llvm::StringRef Header = Headers[0];
+  if (Opts.Includes) {
+    Header = Opts.Includes->mapHeader(Headers, QName);
+    if (Header.startswith("<") || Header.startswith("\""))
+      return Header.str();
+  }
+  return toURI(SM, Header, Opts);
+}
+
+// Return the symbol location of the token at \p Loc.
+llvm::Optional<SymbolLocation>
+getTokenLocation(SourceLocation TokLoc, const SourceManager &SM,
+                 const SymbolCollector::Options &Opts,
+                 const clang::LangOptions &LangOpts,
+                 std::string &FileURIStorage) {
+  auto U = toURI(SM, SM.getFilename(TokLoc), Opts);
+  if (!U)
+    return llvm::None;
+  FileURIStorage = std::move(*U);
+  SymbolLocation Result;
+  Result.FileURI = FileURIStorage;
+  auto TokenLength = clang::Lexer::MeasureTokenLength(TokLoc, SM, LangOpts);
+
+  auto CreatePosition = [&SM](SourceLocation Loc) {
+    auto LSPLoc = sourceLocToPosition(SM, Loc);
+    SymbolLocation::Position Pos;
+    Pos.Line = LSPLoc.line;
+    Pos.Column = LSPLoc.character;
+    return Pos;
+  };
+
+  Result.Start = CreatePosition(TokLoc);
+  auto EndLoc = TokLoc.getLocWithOffset(TokenLength);
+  Result.End = CreatePosition(EndLoc);
+
+  return std::move(Result);
+}
+
+// Checks whether \p ND is a definition of a TagDecl (class/struct/enum/union)
+// in a header file, in which case clangd would prefer to use ND as a canonical
+// declaration.
+// FIXME: handle symbol types that are not TagDecl (e.g. functions), if using
+// the first seen declaration as canonical declaration is not a good enough
+// heuristic.
+bool isPreferredDeclaration(const NamedDecl &ND, index::SymbolRoleSet Roles) {
+  using namespace clang::ast_matchers;
+  return (Roles & static_cast<unsigned>(index::SymbolRole::Definition)) &&
+         llvm::isa<TagDecl>(&ND) &&
+         match(decl(isExpansionInMainFile()), ND, ND.getASTContext()).empty();
+}
+
+} // namespace
+
+SymbolCollector::SymbolCollector(Options Opts) : Opts(std::move(Opts)) {}
+
+void SymbolCollector::initialize(ASTContext &Ctx) {
+  ASTCtx = &Ctx;
+  CompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>();
+  CompletionTUInfo =
+      llvm::make_unique<CodeCompletionTUInfo>(CompletionAllocator);
+}
+
+bool SymbolCollector::shouldCollectSymbol(const NamedDecl &ND,
+                                          ASTContext &ASTCtx,
+                                          const Options &Opts) {
+  using namespace clang::ast_matchers;
+  if (ND.isImplicit())
+    return false;
+  // Skip anonymous declarations, e.g (anonymous enum/class/struct).
+  if (ND.getDeclName().isEmpty())
+    return false;
+
+  // FIXME: figure out a way to handle internal linkage symbols (e.g. static
+  // variables, function) defined in the .cc files. Also we skip the symbols
+  // in anonymous namespace as the qualifier names of these symbols are like
+  // `foo::<anonymous>::bar`, which need a special handling.
+  // In real world projects, we have a relatively large set of header files
+  // that define static variables (like "static const int A = 1;"), we still
+  // want to collect these symbols, although they cause potential ODR
+  // violations.
+  if (ND.isInAnonymousNamespace())
+    return false;
+
+  // We want most things but not "local" symbols such as symbols inside
+  // FunctionDecl, BlockDecl, ObjCMethodDecl and OMPDeclareReductionDecl.
+  // FIXME: Need a matcher for ExportDecl in order to include symbols declared
+  // within an export.
+  auto InNonLocalContext = hasDeclContext(anyOf(
+      translationUnitDecl(), namespaceDecl(), linkageSpecDecl(), recordDecl(),
+      enumDecl(), objcProtocolDecl(), objcInterfaceDecl(), objcCategoryDecl(),
+      objcCategoryImplDecl(), objcImplementationDecl()));
+  // Don't index template specializations and expansions in main files.
+  auto IsSpecialization =
+      anyOf(functionDecl(isExplicitTemplateSpecialization()),
+            cxxRecordDecl(isExplicitTemplateSpecialization()),
+            varDecl(isExplicitTemplateSpecialization()));
+  if (match(decl(allOf(unless(isExpansionInMainFile()), InNonLocalContext,
+                       unless(IsSpecialization))),
+            ND, ASTCtx)
+          .empty())
+    return false;
+
+  // Avoid indexing internal symbols in protobuf generated headers.
+  if (isPrivateProtoDecl(ND))
+    return false;
+  return true;
+}
+
+// Always return true to continue indexing.
+bool SymbolCollector::handleDeclOccurence(
+    const Decl *D, index::SymbolRoleSet Roles,
+    ArrayRef<index::SymbolRelation> Relations, SourceLocation Loc,
+    index::IndexDataConsumer::ASTNodeInfo ASTNode) {
+  assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set.");
+  assert(CompletionAllocator && CompletionTUInfo);
+  assert(ASTNode.OrigD);
+  // If OrigD is an declaration associated with a friend declaration and it's
+  // not a definition, skip it. Note that OrigD is the occurrence that the
+  // collector is currently visiting.
+  if ((ASTNode.OrigD->getFriendObjectKind() !=
+       Decl::FriendObjectKind::FOK_None) &&
+      !(Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
+    return true;
+  // A declaration created for a friend declaration should not be used as the
+  // canonical declaration in the index. Use OrigD instead, unless we've already
+  // picked a replacement for D
+  if (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None)
+    D = CanonicalDecls.try_emplace(D, ASTNode.OrigD).first->second;
+  const NamedDecl *ND = llvm::dyn_cast<NamedDecl>(D);
+  if (!ND)
+    return true;
+
+  // Mark D as referenced if this is a reference coming from the main file.
+  // D may not be an interesting symbol, but it's cheaper to check at the end.
+  auto &SM = ASTCtx->getSourceManager();
+  if (Opts.CountReferences &&
+      (Roles & static_cast<unsigned>(index::SymbolRole::Reference)) &&
+      SM.getFileID(SM.getSpellingLoc(Loc)) == SM.getMainFileID())
+    ReferencedDecls.insert(ND);
+
+  // Don't continue indexing if this is a mere reference.
+  if (!(Roles & static_cast<unsigned>(index::SymbolRole::Declaration) ||
+        Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
+    return true;
+  if (!shouldCollectSymbol(*ND, *ASTCtx, Opts))
+    return true;
+
+  llvm::SmallString<128> USR;
+  if (index::generateUSRForDecl(ND, USR))
+    return true;
+  SymbolID ID(USR);
+
+  const NamedDecl &OriginalDecl = *cast<NamedDecl>(ASTNode.OrigD);
+  const Symbol *BasicSymbol = Symbols.find(ID);
+  if (!BasicSymbol) // Regardless of role, ND is the canonical declaration.
+    BasicSymbol = addDeclaration(*ND, std::move(ID));
+  else if (isPreferredDeclaration(OriginalDecl, Roles))
+    // If OriginalDecl is preferred, replace the existing canonical
+    // declaration (e.g. a class forward declaration). There should be at most
+    // one duplicate as we expect to see only one preferred declaration per
+    // TU, because in practice they are definitions.
+    BasicSymbol = addDeclaration(OriginalDecl, std::move(ID));
+
+  if (Roles & static_cast<unsigned>(index::SymbolRole::Definition))
+    addDefinition(OriginalDecl, *BasicSymbol);
+  return true;
+}
+
+bool SymbolCollector::handleMacroOccurence(const IdentifierInfo *Name,
+                                           const MacroInfo *MI,
+                                           index::SymbolRoleSet Roles,
+                                           SourceLocation Loc) {
+  if (!Opts.CollectMacro)
+    return true;
+  assert(PP.get());
+
+  const auto &SM = PP->getSourceManager();
+  if (SM.isInMainFile(SM.getExpansionLoc(MI->getDefinitionLoc())))
+    return true;
+  // Header guards are not interesting in index. Builtin macros don't have
+  // useful locations and are not needed for code completions.
+  if (MI->isUsedForHeaderGuard() || MI->isBuiltinMacro())
+    return true;
+
+  // Mark the macro as referenced if this is a reference coming from the main
+  // file. The macro may not be an interesting symbol, but it's cheaper to check
+  // at the end.
+  if (Opts.CountReferences &&
+      (Roles & static_cast<unsigned>(index::SymbolRole::Reference)) &&
+      SM.getFileID(SM.getSpellingLoc(Loc)) == SM.getMainFileID())
+    ReferencedMacros.insert(Name);
+  // Don't continue indexing if this is a mere reference.
+  // FIXME: remove macro with ID if it is undefined.
+  if (!(Roles & static_cast<unsigned>(index::SymbolRole::Declaration) ||
+        Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
+    return true;
+
+  llvm::SmallString<128> USR;
+  if (index::generateUSRForMacro(Name->getName(), MI->getDefinitionLoc(), SM,
+                                 USR))
+    return true;
+  SymbolID ID(USR);
+
+  // Only collect one instance in case there are multiple.
+  if (Symbols.find(ID) != nullptr)
+    return true;
+
+  Symbol S;
+  S.ID = std::move(ID);
+  S.Name = Name->getName();
+  S.IsIndexedForCodeCompletion = true;
+  S.SymInfo = index::getSymbolInfoForMacro(*MI);
+  std::string FileURI;
+  if (auto DeclLoc = getTokenLocation(MI->getDefinitionLoc(), SM, Opts,
+                                      PP->getLangOpts(), FileURI))
+    S.CanonicalDeclaration = *DeclLoc;
+
+  CodeCompletionResult SymbolCompletion(Name);
+  const auto *CCS = SymbolCompletion.CreateCodeCompletionStringForMacro(
+      *PP, *CompletionAllocator, *CompletionTUInfo);
+  std::string Signature;
+  std::string SnippetSuffix;
+  getSignature(*CCS, &Signature, &SnippetSuffix);
+
+  std::string Include;
+  if (Opts.CollectIncludePath && shouldCollectIncludePath(S.SymInfo.Kind)) {
+    if (auto Header =
+            getIncludeHeader(Name->getName(), SM,
+                             SM.getExpansionLoc(MI->getDefinitionLoc()), Opts))
+      Include = std::move(*Header);
+  }
+  S.Signature = Signature;
+  S.CompletionSnippetSuffix = SnippetSuffix;
+  Symbol::Details Detail;
+  Detail.IncludeHeader = Include;
+  S.Detail = &Detail;
+  Symbols.insert(S);
+  return true;
+}
+
+void SymbolCollector::finish() {
+  // At the end of the TU, add 1 to the refcount of all referenced symbols.
+  auto IncRef = [this](const SymbolID &ID) {
+    if (const auto *S = Symbols.find(ID)) {
+      Symbol Inc = *S;
+      ++Inc.References;
+      Symbols.insert(Inc);
+    }
+  };
+  for (const NamedDecl *ND : ReferencedDecls) {
+    llvm::SmallString<128> USR;
+    if (!index::generateUSRForDecl(ND, USR))
+      IncRef(SymbolID(USR));
+  }
+  if (Opts.CollectMacro) {
+    assert(PP);
+    for (const IdentifierInfo *II : ReferencedMacros) {
+      llvm::SmallString<128> USR;
+      if (const auto *MI = PP->getMacroDefinition(II).getMacroInfo())
+        if (!index::generateUSRForMacro(II->getName(), MI->getDefinitionLoc(),
+                                        PP->getSourceManager(), USR))
+          IncRef(SymbolID(USR));
+    }
+  }
+  ReferencedDecls.clear();
+  ReferencedMacros.clear();
+}
+
+const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND,
+                                              SymbolID ID) {
+  auto &Ctx = ND.getASTContext();
+  auto &SM = Ctx.getSourceManager();
+
+  Symbol S;
+  S.ID = std::move(ID);
+  std::string QName = printQualifiedName(ND);
+  std::tie(S.Scope, S.Name) = splitQualifiedName(QName);
+  // FIXME: this returns foo:bar: for objective-C methods, we prefer only foo:
+  // for consistency with CodeCompletionString and a clean name/signature split.
+
+  S.IsIndexedForCodeCompletion = isIndexedForCodeCompletion(ND, Ctx);
+  S.SymInfo = index::getSymbolInfo(&ND);
+  std::string FileURI;
+  if (auto DeclLoc = getTokenLocation(findNameLoc(&ND), SM, Opts,
+                                      ASTCtx->getLangOpts(), FileURI))
+    S.CanonicalDeclaration = *DeclLoc;
+
+  // Add completion info.
+  // FIXME: we may want to choose a different redecl, or combine from several.
+  assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set.");
+  // We use the primary template, as clang does during code completion.
+  CodeCompletionResult SymbolCompletion(&getTemplateOrThis(ND), 0);
+  const auto *CCS = SymbolCompletion.CreateCodeCompletionString(
+      *ASTCtx, *PP, CodeCompletionContext::CCC_Name, *CompletionAllocator,
+      *CompletionTUInfo,
+      /*IncludeBriefComments*/ false);
+  std::string Signature;
+  std::string SnippetSuffix;
+  getSignature(*CCS, &Signature, &SnippetSuffix);
+  std::string Documentation =
+      formatDocumentation(*CCS, getDocComment(Ctx, SymbolCompletion,
+                                              /*CommentsFromHeaders=*/true));
+  std::string ReturnType = getReturnType(*CCS);
+
+  std::string Include;
+  if (Opts.CollectIncludePath && shouldCollectIncludePath(S.SymInfo.Kind)) {
+    // Use the expansion location to get the #include header since this is
+    // where the symbol is exposed.
+    if (auto Header = getIncludeHeader(
+            QName, SM, SM.getExpansionLoc(ND.getLocation()), Opts))
+      Include = std::move(*Header);
+  }
+  S.Signature = Signature;
+  S.CompletionSnippetSuffix = SnippetSuffix;
+  Symbol::Details Detail;
+  Detail.Documentation = Documentation;
+  Detail.ReturnType = ReturnType;
+  Detail.IncludeHeader = Include;
+  S.Detail = &Detail;
+
+  S.Origin = Opts.Origin;
+  Symbols.insert(S);
+  return Symbols.find(S.ID);
+}
+
+void SymbolCollector::addDefinition(const NamedDecl &ND,
+                                    const Symbol &DeclSym) {
+  if (DeclSym.Definition)
+    return;
+  // If we saw some forward declaration, we end up copying the symbol.
+  // This is not ideal, but avoids duplicating the "is this a definition" check
+  // in clang::index. We should only see one definition.
+  Symbol S = DeclSym;
+  std::string FileURI;
+  if (auto DefLoc = getTokenLocation(findNameLoc(&ND),
+                                     ND.getASTContext().getSourceManager(),
+                                     Opts, ASTCtx->getLangOpts(), FileURI))
+    S.Definition = *DefLoc;
+  Symbols.insert(S);
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/SymbolCollector.h b/src/third_party/llvm-project/clang-tools-extra/clangd/index/SymbolCollector.h
new file mode 100644
index 0000000..bc882e4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/SymbolCollector.h
@@ -0,0 +1,114 @@
+//===--- SymbolCollector.h ---------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CanonicalIncludes.h"
+#include "Index.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/Index/IndexDataConsumer.h"
+#include "clang/Index/IndexSymbol.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+
+namespace clang {
+namespace clangd {
+
+/// \brief Collect declarations (symbols) from an AST.
+/// It collects most declarations except:
+/// - Implicit declarations
+/// - Anonymous declarations (anonymous enum/class/struct, etc)
+/// - Declarations in anonymous namespaces
+/// - Local declarations (in function bodies, blocks, etc)
+/// - Declarations in main files
+/// - Template specializations
+/// - Library-specific private declarations (e.g. private declaration generated
+/// by protobuf compiler)
+///
+/// See also shouldCollectSymbol(...).
+///
+/// Clients (e.g. clangd) can use SymbolCollector together with
+/// index::indexTopLevelDecls to retrieve all symbols when the source file is
+/// changed.
+class SymbolCollector : public index::IndexDataConsumer {
+public:
+  struct Options {
+    /// When symbol paths cannot be resolved to absolute paths (e.g. files in
+    /// VFS that does not have absolute path), combine the fallback directory
+    /// with symbols' paths to get absolute paths. This must be an absolute
+    /// path.
+    std::string FallbackDir;
+    /// Specifies URI schemes that can be used to generate URIs for file paths
+    /// in symbols. The list of schemes will be tried in order until a working
+    /// scheme is found. If no scheme works, symbol location will be dropped.
+    std::vector<std::string> URISchemes = {"file"};
+    bool CollectIncludePath = false;
+    /// If set, this is used to map symbol #include path to a potentially
+    /// different #include path.
+    const CanonicalIncludes *Includes = nullptr;
+    // Populate the Symbol.References field.
+    bool CountReferences = false;
+    // Every symbol collected will be stamped with this origin.
+    SymbolOrigin Origin = SymbolOrigin::Unknown;
+    /// Collect macros.
+    /// Note that SymbolCollector must be run with preprocessor in order to
+    /// collect macros. For example, `indexTopLevelDecls` will not index any
+    /// macro even if this is true.
+    bool CollectMacro = false;
+  };
+
+  SymbolCollector(Options Opts);
+
+  /// Returns true is \p ND should be collected.
+  /// AST matchers require non-const ASTContext.
+  static bool shouldCollectSymbol(const NamedDecl &ND, ASTContext &ASTCtx,
+                                  const Options &Opts);
+
+  void initialize(ASTContext &Ctx) override;
+
+  void setPreprocessor(std::shared_ptr<Preprocessor> PP) override {
+    this->PP = std::move(PP);
+  }
+
+  bool
+  handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
+                      ArrayRef<index::SymbolRelation> Relations,
+                      SourceLocation Loc,
+                      index::IndexDataConsumer::ASTNodeInfo ASTNode) override;
+
+  bool handleMacroOccurence(const IdentifierInfo *Name, const MacroInfo *MI,
+                            index::SymbolRoleSet Roles,
+                            SourceLocation Loc) override;
+
+  SymbolSlab takeSymbols() { return std::move(Symbols).build(); }
+
+  void finish() override;
+
+private:
+  const Symbol *addDeclaration(const NamedDecl &, SymbolID);
+  void addDefinition(const NamedDecl &, const Symbol &DeclSymbol);
+
+  // All Symbols collected from the AST.
+  SymbolSlab::Builder Symbols;
+  ASTContext *ASTCtx;
+  std::shared_ptr<Preprocessor> PP;
+  std::shared_ptr<GlobalCodeCompletionAllocator> CompletionAllocator;
+  std::unique_ptr<CodeCompletionTUInfo> CompletionTUInfo;
+  Options Opts;
+  // Symbols referenced from the current TU, flushed on finish().
+  llvm::DenseSet<const NamedDecl *> ReferencedDecls;
+  llvm::DenseSet<const IdentifierInfo *> ReferencedMacros;
+  // Maps canonical declaration provided by clang to canonical declaration for
+  // an index symbol, if clangd prefers a different declaration than that
+  // provided by clang. For example, friend declaration might be considered
+  // canonical by clang but should not be considered canonical in the index
+  // unless it's a definition.
+  llvm::DenseMap<const Decl *, const Decl *> CanonicalDecls;
+};
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/SymbolYAML.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/index/SymbolYAML.cpp
new file mode 100644
index 0000000..1701b5a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/SymbolYAML.cpp
@@ -0,0 +1,207 @@
+//===--- SymbolYAML.cpp ------------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolYAML.h"
+#include "Index.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(clang::clangd::Symbol)
+
+namespace llvm {
+namespace yaml {
+
+using clang::clangd::Symbol;
+using clang::clangd::SymbolID;
+using clang::clangd::SymbolLocation;
+using clang::index::SymbolInfo;
+using clang::index::SymbolLanguage;
+using clang::index::SymbolKind;
+
+// Helper to (de)serialize the SymbolID. We serialize it as a hex string.
+struct NormalizedSymbolID {
+  NormalizedSymbolID(IO &) {}
+  NormalizedSymbolID(IO &, const SymbolID& ID) {
+    llvm::raw_string_ostream OS(HexString);
+    OS << ID;
+  }
+
+  SymbolID denormalize(IO&) {
+    SymbolID ID;
+    HexString >> ID;
+    return ID;
+  }
+
+  std::string HexString;
+};
+
+template <> struct MappingTraits<SymbolLocation::Position> {
+  static void mapping(IO &IO, SymbolLocation::Position &Value) {
+    IO.mapRequired("Line", Value.Line);
+    IO.mapRequired("Column", Value.Column);
+  }
+};
+
+template <> struct MappingTraits<SymbolLocation> {
+  static void mapping(IO &IO, SymbolLocation &Value) {
+    IO.mapRequired("FileURI", Value.FileURI);
+    IO.mapRequired("Start", Value.Start);
+    IO.mapRequired("End", Value.End);
+  }
+};
+
+template <> struct MappingTraits<SymbolInfo> {
+  static void mapping(IO &io, SymbolInfo &SymInfo) {
+    // FIXME: expose other fields?
+    io.mapRequired("Kind", SymInfo.Kind);
+    io.mapRequired("Lang", SymInfo.Lang);
+  }
+};
+
+template <> struct MappingTraits<Symbol::Details> {
+  static void mapping(IO &io, Symbol::Details &Detail) {
+    io.mapOptional("Documentation", Detail.Documentation);
+    io.mapOptional("ReturnType", Detail.ReturnType);
+    io.mapOptional("IncludeHeader", Detail.IncludeHeader);
+  }
+};
+
+// A YamlIO normalizer for fields of type "const T*" allocated on an arena.
+// Normalizes to Optional<T>, so traits should be provided for T.
+template <typename T> struct ArenaPtr {
+  ArenaPtr(IO &) {}
+  ArenaPtr(IO &, const T *D) {
+    if (D)
+      Opt = *D;
+  }
+
+  const T *denormalize(IO &IO) {
+    assert(IO.getContext() && "Expecting an arena (as context) to allocate "
+                              "data for read symbols.");
+    if (!Opt)
+      return nullptr;
+    return new (*static_cast<llvm::BumpPtrAllocator *>(IO.getContext()))
+        T(std::move(*Opt)); // Allocate a copy of Opt on the arena.
+  }
+
+  llvm::Optional<T> Opt;
+};
+
+template <> struct MappingTraits<Symbol> {
+  static void mapping(IO &IO, Symbol &Sym) {
+    MappingNormalization<NormalizedSymbolID, SymbolID> NSymbolID(IO, Sym.ID);
+    MappingNormalization<ArenaPtr<Symbol::Details>, const Symbol::Details *>
+        NDetail(IO, Sym.Detail);
+    IO.mapRequired("ID", NSymbolID->HexString);
+    IO.mapRequired("Name", Sym.Name);
+    IO.mapRequired("Scope", Sym.Scope);
+    IO.mapRequired("SymInfo", Sym.SymInfo);
+    IO.mapOptional("CanonicalDeclaration", Sym.CanonicalDeclaration,
+                   SymbolLocation());
+    IO.mapOptional("Definition", Sym.Definition, SymbolLocation());
+    IO.mapOptional("References", Sym.References, 0u);
+    IO.mapOptional("IsIndexedForCodeCompletion", Sym.IsIndexedForCodeCompletion,
+                   false);
+    IO.mapOptional("Signature", Sym.Signature);
+    IO.mapOptional("CompletionSnippetSuffix", Sym.CompletionSnippetSuffix);
+    IO.mapOptional("Detail", NDetail->Opt);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<SymbolLanguage> {
+  static void enumeration(IO &IO, SymbolLanguage &Value) {
+    IO.enumCase(Value, "C", SymbolLanguage::C);
+    IO.enumCase(Value, "Cpp", SymbolLanguage::CXX);
+    IO.enumCase(Value, "ObjC", SymbolLanguage::ObjC);
+    IO.enumCase(Value, "Swift", SymbolLanguage::Swift);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<SymbolKind> {
+  static void enumeration(IO &IO, SymbolKind &Value) {
+#define DEFINE_ENUM(name) IO.enumCase(Value, #name, SymbolKind::name)
+
+    DEFINE_ENUM(Unknown);
+    DEFINE_ENUM(Function);
+    DEFINE_ENUM(Module);
+    DEFINE_ENUM(Namespace);
+    DEFINE_ENUM(NamespaceAlias);
+    DEFINE_ENUM(Macro);
+    DEFINE_ENUM(Enum);
+    DEFINE_ENUM(Struct);
+    DEFINE_ENUM(Class);
+    DEFINE_ENUM(Protocol);
+    DEFINE_ENUM(Extension);
+    DEFINE_ENUM(Union);
+    DEFINE_ENUM(TypeAlias);
+    DEFINE_ENUM(Function);
+    DEFINE_ENUM(Variable);
+    DEFINE_ENUM(Field);
+    DEFINE_ENUM(EnumConstant);
+    DEFINE_ENUM(InstanceMethod);
+    DEFINE_ENUM(ClassMethod);
+    DEFINE_ENUM(StaticMethod);
+    DEFINE_ENUM(InstanceProperty);
+    DEFINE_ENUM(ClassProperty);
+    DEFINE_ENUM(StaticProperty);
+    DEFINE_ENUM(Constructor);
+    DEFINE_ENUM(Destructor);
+    DEFINE_ENUM(ConversionFunction);
+    DEFINE_ENUM(Parameter);
+    DEFINE_ENUM(Using);
+
+#undef DEFINE_ENUM
+  }
+};
+
+} // namespace yaml
+} // namespace llvm
+
+namespace clang {
+namespace clangd {
+
+SymbolSlab symbolsFromYAML(llvm::StringRef YAMLContent) {
+  // Store data of pointer fields (excl. `StringRef`) like `Detail`.
+  llvm::BumpPtrAllocator Arena;
+  llvm::yaml::Input Yin(YAMLContent, &Arena);
+  std::vector<Symbol> S;
+  Yin >> S;
+
+  SymbolSlab::Builder Syms;
+  for (auto &Sym : S)
+    Syms.insert(Sym);
+  return std::move(Syms).build();
+}
+
+Symbol SymbolFromYAML(llvm::yaml::Input &Input, llvm::BumpPtrAllocator &Arena) {
+  // We could grab Arena out of Input, but it'd be a huge hazard for callers.
+  assert(Input.getContext() == &Arena);
+  Symbol S;
+  Input >> S;
+  return S;
+}
+
+void SymbolsToYAML(const SymbolSlab& Symbols, llvm::raw_ostream &OS) {
+  llvm::yaml::Output Yout(OS);
+  for (Symbol S : Symbols) // copy: Yout<< requires mutability.
+    Yout << S;
+}
+
+std::string SymbolToYAML(Symbol Sym) {
+  std::string Str;
+  llvm::raw_string_ostream OS(Str);
+  llvm::yaml::Output Yout(OS);
+  Yout << Sym;
+  return OS.str();
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/SymbolYAML.h b/src/third_party/llvm-project/clang-tools-extra/clangd/index/SymbolYAML.h
new file mode 100644
index 0000000..726af6c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/SymbolYAML.h
@@ -0,0 +1,48 @@
+//===--- SymbolYAML.h --------------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// SymbolYAML provides facilities to convert Symbol to YAML, and vice versa.
+// The YAML format of Symbol is designed for simplicity and experiment, but
+// isn't a suitable/efficient store.
+//
+// This is for **experimental** only. Don't use it in the production code.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_FROM_YAML_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_FROM_YAML_H
+
+#include "Index.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace clangd {
+
+// Read symbols from a YAML-format string.
+SymbolSlab symbolsFromYAML(llvm::StringRef YAMLContent);
+
+// Read one symbol from a YAML-stream.
+// The arena must be the Input's context! (i.e. yaml::Input Input(Text, &Arena))
+// The returned symbol is backed by both Input and Arena.
+Symbol SymbolFromYAML(llvm::yaml::Input &Input, llvm::BumpPtrAllocator &Arena);
+
+// Convert a single symbol to YAML-format string.
+// The YAML result is safe to concatenate.
+std::string SymbolToYAML(Symbol Sym);
+
+// Convert symbols to a YAML-format string.
+// The YAML result is safe to concatenate if you have multiple symbol slabs.
+void SymbolsToYAML(const SymbolSlab &Symbols, llvm::raw_ostream &OS);
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_FROM_YAML_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/dex/Iterator.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/index/dex/Iterator.cpp
new file mode 100644
index 0000000..25107f9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/dex/Iterator.cpp
@@ -0,0 +1,244 @@
+//===--- Iterator.cpp - Query Symbol Retrieval ------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Iterator.h"
+#include <algorithm>
+#include <cassert>
+#include <numeric>
+
+namespace clang {
+namespace clangd {
+namespace dex {
+
+namespace {
+
+/// Implements Iterator over a PostingList. DocumentIterator is the most basic
+/// iterator: it doesn't have any children (hence it is the leaf of iterator
+/// tree) and is simply a wrapper around PostingList::const_iterator.
+class DocumentIterator : public Iterator {
+public:
+  DocumentIterator(PostingListRef Documents)
+      : Documents(Documents), Index(std::begin(Documents)) {}
+
+  bool reachedEnd() const override { return Index == std::end(Documents); }
+
+  /// Advances cursor to the next item.
+  void advance() override {
+    assert(!reachedEnd() && "DocumentIterator can't advance at the end.");
+    ++Index;
+  }
+
+  /// Applies binary search to advance cursor to the next item with DocID equal
+  /// or higher than the given one.
+  void advanceTo(DocID ID) override {
+    assert(!reachedEnd() && "DocumentIterator can't advance at the end.");
+    Index = std::lower_bound(Index, std::end(Documents), ID);
+  }
+
+  DocID peek() const override {
+    assert(!reachedEnd() && "DocumentIterator can't call peek() at the end.");
+    return *Index;
+  }
+
+  llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
+    OS << '[';
+    auto Separator = "";
+    for (const auto &ID : Documents) {
+      OS << Separator << ID;
+      Separator = ", ";
+    }
+    OS << ']';
+    return OS;
+  }
+
+private:
+  PostingListRef Documents;
+  PostingListRef::const_iterator Index;
+};
+
+/// Implements Iterator over the intersection of other iterators.
+///
+/// AndIterator iterates through common items among all children. It becomes
+/// exhausted as soon as any child becomes exhausted. After each mutation, the
+/// iterator restores the invariant: all children must point to the same item.
+class AndIterator : public Iterator {
+public:
+  AndIterator(std::vector<std::unique_ptr<Iterator>> AllChildren)
+      : Children(std::move(AllChildren)) {
+    assert(!Children.empty() && "AndIterator should have at least one child.");
+    // Establish invariants.
+    sync();
+  }
+
+  bool reachedEnd() const override { return ReachedEnd; }
+
+  /// Advances all children to the next common item.
+  void advance() override {
+    assert(!reachedEnd() && "AndIterator can't call advance() at the end.");
+    Children.front()->advance();
+    sync();
+  }
+
+  /// Advances all children to the next common item with DocumentID >= ID.
+  void advanceTo(DocID ID) override {
+    assert(!reachedEnd() && "AndIterator can't call advanceTo() at the end.");
+    Children.front()->advanceTo(ID);
+    sync();
+  }
+
+  DocID peek() const override { return Children.front()->peek(); }
+
+  llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
+    OS << "(& ";
+    auto Separator = "";
+    for (const auto &Child : Children) {
+      OS << Separator << *Child;
+      Separator = " ";
+    }
+    OS << ')';
+    return OS;
+  }
+
+private:
+  /// Restores class invariants: each child will point to the same element after
+  /// sync.
+  void sync() {
+    ReachedEnd |= Children.front()->reachedEnd();
+    if (ReachedEnd)
+      return;
+    auto SyncID = Children.front()->peek();
+    // Indicates whether any child needs to be advanced to new SyncID.
+    bool NeedsAdvance = false;
+    do {
+      NeedsAdvance = false;
+      for (auto &Child : Children) {
+        Child->advanceTo(SyncID);
+        ReachedEnd |= Child->reachedEnd();
+        // If any child reaches end And iterator can not match any other items.
+        // In this case, just terminate the process.
+        if (ReachedEnd)
+          return;
+        // If any child goes beyond given ID (i.e. ID is not the common item),
+        // all children should be advanced to the next common item.
+        // FIXME(kbobyrev): This is not a very optimized version; after costs
+        // are introduced, cycle should break whenever ID exceeds current one
+        // and cheapest children should be advanced over again.
+        if (Child->peek() > SyncID) {
+          SyncID = Child->peek();
+          NeedsAdvance = true;
+        }
+      }
+    } while (NeedsAdvance);
+  }
+
+  /// AndIterator owns its children and ensures that all of them point to the
+  /// same element. As soon as one child gets exhausted, AndIterator can no
+  /// longer advance and has reached its end.
+  std::vector<std::unique_ptr<Iterator>> Children;
+  /// Indicates whether any child is exhausted. It is cheaper to maintain and
+  /// update the field, rather than traversing the whole subtree in each
+  /// reachedEnd() call.
+  bool ReachedEnd = false;
+};
+
+/// Implements Iterator over the union of other iterators.
+///
+/// OrIterator iterates through all items which can be pointed to by at least
+/// one child. To preserve the sorted order, this iterator always advances the
+/// child with smallest Child->peek() value. OrIterator becomes exhausted as
+/// soon as all of its children are exhausted.
+class OrIterator : public Iterator {
+public:
+  OrIterator(std::vector<std::unique_ptr<Iterator>> AllChildren)
+      : Children(std::move(AllChildren)) {
+    assert(Children.size() > 0 && "Or Iterator must have at least one child.");
+  }
+
+  /// Returns true if all children are exhausted.
+  bool reachedEnd() const override {
+    return std::all_of(begin(Children), end(Children),
+                       [](const std::unique_ptr<Iterator> &Child) {
+                         return Child->reachedEnd();
+                       });
+  }
+
+  /// Moves each child pointing to the smallest DocID to the next item.
+  void advance() override {
+    assert(!reachedEnd() &&
+           "OrIterator must have at least one child to advance().");
+    const auto SmallestID = peek();
+    for (const auto &Child : Children)
+      if (!Child->reachedEnd() && Child->peek() == SmallestID)
+        Child->advance();
+  }
+
+  /// Advances each child to the next existing element with DocumentID >= ID.
+  void advanceTo(DocID ID) override {
+    assert(!reachedEnd() && "Can't advance iterator after it reached the end.");
+    for (const auto &Child : Children)
+      if (!Child->reachedEnd())
+        Child->advanceTo(ID);
+  }
+
+  /// Returns the element under cursor of the child with smallest Child->peek()
+  /// value.
+  DocID peek() const override {
+    assert(!reachedEnd() &&
+           "OrIterator must have at least one child to peek().");
+    DocID Result = std::numeric_limits<DocID>::max();
+
+    for (const auto &Child : Children)
+      if (!Child->reachedEnd())
+        Result = std::min(Result, Child->peek());
+
+    return Result;
+  }
+
+  llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
+    OS << "(| ";
+    auto Separator = "";
+    for (const auto &Child : Children) {
+      OS << Separator << *Child;
+      Separator = " ";
+    }
+    OS << ')';
+    return OS;
+  }
+
+private:
+  // FIXME(kbobyrev): Would storing Children in min-heap be faster?
+  std::vector<std::unique_ptr<Iterator>> Children;
+};
+
+} // end namespace
+
+std::vector<DocID> consume(Iterator &It) {
+  std::vector<DocID> Result;
+  for (; !It.reachedEnd(); It.advance())
+    Result.push_back(It.peek());
+  return Result;
+}
+
+std::unique_ptr<Iterator> create(PostingListRef Documents) {
+  return llvm::make_unique<DocumentIterator>(Documents);
+}
+
+std::unique_ptr<Iterator>
+createAnd(std::vector<std::unique_ptr<Iterator>> Children) {
+  return llvm::make_unique<AndIterator>(move(Children));
+}
+
+std::unique_ptr<Iterator>
+createOr(std::vector<std::unique_ptr<Iterator>> Children) {
+  return llvm::make_unique<OrIterator>(move(Children));
+}
+
+} // namespace dex
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/dex/Iterator.h b/src/third_party/llvm-project/clang-tools-extra/clangd/index/dex/Iterator.h
new file mode 100644
index 0000000..f6270f1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/dex/Iterator.h
@@ -0,0 +1,152 @@
+//===--- Iterator.h - Query Symbol Retrieval --------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Symbol index queries consist of specific requirements for the requested
+// symbol, such as high fuzzy matching score, scope, type etc. The lists of all
+// symbols matching some criteria (e.g. belonging to "clang::clangd::" scope)
+// are expressed in a form of Search Tokens which are stored in the inverted
+// index.  Inverted index maps these tokens to the posting lists - sorted ( by
+// symbol quality) sequences of symbol IDs matching the token, e.g.  scope token
+// "clangd::clangd::" is mapped to the list of IDs of all symbols which are
+// declared in this namespace. Search queries are build from a set of
+// requirements which can be combined with each other forming the query trees.
+// The leafs of such trees are posting lists, and the nodes are operations on
+// these posting lists, e.g. intersection or union.  Efficient processing of
+// these multi-level queries is handled by Iterators.  Iterators advance through
+// all leaf posting lists producing the result of search query, which preserves
+// the sorted order of IDs. Having the resulting IDs sorted is important,
+// because it allows receiving a certain number of the most valuable items (e.g.
+// symbols with highest quality which was the sorting key in the first place)
+// without processing all items with requested properties (this might not be
+// computationally effective if search request is not very restrictive).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_DEX_ITERATOR_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_DEX_ITERATOR_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <memory>
+#include <vector>
+
+namespace clang {
+namespace clangd {
+namespace dex {
+
+/// Symbol position in the list of all index symbols sorted by a pre-computed
+/// symbol quality.
+using DocID = uint32_t;
+/// Contains sorted sequence of DocIDs all of which belong to symbols matching
+/// certain criteria, i.e. containing a Search Token. PostingLists are values
+/// for the inverted index.
+using PostingList = std::vector<DocID>;
+/// Immutable reference to PostingList object.
+using PostingListRef = llvm::ArrayRef<DocID>;
+
+/// Iterator is the interface for Query Tree node. The simplest type of Iterator
+/// is DocumentIterator which is simply a wrapper around PostingList iterator
+/// and serves as the Query Tree leaf. More sophisticated examples of iterators
+/// can manage intersection, union of the elements produced by other iterators
+/// (their children) to form a multi-level Query Tree. The interface is designed
+/// to be extensible in order to support multiple types of iterators.
+class Iterator {
+  // FIXME(kbobyrev): Provide callback for matched documents.
+  // FIXME(kbobyrev): Implement new types of iterators: Label, Boost (with
+  // scoring), Limit.
+  // FIXME(kbobyrev): Implement iterator cost, an estimate of advance() calls
+  // before iterator exhaustion.
+public:
+  /// Returns true if all valid DocIDs were processed and hence the iterator is
+  /// exhausted.
+  virtual bool reachedEnd() const = 0;
+  /// Moves to next valid DocID. If it doesn't exist, the iterator is exhausted
+  /// and proceeds to the END.
+  ///
+  /// Note: reachedEnd() must be false.
+  virtual void advance() = 0;
+  /// Moves to the first valid DocID which is equal or higher than given ID. If
+  /// it doesn't exist, the iterator is exhausted and proceeds to the END.
+  ///
+  /// Note: reachedEnd() must be false.
+  virtual void advanceTo(DocID ID) = 0;
+  /// Returns the current element this iterator points to.
+  ///
+  /// Note: reachedEnd() must be false.
+  virtual DocID peek() const = 0;
+
+  virtual ~Iterator() {}
+
+  /// Prints a convenient human-readable iterator representation by recursively
+  /// dumping iterators in the following format:
+  ///
+  /// (Type Child1 Child2 ...)
+  ///
+  /// Where Type is the iterator type representation: "&" for And, "|" for Or,
+  /// ChildN is N-th iterator child. Raw iterators over PostingList are
+  /// represented as "[ID1, ID2, ...]" where IDN is N-th PostingList entry.
+  friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+                                       const Iterator &Iterator) {
+    return Iterator.dump(OS);
+  }
+
+private:
+  virtual llvm::raw_ostream &dump(llvm::raw_ostream &OS) const = 0;
+};
+
+/// Exhausts given iterator and returns all processed DocIDs. The result
+/// contains sorted DocumentIDs.
+std::vector<DocID> consume(Iterator &It);
+
+/// Returns a document iterator over given PostingList.
+std::unique_ptr<Iterator> create(PostingListRef Documents);
+
+/// Returns AND Iterator which performs the intersection of the PostingLists of
+/// its children.
+std::unique_ptr<Iterator>
+createAnd(std::vector<std::unique_ptr<Iterator>> Children);
+
+/// Returns OR Iterator which performs the union of the PostingLists of its
+/// children.
+std::unique_ptr<Iterator>
+createOr(std::vector<std::unique_ptr<Iterator>> Children);
+
+/// This allows createAnd(create(...), create(...)) syntax.
+template <typename... Args> std::unique_ptr<Iterator> createAnd(Args... args) {
+  std::vector<std::unique_ptr<Iterator>> Children;
+  populateChildren(Children, args...);
+  return createAnd(move(Children));
+}
+
+/// This allows createOr(create(...), create(...)) syntax.
+template <typename... Args> std::unique_ptr<Iterator> createOr(Args... args) {
+  std::vector<std::unique_ptr<Iterator>> Children;
+  populateChildren(Children, args...);
+  return createOr(move(Children));
+}
+
+template <typename HeadT, typename... TailT>
+void populateChildren(std::vector<std::unique_ptr<Iterator>> &Children,
+                      HeadT &Head, TailT &... Tail) {
+  Children.push_back(move(Head));
+  populateChildren(Children, Tail...);
+}
+
+template <typename HeadT>
+void populateChildren(std::vector<std::unique_ptr<Iterator>> &Children,
+                      HeadT &Head) {
+  Children.push_back(move(Head));
+}
+
+} // namespace dex
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/dex/Token.h b/src/third_party/llvm-project/clang-tools-extra/clangd/index/dex/Token.h
new file mode 100644
index 0000000..33a16d3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/dex/Token.h
@@ -0,0 +1,112 @@
+//===--- Token.h - Symbol Search primitive ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Token objects represent a characteristic of a symbol, which can be used to
+// perform efficient search. Tokens are keys for inverted index which are mapped
+// to the corresponding posting lists.
+//
+// The symbol std::cout might have the tokens:
+// * Scope "std::"
+// * Trigram "cou"
+// * Trigram "out"
+// * Type "std::ostream"
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_DEX_TOKEN_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_DEX_TOKEN_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace clangd {
+namespace dex {
+
+/// A Token represents an attribute of a symbol, such as a particular trigram
+/// present in the name (used for fuzzy search).
+///
+/// Tokens can be used to perform more sophisticated search queries by
+/// constructing complex iterator trees.
+struct Token {
+  /// Kind specifies Token type which defines semantics for the internal
+  /// representation. Each Kind has different representation stored in Data
+  /// field.
+  enum class Kind {
+    /// Represents trigram used for fuzzy search of unqualified symbol names.
+    ///
+    /// Data contains 3 bytes with trigram contents.
+    Trigram,
+    /// Scope primitives, e.g. "symbol belongs to namespace foo::bar".
+    ///
+    /// Data stroes full scope name , e.g. "foo::bar::baz::" or "" (for global
+    /// scope).
+    Scope,
+    /// Internal Token type for invalid/special tokens, e.g. empty tokens for
+    /// llvm::DenseMap.
+    Sentinel,
+    /// FIXME(kbobyrev): Add other Token Kinds
+    /// * Path with full or relative path to the directory in which symbol is
+    ///   defined
+    /// * Type with qualified type name or its USR
+  };
+
+  Token(Kind TokenKind, llvm::StringRef Data)
+      : Data(Data), TokenKind(TokenKind) {}
+
+  bool operator==(const Token &Other) const {
+    return TokenKind == Other.TokenKind && Data == Other.Data;
+  }
+
+  /// Representation which is unique among Token with the same Kind.
+  std::string Data;
+  Kind TokenKind;
+
+  friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Token &T) {
+    return OS << T.Data;
+  }
+
+private:
+  friend llvm::hash_code hash_value(const Token &Token) {
+    return llvm::hash_combine(static_cast<int>(Token.TokenKind), Token.Data);
+  }
+};
+
+} // namespace dex
+} // namespace clangd
+} // namespace clang
+
+namespace llvm {
+
+// Support Tokens as DenseMap keys.
+template <> struct DenseMapInfo<clang::clangd::dex::Token> {
+  static inline clang::clangd::dex::Token getEmptyKey() {
+    return {clang::clangd::dex::Token::Kind::Sentinel, "EmptyKey"};
+  }
+
+  static inline clang::clangd::dex::Token getTombstoneKey() {
+    return {clang::clangd::dex::Token::Kind::Sentinel, "TombstoneKey"};
+  }
+
+  static unsigned getHashValue(const clang::clangd::dex::Token &Tag) {
+    return hash_value(Tag);
+  }
+
+  static bool isEqual(const clang::clangd::dex::Token &LHS,
+                      const clang::clangd::dex::Token &RHS) {
+    return LHS == RHS;
+  }
+};
+
+} // namespace llvm
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/dex/Trigram.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/index/dex/Trigram.cpp
new file mode 100644
index 0000000..549093d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/dex/Trigram.cpp
@@ -0,0 +1,132 @@
+//===--- Trigram.cpp - Trigram generation for Fuzzy Matching ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Trigram.h"
+#include "../../FuzzyMatch.h"
+#include "Token.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/StringExtras.h"
+
+#include <cctype>
+#include <queue>
+#include <string>
+
+using namespace llvm;
+
+namespace clang {
+namespace clangd {
+namespace dex {
+
+// FIXME(kbobyrev): Deal with short symbol symbol names. A viable approach would
+// be generating unigrams and bigrams here, too. This would prevent symbol index
+// from applying fuzzy matching on a tremendous number of symbols and allow
+// supplementary retrieval for short queries.
+//
+// Short names (total segment length <3 characters) are currently ignored.
+std::vector<Token> generateIdentifierTrigrams(llvm::StringRef Identifier) {
+  // Apply fuzzy matching text segmentation.
+  std::vector<CharRole> Roles(Identifier.size());
+  calculateRoles(Identifier,
+                 llvm::makeMutableArrayRef(Roles.data(), Identifier.size()));
+
+  std::string LowercaseIdentifier = Identifier.lower();
+
+  // For each character, store indices of the characters to which fuzzy matching
+  // algorithm can jump. There are 3 possible variants:
+  //
+  // * Next Tail - next character from the same segment
+  // * Next Head - front character of the next segment
+  // * Skip-1-Next Head - front character of the skip-1-next segment
+  //
+  // Next stores tuples of three indices in the presented order, if a variant is
+  // not available then 0 is stored.
+  std::vector<std::array<unsigned, 3>> Next(LowercaseIdentifier.size());
+  unsigned NextTail = 0, NextHead = 0, NextNextHead = 0;
+  for (int I = LowercaseIdentifier.size() - 1; I >= 0; --I) {
+    Next[I] = {{NextTail, NextHead, NextNextHead}};
+    NextTail = Roles[I] == Tail ? I : 0;
+    if (Roles[I] == Head) {
+      NextNextHead = NextHead;
+      NextHead = I;
+    }
+  }
+
+  DenseSet<Token> UniqueTrigrams;
+  std::array<char, 4> Chars;
+  for (size_t I = 0; I < LowercaseIdentifier.size(); ++I) {
+    // Skip delimiters.
+    if (Roles[I] != Head && Roles[I] != Tail)
+      continue;
+    for (const unsigned J : Next[I]) {
+      if (!J)
+        continue;
+      for (const unsigned K : Next[J]) {
+        if (!K)
+          continue;
+        Chars = {{LowercaseIdentifier[I], LowercaseIdentifier[J],
+                  LowercaseIdentifier[K], 0}};
+        auto Trigram = Token(Token::Kind::Trigram, Chars.data());
+        // Push unique trigrams to the result.
+        if (!UniqueTrigrams.count(Trigram)) {
+          UniqueTrigrams.insert(Trigram);
+        }
+      }
+    }
+  }
+
+  std::vector<Token> Result;
+  for (const auto &Trigram : UniqueTrigrams)
+    Result.push_back(Trigram);
+
+  return Result;
+}
+
+// FIXME(kbobyrev): Similarly, to generateIdentifierTrigrams, this ignores short
+// inputs (total segment length <3 characters).
+std::vector<Token> generateQueryTrigrams(llvm::StringRef Query) {
+  // Apply fuzzy matching text segmentation.
+  std::vector<CharRole> Roles(Query.size());
+  calculateRoles(Query, llvm::makeMutableArrayRef(Roles.data(), Query.size()));
+
+  std::string LowercaseQuery = Query.lower();
+
+  DenseSet<Token> UniqueTrigrams;
+  std::deque<char> Chars;
+
+  for (size_t I = 0; I < LowercaseQuery.size(); ++I) {
+    // If current symbol is delimiter, just skip it.
+    if (Roles[I] != Head && Roles[I] != Tail)
+      continue;
+
+    Chars.push_back(LowercaseQuery[I]);
+
+    if (Chars.size() > 3)
+      Chars.pop_front();
+    if (Chars.size() == 3) {
+      auto Trigram =
+          Token(Token::Kind::Trigram, std::string(begin(Chars), end(Chars)));
+      // Push unique trigrams to the result.
+      if (!UniqueTrigrams.count(Trigram)) {
+        UniqueTrigrams.insert(Trigram);
+      }
+    }
+  }
+
+  std::vector<Token> Result;
+  for (const auto &Trigram : UniqueTrigrams)
+    Result.push_back(Trigram);
+
+  return Result;
+}
+
+} // namespace dex
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/index/dex/Trigram.h b/src/third_party/llvm-project/clang-tools-extra/clangd/index/dex/Trigram.h
new file mode 100644
index 0000000..0e21c7d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/index/dex/Trigram.h
@@ -0,0 +1,62 @@
+//===--- Trigram.h - Trigram generation for Fuzzy Matching ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Trigrams are attributes of the symbol unqualified name used to effectively
+// extract symbols which can be fuzzy-matched given user query from the inverted
+// index. To match query with the extracted set of trigrams Q, the set of
+// generated trigrams T for identifier (unqualified symbol name) should contain
+// all items of Q, i.e. Q ⊆ T.
+//
+// Trigram sets extracted from unqualified name and from query are different:
+// the set of query trigrams only contains consecutive sequences of three
+// characters (which is only a subset of all trigrams generated for an
+// identifier).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_DEX_TRIGRAM_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_DEX_TRIGRAM_H
+
+#include "Token.h"
+
+#include <string>
+
+namespace clang {
+namespace clangd {
+namespace dex {
+
+/// Returns list of unique fuzzy-search trigrams from unqualified symbol.
+///
+/// First, given Identifier (unqualified symbol name) is segmented using
+/// FuzzyMatch API and lowercased. After segmentation, the following technique
+/// is applied for generating trigrams: for each letter or digit in the input
+/// string the algorithms looks for the possible next and skip-1-next symbols
+/// which can be jumped to during fuzzy matching. Each combination of such three
+/// symbols is inserted into the result.
+///
+/// Trigrams can start at any character in the input. Then we can choose to move
+/// to the next character, move to the start of the next segment, or skip over a
+/// segment.
+///
+/// Note: the returned list of trigrams does not have duplicates, if any trigram
+/// belongs to more than one class it is only inserted once.
+std::vector<Token> generateIdentifierTrigrams(llvm::StringRef Identifier);
+
+/// Returns list of unique fuzzy-search trigrams given a query.
+///
+/// Query is segmented using FuzzyMatch API and downcasted to lowercase. Then,
+/// the simplest trigrams - sequences of three consecutive letters and digits
+/// are extracted and returned after deduplication.
+std::vector<Token> generateQueryTrigrams(llvm::StringRef Query);
+
+} // namespace dex
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/tool/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/clangd/tool/CMakeLists.txt
new file mode 100644
index 0000000..c188761
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/tool/CMakeLists.txt
@@ -0,0 +1,20 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
+
+add_clang_tool(clangd
+  ClangdMain.cpp
+  )
+
+set(LLVM_LINK_COMPONENTS
+  support
+  )
+
+target_link_libraries(clangd
+  PRIVATE
+  clangBasic
+  clangDaemon
+  clangFormat
+  clangFrontend
+  clangSema
+  clangTooling
+  clangToolingCore
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/clangd/tool/ClangdMain.cpp b/src/third_party/llvm-project/clang-tools-extra/clangd/tool/ClangdMain.cpp
new file mode 100644
index 0000000..95ffdfa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -0,0 +1,298 @@
+//===--- ClangdMain.cpp - clangd server loop ------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangdLSPServer.h"
+#include "JSONRPCDispatcher.h"
+#include "Path.h"
+#include "Trace.h"
+#include "index/SymbolYAML.h"
+#include "clang/Basic/Version.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdlib>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+
+using namespace clang;
+using namespace clang::clangd;
+
+namespace {
+enum class PCHStorageFlag { Disk, Memory };
+
+// Build an in-memory static index for global symbols from a YAML-format file.
+// The size of global symbols should be relatively small, so that all symbols
+// can be managed in memory.
+std::unique_ptr<SymbolIndex> buildStaticIndex(llvm::StringRef YamlSymbolFile) {
+  auto Buffer = llvm::MemoryBuffer::getFile(YamlSymbolFile);
+  if (!Buffer) {
+    llvm::errs() << "Can't open " << YamlSymbolFile << "\n";
+    return nullptr;
+  }
+  auto Slab = symbolsFromYAML(Buffer.get()->getBuffer());
+  SymbolSlab::Builder SymsBuilder;
+  for (auto Sym : Slab)
+    SymsBuilder.insert(Sym);
+
+  return MemIndex::build(std::move(SymsBuilder).build());
+}
+} // namespace
+
+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()));
+
+// FIXME: also support "plain" style where signatures are always omitted.
+enum CompletionStyleFlag {
+  Detailed,
+  Bundled,
+};
+static llvm::cl::opt<CompletionStyleFlag> CompletionStyle(
+    "completion-style",
+    llvm::cl::desc("Granularity of code completion suggestions"),
+    llvm::cl::values(
+        clEnumValN(Detailed, "detailed",
+                   "One completion item for each semantically distinct "
+                   "completion, with full type information."),
+        clEnumValN(Bundled, "bundled",
+                   "Similar completion items (e.g. function overloads) are "
+                   "combined. Type information shown where possible.")),
+    llvm::cl::init(Detailed));
+
+// FIXME: Flags are the wrong mechanism for user preferences.
+// We should probably read a dotfile or similar.
+static llvm::cl::opt<bool> IncludeIneligibleResults(
+    "include-ineligible-results",
+    llvm::cl::desc(
+        "Include ineligible completion results (e.g. private members)"),
+    llvm::cl::init(clangd::CodeCompleteOptions().IncludeIneligibleResults),
+    llvm::cl::Hidden);
+
+static llvm::cl::opt<JSONStreamStyle> InputStyle(
+    "input-style", llvm::cl::desc("Input JSON stream encoding"),
+    llvm::cl::values(
+        clEnumValN(JSONStreamStyle::Standard, "standard", "usual LSP protocol"),
+        clEnumValN(JSONStreamStyle::Delimited, "delimited",
+                   "messages delimited by --- lines, with # comment support")),
+    llvm::cl::init(JSONStreamStyle::Standard));
+
+static llvm::cl::opt<bool>
+    PrettyPrint("pretty", llvm::cl::desc("Pretty-print JSON output"),
+                llvm::cl::init(false));
+
+static llvm::cl::opt<Logger::Level> LogLevel(
+    "log", llvm::cl::desc("Verbosity of log messages written to stderr"),
+    llvm::cl::values(clEnumValN(Logger::Error, "error", "Error messages only"),
+                     clEnumValN(Logger::Info, "info",
+                                "High level execution tracing"),
+                     clEnumValN(Logger::Debug, "verbose", "Low level details")),
+    llvm::cl::init(Logger::Info));
+
+static llvm::cl::opt<bool> Test(
+    "lit-test",
+    llvm::cl::desc(
+        "Abbreviation for -input-style=delimited -pretty -run-synchronously. "
+        "Intended to simplify lit tests."),
+    llvm::cl::init(false), llvm::cl::Hidden);
+
+static llvm::cl::opt<PCHStorageFlag> PCHStorage(
+    "pch-storage",
+    llvm::cl::desc("Storing PCHs in memory increases memory usages, but may "
+                   "improve performance"),
+    llvm::cl::values(
+        clEnumValN(PCHStorageFlag::Disk, "disk", "store PCHs on disk"),
+        clEnumValN(PCHStorageFlag::Memory, "memory", "store PCHs in memory")),
+    llvm::cl::init(PCHStorageFlag::Disk));
+
+static llvm::cl::opt<int> LimitResults(
+    "limit-results",
+    llvm::cl::desc("Limit the number of results returned by clangd. "
+                   "0 means no limit."),
+    llvm::cl::init(100));
+
+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);
+
+static llvm::cl::opt<bool> EnableIndex(
+    "index",
+    llvm::cl::desc("Enable index-based features such as global code completion "
+                   "and searching for symbols."
+                   "Clang uses an index built from symbols in opened files"),
+    llvm::cl::init(true));
+
+static llvm::cl::opt<bool>
+    ShowOrigins("debug-origin",
+                llvm::cl::desc("Show origins of completion items"),
+                llvm::cl::init(clangd::CodeCompleteOptions().ShowOrigins),
+                llvm::cl::Hidden);
+
+static llvm::cl::opt<bool> HeaderInsertionDecorators(
+    "header-insertion-decorators",
+    llvm::cl::desc("Prepend a circular dot or space before the completion "
+                   "label, depending on wether "
+                   "an include line will be inserted or not."),
+    llvm::cl::init(true));
+
+static llvm::cl::opt<Path> YamlSymbolFile(
+    "yaml-symbol-file",
+    llvm::cl::desc(
+        "YAML-format global symbol file to build the static index. Clangd will "
+        "use the static index for global code completion.\n"
+        "WARNING: This option is experimental only, and will be removed "
+        "eventually. Don't rely on it."),
+    llvm::cl::init(""), llvm::cl::Hidden);
+
+int main(int argc, char *argv[]) {
+  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+  llvm::cl::SetVersionPrinter([](llvm::raw_ostream &OS) {
+    OS << clang::getClangToolFullVersion("clangd") << "\n";
+  });
+  llvm::cl::ParseCommandLineOptions(
+      argc, argv,
+      "clangd is a language server that provides IDE-like features to editors. "
+      "\n\nIt should be used via an editor plugin rather than invoked directly."
+      "For more information, see:"
+      "\n\thttps://clang.llvm.org/extra/clangd.html"
+      "\n\thttps://microsoft.github.io/language-server-protocol/");
+  if (Test) {
+    RunSynchronously = true;
+    InputStyle = JSONStreamStyle::Delimited;
+    PrettyPrint = true;
+  }
+
+  if (!RunSynchronously && WorkerThreadsCount == 0) {
+    llvm::errs() << "A number of worker threads cannot be 0. Did you mean to "
+                    "specify -run-synchronously?";
+    return 1;
+  }
+
+  if (RunSynchronously) {
+    if (WorkerThreadsCount.getNumOccurrences())
+      llvm::errs() << "Ignoring -j because -run-synchronously is set.\n";
+    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::FA_Read | llvm::sys::fs::FA_Write);
+    if (EC) {
+      InputMirrorStream.reset();
+      llvm::errs() << "Error while opening an input mirror file: "
+                   << EC.message();
+    }
+  }
+
+  // Setup tracing facilities if CLANGD_TRACE is set. In practice enabling a
+  // trace flag in your editor's config is annoying, launching with
+  // `CLANGD_TRACE=trace.json vim` is easier.
+  llvm::Optional<llvm::raw_fd_ostream> TraceStream;
+  std::unique_ptr<trace::EventTracer> Tracer;
+  if (auto *TraceFile = getenv("CLANGD_TRACE")) {
+    std::error_code EC;
+    TraceStream.emplace(TraceFile, /*ref*/ EC,
+                        llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
+    if (EC) {
+      TraceStream.reset();
+      llvm::errs() << "Error while opening trace file " << TraceFile << ": "
+                   << EC.message();
+    } else {
+      Tracer = trace::createJSONTracer(*TraceStream, PrettyPrint);
+    }
+  }
+
+  llvm::Optional<trace::Session> TracingSession;
+  if (Tracer)
+    TracingSession.emplace(*Tracer);
+
+  JSONOutput Out(llvm::outs(), llvm::errs(), LogLevel,
+                 InputMirrorStream ? InputMirrorStream.getPointer() : nullptr,
+                 PrettyPrint);
+
+  clangd::LoggingSession LoggingSession(Out);
+
+  // If --compile-commands-dir arg was invoked, check value and override default
+  // 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;
+  }
+
+  ClangdServer::Options Opts;
+  switch (PCHStorage) {
+  case PCHStorageFlag::Memory:
+    Opts.StorePreamblesInMemory = true;
+    break;
+  case PCHStorageFlag::Disk:
+    Opts.StorePreamblesInMemory = false;
+    break;
+  }
+  if (!ResourceDir.empty())
+    Opts.ResourceDir = ResourceDir;
+  Opts.BuildDynamicSymbolIndex = EnableIndex;
+  std::unique_ptr<SymbolIndex> StaticIdx;
+  if (EnableIndex && !YamlSymbolFile.empty()) {
+    StaticIdx = buildStaticIndex(YamlSymbolFile);
+    Opts.StaticIndex = StaticIdx.get();
+  }
+  Opts.AsyncThreadsCount = WorkerThreadsCount;
+
+  clangd::CodeCompleteOptions CCOpts;
+  CCOpts.IncludeIneligibleResults = IncludeIneligibleResults;
+  CCOpts.Limit = LimitResults;
+  CCOpts.BundleOverloads = CompletionStyle != Detailed;
+  CCOpts.ShowOrigins = ShowOrigins;
+  if (!HeaderInsertionDecorators) {
+    CCOpts.IncludeIndicator.Insert.clear();
+    CCOpts.IncludeIndicator.NoInsert.clear();
+  }
+
+  // Initialize and run ClangdLSPServer.
+  ClangdLSPServer LSPServer(Out, CCOpts, CompileCommandsDirPath, Opts);
+  constexpr int NoShutdownRequestErrorCode = 1;
+  llvm::set_thread_name("clangd.main");
+  // Change stdin to binary to not lose \r\n on windows.
+  llvm::sys::ChangeStdinToBinary();
+  return LSPServer.run(stdin, InputStyle) ? 0 : NoShutdownRequestErrorCode;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/docs/CMakeLists.txt
new file mode 100644
index 0000000..8f442e1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/CMakeLists.txt
@@ -0,0 +1,102 @@
+if (DOXYGEN_FOUND)
+  if (LLVM_ENABLE_DOXYGEN)
+    set(abs_srcdir ${CMAKE_CURRENT_SOURCE_DIR})
+    set(abs_builddir ${CMAKE_CURRENT_BINARY_DIR})
+
+    if (HAVE_DOT)
+      set(DOT ${LLVM_PATH_DOT})
+    endif()
+
+    if (LLVM_DOXYGEN_EXTERNAL_SEARCH)
+      set(enable_searchengine "YES")
+      set(searchengine_url "${LLVM_DOXYGEN_SEARCHENGINE_URL}")
+      set(enable_server_based_search "YES")
+      set(enable_external_search "YES")
+      set(extra_search_mappings "${LLVM_DOXYGEN_SEARCH_MAPPINGS}")
+    else()
+      set(enable_searchengine "NO")
+      set(searchengine_url "")
+      set(enable_server_based_search "NO")
+      set(enable_external_search "NO")
+      set(extra_search_mappings "")
+    endif()
+
+    # If asked, configure doxygen for the creation of a Qt Compressed Help file.
+    if (LLVM_ENABLE_DOXYGEN_QT_HELP)
+      set(CLANG_TOOLS_DOXYGEN_QCH_FILENAME "org.llvm.clang.qch" CACHE STRING
+        "Filename of the Qt Compressed help file")
+      set(CLANG_TOOLS_DOXYGEN_QHP_NAMESPACE "org.llvm.clang" CACHE STRING
+        "Namespace under which the intermediate Qt Help Project file lives")
+      set(CLANG_TOOLS_DOXYGEN_QHP_CUST_FILTER_NAME "Clang ${CLANG_VERSION}" CACHE STRING
+        "See http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-filters")
+      set(CLANG_TOOLS_DOXYGEN_QHP_CUST_FILTER_ATTRS "Clang,${CLANG_VERSION}" CACHE STRING
+        "See http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes")
+      set(clang_tools_doxygen_generate_qhp "YES")
+      set(clang_tools_doxygen_qch_filename "${CLANG_DOXYGEN_QCH_FILENAME}")
+      set(clang_tools_doxygen_qhp_namespace "${CLANG_DOXYGEN_QHP_NAMESPACE}")
+      set(clang_tools_doxygen_qhelpgenerator_path "${LLVM_DOXYGEN_QHELPGENERATOR_PATH}")
+      set(clang_tools_doxygen_qhp_cust_filter_name "${CLANG_DOXYGEN_QHP_CUST_FILTER_NAME}")
+      set(clang_tools_doxygen_qhp_cust_filter_attrs "${CLANG_DOXYGEN_QHP_CUST_FILTER_ATTRS}")
+    else()
+      set(clang_tools_doxygen_generate_qhp "NO")
+      set(clang_tools_doxygen_qch_filename "")
+      set(clang_tools_doxygen_qhp_namespace "")
+      set(clang_tools_doxygen_qhelpgenerator_path "")
+      set(clang_tools_doxygen_qhp_cust_filter_name "")
+      set(clang_tools_doxygen_qhp_cust_filter_attrs "")
+    endif()
+
+    option(LLVM_DOXYGEN_SVG
+      "Use svg instead of png files for doxygen graphs." OFF)
+    if (LLVM_DOXYGEN_SVG)
+      set(DOT_IMAGE_FORMAT "svg")
+    else()
+      set(DOT_IMAGE_FORMAT "png")
+    endif()
+
+    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxygen.cfg.in
+      ${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg @ONLY)
+
+    set(abs_top_srcdir)
+    set(abs_top_builddir)
+    set(DOT)
+    set(enable_searchengine)
+    set(searchengine_url)
+    set(enable_server_based_search)
+    set(enable_external_search)
+    set(extra_search_mappings)
+    set(clang_tools_doxygen_generate_qhp)
+    set(clang_tools_doxygen_qch_filename)
+    set(clang_tools_doxygen_qhp_namespace)
+    set(clang_tools_doxygen_qhelpgenerator_path)
+    set(clang_tools_doxygen_qhp_cust_filter_name)
+    set(clang_tools_doxygen_qhp_cust_filter_attrs)
+    set(DOT_IMAGE_FORMAT)
+
+    add_custom_target(doxygen-clang-tools
+      COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg
+      WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+      COMMENT "Generating clang doxygen documentation." VERBATIM)
+
+    if (LLVM_BUILD_DOCS)
+      add_dependencies(doxygen doxygen-clang-tools)
+    endif()
+
+    if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
+      install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doxygen/html
+        DESTINATION docs/html)
+    endif()
+  endif()
+endif()
+
+if (LLVM_ENABLE_SPHINX)
+  include(AddSphinxTarget)
+  if (SPHINX_FOUND)
+    if (${SPHINX_OUTPUT_HTML})
+      add_sphinx_target(html clang-tools)
+    endif()
+    if (${SPHINX_OUTPUT_MAN})
+      add_sphinx_target(man clang-tools)
+    endif()
+  endif()
+endif()
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/ModularizeUsage.rst b/src/third_party/llvm-project/clang-tools-extra/docs/ModularizeUsage.rst
new file mode 100644
index 0000000..9f01165
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/ModularizeUsage.rst
@@ -0,0 +1,98 @@
+================
+Modularize Usage
+================
+
+``modularize [<modularize-options>] [<module-map>|<include-files-list>]*
+[<front-end-options>...]``
+
+``<modularize-options>`` is a place-holder for options
+specific to modularize, which are described below in
+`Modularize Command Line Options`.
+
+``<module-map>`` specifies the path of a file name for an
+existing module map. The module map must be well-formed in
+terms of syntax. Modularize will extract the header file names
+from the map. Only normal headers are checked, assuming headers
+marked "private", "textual", or "exclude" are not to be checked
+as a top-level include, assuming they either are included by
+other headers which are checked, or they are not suitable for
+modules.
+
+``<include-files-list>`` specifies the path of a file name for a
+file containing the newline-separated list of headers to check
+with respect to each other. Lines beginning with '#' and empty
+lines are ignored. Header file names followed by a colon and
+other space-separated file names will include those extra files
+as dependencies. The file names can be relative or full paths,
+but must be on the same line. For example::
+
+  header1.h
+  header2.h
+  header3.h: header1.h header2.h
+
+Note that unless a ``-prefix (header path)`` option is specified,
+non-absolute file paths in the header list file will be relative
+to the header list file directory. Use -prefix to specify a different
+directory.
+
+``<front-end-options>`` is a place-holder for regular Clang
+front-end arguments, which must follow the <include-files-list>.
+Note that by default, modularize assumes .h files
+contain C++ source, so if you are using a different language,
+you might need to use a ``-x`` option to tell Clang that the
+header contains another language, i.e.:  ``-x c``
+
+Note also that because modularize does not use the clang driver,
+you will likely need to pass in additional compiler front-end
+arguments to match those passed in by default by the driver.
+
+Modularize Command Line Options
+===============================
+
+.. option:: -prefix=<header-path>
+
+  Prepend the given path to non-absolute file paths in the header list file.
+  By default, headers are assumed to be relative to the header list file
+  directory. Use ``-prefix`` to specify a different directory.
+
+.. option:: -module-map-path=<module-map-path>
+
+  Generate a module map and output it to the given file. See the description
+  in :ref:`module-map-generation`.
+
+.. option:: -problem-files-list=<problem-files-list-file-name>
+
+  For use only with module map assistant. Input list of files that
+  have problems with respect to modules. These will still be
+  included in the generated module map, but will be marked as
+  "excluded" headers.
+
+.. option:: -root-module=<root-name>
+
+  Put modules generated by the -module-map-path option in an enclosing
+  module with the given name. See the description in :ref:`module-map-generation`.
+
+.. option:: -block-check-header-list-only
+
+  Limit the #include-inside-extern-or-namespace-block
+  check to only those headers explicitly listed in the header list.
+  This is a work-around for avoiding error messages for private includes that
+  purposefully get included inside blocks.
+
+.. option:: -no-coverage-check
+
+  Don't do the coverage check for a module map.
+
+.. option:: -coverage-check-only
+
+  Only do the coverage check for a module map.
+
+.. option:: -display-file-lists
+
+  Display lists of good files (no compile errors), problem files,
+  and a combined list with problem files preceded by a '#'.
+  This can be used to quickly determine which files have problems.
+  The latter combined list might be useful in starting to modularize
+  a set of headers. You can start with a full list of headers,
+  use -display-file-lists option, and then use the combined list as
+  your intermediate list, uncommenting-out headers as you fix them.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/README.txt b/src/third_party/llvm-project/clang-tools-extra/docs/README.txt
new file mode 100644
index 0000000..4b60777
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/README.txt
@@ -0,0 +1,11 @@
+-------------------------------------------------------------
+Documentation for the tools of clang-tools-extra repo project
+-------------------------------------------------------------
+
+Sphinx and doxygen documentation is generated by executing make.
+
+Sphinx html files can be generated separately using make html.
+
+Doxygen html files can also be generated using make doxygen.
+
+The generated documentation will be placed in _build/html.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/ReleaseNotes.rst b/src/third_party/llvm-project/clang-tools-extra/docs/ReleaseNotes.rst
new file mode 100644
index 0000000..157db97
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/ReleaseNotes.rst
@@ -0,0 +1,245 @@
+=====================================
+Extra Clang Tools 7.0.0 Release Notes
+=====================================
+
+.. contents::
+   :local:
+   :depth: 3
+
+Written by the `LLVM Team <https://llvm.org/>`_
+
+
+Introduction
+============
+
+This document contains the release notes for the Extra Clang Tools, part of the
+Clang release 7.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 <https://llvm.org/releases/>`_.
+
+For more information about Clang or LLVM, including information about
+the latest release, please see the `Clang Web Site <https://clang.llvm.org>`_ or
+the `LLVM Web Site <https://llvm.org>`_.
+
+What's New in Extra Clang Tools 7.0.0?
+======================================
+
+Some of the major new features and improvements to Extra Clang Tools are listed
+here. Generic improvements to Extra Clang Tools as a whole or to its underlying
+infrastructure are described first, followed by tool-specific sections.
+
+Improvements to clang-tidy
+--------------------------
+
+- The checks profiling info can now be stored as JSON files for futher
+  post-processing and analysis.
+
+- New module `abseil` for checks related to the `Abseil <https://abseil.io>`_
+  library.
+
+- New module ``portability``.
+
+- New module ``zircon`` for checks related to Fuchsia's Zircon kernel.
+
+- New :doc:`abseil-string-find-startswith
+  <clang-tidy/checks/abseil-string-find-startswith>` check.
+
+  Checks whether a ``std::string::find()`` result is compared with 0, and
+  suggests replacing with ``absl::StartsWith()``.
+
+- New :doc:`android-comparison-in-temp-failure-retry
+  <clang-tidy/checks/android-comparison-in-temp-failure-retry>` check.
+
+  Diagnoses comparisons that appear to be incorrectly placed in the argument to
+  the ``TEMP_FAILURE_RETRY`` macro.
+
+- New :doc:`bugprone-exception-escape
+  <clang-tidy/checks/bugprone-exception-escape>` check
+
+  Finds functions which may throw an exception directly or indirectly, but they
+  should not.
+
+- New :doc:`bugprone-parent-virtual-call
+  <clang-tidy/checks/bugprone-parent-virtual-call>` check.
+
+  Detects and fixes calls to grand-...parent virtual methods instead of calls
+  to overridden parent's virtual methods.
+
+- New :doc:`bugprone-terminating-continue
+  <clang-tidy/checks/bugprone-terminating-continue>` check
+
+  Checks if a ``continue`` statement terminates the loop.
+
+- New :doc:`bugprone-throw-keyword-missing
+  <clang-tidy/checks/bugprone-throw-keyword-missing>` check.
+
+  Diagnoses when a temporary object that appears to be an exception is
+  constructed but not thrown.
+
+- New :doc:`bugprone-unused-return-value
+  <clang-tidy/checks/bugprone-unused-return-value>` check.
+
+  Warns on unused function return values.
+
+- New :doc:`cert-msc32-c
+  <clang-tidy/checks/cert-msc32-c>` check
+
+  Detects inappropriate seeding of ``srand()`` function.
+
+- New :doc:`cert-msc51-cpp
+  <clang-tidy/checks/cert-msc51-cpp>` check
+
+  Detects inappropriate seeding of C++ random generators and C ``srand()`` function.
+
+- New :doc:`cppcoreguidelines-avoid-goto
+  <clang-tidy/checks/cppcoreguidelines-avoid-goto>` check.
+
+  The usage of ``goto`` for control flow is error prone and should be replaced
+  with looping constructs. Every backward jump is rejected. Forward jumps are
+  only allowed in nested loops.
+
+- New :doc:`cppcoreguidelines-narrowing-conversions
+  <clang-tidy/checks/cppcoreguidelines-narrowing-conversions>` check
+
+  Checks for narrowing conversions, e.g. ``int i = 0; i += 0.1;``.
+
+- New :doc:`fuchsia-multiple-inheritance
+  <clang-tidy/checks/fuchsia-multiple-inheritance>` check.
+
+  Warns if a class inherits from multiple classes that are not pure virtual.
+
+- New `fuchsia-restrict-system-includes
+  <https://clang.llvm.org/extra/clang-tidy/checks/fuchsia-restrict-system-includes.html>`_ check
+
+  Checks for allowed system includes and suggests removal of any others.
+
+- New `fuchsia-statically-constructed-objects
+  <https://clang.llvm.org/extra/clang-tidy/checks/fuchsia-statically-constructed-objects.html>`_ check
+
+  Warns if global, non-trivial objects with static storage are constructed,
+  unless the object is statically initialized with a ``constexpr`` constructor
+  or has no explicit constructor.
+
+- New :doc:`fuchsia-trailing-return
+  <clang-tidy/checks/fuchsia-trailing-return>` check.
+
+  Functions that have trailing returns are disallowed, except for those
+  using ``decltype`` specifiers and lambda with otherwise unutterable
+  return types.
+
+- New :doc:`hicpp-multiway-paths-covered
+  <clang-tidy/checks/hicpp-multiway-paths-covered>` check.
+
+  Checks on ``switch`` and ``if`` - ``else if`` constructs that do not cover all possible code paths.
+
+- New :doc:`modernize-use-uncaught-exceptions
+  <clang-tidy/checks/modernize-use-uncaught-exceptions>` check.
+
+  Finds and replaces deprecated uses of ``std::uncaught_exception`` to
+  ``std::uncaught_exceptions``.
+
+- New :doc:`portability-simd-intrinsics
+  <clang-tidy/checks/portability-simd-intrinsics>` check.
+
+  Warns or suggests alternatives if SIMD intrinsics are used which can be replaced by
+  ``std::experimental::simd`` operations.
+
+- New :doc:`readability-simplify-subscript-expr
+  <clang-tidy/checks/readability-simplify-subscript-expr>` check.
+
+  Simplifies subscript expressions like ``s.data()[i]`` into ``s[i]``.
+
+- New :doc:`zircon-temporary-objects
+  <clang-tidy/checks/zircon-temporary-objects>` check.
+
+  Warns on construction of specific temporary objects in the Zircon kernel.
+
+- Added the missing bitwise assignment operations to
+  :doc:`hicpp-signed-bitwise <clang-tidy/checks/hicpp-signed-bitwise>`.
+
+- New option `MinTypeNameLength` for :doc:`modernize-use-auto
+  <clang-tidy/checks/modernize-use-auto>` check to limit the minimal length of
+  type names to be replaced with ``auto``. Use to skip replacing short type
+  names like ``int``/``bool`` with ``auto``. Default value is 5 which means
+  replace types with the name length >= 5 letters only (ex. ``double``,
+  ``unsigned``).
+
+- Add `VariableThreshold` option to :doc:`readability-function-size
+  <clang-tidy/checks/readability-function-size>` check.
+
+  Flags functions that have more than a specified number of variables declared
+  in the body.
+
+- The `AnalyzeTemporaryDtors` option was removed, since the corresponding
+  `cfg-temporary-dtors` option of the Static Analyzer now defaults to `true`.
+
+- New alias :doc:`fuchsia-header-anon-namespaces
+  <clang-tidy/checks/fuchsia-header-anon-namespaces>` to :doc:`google-build-namespaces
+  <clang-tidy/checks/google-build-namespaces>`
+  added.
+
+- New alias :doc:`hicpp-avoid-goto
+  <clang-tidy/checks/hicpp-avoid-goto>` to :doc:`cppcoreguidelines-avoid-goto
+  <clang-tidy/checks/cppcoreguidelines-avoid-goto>`
+  added.
+
+- Removed the `google-readability-redundant-smartptr-get` alias of the
+  :doc:`readability-redundant-smartptr-get
+  <clang-tidy/checks/readability-redundant-smartptr-get>` check.
+
+- The 'misc-forwarding-reference-overload' check was renamed to :doc:`bugprone-forwarding-reference-overload
+  <clang-tidy/checks/bugprone-forwarding-reference-overload>`
+
+- The 'misc-incorrect-roundings' check was renamed to :doc:`bugprone-incorrect-roundings
+  <clang-tidy/checks/bugprone-incorrect-roundings>`
+
+- The 'misc-lambda-function-name' check was renamed to :doc:`bugprone-lambda-function-name
+  <clang-tidy/checks/bugprone-lambda-function-name>`
+
+- The 'misc-macro-parentheses' check was renamed to :doc:`bugprone-macro-parentheses
+  <clang-tidy/checks/bugprone-macro-parentheses>`
+
+- The 'misc-macro-repeated-side-effects' check was renamed to :doc:`bugprone-macro-repeated-side-effects
+  <clang-tidy/checks/bugprone-macro-repeated-side-effects>`
+
+- The 'misc-misplaced-widening-cast' check was renamed to :doc:`bugprone-misplaced-widening-cast
+  <clang-tidy/checks/bugprone-misplaced-widening-cast>`
+
+- The 'misc-sizeof-container' check was renamed to :doc:`bugprone-sizeof-container
+  <clang-tidy/checks/bugprone-sizeof-container>`
+
+- The 'misc-sizeof-expression' check was renamed to :doc:`bugprone-sizeof-expression
+  <clang-tidy/checks/bugprone-sizeof-expression>`
+
+- The 'misc-string-compare' check was renamed to :doc:`readability-string-compare
+  <clang-tidy/checks/readability-string-compare>`
+
+- The 'misc-string-integer-assignment' check was renamed to :doc:`bugprone-string-integer-assignment
+  <clang-tidy/checks/bugprone-string-integer-assignment>`
+
+- The 'misc-string-literal-with-embedded-nul' check was renamed to :doc:`bugprone-string-literal-with-embedded-nul
+  <clang-tidy/checks/bugprone-string-literal-with-embedded-nul>`
+
+- The 'misc-suspicious-enum-usage' check was renamed to :doc:`bugprone-suspicious-enum-usage
+  <clang-tidy/checks/bugprone-suspicious-enum-usage>`
+
+- The 'misc-suspicious-missing-comma' check was renamed to :doc:`bugprone-suspicious-missing-comma
+  <clang-tidy/checks/bugprone-suspicious-missing-comma>`
+
+- The 'misc-suspicious-semicolon' check was renamed to :doc:`bugprone-suspicious-semicolon
+  <clang-tidy/checks/bugprone-suspicious-semicolon>`
+
+- The 'misc-suspicious-string-compare' check was renamed to :doc:`bugprone-suspicious-string-compare
+  <clang-tidy/checks/bugprone-suspicious-string-compare>`
+
+- The 'misc-swapped-arguments' check was renamed to :doc:`bugprone-swapped-arguments
+  <clang-tidy/checks/bugprone-swapped-arguments>`
+
+- The 'misc-undelegated-constructor' check was renamed to :doc:`bugprone-undelegated-constructor
+  <clang-tidy/checks/bugprone-undelegated-constructor>`
+
+- The 'misc-unused-raii' check was renamed to :doc:`bugprone-unused-raii
+  <clang-tidy/checks/bugprone-unused-raii>`
+
+- The 'google-runtime-member-string-references' check was removed.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-doc.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-doc.rst
new file mode 100644
index 0000000..f891b71
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-doc.rst
@@ -0,0 +1,65 @@
+===================
+Clang-Doc
+===================
+
+.. contents::
+
+.. toctree::
+   :maxdepth: 1
+
+:program:`clang-doc` is a tool for generating C and C++ documenation from 
+source code and comments. 
+
+The tool is in a very early development stage, so you might encounter bugs and
+crashes. Submitting reports with information about how to reproduce the issue
+to `the LLVM bugtracker <https://llvm.org/bugs>`_ will definitely help the
+project. If you have any ideas or suggestions, please to put a feature request
+there.
+
+Use
+=====
+
+:program:`clang-doc` is a `LibTooling
+<http://clang.llvm.org/docs/LibTooling.html>`_-based tool, and so requires a
+compile command database for your project (for an example of how to do this 
+see `How To Setup Tooling For LLVM
+<http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html>`_).
+
+The tool can be used on a single file or multiple files as defined in 
+the compile commands database:
+
+.. code-block:: console
+
+  $ clang-doc /path/to/file.cpp -p /path/to/compile/commands
+
+This generates an intermediate representation of the declarations and their
+associated information in the specified TUs, serialized to LLVM bitcode.
+
+As currently implemented, the tool is only able to parse TUs that can be 
+stored in-memory. Future additions will extend the current framework to use
+map-reduce frameworks to allow for use with large codebases.
+
+:program:`clang-doc` offers the following options:
+
+.. code-block:: console
+
+	$ clang-doc --help
+  USAGE: clang-doc [options] <source0> [... <sourceN>]
+
+  OPTIONS:
+
+  Generic Options:
+
+    -help                      - Display available options (-help-hidden for more)
+    -help-list                 - Display list of available options (-help-list-hidden for more)
+    -version                   - Display the version of this program
+
+  clang-doc options:
+
+    -doxygen                   - Use only doxygen-style comments to generate docs.
+    -dump                      - Dump intermediate results to bitcode file.
+    -extra-arg=<string>        - Additional argument to append to the compiler command line
+    -extra-arg-before=<string> - Additional argument to prepend to the compiler command line
+    -omit-filenames            - Omit filenames in output.
+    -output=<string>           - Directory for outputting generated files.
+    -p=<string>                - Build path
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-modernize.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-modernize.rst
new file mode 100644
index 0000000..0a42961
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-modernize.rst
@@ -0,0 +1,4 @@
+:orphan:
+
+All :program:`clang-modernize` transforms have moved to :doc:`clang-tidy/index`
+(see the ``modernize`` module).
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-rename.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-rename.rst
new file mode 100644
index 0000000..f622779
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-rename.rst
@@ -0,0 +1,166 @@
+============
+Clang-Rename
+============
+
+.. contents::
+
+See also:
+
+.. toctree::
+   :maxdepth: 1
+
+
+:program:`clang-rename` is a C++ refactoring tool. Its purpose is to perform
+efficient renaming actions in large-scale projects such as renaming classes,
+functions, variables, arguments, namespaces etc.
+
+The tool is in a very early development stage, so you might encounter bugs and
+crashes. Submitting reports with information about how to reproduce the issue
+to `the LLVM bugtracker <https://llvm.org/bugs>`_ will definitely help the
+project. If you have any ideas or suggestions, you might want to put a feature
+request there.
+
+Using Clang-Rename
+==================
+
+:program:`clang-rename` is a `LibTooling
+<http://clang.llvm.org/docs/LibTooling.html>`_-based tool, and it's easier to
+work with if you set up a compile command database for your project (for an
+example of how to do this see `How To Setup Tooling For LLVM
+<http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html>`_). You can also
+specify compilation options on the command line after `--`:
+
+.. code-block:: console
+
+  $ clang-rename -offset=42 -new-name=foo test.cpp -- -Imy_project/include -DMY_DEFINES ...
+
+
+To get an offset of a symbol in a file run
+
+.. code-block:: console
+
+  $ grep -FUbo 'foo' file.cpp
+
+
+The tool currently supports renaming actions inside a single translation unit
+only. It is planned to extend the tool's functionality to support multi-TU
+renaming actions in the future.
+
+:program:`clang-rename` also aims to be easily integrated into popular text
+editors, such as Vim and Emacs, and improve the workflow of users.
+
+Although a command line interface exists, it is highly recommended to use the
+text editor interface instead for better experience.
+
+You can also identify one or more symbols to be renamed by giving the fully
+qualified name:
+
+.. code-block:: console
+
+  $ clang-rename -qualified-name=foo -new-name=bar test.cpp
+
+Renaming multiple symbols at once is supported, too. However,
+:program:`clang-rename` doesn't accept both `-offset` and `-qualified-name` at
+the same time. So, you can either specify multiple `-offset` or
+`-qualified-name`.
+
+.. code-block:: console
+
+  $ clang-rename -offset=42 -new-name=bar1 -offset=150 -new-name=bar2 test.cpp
+
+or
+
+.. code-block:: console
+
+  $ clang-rename -qualified-name=foo1 -new-name=bar1 -qualified-name=foo2 -new-name=bar2 test.cpp
+
+
+Alternatively, {offset | qualified-name} / new-name pairs can be put into a YAML
+file:
+
+.. code-block:: yaml
+
+  ---
+  - Offset:         42
+    NewName:        bar1
+  - Offset:         150
+    NewName:        bar2
+  ...
+
+or
+
+.. code-block:: yaml
+
+  ---
+  - QualifiedName:  foo1
+    NewName:        bar1
+  - QualifiedName:  foo2
+    NewName:        bar2
+  ...
+
+That way you can avoid spelling out all the names as command line arguments:
+
+.. code-block:: console
+
+  $ clang-rename -input=test.yaml test.cpp
+
+:program:`clang-rename` offers the following options:
+
+.. code-block:: console
+
+  $ clang-rename --help
+  USAGE: clang-rename [subcommand] [options] <source0> [... <sourceN>]
+
+  OPTIONS:
+
+  Generic Options:
+
+    -help                      - Display available options (-help-hidden for more)
+    -help-list                 - Display list of available options (-help-list-hidden for more)
+    -version                   - Display the version of this program
+
+  clang-rename common options:
+
+    -export-fixes=<filename>   - YAML file to store suggested fixes in.
+    -extra-arg=<string>        - Additional argument to append to the compiler command line
+    -extra-arg-before=<string> - Additional argument to prepend to the compiler command line
+    -force                     - Ignore nonexistent qualified names.
+    -i                         - Overwrite edited <file>s.
+    -input=<string>            - YAML file to load oldname-newname pairs from.
+    -new-name=<string>         - The new name to change the symbol to.
+    -offset=<uint>             - Locates the symbol by offset as opposed to <line>:<column>.
+    -p=<string>                - Build path
+    -pl                        - Print the locations affected by renaming to stderr.
+    -pn                        - Print the found symbol's name prior to renaming to stderr.
+    -qualified-name=<string>   - The fully qualified name of the symbol.
+
+Vim Integration
+===============
+
+You can call :program:`clang-rename` directly from Vim! To set up
+:program:`clang-rename` integration for Vim see
+`clang-rename/tool/clang-rename.py
+<http://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/clang-rename/tool/clang-rename.py>`_.
+
+Please note that **you have to save all buffers, in which the replacement will
+happen before running the tool**.
+
+Once installed, you can point your cursor to symbols you want to rename, press
+`<leader>cr` and type new desired name. The `<leader> key
+<http://vim.wikia.com/wiki/Mapping_keys_in_Vim_-_Tutorial_(Part_3)#Map_leader>`_
+is a reference to a specific key defined by the mapleader variable and is bound
+to backslash by default.
+
+Emacs Integration
+=================
+
+You can also use :program:`clang-rename` while using Emacs! To set up
+:program:`clang-rename` integration for Emacs see
+`clang-rename/tool/clang-rename.el
+<http://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/clang-rename/tool/clang-rename.el>`_.
+
+Once installed, you can point your cursor to symbols you want to rename, press
+`M-X`, type `clang-rename` and new desired name.
+
+Please note that **you have to save all buffers, in which the replacement will
+happen before running the tool**.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy.rst
new file mode 100644
index 0000000..bcd2bf1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy.rst
@@ -0,0 +1,6 @@
+:orphan:
+
+.. meta::
+   :http-equiv=refresh: 0;URL='clang-tidy/'
+
+clang-tidy documentation has moved here: http://clang.llvm.org/extra/clang-tidy/
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/abseil-string-find-startswith.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/abseil-string-find-startswith.rst
new file mode 100644
index 0000000..43f35ac
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/abseil-string-find-startswith.rst
@@ -0,0 +1,41 @@
+.. title:: clang-tidy - abseil-string-find-startswith
+
+abseil-string-find-startswith
+=============================
+
+Checks whether a ``std::string::find()`` result is compared with 0, and
+suggests replacing with ``absl::StartsWith()``. This is both a readability and
+performance issue.
+
+.. code-block:: c++
+
+  string s = "...";
+  if (s.find("Hello World") == 0) { /* do something */ }
+
+becomes
+
+
+.. code-block:: c++
+
+  string s = "...";
+  if (absl::StartsWith(s, "Hello World")) { /* do something */ }
+
+
+Options
+-------
+
+.. option:: StringLikeClasses
+
+   Semicolon-separated list of names of string-like classes. By default only
+   ``std::basic_string`` is considered. The list of methods to considered is
+   fixed.
+
+.. option:: IncludeStyle
+
+   A string specifying which include-style is used, `llvm` or `google`. Default
+   is `llvm`.
+
+.. option:: AbseilStringsMatchHeader
+
+   The location of Abseil's ``strings/match.h``. Defaults to
+   ``absl/strings/match.h``.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-accept.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-accept.rst
new file mode 100644
index 0000000..58ce05f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-accept.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-accept
+
+android-cloexec-accept
+======================
+
+The usage of ``accept()`` is not recommended, it's better to use ``accept4()``.
+Without this flag, an opened sensitive file descriptor would remain open across
+a fork+exec to a lower-privileged SELinux domain.
+
+Examples:
+
+.. code-block:: c++
+
+  accept(sockfd, addr, addrlen);
+
+  // becomes
+
+  accept4(sockfd, addr, addrlen, SOCK_CLOEXEC);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-accept4.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-accept4.rst
new file mode 100644
index 0000000..1633395
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-accept4.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-accept4
+
+android-cloexec-accept4
+=======================
+
+``accept4()`` should include ``SOCK_CLOEXEC`` in its type argument to avoid the
+file descriptor leakage. Without this flag, an opened sensitive file would
+remain open across a fork+exec to a lower-privileged SELinux domain.
+
+Examples:
+
+.. code-block:: c++
+
+  accept4(sockfd, addr, addrlen, SOCK_NONBLOCK);
+
+  // becomes
+
+  accept4(sockfd, addr, addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-creat.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-creat.rst
new file mode 100644
index 0000000..d2892a0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-creat.rst
@@ -0,0 +1,16 @@
+.. title:: clang-tidy - android-cloexec-creat
+
+android-cloexec-creat
+=====================
+
+The usage of ``creat()`` is not recommended, it's better to use ``open()``.
+
+Examples:
+
+.. code-block:: c++
+
+  int fd = creat(path, mode);
+
+  // becomes
+
+  int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-dup.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-dup.rst
new file mode 100644
index 0000000..d287a65
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-dup.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-dup
+
+android-cloexec-dup
+===================
+
+The usage of ``dup()`` is not recommended, it's better to use ``fcntl()``,
+which can set the close-on-exec flag. Otherwise, an opened sensitive file would
+remain open across a fork+exec to a lower-privileged SELinux domain.
+
+Examples:
+
+.. code-block:: c++
+
+  int fd = dup(oldfd);
+
+  // becomes
+
+  int fd = fcntl(oldfd, F_DUPFD_CLOEXEC);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-epoll-create.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-epoll-create.rst
new file mode 100644
index 0000000..98f0f6c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-epoll-create.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - android-cloexec-epoll-create
+
+android-cloexec-epoll-create
+============================
+
+The usage of ``epoll_create()`` is not recommended, it's better to use
+``epoll_create1()``, which allows close-on-exec.
+
+Examples:
+
+.. code-block:: c++
+
+  epoll_create(size);
+
+  // becomes
+
+  epoll_create1(EPOLL_CLOEXEC);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-epoll-create1.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-epoll-create1.rst
new file mode 100644
index 0000000..7e7c4ad
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-epoll-create1.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-epoll-create1
+
+android-cloexec-epoll-create1
+=============================
+
+``epoll_create1()`` should include ``EPOLL_CLOEXEC`` in its type argument to
+avoid the file descriptor leakage. Without this flag, an opened sensitive file
+would remain open across a fork+exec to a lower-privileged SELinux domain.
+
+Examples:
+
+.. code-block:: c++
+
+  epoll_create1(0);
+
+  // becomes
+
+  epoll_create1(EPOLL_CLOEXEC);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-fopen.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-fopen.rst
new file mode 100644
index 0000000..0552969
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-fopen.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-fopen
+
+android-cloexec-fopen
+=====================
+
+``fopen()`` should include ``e`` in their mode string; so ``re`` would be
+valid. This is equivalent to having set ``FD_CLOEXEC on`` that descriptor.
+
+Examples:
+
+.. code-block:: c++
+
+  fopen("fn", "r");
+
+  // becomes
+
+  fopen("fn", "re");
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-inotify-init.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-inotify-init.rst
new file mode 100644
index 0000000..cee4c7b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-inotify-init.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - android-cloexec-inotify-init
+
+android-cloexec-inotify-init
+============================
+
+The usage of ``inotify_init()`` is not recommended, it's better to use
+``inotify_init1()``.
+
+Examples:
+
+.. code-block:: c++
+
+  inotify_init();
+
+  // becomes
+
+  inotify_init1(IN_CLOEXEC);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-inotify-init1.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-inotify-init1.rst
new file mode 100644
index 0000000..827598c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-inotify-init1.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-inotify-init1
+
+android-cloexec-inotify-init1
+=============================
+
+``inotify_init1()`` should include ``IN_CLOEXEC`` in its type argument to avoid the
+file descriptor leakage. Without this flag, an opened sensitive file would
+remain open across a fork+exec to a lower-privileged SELinux domain.
+
+Examples:
+
+.. code-block:: c++
+
+  inotify_init1(IN_NONBLOCK);
+
+  // becomes
+
+  inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-memfd-create.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-memfd-create.rst
new file mode 100644
index 0000000..a45321d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-memfd-create.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-memfd-create
+
+android-cloexec-memfd-create
+============================
+
+``memfd_create()`` should include ``MFD_CLOEXEC`` in its type argument to avoid
+the file descriptor leakage. Without this flag, an opened sensitive file would
+remain open across a fork+exec to a lower-privileged SELinux domain.
+
+Examples:
+
+.. code-block:: c++
+
+  memfd_create(name, MFD_ALLOW_SEALING);
+
+  // becomes
+
+  memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-open.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-open.rst
new file mode 100644
index 0000000..ee3e4b5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-open.rst
@@ -0,0 +1,24 @@
+.. title:: clang-tidy - android-cloexec-open
+
+android-cloexec-open
+====================
+
+A common source of security bugs is code that opens a file without using the
+``O_CLOEXEC`` flag.  Without that flag, an opened sensitive file would remain
+open across a fork+exec to a lower-privileged SELinux domain, leaking that
+sensitive data. Open-like functions including ``open()``, ``openat()``, and
+``open64()`` should include ``O_CLOEXEC`` in their flags argument.
+
+Examples:
+
+.. code-block:: c++
+
+  open("filename", O_RDWR);
+  open64("filename", O_RDWR);
+  openat(0, "filename", O_RDWR);
+
+  // becomes
+
+  open("filename", O_RDWR | O_CLOEXEC);
+  open64("filename", O_RDWR | O_CLOEXEC);
+  openat(0, "filename", O_RDWR | O_CLOEXEC);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-socket.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-socket.rst
new file mode 100644
index 0000000..10b1976
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-cloexec-socket.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-socket
+
+android-cloexec-socket
+======================
+
+``socket()`` should include ``SOCK_CLOEXEC`` in its type argument to avoid the
+file descriptor leakage. Without this flag, an opened sensitive file would
+remain open across a fork+exec to a lower-privileged SELinux domain.
+
+Examples:
+
+.. code-block:: c++
+
+  socket(domain, type, SOCK_STREAM);
+
+  // becomes
+
+  socket(domain, type, SOCK_STREAM | SOCK_CLOEXEC);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-comparison-in-temp-failure-retry.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-comparison-in-temp-failure-retry.rst
new file mode 100644
index 0000000..e4de4b0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/android-comparison-in-temp-failure-retry.rst
@@ -0,0 +1,36 @@
+.. title:: clang-tidy - android-comparison-in-temp-failure-retry
+
+android-comparison-in-temp-failure-retry
+========================================
+
+Diagnoses comparisons that appear to be incorrectly placed in the argument to
+the ``TEMP_FAILURE_RETRY`` macro. Having such a use is incorrect in the vast
+majority of cases, and will often silently defeat the purpose of the
+``TEMP_FAILURE_RETRY`` macro.
+
+For context, ``TEMP_FAILURE_RETRY`` is `a convenience macro
+<https://www.gnu.org/software/libc/manual/html_node/Interrupted-Primitives.html>`_
+provided by both glibc and Bionic. Its purpose is to repeatedly run a syscall
+until it either succeeds, or fails for reasons other than being interrupted.
+
+Example buggy usage looks like:
+
+.. code-block:: c
+
+  char cs[1];
+  while (TEMP_FAILURE_RETRY(read(STDIN_FILENO, cs, sizeof(cs)) != 0)) {
+    // Do something with cs.
+  }
+
+Because TEMP_FAILURE_RETRY will check for whether the result *of the comparison*
+is ``-1``, and retry if so.
+
+If you encounter this, the fix is simple: lift the comparison out of the
+``TEMP_FAILURE_RETRY`` argument, like so:
+
+.. code-block:: c
+
+  char cs[1];
+  while (TEMP_FAILURE_RETRY(read(STDIN_FILENO, cs, sizeof(cs))) != 0) {
+    // Do something with cs.
+  }
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/boost-use-to-string.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/boost-use-to-string.rst
new file mode 100644
index 0000000..ebeb829
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/boost-use-to-string.rst
@@ -0,0 +1,22 @@
+.. title:: clang-tidy - boost-use-to-string
+
+boost-use-to-string
+===================
+
+This check finds conversion from integer type like ``int`` to ``std::string`` or
+``std::wstring`` using ``boost::lexical_cast``, and replace it with calls to
+``std::to_string`` and ``std::to_wstring``.
+
+It doesn't replace conversion from floating points despite the ``to_string``
+overloads, because it would change the behaviour.
+
+
+  .. code-block:: c++
+
+    auto str = boost::lexical_cast<std::string>(42);
+    auto wstr = boost::lexical_cast<std::wstring>(2137LL);
+
+    // Will be changed to
+    auto str = std::to_string(42);
+    auto wstr = std::to_wstring(2137LL);
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-argument-comment.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-argument-comment.rst
new file mode 100644
index 0000000..5f7e5f0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-argument-comment.rst
@@ -0,0 +1,29 @@
+.. title:: clang-tidy - bugprone-argument-comment
+
+bugprone-argument-comment
+=========================
+
+Checks that argument comments match parameter names.
+
+The check understands argument comments in the form ``/*parameter_name=*/``
+that are placed right before the argument.
+
+.. code-block:: c++
+
+  void f(bool foo);
+
+  ...
+
+  f(/*bar=*/true);
+  // warning: argument name 'bar' in comment does not match parameter name 'foo'
+
+The check tries to detect typos and suggest automated fixes for them.
+
+Options
+-------
+
+.. option:: StrictMode
+
+   When zero (default value), the check will ignore leading and trailing
+   underscores and case when comparing names -- otherwise they are taken into
+   account.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-assert-side-effect.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-assert-side-effect.rst
new file mode 100644
index 0000000..dc7a3c9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-assert-side-effect.rst
@@ -0,0 +1,23 @@
+.. title:: clang-tidy - bugprone-assert-side-effect
+
+bugprone-assert-side-effect
+===========================
+
+Finds ``assert()`` with side effect.
+
+The condition of ``assert()`` is evaluated only in debug builds so a
+condition with side effect can cause different behavior in debug / release
+builds.
+
+Options
+-------
+
+.. option:: AssertMacros
+
+   A comma-separated list of the names of assert macros to be checked.
+
+.. option:: CheckFunctionCalls
+
+   Whether to treat non-const member and non-member functions as they produce
+   side effects. Disabled by default because it can increase the number of false
+   positive warnings.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-bool-pointer-implicit-conversion.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-bool-pointer-implicit-conversion.rst
new file mode 100644
index 0000000..e42ee5f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-bool-pointer-implicit-conversion.rst
@@ -0,0 +1,16 @@
+.. title:: clang-tidy - bugprone-bool-pointer-implicit-conversion
+
+bugprone-bool-pointer-implicit-conversion
+=========================================
+
+Checks for conditions based on implicit conversion from a ``bool`` pointer to
+``bool``.
+
+Example:
+
+.. code-block:: c++
+
+  bool *p;
+  if (p) {
+    // Never used in a pointer-specific way.
+  }
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-copy-constructor-init.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-copy-constructor-init.rst
new file mode 100644
index 0000000..a2b39bc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-copy-constructor-init.rst
@@ -0,0 +1,29 @@
+.. title:: clang-tidy - bugprone-copy-constructor-init
+
+bugprone-copy-constructor-init
+==============================
+
+Finds copy constructors where the constructor doesn't call
+the copy constructor of the base class.
+
+.. code-block:: c++
+
+    class Copyable {
+    public:
+      Copyable() = default;
+      Copyable(const Copyable &) = default;
+    };
+    class X2 : public Copyable {
+      X2(const X2 &other) {} // Copyable(other) is missing
+    };
+
+Also finds copy constructors where the constructor of
+the base class don't have parameter.
+
+.. code-block:: c++
+
+    class X4 : public Copyable {
+      X4(const X4 &other) : Copyable() {} // other is missing
+    };
+
+The check also suggests a fix-its in some cases.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-dangling-handle.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-dangling-handle.rst
new file mode 100644
index 0000000..8c2c316
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-dangling-handle.rst
@@ -0,0 +1,38 @@
+.. title:: clang-tidy - bugprone-dangling-handle
+
+bugprone-dangling-handle
+========================
+
+Detect dangling references in value handles like
+``std::experimental::string_view``.
+These dangling references can be a result of constructing handles from temporary
+values, where the temporary is destroyed soon after the handle is created.
+
+Examples:
+
+.. code-block:: c++
+
+  string_view View = string();  // View will dangle.
+  string A;
+  View = A + "A";  // still dangle.
+
+  vector<string_view> V;
+  V.push_back(string());  // V[0] is dangling.
+  V.resize(3, string());  // V[1] and V[2] will also dangle.
+
+  string_view f() {
+    // All these return values will dangle.
+    return string();
+    string S;
+    return S;
+    char Array[10]{};
+    return Array;
+  }
+
+Options
+-------
+
+.. option:: HandleClasses
+
+   A semicolon-separated list of class names that should be treated as handles.
+   By default only ``std::experimental::basic_string_view`` is considered.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-exception-escape.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-exception-escape.rst
new file mode 100644
index 0000000..e9653a7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-exception-escape.rst
@@ -0,0 +1,39 @@
+.. title:: clang-tidy - bugprone-exception-escape
+
+bugprone-exception-escape
+=========================
+
+Finds functions which may throw an exception directly or indirectly, but they
+should not. The functions which should not throw exceptions are the following:
+* Destructors
+* Move constructors
+* Move assignment operators
+* The ``main()`` functions
+* ``swap()`` functions
+* Functions marked with ``throw()`` or ``noexcept``
+* Other functions given as option
+
+A destructor throwing an exception may result in undefined behavior, resource
+leaks or unexpected termination of the program. Throwing move constructor or
+move assignment also may result in undefined behavior or resource leak. The
+``swap()`` operations expected to be non throwing most of the cases and they
+are always possible to implement in a non throwing way. Non throwing ``swap()``
+operations are also used to create move operations. A throwing ``main()``
+function also results in unexpected termination.
+
+WARNING! This check may be expensive on large source files.
+
+Options
+-------
+
+.. option:: FunctionsThatShouldNotThrow
+
+   Comma separated list containing function names which should not throw. An
+   example value for this parameter can be ``WinMain`` which adds function
+   ``WinMain()`` in the Windows API to the list of the funcions which should
+   not throw. Default value is an empty string.
+
+.. option:: IgnoredExceptions
+
+   Comma separated list containing type names which are not counted as thrown
+   exceptions in the check. Default value is an empty string.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-fold-init-type.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-fold-init-type.rst
new file mode 100644
index 0000000..ebe3d22
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-fold-init-type.rst
@@ -0,0 +1,27 @@
+.. title:: clang-tidy - bugprone-fold-init-type
+
+bugprone-fold-init-type
+=======================
+
+The check flags type mismatches in
+`folds <https://en.wikipedia.org/wiki/Fold_(higher-order_function)>`_
+like ``std::accumulate`` that might result in loss of precision.
+``std::accumulate`` folds an input range into an initial value using the type of
+the latter, with ``operator+`` by default. This can cause loss of precision
+through:
+
+- Truncation: The following code uses a floating point range and an int
+  initial value, so trucation wil happen at every application of ``operator+``
+  and the result will be `0`, which might not be what the user expected.
+
+.. code-block:: c++
+
+  auto a = {0.5f, 0.5f, 0.5f, 0.5f};
+  return std::accumulate(std::begin(a), std::end(a), 0);
+
+- Overflow: The following code also returns `0`.
+
+.. code-block:: c++
+
+  auto a = {65536LL * 65536 * 65536};
+  return std::accumulate(std::begin(a), std::end(a), 0);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-forward-declaration-namespace.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-forward-declaration-namespace.rst
new file mode 100644
index 0000000..99ecb63
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-forward-declaration-namespace.rst
@@ -0,0 +1,20 @@
+.. title:: clang-tidy - bugprone-forward-declaration-namespace
+
+bugprone-forward-declaration-namespace
+======================================
+
+Checks if an unused forward declaration is in a wrong namespace.
+
+The check inspects all unused forward declarations and checks if there is any
+declaration/definition with the same name existing, which could indicate that
+the forward declaration is in a potentially wrong namespace.
+
+.. code-block:: c++
+
+  namespace na { struct A; }
+  namespace nb { struct A {}; }
+  nb::A a;
+  // warning : no definition found for 'A', but a definition with the same name
+  // 'A' found in another namespace 'nb::'
+
+This check can only generate warnings, but it can't suggest a fix at this point.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-forwarding-reference-overload.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-forwarding-reference-overload.rst
new file mode 100644
index 0000000..ddf69dc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-forwarding-reference-overload.rst
@@ -0,0 +1,49 @@
+.. title:: clang-tidy - bugprone-forwarding-reference-overload
+
+bugprone-forwarding-reference-overload
+======================================
+
+The check looks for perfect forwarding constructors that can hide copy or move
+constructors. If a non const lvalue reference is passed to the constructor, the
+forwarding reference parameter will be a better match than the const reference
+parameter of the copy constructor, so the perfect forwarding constructor will be
+called, which can be confusing.
+For detailed description of this issue see: Scott Meyers, Effective Modern C++,
+Item 26.
+
+Consider the following example:
+
+  .. code-block:: c++
+
+    class Person {
+    public:
+      // C1: perfect forwarding ctor
+      template<typename T>
+      explicit Person(T&& n) {}
+
+      // C2: perfect forwarding ctor with parameter default value
+      template<typename T>
+      explicit Person(T&& n, int x = 1) {}
+
+      // C3: perfect forwarding ctor guarded with enable_if
+      template<typename T, typename X = enable_if_t<is_special<T>,void>>
+      explicit Person(T&& n) {}
+
+      // (possibly compiler generated) copy ctor
+      Person(const Person& rhs);
+    };
+
+The check warns for constructors C1 and C2, because those can hide copy and move
+constructors. We suppress warnings if the copy and the move constructors are both
+disabled (deleted or private), because there is nothing the perfect forwarding
+constructor could hide in this case. We also suppress warnings for constructors
+like C3 that are guarded with an enable_if, assuming the programmer was aware of
+the possible hiding.
+
+Background
+----------
+
+For deciding whether a constructor is guarded with enable_if, we consider the
+default values of the type parameters and the types of the constructor
+parameters. If any part of these types is std::enable_if or std::enable_if_t, we
+assume the constructor is guarded.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-inaccurate-erase.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-inaccurate-erase.rst
new file mode 100644
index 0000000..7df47b0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-inaccurate-erase.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - bugprone-inaccurate-erase
+
+bugprone-inaccurate-erase
+=========================
+
+
+Checks for inaccurate use of the ``erase()`` method.
+
+Algorithms like ``remove()`` do not actually remove any element from the
+container but return an iterator to the first redundant element at the end
+of the container. These redundant elements must be removed using the
+``erase()`` method. This check warns when not all of the elements will be
+removed due to using an inappropriate overload.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-incorrect-roundings.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-incorrect-roundings.rst
new file mode 100644
index 0000000..0a5047a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-incorrect-roundings.rst
@@ -0,0 +1,16 @@
+.. title:: clang-tidy - bugprone-incorrect-roundings
+
+bugprone-incorrect-roundings
+============================
+
+Checks the usage of patterns known to produce incorrect rounding.
+Programmers often use::
+
+   (int)(double_expression + 0.5)
+
+to round the double expression to an integer. The problem with this:
+
+1. It is unnecessarily slow.
+2. It is incorrect. The number 0.499999975 (smallest representable float
+   number below 0.5) rounds to 1.0. Even worse behavior for negative
+   numbers where both -0.5f and -1.4f both round to 0.0.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-integer-division.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-integer-division.rst
new file mode 100644
index 0000000..2c82e6f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-integer-division.rst
@@ -0,0 +1,39 @@
+.. title:: clang-tidy - bugprone-integer-division
+
+bugprone-integer-division
+=========================
+
+Finds cases where integer division in a floating point context is likely to
+cause unintended loss of precision.
+
+No reports are made if divisions are part of the following expressions:
+
+- operands of operators expecting integral or bool types,
+- call expressions of integral or bool types, and
+- explicit cast expressions to integral or bool types,
+
+as these are interpreted as signs of deliberateness from the programmer.
+
+Examples:
+
+.. code-block:: c++
+
+  float floatFunc(float);
+  int intFunc(int);
+  double d;
+  int i = 42;
+
+  // Warn, floating-point values expected.
+  d = 32 * 8 / (2 + i);
+  d = 8 * floatFunc(1 + 7 / 2);
+  d = i / (1 << 4);
+
+  // OK, no integer division.
+  d = 32 * 8.0 / (2 + i);
+  d = 8 * floatFunc(1 + 7.0 / 2);
+  d = (double)i / (1 << 4);
+
+  // OK, there are signs of deliberateness.
+  d = 1 << (i / 2);
+  d = 9 + intFunc(6 * i / 32);
+  d = (int)(i / 32) - 8;
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-lambda-function-name.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-lambda-function-name.rst
new file mode 100644
index 0000000..683977a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-lambda-function-name.rst
@@ -0,0 +1,27 @@
+.. title:: clang-tidy - bugprone-lambda-function-name
+
+bugprone-lambda-function-name
+=============================
+
+Checks for attempts to get the name of a function from within a lambda
+expression. The name of a lambda is always something like ``operator()``, which
+is almost never what was intended.
+
+Example:
+
+.. code-block:: c++
+								
+  void FancyFunction() {
+    [] { printf("Called from %s\n", __func__); }();
+    [] { printf("Now called from %s\n", __FUNCTION__); }();
+  }
+
+Output::
+
+  Called from operator()
+  Now called from operator()
+
+Likely intended output::
+
+  Called from FancyFunction
+  Now called from FancyFunction
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-macro-parentheses.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-macro-parentheses.rst
new file mode 100644
index 0000000..f827080
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-macro-parentheses.rst
@@ -0,0 +1,19 @@
+.. title:: clang-tidy - bugprone-macro-parentheses
+
+bugprone-macro-parentheses
+==========================
+
+
+Finds macros that can have unexpected behaviour due to missing parentheses.
+
+Macros are expanded by the preprocessor as-is. As a result, there can be
+unexpected behaviour; operators may be evaluated in unexpected order and
+unary operators may become binary operators, etc.
+
+When the replacement list has an expression, it is recommended to surround
+it with parentheses. This ensures that the macro result is evaluated
+completely before it is used.
+
+It is also recommended to surround macro arguments in the replacement list
+with parentheses. This ensures that the argument value is calculated
+properly.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-macro-repeated-side-effects.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-macro-repeated-side-effects.rst
new file mode 100644
index 0000000..15dfdca
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-macro-repeated-side-effects.rst
@@ -0,0 +1,7 @@
+.. title:: clang-tidy - bugprone-macro-repeated-side-effects
+
+bugprone-macro-repeated-side-effects
+====================================
+
+
+Checks for repeated argument with side effects in macros.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst
new file mode 100644
index 0000000..e6ff2fe
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst
@@ -0,0 +1,57 @@
+.. title:: clang-tidy - bugprone-misplaced-operator-in-strlen-in-alloc
+
+bugprone-misplaced-operator-in-strlen-in-alloc
+==============================================
+
+Finds cases where ``1`` is added to the string in the argument to ``strlen()``,
+``strnlen()``, ``strnlen_s()``, ``wcslen()``, ``wcsnlen()``, and ``wcsnlen_s()``
+instead of the result and the value is used as an argument to a memory
+allocation function (``malloc()``, ``calloc()``, ``realloc()``, ``alloca()``) or
+the ``new[]`` operator in `C++`. The check detects error cases even if one of
+these functions (except the ``new[]`` operator) is called by a constant function
+pointer.  Cases where ``1`` is added both to the parameter and the result of the
+``strlen()``-like function are ignored, as are cases where the whole addition is
+surrounded by extra parentheses.
+
+`C` example code:
+
+.. code-block:: c
+
+    void bad_malloc(char *str) {
+      char *c = (char*) malloc(strlen(str + 1));
+    }
+
+
+The suggested fix is to add ``1`` to the return value of ``strlen()`` and not
+to its argument. In the example above the fix would be
+
+.. code-block:: c
+
+      char *c = (char*) malloc(strlen(str) + 1);
+
+
+`C++` example code:
+
+.. code-block:: c++
+
+    void bad_new(char *str) {
+      char *c = new char[strlen(str + 1)];
+    }
+
+
+As in the `C` code with the ``malloc()`` function, the suggested fix is to
+add ``1`` to the return value of ``strlen()`` and not to its argument. In the
+example above the fix would be
+
+.. code-block:: c++
+
+      char *c = new char[strlen(str) + 1];
+
+
+Example for silencing the diagnostic:
+
+.. code-block:: c
+
+    void bad_malloc(char *str) {
+      char *c = (char*) malloc(strlen((str + 1)));
+    }
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-widening-cast.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-widening-cast.rst
new file mode 100644
index 0000000..f42be76
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-widening-cast.rst
@@ -0,0 +1,65 @@
+.. title:: clang-tidy - bugprone-misplaced-widening-cast
+
+bugprone-misplaced-widening-cast
+================================
+
+This check will warn when there is a cast of a calculation result to a bigger
+type. If the intention of the cast is to avoid loss of precision then the cast
+is misplaced, and there can be loss of precision. Otherwise the cast is
+ineffective.
+
+Example code:
+
+.. code-block:: c++
+
+    long f(int x) {
+        return (long)(x * 1000);
+    }
+
+The result ``x * 1000`` is first calculated using ``int`` precision. If the
+result exceeds ``int`` precision there is loss of precision. Then the result is
+casted to ``long``.
+
+If there is no loss of precision then the cast can be removed or you can
+explicitly cast to ``int`` instead.
+
+If you want to avoid loss of precision then put the cast in a proper location,
+for instance:
+
+.. code-block:: c++
+
+    long f(int x) {
+        return (long)x * 1000;
+    }
+
+Implicit casts
+--------------
+
+Forgetting to place the cast at all is at least as dangerous and at least as
+common as misplacing it. If :option:`CheckImplicitCasts` is enabled the check
+also detects these cases, for instance:
+
+.. code-block:: c++
+
+    long f(int x) {
+        return x * 1000;
+    }
+
+Floating point
+--------------
+
+Currently warnings are only written for integer conversion. No warning is
+written for this code:
+
+.. code-block:: c++
+
+    double f(float x) {
+        return (double)(x * 10.0f);
+    }
+
+Options
+-------
+
+.. option:: CheckImplicitCasts
+
+   If non-zero, enables detection of implicit casts. Default is non-zero.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-move-forwarding-reference.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-move-forwarding-reference.rst
new file mode 100644
index 0000000..3b57d50
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-move-forwarding-reference.rst
@@ -0,0 +1,60 @@
+.. title:: clang-tidy - bugprone-move-forwarding-reference
+
+bugprone-move-forwarding-reference
+==================================
+
+Warns if ``std::move`` is called on a forwarding reference, for example:
+
+  .. code-block:: c++
+
+    template <typename T>
+    void foo(T&& t) {
+      bar(std::move(t));
+    }
+
+`Forwarding references
+<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4164.pdf>`_ should
+typically be passed to ``std::forward`` instead of ``std::move``, and this is
+the fix that will be suggested.
+
+(A forwarding reference is an rvalue reference of a type that is a deduced
+function template argument.)
+
+In this example, the suggested fix would be
+
+  .. code-block:: c++
+
+    bar(std::forward<T>(t));
+
+Background
+----------
+
+Code like the example above is sometimes written with the expectation that
+``T&&`` will always end up being an rvalue reference, no matter what type is
+deduced for ``T``, and that it is therefore not possible to pass an lvalue to
+``foo()``. However, this is not true. Consider this example:
+
+  .. code-block:: c++
+
+    std::string s = "Hello, world";
+    foo(s);
+
+This code compiles and, after the call to ``foo()``, ``s`` is left in an
+indeterminate state because it has been moved from. This may be surprising to
+the caller of ``foo()`` because no ``std::move`` was used when calling
+``foo()``.
+
+The reason for this behavior lies in the special rule for template argument
+deduction on function templates like ``foo()`` -- i.e. on function templates
+that take an rvalue reference argument of a type that is a deduced function
+template argument. (See section [temp.deduct.call]/3 in the C++11 standard.)
+
+If ``foo()`` is called on an lvalue (as in the example above), then ``T`` is
+deduced to be an lvalue reference. In the example, ``T`` is deduced to be
+``std::string &``. The type of the argument ``t`` therefore becomes
+``std::string& &&``; by the reference collapsing rules, this collapses to
+``std::string&``.
+
+This means that the ``foo(s)`` call passes ``s`` as an lvalue reference, and
+``foo()`` ends up moving ``s`` and thereby placing it into an indeterminate
+state.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-multiple-statement-macro.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-multiple-statement-macro.rst
new file mode 100644
index 0000000..708dc95
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-multiple-statement-macro.rst
@@ -0,0 +1,16 @@
+.. title:: clang-tidy - bugprone-multiple-statement-macro
+
+bugprone-multiple-statement-macro
+=================================
+
+Detect multiple statement macros that are used in unbraced conditionals. Only
+the first statement of the macro will be inside the conditional and the other
+ones will be executed unconditionally.
+
+Example:
+
+.. code-block:: c++
+
+  #define INCREMENT_TWO(x, y) (x)++; (y)++
+  if (do_increment)
+    INCREMENT_TWO(a, b);  // (b)++ will be executed unconditionally.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-parent-virtual-call.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-parent-virtual-call.rst
new file mode 100755
index 0000000..e1021b1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-parent-virtual-call.rst
@@ -0,0 +1,23 @@
+.. title:: clang-tidy - bugprone-parent-virtual-call
+
+bugprone-parent-virtual-call
+============================
+
+Detects and fixes calls to grand-...parent virtual methods instead of calls
+to overridden parent's virtual methods.
+
+.. code-block:: c++
+
+  class A {
+    int virtual foo() {...}
+  };
+
+  class B: public A {
+    int foo() override {...}
+  };
+
+  class C: public B {
+    int foo() override { A::foo(); }
+  //                     ^^^^^^^^
+  // warning: qualified name A::foo refers to a member overridden in subclass; did you mean 'B'?  [bugprone-parent-virtual-call]
+  };
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-sizeof-container.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-sizeof-container.rst
new file mode 100644
index 0000000..fb2f0b2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-sizeof-container.rst
@@ -0,0 +1,26 @@
+.. title:: clang-tidy - bugprone-sizeof-container
+
+bugprone-sizeof-container
+=========================
+
+The check finds usages of ``sizeof`` on expressions of STL container types. Most
+likely the user wanted to use ``.size()`` instead.
+
+All class/struct types declared in namespace ``std::`` having a const ``size()``
+method are considered containers, with the exception of ``std::bitset`` and
+``std::array``.
+
+Examples:
+
+.. code-block:: c++
+
+  std::string s;
+  int a = 47 + sizeof(s); // warning: sizeof() doesn't return the size of the container. Did you mean .size()?
+
+  int b = sizeof(std::string); // no warning, probably intended.
+
+  std::string array_of_strings[10];
+  int c = sizeof(array_of_strings) / sizeof(array_of_strings[0]); // no warning, definitely intended.
+
+  std::array<int, 3> std_array;
+  int d = sizeof(std_array); // no warning, probably intended.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-sizeof-expression.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-sizeof-expression.rst
new file mode 100644
index 0000000..b58deaa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-sizeof-expression.rst
@@ -0,0 +1,189 @@
+.. title:: clang-tidy - bugprone-sizeof-expression
+
+bugprone-sizeof-expression
+==========================
+
+The check finds usages of ``sizeof`` expressions which are most likely errors.
+
+The ``sizeof`` operator yields the size (in bytes) of its operand, which may be
+an expression or the parenthesized name of a type. Misuse of this operator may
+be leading to errors and possible software vulnerabilities.
+
+Suspicious usage of 'sizeof(K)'
+-------------------------------
+
+A common mistake is to query the ``sizeof`` of an integer literal. This is
+equivalent to query the size of its type (probably ``int``). The intent of the
+programmer was probably to simply get the integer and not its size.
+
+.. code-block:: c++
+
+  #define BUFLEN 42
+  char buf[BUFLEN];
+  memset(buf, 0, sizeof(BUFLEN));  // sizeof(42) ==> sizeof(int)
+
+Suspicious usage of 'sizeof(expr)'
+----------------------------------
+
+In cases, where there is an enum or integer to represent a type, a common
+mistake is to query the ``sizeof`` on the integer or enum that represents the
+type that should be used by ``sizeof``. This results in the size of the integer
+and not of the type the integer represents:
+
+.. code-block:: c++
+
+  enum data_type {
+    FLOAT_TYPE,
+    DOUBLE_TYPE
+  };
+
+  struct data {
+    data_type type;
+    void* buffer;
+    data_type get_type() {
+      return type;
+    }
+  };
+
+  void f(data d, int numElements) {
+    // should be sizeof(float) or sizeof(double), depending on d.get_type()
+    int numBytes = numElements * sizeof(d.get_type());
+    ...
+  }
+
+
+Suspicious usage of 'sizeof(this)'
+----------------------------------
+
+The ``this`` keyword is evaluated to a pointer to an object of a given type.
+The expression ``sizeof(this)`` is returning the size of a pointer. The
+programmer most likely wanted the size of the object and not the size of the
+pointer.
+
+.. code-block:: c++
+
+  class Point {
+    [...]
+    size_t size() { return sizeof(this); }  // should probably be sizeof(*this)
+    [...]
+  };
+
+Suspicious usage of 'sizeof(char*)'
+-----------------------------------
+
+There is a subtle difference between declaring a string literal with
+``char* A = ""`` and ``char A[] = ""``. The first case has the type ``char*``
+instead of the aggregate type ``char[]``. Using ``sizeof`` on an object declared
+with ``char*`` type is returning the size of a pointer instead of the number of
+characters (bytes) in the string literal.
+
+.. code-block:: c++
+
+  const char* kMessage = "Hello World!";      // const char kMessage[] = "...";
+  void getMessage(char* buf) {
+    memcpy(buf, kMessage, sizeof(kMessage));  // sizeof(char*)
+  }
+
+Suspicious usage of 'sizeof(A*)'
+--------------------------------
+
+A common mistake is to compute the size of a pointer instead of its pointee.
+These cases may occur because of explicit cast or implicit conversion.
+
+.. code-block:: c++
+
+  int A[10];
+  memset(A, 0, sizeof(A + 0));
+
+  struct Point point;
+  memset(point, 0, sizeof(&point));
+
+Suspicious usage of 'sizeof(...)/sizeof(...)'
+---------------------------------------------
+
+Dividing ``sizeof`` expressions is typically used to retrieve the number of
+elements of an aggregate. This check warns on incompatible or suspicious cases.
+
+In the following example, the entity has 10-bytes and is incompatible with the
+type ``int`` which has 4 bytes.
+
+.. code-block:: c++
+
+  char buf[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };  // sizeof(buf) => 10
+  void getMessage(char* dst) {
+    memcpy(dst, buf, sizeof(buf) / sizeof(int));  // sizeof(int) => 4  [incompatible sizes]
+  }
+
+In the following example, the expression ``sizeof(Values)`` is returning the
+size of ``char*``. One can easily be fooled by its declaration, but in parameter
+declaration the size '10' is ignored and the function is receiving a ``char*``.
+
+.. code-block:: c++
+
+  char OrderedValues[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+  return CompareArray(char Values[10]) {
+    return memcmp(OrderedValues, Values, sizeof(Values)) == 0;  // sizeof(Values) ==> sizeof(char*) [implicit cast to char*]
+  }
+
+Suspicious 'sizeof' by 'sizeof' expression
+------------------------------------------
+
+Multiplying ``sizeof`` expressions typically makes no sense and is probably a
+logic error. In the following example, the programmer used ``*`` instead of
+``/``.
+
+.. code-block:: c++
+
+  const char kMessage[] = "Hello World!";
+  void getMessage(char* buf) {
+    memcpy(buf, kMessage, sizeof(kMessage) * sizeof(char));  //  sizeof(kMessage) / sizeof(char)
+  }
+
+This check may trigger on code using the arraysize macro. The following code is
+working correctly but should be simplified by using only the ``sizeof``
+operator.
+
+.. code-block:: c++
+
+  extern Object objects[100];
+  void InitializeObjects() {
+    memset(objects, 0, arraysize(objects) * sizeof(Object));  // sizeof(objects)
+  }
+
+Suspicious usage of 'sizeof(sizeof(...))'
+-----------------------------------------
+
+Getting the ``sizeof`` of a ``sizeof`` makes no sense and is typically an error
+hidden through macros.
+
+.. code-block:: c++
+
+  #define INT_SZ sizeof(int)
+  int buf[] = { 42 };
+  void getInt(int* dst) {
+    memcpy(dst, buf, sizeof(INT_SZ));  // sizeof(sizeof(int)) is suspicious.
+  }
+
+Options
+-------
+
+.. option:: WarnOnSizeOfConstant
+
+   When non-zero, the check will warn on an expression like
+   ``sizeof(CONSTANT)``. Default is `1`.
+
+.. option:: WarnOnSizeOfIntegerExpression
+
+   When non-zero, the check will warn on an expression like ``sizeof(expr)``
+   where the expression results in an integer. Default is `0`.
+
+.. option:: WarnOnSizeOfThis
+
+   When non-zero, the check will warn on an expression like ``sizeof(this)``.
+   Default is `1`.
+
+.. option:: WarnOnSizeOfCompareToConstant
+
+   When non-zero, the check will warn on an expression like
+   ``sizeof(epxr) <= k`` for a suspicious constant `k` while `k` is `0` or
+   greater than `0x8000`. Default is `1`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-string-constructor.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-string-constructor.rst
new file mode 100644
index 0000000..5deedf1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-string-constructor.rst
@@ -0,0 +1,44 @@
+.. title:: clang-tidy - bugprone-string-constructor
+
+bugprone-string-constructor
+===========================
+
+Finds string constructors that are suspicious and probably errors.
+
+A common mistake is to swap parameters to the 'fill' string-constructor.
+
+Examples:
+
+.. code-block:: c++
+
+  std::string str('x', 50); // should be str(50, 'x')
+
+Calling the string-literal constructor with a length bigger than the literal is
+suspicious and adds extra random characters to the string.
+
+Examples:
+
+.. code-block:: c++
+
+  std::string("test", 200);   // Will include random characters after "test".
+
+Creating an empty string from constructors with parameters is considered
+suspicious. The programmer should use the empty constructor instead.
+
+Examples:
+
+.. code-block:: c++
+
+  std::string("test", 0);   // Creation of an empty string.
+
+Options
+-------
+
+.. option::  WarnOnLargeLength
+
+   When non-zero, the check will warn on a string with a length greater than
+   `LargeLengthThreshold`. Default is `1`.
+
+.. option::  LargeLengthThreshold
+
+   An integer specifying the large length threshold. Default is `0x800000`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-string-integer-assignment.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-string-integer-assignment.rst
new file mode 100644
index 0000000..6401f00
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-string-integer-assignment.rst
@@ -0,0 +1,37 @@
+.. title:: clang-tidy - bugprone-string-integer-assignment
+
+bugprone-string-integer-assignment
+==================================
+
+The check finds assignments of an integer to ``std::basic_string<CharT>``
+(``std::string``, ``std::wstring``, etc.). The source of the problem is the
+following assignment operator of ``std::basic_string<CharT>``:
+
+.. code-block:: c++
+
+  basic_string& operator=( CharT ch );
+
+Numeric types can be implicitly casted to character types.
+
+.. code-block:: c++
+
+  std::string s;
+  int x = 5965;
+  s = 6;
+  s = x;
+
+Use the appropriate conversion functions or character literals.
+
+.. code-block:: c++
+
+  std::string s;
+  int x = 5965;
+  s = '6';
+  s = std::to_string(x);
+
+In order to suppress false positives, use an explicit cast.
+
+.. code-block:: c++
+
+  std::string s;
+  s = static_cast<char>(6);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-string-literal-with-embedded-nul.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-string-literal-with-embedded-nul.rst
new file mode 100644
index 0000000..c1c4d32
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-string-literal-with-embedded-nul.rst
@@ -0,0 +1,36 @@
+.. title:: clang-tidy - bugprone-string-literal-with-embedded-nul
+
+bugprone-string-literal-with-embedded-nul
+=========================================
+
+Finds occurrences of string literal with embedded NUL character and validates
+their usage.
+
+Invalid escaping
+----------------
+
+Special characters can be escaped within a string literal by using their
+hexadecimal encoding like ``\x42``. A common mistake is to escape them
+like this ``\0x42`` where the ``\0`` stands for the NUL character.
+
+.. code-block:: c++
+
+  const char* Example[] = "Invalid character: \0x12 should be \x12";
+  const char* Bytes[] = "\x03\0x02\0x01\0x00\0xFF\0xFF\0xFF";
+
+Truncated literal
+-----------------
+
+String-like classes can manipulate strings with embedded NUL as they are keeping
+track of the bytes and the length. This is not the case for a ``char*``
+(NUL-terminated) string.
+
+A common mistake is to pass a string-literal with embedded NUL to a string
+constructor expecting a NUL-terminated string. The bytes after the first NUL
+character are truncated.
+
+.. code-block:: c++
+
+  std::string str("abc\0def");  // "def" is truncated
+  str += "\0";                  // This statement is doing nothing
+  if (str == "\0abc") return;   // This expression is always true
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-enum-usage.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-enum-usage.rst
new file mode 100644
index 0000000..5e765be
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-enum-usage.rst
@@ -0,0 +1,78 @@
+.. title:: clang-tidy - bugprone-suspicious-enum-usage
+
+bugprone-suspicious-enum-usage
+==============================
+
+The checker detects various cases when an enum is probably misused (as a bitmask
+).
+  
+1. When "ADD" or "bitwise OR" is used between two enum which come from different
+   types and these types value ranges are not disjoint.
+
+The following cases will be investigated only using :option:`StrictMode`. We 
+regard the enum as a (suspicious)
+bitmask if the three conditions below are true at the same time:
+
+* at most half of the elements of the enum are non pow-of-2 numbers (because of
+  short enumerations)
+* there is another non pow-of-2 number than the enum constant representing all
+  choices (the result "bitwise OR" operation of all enum elements)
+* enum type variable/enumconstant is used as an argument of a `+` or "bitwise OR
+  " operator
+
+So whenever the non pow-of-2 element is used as a bitmask element we diagnose a
+misuse and give a warning.
+
+2. Investigating the right hand side of `+=` and `|=` operator.
+3. Check only the enum value side of a `|` and `+` operator if one of them is not
+   enum val.
+4. Check both side of `|` or `+` operator where the enum values are from the
+   same enum type.
+
+Examples:
+
+.. code-block:: c++
+
+  enum { A, B, C };
+  enum { D, E, F = 5 };
+  enum { G = 10, H = 11, I = 12 };
+  
+  unsigned flag;
+  flag =
+      A |
+      H; // OK, disjoint value intervalls in the enum types ->probably good use.
+  flag = B | F; // Warning, have common values so they are probably misused.
+  
+  // Case 2:
+  enum Bitmask {
+    A = 0,
+    B = 1,
+    C = 2,
+    D = 4,
+    E = 8,
+    F = 16,
+    G = 31 // OK, real bitmask.
+  };
+  
+  enum Almostbitmask {
+    AA = 0,
+    BB = 1,
+    CC = 2,
+    DD = 4,
+    EE = 8,
+    FF = 16,
+    GG // Problem, forgot to initialize.
+  };
+  
+  unsigned flag = 0;
+  flag |= E; // OK.
+  flag |=
+      EE; // Warning at the decl, and note that it was used here as a bitmask.
+
+Options
+-------
+.. option:: StrictMode
+
+   Default value: 0.
+   When non-null the suspicious bitmask usage will be investigated additionally
+   to the different enum usage check.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-memset-usage.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-memset-usage.rst
new file mode 100644
index 0000000..82609d1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-memset-usage.rst
@@ -0,0 +1,54 @@
+.. title:: clang-tidy - bugprone-suspicious-memset-usage
+
+bugprone-suspicious-memset-usage
+================================
+
+This check finds ``memset()`` calls with potential mistakes in their arguments.
+Considering the function as ``void* memset(void* destination, int fill_value,
+size_t byte_count)``, the following cases are covered:
+
+**Case 1: Fill value is a character ``'0'``**
+
+Filling up a memory area with ASCII code 48 characters is not customary,
+possibly integer zeroes were intended instead.
+The check offers a replacement of ``'0'`` with ``0``. Memsetting character
+pointers with ``'0'`` is allowed.
+
+**Case 2: Fill value is truncated**
+
+Memset converts ``fill_value`` to ``unsigned char`` before using it. If
+``fill_value`` is out of unsigned character range, it gets truncated
+and memory will not contain the desired pattern.
+
+**Case 3: Byte count is zero**
+
+Calling memset with a literal zero in its ``byte_count`` argument is likely
+to be unintended and swapped with ``fill_value``. The check offers to swap
+these two arguments.
+
+Corresponding cpplint.py check name: ``runtime/memset``.
+
+
+Examples:
+
+.. code-block:: c++
+
+  void foo() {
+    int i[5] = {1, 2, 3, 4, 5};
+    int *ip = i;
+    char c = '1';
+    char *cp = &c;
+    int v = 0;
+
+    // Case 1
+    memset(ip, '0', 1); // suspicious
+    memset(cp, '0', 1); // OK
+
+    // Case 2
+    memset(ip, 0xabcd, 1); // fill value gets truncated
+    memset(ip, 0x00, 1);   // OK
+
+    // Case 3
+    memset(ip, sizeof(int), v); // zero length, potentially swapped
+    memset(ip, 0, 1);           // OK
+  }
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-missing-comma.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-missing-comma.rst
new file mode 100644
index 0000000..9fe9153
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-missing-comma.rst
@@ -0,0 +1,59 @@
+.. title:: clang-tidy - bugprone-suspicious-missing-comma
+
+bugprone-suspicious-missing-comma
+=================================
+
+String literals placed side-by-side are concatenated at translation phase 6
+(after the preprocessor). This feature is used to represent long string
+literal on multiple lines.
+
+For instance, the following declarations are equivalent:
+
+.. code-block:: c++
+
+  const char* A[] = "This is a test";
+  const char* B[] = "This" " is a "    "test";
+
+A common mistake done by programmers is to forget a comma between two string
+literals in an array initializer list.
+
+.. code-block:: c++
+
+  const char* Test[] = {
+    "line 1",
+    "line 2"     // Missing comma!
+    "line 3",
+    "line 4",
+    "line 5"
+  };
+
+The array contains the string "line 2line3" at offset 1 (i.e. Test[1]). Clang
+won't generate warnings at compile time.
+
+This check may warn incorrectly on cases like:
+
+.. code-block:: c++
+
+  const char* SupportedFormat[] = {
+    "Error %s",
+    "Code " PRIu64,   // May warn here.
+    "Warning %s",
+  };
+
+Options
+-------
+
+.. option::  SizeThreshold
+
+   An unsigned integer specifying the minimum size of a string literal to be
+   considered by the check. Default is `5U`.
+
+.. option::  RatioThreshold
+
+   A string specifying the maximum threshold ratio [0, 1.0] of suspicious string
+   literals to be considered. Default is `".2"`.
+
+.. option::  MaxConcatenatedTokens
+
+   An unsigned integer specifying the maximum number of concatenated tokens.
+   Default is `5U`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-semicolon.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-semicolon.rst
new file mode 100644
index 0000000..a3eb098
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-semicolon.rst
@@ -0,0 +1,72 @@
+.. title:: clang-tidy - bugprone-suspicious-semicolon
+
+bugprone-suspicious-semicolon
+=============================
+
+Finds most instances of stray semicolons that unexpectedly alter the meaning of
+the code. More specifically, it looks for ``if``, ``while``, ``for`` and
+``for-range`` statements whose body is a single semicolon, and then analyzes the
+context of the code (e.g. indentation) in an attempt to determine whether that
+is intentional.
+
+  .. code-block:: c++
+
+    if (x < y);
+    {
+      x++;
+    }
+
+Here the body of the ``if`` statement consists of only the semicolon at the end
+of the first line, and `x` will be incremented regardless of the condition.
+
+
+  .. code-block:: c++
+
+    while ((line = readLine(file)) != NULL);
+      processLine(line);
+
+As a result of this code, `processLine()` will only be called once, when the
+``while`` loop with the empty body exits with `line == NULL`. The indentation of
+the code indicates the intention of the programmer.
+
+
+  .. code-block:: c++
+
+    if (x >= y);
+    x -= y;
+
+While the indentation does not imply any nesting, there is simply no valid
+reason to have an `if` statement with an empty body (but it can make sense for
+a loop). So this check issues a warning for the code above.
+
+To solve the issue remove the stray semicolon or in case the empty body is
+intentional, reflect this using code indentation or put the semicolon in a new
+line. For example:
+
+  .. code-block:: c++
+
+    while (readWhitespace());
+      Token t = readNextToken();
+
+Here the second line is indented in a way that suggests that it is meant to be
+the body of the `while` loop - whose body is in fact empty, because of the
+semicolon at the end of the first line.
+
+Either remove the indentation from the second line:
+
+  .. code-block:: c++
+
+    while (readWhitespace());
+    Token t = readNextToken();
+
+... or move the semicolon from the end of the first line to a new line:
+
+  .. code-block:: c++
+
+    while (readWhitespace())
+      ;
+
+      Token t = readNextToken();
+
+In this case the check will assume that you know what you are doing, and will
+not raise a warning.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-string-compare.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-string-compare.rst
new file mode 100644
index 0000000..be3d2b6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-string-compare.rst
@@ -0,0 +1,64 @@
+.. title:: clang-tidy - bugprone-suspicious-string-compare
+
+bugprone-suspicious-string-compare
+==================================
+
+Find suspicious usage of runtime string comparison functions.
+This check is valid in C and C++.
+
+Checks for calls with implicit comparator and proposed to explicitly add it.
+
+.. code-block:: c++
+
+    if (strcmp(...))       // Implicitly compare to zero
+    if (!strcmp(...))      // Won't warn
+    if (strcmp(...) != 0)  // Won't warn
+
+Checks that compare function results (i,e, ``strcmp``) are compared to valid
+constant. The resulting value is
+
+.. code::
+
+    <  0    when lower than,
+    >  0    when greater than,
+    == 0    when equals.
+
+A common mistake is to compare the result to `1` or `-1`.
+
+.. code-block:: c++
+
+    if (strcmp(...) == -1)  // Incorrect usage of the returned value.
+
+Additionally, the check warns if the results value is implicitly cast to a
+*suspicious* non-integer type. It's happening when the returned value is used in
+a wrong context.
+
+.. code-block:: c++
+
+    if (strcmp(...) < 0.)  // Incorrect usage of the returned value.
+
+Options
+-------
+
+.. option:: WarnOnImplicitComparison
+
+   When non-zero, the check will warn on implicit comparison. `1` by default.
+
+.. option:: WarnOnLogicalNotComparison
+
+   When non-zero, the check will warn on logical not comparison. `0` by default.
+
+.. option:: StringCompareLikeFunctions
+
+   A string specifying the comma-separated names of the extra string comparison
+   functions. Default is an empty string.
+   The check will detect the following string comparison functions:
+   `__builtin_memcmp`, `__builtin_strcasecmp`, `__builtin_strcmp`,
+   `__builtin_strncasecmp`, `__builtin_strncmp`, `_mbscmp`, `_mbscmp_l`,
+   `_mbsicmp`, `_mbsicmp_l`, `_mbsnbcmp`, `_mbsnbcmp_l`, `_mbsnbicmp`,
+   `_mbsnbicmp_l`, `_mbsncmp`, `_mbsncmp_l`, `_mbsnicmp`, `_mbsnicmp_l`,
+   `_memicmp`, `_memicmp_l`, `_stricmp`, `_stricmp_l`, `_strnicmp`,
+   `_strnicmp_l`, `_wcsicmp`, `_wcsicmp_l`, `_wcsnicmp`, `_wcsnicmp_l`,
+   `lstrcmp`, `lstrcmpi`, `memcmp`, `memicmp`, `strcasecmp`, `strcmp`,
+   `strcmpi`, `stricmp`, `strncasecmp`, `strncmp`, `strnicmp`, `wcscasecmp`,
+   `wcscmp`, `wcsicmp`, `wcsncmp`, `wcsnicmp`, `wmemcmp`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-swapped-arguments.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-swapped-arguments.rst
new file mode 100644
index 0000000..30ae925
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-swapped-arguments.rst
@@ -0,0 +1,6 @@
+.. title:: clang-tidy - bugprone-swapped-arguments
+
+bugprone-swapped-arguments
+==========================
+
+Finds potentially swapped arguments by looking at implicit conversions.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-terminating-continue.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-terminating-continue.rst
new file mode 100644
index 0000000..1a6ae81
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-terminating-continue.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - bugprone-terminating-continue
+
+bugprone-terminating-continue
+=============================
+
+Detects `do while` loops with a condition always evaluating to false that
+have a `continue` statement, as this `continue` terminates the loop
+effectively.
+
+.. code-block:: c++
+
+  void f() {
+  do {
+  	// some code
+    continue; // terminating continue
+    // some other code
+  } while(false);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-throw-keyword-missing.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-throw-keyword-missing.rst
new file mode 100644
index 0000000..240a62e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-throw-keyword-missing.rst
@@ -0,0 +1,21 @@
+.. title:: clang-tidy - bugprone-throw-keyword-missing
+
+bugprone-throw-keyword-missing
+==============================
+
+Warns about a potentially missing ``throw`` keyword. If a temporary object is created, but the
+object's type derives from (or is the same as) a class that has 'EXCEPTION', 'Exception' or
+'exception' in its name, we can assume that the programmer's intention was to throw that object.
+
+Example:
+
+.. code-block:: c++
+
+  void f(int i) {
+    if (i < 0) {
+      // Exception is created but is not thrown.
+      std::runtime_error("Unexpected argument");
+    }
+  }
+
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-undefined-memory-manipulation.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-undefined-memory-manipulation.rst
new file mode 100644
index 0000000..2735184
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-undefined-memory-manipulation.rst
@@ -0,0 +1,7 @@
+.. title:: clang-tidy - bugprone-undefined-memory-manipulation
+
+bugprone-undefined-memory-manipulation
+======================================
+
+Finds calls of memory manipulation functions ``memset()``, ``memcpy()`` and
+``memmove()`` on not TriviallyCopyable objects resulting in undefined behavior.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-undelegated-constructor.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-undelegated-constructor.rst
new file mode 100644
index 0000000..b32ed38
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-undelegated-constructor.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - bugprone-undelegated-constructor
+
+bugprone-undelegated-constructor
+================================
+
+Finds creation of temporary objects in constructors that look like a
+function call to another constructor of the same class.
+
+The user most likely meant to use a delegating constructor or base class
+initializer.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-unused-raii.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-unused-raii.rst
new file mode 100644
index 0000000..f1987c5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-unused-raii.rst
@@ -0,0 +1,30 @@
+.. title:: clang-tidy - bugprone-unused-raii
+
+bugprone-unused-raii
+====================
+
+Finds temporaries that look like RAII objects.
+
+The canonical example for this is a scoped lock.
+
+.. code-block:: c++
+
+  {
+    scoped_lock(&global_mutex);
+    critical_section();
+  }
+
+The destructor of the scoped_lock is called before the ``critical_section`` is
+entered, leaving it unprotected.
+
+We apply a number of heuristics to reduce the false positive count of this
+check:
+
+- Ignore code expanded from macros. Testing frameworks make heavy use of this.
+
+- Ignore types with trivial destructors. They are very unlikely to be RAII
+  objects and there's no difference when they are deleted.
+
+- Ignore objects at the end of a compound statement (doesn't change behavior).
+
+- Ignore objects returned from a call.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-unused-return-value.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-unused-return-value.rst
new file mode 100644
index 0000000..68d8e73
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-unused-return-value.rst
@@ -0,0 +1,31 @@
+.. title:: clang-tidy - bugprone-unused-return-value
+
+bugprone-unused-return-value
+============================
+
+Warns on unused function return values. The checked funtions can be configured.
+
+Options
+-------
+
+.. option:: CheckedFunctions
+
+   Semicolon-separated list of functions to check. Defaults to
+   ``::std::async;::std::launder;::std::remove;::std::remove_if;::std::unique;::std::unique_ptr::release;::std::basic_string::empty;::std::vector::empty``.
+   This means that the calls to following functions are checked by default:
+
+   - ``std::async()``. Not using the return value makes the call synchronous.
+   - ``std::launder()``. Not using the return value usually means that the
+     function interface was misunderstood by the programmer. Only the returned
+     pointer is "laundered", not the argument.
+   - ``std::remove()``, ``std::remove_if()`` and ``std::unique()``. The returned
+     iterator indicates the boundary between elements to keep and elements to be
+     removed. Not using the return value means that the information about which
+     elements to remove is lost.
+   - ``std::unique_ptr::release()``. Not using the return value can lead to
+     resource leaks if the same pointer isn't stored anywhere else. Often,
+     ignoring the ``release()`` return value indicates that the programmer
+     confused the function with ``reset()``.
+   - ``std::basic_string::empty()`` and ``std::vector::empty()``. Not using the
+     return value often indicates that the programmer confused the function with
+     ``clear()``.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-use-after-move.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-use-after-move.rst
new file mode 100644
index 0000000..05b0e09
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-use-after-move.rst
@@ -0,0 +1,203 @@
+.. title:: clang-tidy - bugprone-use-after-move
+
+bugprone-use-after-move
+=======================
+
+Warns if an object is used after it has been moved, for example:
+
+  .. code-block:: c++
+
+    std::string str = "Hello, world!\n";
+    std::vector<std::string> messages;
+    messages.emplace_back(std::move(str));
+    std::cout << str;
+
+The last line will trigger a warning that ``str`` is used after it has been
+moved.
+
+The check does not trigger a warning if the object is reinitialized after the
+move and before the use. For example, no warning will be output for this code:
+
+  .. code-block:: c++
+
+    messages.emplace_back(std::move(str));
+    str = "Greetings, stranger!\n";
+    std::cout << str;
+
+The check takes control flow into account. A warning is only emitted if the use
+can be reached from the move. This means that the following code does not
+produce a warning:
+
+  .. code-block:: c++
+
+    if (condition) {
+      messages.emplace_back(std::move(str));
+    } else {
+      std::cout << str;
+    }
+
+On the other hand, the following code does produce a warning:
+
+  .. code-block:: c++
+
+    for (int i = 0; i < 10; ++i) {
+      std::cout << str;
+      messages.emplace_back(std::move(str));
+    }
+
+(The use-after-move happens on the second iteration of the loop.)
+
+In some cases, the check may not be able to detect that two branches are
+mutually exclusive. For example (assuming that ``i`` is an int):
+
+  .. code-block:: c++
+
+    if (i == 1) {
+      messages.emplace_back(std::move(str));
+    }
+    if (i == 2) {
+      std::cout << str;
+    }
+
+In this case, the check will erroneously produce a warning, even though it is
+not possible for both the move and the use to be executed.
+
+An erroneous warning can be silenced by reinitializing the object after the
+move:
+
+  .. code-block:: c++
+
+    if (i == 1) {
+      messages.emplace_back(std::move(str));
+      str = "";
+    }
+    if (i == 2) {
+      std::cout << str;
+    }
+
+Subsections below explain more precisely what exactly the check considers to be
+a move, use, and reinitialization.
+
+Unsequenced moves, uses, and reinitializations
+----------------------------------------------
+
+In many cases, C++ does not make any guarantees about the order in which
+sub-expressions of a statement are evaluated. This means that in code like the
+following, it is not guaranteed whether the use will happen before or after the
+move:
+
+  .. code-block:: c++
+
+    void f(int i, std::vector<int> v);
+    std::vector<int> v = { 1, 2, 3 };
+    f(v[1], std::move(v));
+
+In this kind of situation, the check will note that the use and move are
+unsequenced.
+
+The check will also take sequencing rules into account when reinitializations
+occur in the same statement as moves or uses. A reinitialization is only
+considered to reinitialize a variable if it is guaranteed to be evaluated after
+the move and before the use.
+
+Move
+----
+
+The check currently only considers calls of ``std::move`` on local variables or
+function parameters. It does not check moves of member variables or global
+variables.
+
+Any call of ``std::move`` on a variable is considered to cause a move of that
+variable, even if the result of ``std::move`` is not passed to an rvalue
+reference parameter.
+
+This means that the check will flag a use-after-move even on a type that does
+not define a move constructor or move assignment operator. This is intentional.
+Developers may use ``std::move`` on such a type in the expectation that the type
+will add move semantics in the future. If such a ``std::move`` has the potential
+to cause a use-after-move, we want to warn about it even if the type does not
+implement move semantics yet.
+
+Furthermore, if the result of ``std::move`` *is* passed to an rvalue reference
+parameter, this will always be considered to cause a move, even if the function
+that consumes this parameter does not move from it, or if it does so only
+conditionally. For example, in the following situation, the check will assume
+that a move always takes place:
+
+  .. code-block:: c++
+
+    std::vector<std::string> messages;
+    void f(std::string &&str) {
+      // Only remember the message if it isn't empty.
+      if (!str.empty()) {
+        messages.emplace_back(std::move(str));
+      }
+    }
+    std::string str = "";
+    f(std::move(str));
+
+The check will assume that the last line causes a move, even though, in this
+particular case, it does not. Again, this is intentional.
+
+When analyzing the order in which moves, uses and reinitializations happen (see
+section `Unsequenced moves, uses, and reinitializations`_), the move is assumed
+to occur in whichever function the result of the ``std::move`` is passed to.
+
+Use
+---
+
+Any occurrence of the moved variable that is not a reinitialization (see below)
+is considered to be a use.
+
+An exception to this are objects of type ``std::unique_ptr``,
+``std::shared_ptr`` and ``std::weak_ptr``, which have defined move behavior
+(objects of these classes are guaranteed to be empty after they have been moved
+from). Therefore, an object of these classes will only be considered to be used
+if it is dereferenced, i.e. if ``operator*``, ``operator->`` or ``operator[]``
+(in the case of ``std::unique_ptr<T []>``) is called on it.
+
+If multiple uses occur after a move, only the first of these is flagged.
+
+Reinitialization
+----------------
+
+The check considers a variable to be reinitialized in the following cases:
+
+  - The variable occurs on the left-hand side of an assignment.
+
+  - The variable is passed to a function as a non-const pointer or non-const
+    lvalue reference. (It is assumed that the variable may be an out-parameter
+    for the function.)
+
+  - ``clear()`` or ``assign()`` is called on the variable and the variable is of
+    one of the standard container types ``basic_string``, ``vector``, ``deque``,
+    ``forward_list``, ``list``, ``set``, ``map``, ``multiset``, ``multimap``,
+    ``unordered_set``, ``unordered_map``, ``unordered_multiset``,
+    ``unordered_multimap``.
+
+  - ``reset()`` is called on the variable and the variable is of type
+    ``std::unique_ptr``, ``std::shared_ptr`` or ``std::weak_ptr``.
+
+If the variable in question is a struct and an individual member variable of
+that struct is written to, the check does not consider this to be a
+reinitialization -- even if, eventually, all member variables of the struct are
+written to. For example:
+
+  .. code-block:: c++
+
+    struct S {
+      std::string str;
+      int i;
+    };
+    S s = { "Hello, world!\n", 42 };
+    S s_other = std::move(s);
+    s.str = "Lorem ipsum";
+    s.i = 99;
+
+The check will not consider ``s`` to be reinitialized after the last line;
+instead, the line that assigns to ``s.str`` will be flagged as a use-after-move.
+This is intentional as this pattern of reinitializing a struct is error-prone.
+For example, if an additional member variable is added to ``S``, it is easy to
+forget to add the reinitialization for this additional member. Instead, it is
+safer to assign to the entire struct in one go, and this will also avoid the
+use-after-move warning.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-virtual-near-miss.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-virtual-near-miss.rst
new file mode 100644
index 0000000..ac27479
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone-virtual-near-miss.rst
@@ -0,0 +1,20 @@
+.. title:: clang-tidy - bugprone-virtual-near-miss
+
+bugprone-virtual-near-miss
+==========================
+
+Warn if a function is a near miss (ie. the name is very similar and the function
+signiture is the same) to a virtual function from a base class.
+
+Example:
+
+.. code-block:: c++
+
+  struct Base {
+    virtual void func();
+  };
+
+  struct Derived : Base {
+    virtual funk();
+    // warning: 'Derived::funk' has a similar name and the same signature as virtual method 'Base::func'; did you mean to override it?
+  };
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl03-c.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl03-c.rst
new file mode 100644
index 0000000..2e4780b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl03-c.rst
@@ -0,0 +1,9 @@
+.. title:: clang-tidy - cert-dcl03-c
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-static-assert.html
+
+cert-dcl03-c
+============
+
+The cert-dcl03-c check is an alias, please see
+`misc-static-assert <misc-static-assert.html>`_ for more information.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl21-cpp.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl21-cpp.rst
new file mode 100644
index 0000000..d5c2948
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl21-cpp.rst
@@ -0,0 +1,12 @@
+.. title:: clang-tidy - cert-dcl21-cpp
+
+cert-dcl21-cpp
+==============
+
+This check flags postfix ``operator++`` and ``operator--`` declarations
+if the return type is not a const object. This also warns if the return type
+is a reference type.
+
+This check corresponds to the CERT C++ Coding Standard recommendation
+`DCL21-CPP. Overloaded postfix increment and decrement operators should return a const object
+<https://www.securecoding.cert.org/confluence/display/cplusplus/DCL21-CPP.+Overloaded+postfix+increment+and+decrement+operators+should+return+a+const+object>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl50-cpp.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl50-cpp.rst
new file mode 100644
index 0000000..5fc1fbf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl50-cpp.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - cert-dcl50-cpp
+
+cert-dcl50-cpp
+==============
+
+This check flags all function definitions (but not declarations) of C-style
+variadic functions.
+
+This check corresponds to the CERT C++ Coding Standard rule
+`DCL50-CPP. Do not define a C-style variadic function
+<https://www.securecoding.cert.org/confluence/display/cplusplus/DCL50-CPP.+Do+not+define+a+C-style+variadic+function>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl54-cpp.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl54-cpp.rst
new file mode 100644
index 0000000..e0b575c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl54-cpp.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cert-dcl54-cpp
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-new-delete-overloads.html
+
+cert-dcl54-cpp
+==============
+
+The cert-dcl54-cpp check is an alias, please see
+`misc-new-delete-overloads <misc-new-delete-overloads.html>`_ for more
+information.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl58-cpp.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl58-cpp.rst
new file mode 100644
index 0000000..a86d1b9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl58-cpp.rst
@@ -0,0 +1,21 @@
+.. title:: clang-tidy - cert-dcl58-cpp
+
+cert-dcl58-cpp
+==============
+
+Modification of the ``std`` or ``posix`` namespace can result in undefined
+behavior.
+This check warns for such modifications.
+
+Examples:
+
+.. code-block:: c++
+
+  namespace std {
+    int x; // May cause undefined behavior.
+  }
+
+
+This check corresponds to the CERT C++ Coding Standard rule
+`DCL58-CPP. Do not modify the standard namespaces
+<https://www.securecoding.cert.org/confluence/display/cplusplus/DCL58-CPP.+Do+not+modify+the+standard+namespaces>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl59-cpp.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl59-cpp.rst
new file mode 100644
index 0000000..9528c04
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-dcl59-cpp.rst
@@ -0,0 +1,9 @@
+.. title:: clang-tidy - cert-dcl59-cpp
+.. meta::
+   :http-equiv=refresh: 5;URL=google-build-namespaces.html
+
+cert-dcl59-cpp
+==============
+
+The cert-dcl59-cpp check is an alias, please see
+`google-build-namespaces <google-build-namespaces.html>`_ for more information.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-env33-c.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-env33-c.rst
new file mode 100644
index 0000000..c5321b0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-env33-c.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - cert-env33-c
+
+cert-env33-c
+============
+
+This check flags calls to ``system()``, ``popen()``, and ``_popen()``, which
+execute a command processor. It does not flag calls to ``system()`` with a null
+pointer argument, as such a call checks for the presence of a command processor
+but does not actually attempt to execute a command.
+
+This check corresponds to the CERT C Coding Standard rule
+`ENV33-C. Do not call system()
+<https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=2130132>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err09-cpp.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err09-cpp.rst
new file mode 100644
index 0000000..1494bcc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err09-cpp.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cert-err09-cpp
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-throw-by-value-catch-by-reference.html
+
+cert-err09-cpp
+==============
+
+The cert-err09-cpp check is an alias, please see
+`misc-throw-by-value-catch-by-reference <misc-throw-by-value-catch-by-reference.html>`_
+for more information.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err34-c.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err34-c.rst
new file mode 100644
index 0000000..362aef2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err34-c.rst
@@ -0,0 +1,28 @@
+.. title:: clang-tidy - cert-err34-c
+
+cert-err34-c
+============
+
+This check flags calls to string-to-number conversion functions that do not
+verify the validity of the conversion, such as ``atoi()`` or ``scanf()``. It
+does not flag calls to ``strtol()``, or other, related conversion functions that
+do perform better error checking.
+
+.. code-block:: c
+
+  #include <stdlib.h>
+
+  void func(const char *buff) {
+    int si;
+
+    if (buff) {
+      si = atoi(buff); /* 'atoi' used to convert a string to an integer, but function will
+                           not report conversion errors; consider using 'strtol' instead. */
+    } else {
+      /* Handle error */
+    }
+  }
+
+This check corresponds to the CERT C Coding Standard rule
+`ERR34-C. Detect errors when converting a string to a number
+<https://www.securecoding.cert.org/confluence/display/c/ERR34-C.+Detect+errors+when+converting+a+string+to+a+number>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err52-cpp.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err52-cpp.rst
new file mode 100644
index 0000000..a29dc7b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err52-cpp.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cert-err52-cpp
+
+cert-err52-cpp
+==============
+
+This check flags all call expressions involving ``setjmp()`` and ``longjmp()``.
+
+This check corresponds to the CERT C++ Coding Standard rule
+`ERR52-CPP. Do not use setjmp() or longjmp()
+<https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=1834>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err58-cpp.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err58-cpp.rst
new file mode 100644
index 0000000..6a7f615
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err58-cpp.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - cert-err58-cpp
+
+cert-err58-cpp
+==============
+
+This check flags all ``static`` or ``thread_local`` variable declarations where
+the initializer for the object may throw an exception.
+
+This check corresponds to the CERT C++ Coding Standard rule
+`ERR58-CPP. Handle all exceptions thrown before main() begins executing
+<https://www.securecoding.cert.org/confluence/display/cplusplus/ERR58-CPP.+Handle+all+exceptions+thrown+before+main%28%29+begins+executing>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err60-cpp.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err60-cpp.rst
new file mode 100644
index 0000000..9fcb840
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err60-cpp.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - cert-err60-cpp
+
+cert-err60-cpp
+==============
+
+This check flags all throw expressions where the exception object is not nothrow
+copy constructible.
+
+This check corresponds to the CERT C++ Coding Standard rule
+`ERR60-CPP. Exception objects must be nothrow copy constructible
+<https://www.securecoding.cert.org/confluence/display/cplusplus/ERR60-CPP.+Exception+objects+must+be+nothrow+copy+constructible>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err61-cpp.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err61-cpp.rst
new file mode 100644
index 0000000..f0cd0fe
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-err61-cpp.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cert-err61-cpp
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-throw-by-value-catch-by-reference.html
+
+cert-err61-cpp
+==============
+
+The cert-err61-cpp check is an alias, please see
+`misc-throw-by-value-catch-by-reference <misc-throw-by-value-catch-by-reference.html>`_
+for more information.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-fio38-c.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-fio38-c.rst
new file mode 100644
index 0000000..5ce37f4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-fio38-c.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cert-fio38-c
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-non-copyable-objects.html
+
+cert-fio38-c
+============
+
+The cert-fio38-c check is an alias, please see
+`misc-non-copyable-objects <misc-non-copyable-objects.html>`_ for more
+information.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-flp30-c.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-flp30-c.rst
new file mode 100644
index 0000000..c37b639
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-flp30-c.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - cert-flp30-c
+
+cert-flp30-c
+============
+
+This check flags ``for`` loops where the induction expression has a
+floating-point type.
+
+This check corresponds to the CERT C Coding Standard rule
+`FLP30-C. Do not use floating-point variables as loop counters
+<https://www.securecoding.cert.org/confluence/display/c/FLP30-C.+Do+not+use+floating-point+variables+as+loop+counters>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-msc30-c.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-msc30-c.rst
new file mode 100644
index 0000000..afd9b1a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-msc30-c.rst
@@ -0,0 +1,9 @@
+.. title:: clang-tidy - cert-msc30-c
+.. meta::
+   :http-equiv=refresh: 5;URL=cert-msc50-cpp.html
+
+cert-msc30-c
+============
+
+The cert-msc30-c check is an alias, please see
+`cert-msc50-cpp <cert-msc50-cpp.html>`_ for more information.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-msc32-c.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-msc32-c.rst
new file mode 100644
index 0000000..df527ec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-msc32-c.rst
@@ -0,0 +1,9 @@
+.. title:: clang-tidy - cert-msc32-c
+.. meta::
+   :http-equiv=refresh: 5;URL=cert-msc51-cpp.html
+
+cert-msc32-c
+============
+
+The cert-msc32-c check is an alias, please see
+`cert-msc51-cpp <cert-msc51-cpp.html>`_ for more information.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-msc50-cpp.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-msc50-cpp.rst
new file mode 100644
index 0000000..debf01c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-msc50-cpp.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - cert-msc50-cpp
+
+cert-msc50-cpp
+==============
+
+Pseudorandom number generators use mathematical algorithms to produce a sequence
+of numbers with good statistical properties, but the numbers produced are not
+genuinely random. The ``std::rand()`` function takes a seed (number), runs a
+mathematical operation on it and returns the result. By manipulating the seed
+the result can be predictable. This check warns for the usage of
+``std::rand()``.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-msc51-cpp.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-msc51-cpp.rst
new file mode 100644
index 0000000..5365369
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-msc51-cpp.rst
@@ -0,0 +1,40 @@
+.. title:: clang-tidy - cert-msc51-cpp
+
+cert-msc51-cpp
+==============
+
+This check flags all pseudo-random number engines, engine adaptor
+instantiations and ``srand()`` when initialized or seeded with default argument,
+constant expression or any user-configurable type. Pseudo-random number
+engines seeded with a predictable value may cause vulnerabilities e.g. in
+security protocols.
+This is a CERT security rule, see
+`MSC51-CPP. Ensure your random number generator is properly seeded
+<https://wiki.sei.cmu.edu/confluence/display/cplusplus/MSC51-CPP.+Ensure+your+random+number+generator+is+properly+seeded>`_ and
+`MSC32-C. Properly seed pseudorandom number generators
+<https://wiki.sei.cmu.edu/confluence/display/c/MSC32-C.+Properly+seed+pseudorandom+number+generators>`_.
+
+Examples:
+
+.. code-block:: c++
+
+  void foo() {
+    std::mt19937 engine1; // Diagnose, always generate the same sequence
+    std::mt19937 engine2(1); // Diagnose
+    engine1.seed(); // Diagnose
+    engine2.seed(1); // Diagnose
+    
+    std::time_t t;
+    engine1.seed(std::time(&t)); // Diagnose, system time might be controlled by user
+
+    int x = atoi(argv[1]);
+    std::mt19937 engine3(x);  // Will not warn
+  }
+
+Options
+-------
+
+.. option:: DisallowedSeedTypes
+
+   A comma-separated list of the type names which are disallowed.
+   Default values are ``time_t``, ``std::time_t``.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-oop11-cpp.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-oop11-cpp.rst
new file mode 100644
index 0000000..dcd0fee
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cert-oop11-cpp.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cert-oop11-cpp
+.. meta::
+   :http-equiv=refresh: 5;URL=performance-move-constructor-init.html
+
+cert-oop11-cpp
+==============
+
+The cert-oop11-cpp check is an alias, please see
+`performance-move-constructor-init <performance-move-constructor-init.html>`_
+for more information.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-avoid-goto.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-avoid-goto.rst
new file mode 100644
index 0000000..fcb7dd3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-avoid-goto.rst
@@ -0,0 +1,50 @@
+.. title:: clang-tidy - cppcoreguidelines-avoid-goto
+
+cppcoreguidelines-avoid-goto
+============================
+
+The usage of ``goto`` for control flow is error prone and should be replaced
+with looping constructs. Only forward jumps in nested loops are accepted.
+
+This check implements `ES.76 <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es76-avoid-goto>`_ 
+from the CppCoreGuidelines and 
+`6.3.1 from High Integrity C++ <http://www.codingstandard.com/rule/6-3-1-ensure-that-the-labels-for-a-jump-statement-or-a-switch-condition-appear-later-in-the-same-or-an-enclosing-block/>`_.
+
+For more information on why to avoid programming 
+with ``goto`` you can read the famous paper `A Case against the GO TO Statement. <https://www.cs.utexas.edu/users/EWD/ewd02xx/EWD215.PDF>`_.
+
+The check diagnoses ``goto`` for backward jumps in every language mode. These
+should be replaced with `C/C++` looping constructs.
+
+.. code-block:: c++
+
+  // Bad, handwritten for loop.
+  int i = 0;
+  // Jump label for the loop
+  loop_start:
+  do_some_operation();
+
+  if (i < 100) {
+    ++i;
+    goto loop_start;
+  }
+
+  // Better
+  for(int i = 0; i < 100; ++i)
+    do_some_operation();
+
+Modern C++ needs ``goto`` only to jump out of nested loops.
+
+.. code-block:: c++
+
+  for(int i = 0; i < 100; ++i) {
+    for(int j = 0; j < 100; ++j) {
+      if (i * j > 500)
+        goto early_exit;
+    }
+  }
+
+  early_exit:
+  some_operation();
+
+All other uses of ``goto`` are diagnosed in `C++`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-c-copy-assignment-signature.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-c-copy-assignment-signature.rst
new file mode 100644
index 0000000..9096ef4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-c-copy-assignment-signature.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cppcoreguidelines-c-copy-assignment-signature
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-unconventional-assign-operator.html
+
+cppcoreguidelines-c-copy-assignment-signature
+=============================================
+
+The cppcoreguidelines-c-copy-assignment-signature check is an alias, please see
+`misc-unconventional-assign-operator <misc-unconventional-assign-operator.html>`_
+for more information.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-interfaces-global-init.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-interfaces-global-init.rst
new file mode 100644
index 0000000..4907858
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-interfaces-global-init.rst
@@ -0,0 +1,14 @@
+.. title:: clang-tidy - cppcoreguidelines-interfaces-global-init
+
+cppcoreguidelines-interfaces-global-init
+========================================
+
+This check flags initializers of globals that access extern objects,
+and therefore can lead to order-of-initialization problems.
+
+This rule is part of the "Interfaces" profile of the C++ Core Guidelines, see
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Ri-global-init
+
+Note that currently this does not flag calls to non-constexpr functions, and
+therefore globals could still be accessed from functions themselves.
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-narrowing-conversions.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-narrowing-conversions.rst
new file mode 100644
index 0000000..b1e82ca
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-narrowing-conversions.rst
@@ -0,0 +1,22 @@
+.. title:: clang-tidy - cppcoreguidelines-narrowing-conversions
+
+cppcoreguidelines-narrowing-conversions
+=======================================
+
+Checks for silent narrowing conversions, e.g: ``int i = 0; i += 0.1;``. While
+the issue is obvious in this former example, it might not be so in the
+following: ``void MyClass::f(double d) { int_member_ += d; }``.
+
+This rule is part of the "Expressions and statements" profile of the C++ Core
+Guidelines, corresponding to rule ES.46. See
+
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Res-narrowing.
+
+We enforce only part of the guideline, more specifically, we flag:
+ - All floating-point to integer conversions that are not marked by an explicit
+   cast (c-style or ``static_cast``). For example: ``int i = 0; i += 0.1;``,
+   ``void f(int); f(0.1);``,
+ - All applications of binary operators where the left-hand-side is an integer
+   and the right-hand-size is a floating-point. For example:
+   ``int i; i+= 0.1;``.
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-no-malloc.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-no-malloc.rst
new file mode 100644
index 0000000..d481a67
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-no-malloc.rst
@@ -0,0 +1,46 @@
+.. title:: clang-tidy - cppcoreguidelines-no-malloc
+
+cppcoreguidelines-no-malloc
+===========================
+
+This check handles C-Style memory management using ``malloc()``, ``realloc()``,
+``calloc()`` and ``free()``. It warns about its use and tries to suggest the use
+of an appropriate RAII object.
+Furthermore, it can be configured to check against a user-specified list of functions 
+that are used for memory management (e.g. ``posix_memalign()``).
+See `C++ Core Guidelines <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rr-mallocfree>`_.
+
+There is no attempt made to provide fix-it hints, since manual resource
+management isn't easily transformed automatically into RAII.
+
+.. code-block:: c++
+
+  // Warns each of the following lines.
+  // Containers like std::vector or std::string should be used.
+  char* some_string = (char*) malloc(sizeof(char) * 20);
+  char* some_string = (char*) realloc(sizeof(char) * 30);
+  free(some_string);
+
+  int* int_array = (int*) calloc(30, sizeof(int));
+
+  // Rather use a smartpointer or stack variable.
+  struct some_struct* s = (struct some_struct*) malloc(sizeof(struct some_struct));
+
+Options
+-------
+
+.. option:: Allocations
+
+   Semicolon-separated list of fully qualified names of memory allocation functions. 
+   Defaults to ``::malloc;::calloc``.
+
+.. option:: Deallocations
+
+   Semicolon-separated list of fully qualified names of memory allocation functions. 
+   Defaults to ``::free``.
+
+.. option:: Reallocations
+
+   Semicolon-separated list of fully qualified names of memory allocation functions. 
+   Defaults to ``::realloc``.
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-owning-memory.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-owning-memory.rst
new file mode 100644
index 0000000..3f6f8c4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-owning-memory.rst
@@ -0,0 +1,176 @@
+.. title:: clang-tidy - cppcoreguidelines-owning-memory
+
+cppcoreguidelines-owning-memory
+===============================
+
+This check implements the type-based semantics of ``gsl::owner<T*>``, which allows 
+static analysis on code, that uses raw pointers to handle resources like 
+dynamic memory, but won't introduce RAII concepts.
+
+The relevant sections in the `C++ Core Guidelines <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md>`_ are I.11, C.33, R.3 and GSL.Views
+The definition of a ``gsl::owner<T*>`` is straight forward
+
+.. code-block:: c++
+
+  namespace gsl { template <typename T> owner = T; }
+
+It is therefore simple to introduce the owner even without using an implementation of
+the `Guideline Support Library <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gsl-guideline-support-library>`_.
+
+All checks are purely type based and not (yet) flow sensitive.
+
+The following examples will demonstrate the correct and incorrect initializations
+of owners, assignment is handled the same way. Note that both ``new`` and 
+``malloc()``-like resource functions are considered to produce resources.
+
+.. code-block:: c++
+
+  // Creating an owner with factory functions is checked.
+  gsl::owner<int*> function_that_returns_owner() { return gsl::owner<int*>(new int(42)); }
+
+  // Dynamic memory must be assigned to an owner
+  int* Something = new int(42); // BAD, will be caught
+  gsl::owner<int*> Owner = new int(42); // Good
+  gsl::owner<int*> Owner = new int[42]; // Good as well
+
+  // Returned owner must be assigned to an owner
+  int* Something = function_that_returns_owner(); // Bad, factory function
+  gsl::owner<int*> Owner = function_that_returns_owner(); // Good, result lands in owner
+
+  // Something not a resource or owner should not be assigned to owners
+  int Stack = 42;
+  gsl::owner<int*> Owned = &Stack; // Bad, not a resource assigned
+
+In the case of dynamic memory as resource, only ``gsl::owner<T*>`` variables are allowed
+to be deleted.
+
+.. code-block:: c++
+
+  // Example Bad, non-owner as resource handle, will be caught.
+  int* NonOwner = new int(42); // First warning here, since new must land in an owner
+  delete NonOwner; // Second warning here, since only owners are allowed to be deleted
+
+  // Example Good, Ownership correclty stated
+  gsl::owner<int*> Owner = new int(42); // Good
+  delete Owner; // Good as well, statically enforced, that only owners get deleted
+  
+The check will furthermore ensure, that functions, that expect a ``gsl::owner<T*>`` as
+argument get called with either a ``gsl::owner<T*>`` or a newly created resource.
+
+.. code-block:: c++
+
+  void expects_owner(gsl::owner<int*> o) { delete o; }
+
+  // Bad Code
+  int NonOwner = 42;
+  expects_owner(&NonOwner); // Bad, will get caught
+
+  // Good Code
+  gsl::owner<int*> Owner = new int(42);
+  expects_owner(Owner); // Good
+  expects_owner(new int(42)); // Good as well, recognized created resource
+
+  // Port legacy code for better resource-safety
+  gsl::owner<FILE*> File = fopen("my_file.txt", "rw+");
+  FILE* BadFile = fopen("another_file.txt", "w"); // Bad, warned
+
+  // ... use the file
+
+  fclose(File); // Ok, File is annotated as 'owner<>'
+  fclose(BadFile); // BadFile is not an 'owner<>', will be warned
+
+
+Options
+-------
+
+.. option:: LegacyResourceProducers
+
+   Semicolon-separated list of fully qualified names of legacy functions that create
+   resources but cannot introduce ``gsl::owner<>``.
+   Defaults to ``::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile``.
+
+
+.. option:: LegacyResourceConsumers
+
+   Semicolon-separated list of fully qualified names of legacy functions expecting
+   resource owners as pointer arguments but cannot introduce ``gsl::owner<>``.
+   Defaults to ``::free;::realloc;::freopen;::fclose``.
+
+
+Limitations
+-----------
+
+Using ``gsl::owner<T*>`` in a typedef or alias is not handled correctly. 
+
+.. code-block:: c++
+
+  using heap_int = gsl::owner<int*>;
+  heap_int allocated = new int(42); // False positive!
+
+The ``gsl::owner<T*>`` is declared as a templated type alias.
+In template functions and classes, like in the example below, the information
+of the type aliases gets lost. Therefore using ``gsl::owner<T*>`` in a heavy templated
+code base might lead to false positives. 
+
+Known code constructs that do not get diagnosed correctly are:
+
+- ``std::exchange``
+- ``std::vector<gsl::owner<T*>>``
+
+.. code-block:: c++
+
+  // This template function works as expected. Type information doesn't get lost.
+  template <typename T>
+  void delete_owner(gsl::owner<T*> owned_object) {
+    delete owned_object; // Everything alright
+  }
+
+  gsl::owner<int*> function_that_returns_owner() { return gsl::owner<int*>(new int(42)); }
+
+  // Type deduction does not work for auto variables. 
+  // This is caught by the check and will be noted accordingly.
+  auto OwnedObject = function_that_returns_owner(); // Type of OwnedObject will be int*
+
+  // Problematic function template that looses the typeinformation on owner
+  template <typename T>
+  void bad_template_function(T some_object) {
+    // This line will trigger the warning, that a non-owner is assigned to an owner
+    gsl::owner<T*> new_owner = some_object;
+  }
+
+  // Calling the function with an owner still yields a false positive.
+  bad_template_function(gsl::owner<int*>(new int(42)));
+
+
+  // The same issue occurs with templated classes like the following.
+  template <typename T>
+  class OwnedValue {
+  public:
+    const T getValue() const { return _val; }
+  private:
+    T _val;
+  };
+
+  // Code, that yields a false positive.
+  OwnedValue<gsl::owner<int*>> Owner(new int(42)); // Type deduction yield T -> int * 
+  // False positive, getValue returns int* and not gsl::owner<int*>
+  gsl::owner<int*> OwnedInt = Owner.getValue(); 
+
+Another limitation of the current implementation is only the type based checking.
+Suppose you have code like the following:
+
+.. code-block:: c++
+
+  // Two owners with assigned resources
+  gsl::owner<int*> Owner1 = new int(42); 
+  gsl::owner<int*> Owner2 = new int(42);
+
+  Owner2 = Owner1; // Conceptual Leak of initial resource of Owner2!
+  Owner1 = nullptr;
+
+The semantic of a ``gsl::owner<T*>`` is mostly like a ``std::unique_ptr<T>``, therefore
+assignment of two ``gsl::owner<T*>`` is considered a move, which requires that the 
+resource ``Owner2`` must have been released before the assignment.
+This kind of condition could be catched in later improvements of this check with 
+flowsensitive analysis. Currently, the `Clang Static Analyzer` catches this bug
+for dynamic memory, but not for general types of resources.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-bounds-array-to-pointer-decay.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-bounds-array-to-pointer-decay.rst
new file mode 100644
index 0000000..172df2b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-bounds-array-to-pointer-decay.rst
@@ -0,0 +1,12 @@
+.. title:: clang-tidy - cppcoreguidelines-pro-bounds-array-to-pointer-decay
+
+cppcoreguidelines-pro-bounds-array-to-pointer-decay
+===================================================
+
+This check flags all array to pointer decays.
+
+Pointers should not be used as arrays. ``span<T>`` is a bounds-checked, safe
+alternative to using pointers to access arrays.
+
+This rule is part of the "Bounds safety" profile of the C++ Core Guidelines, see
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Pro-bounds-decay.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-bounds-constant-array-index.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-bounds-constant-array-index.rst
new file mode 100644
index 0000000..4528f2a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-bounds-constant-array-index.rst
@@ -0,0 +1,25 @@
+.. title:: clang-tidy - cppcoreguidelines-pro-bounds-constant-array-index
+
+cppcoreguidelines-pro-bounds-constant-array-index
+=================================================
+
+This check flags all array subscript expressions on static arrays and
+``std::arrays`` that either do not have a constant integer expression index or
+are out of bounds (for ``std::array``). For out-of-bounds checking of static
+arrays, see the `-Warray-bounds` Clang diagnostic.
+
+This rule is part of the "Bounds safety" profile of the C++ Core Guidelines, see
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Pro-bounds-arrayindex.
+
+Options
+-------
+
+.. option:: GslHeader
+
+   The check can generate fixes after this option has been set to the name of
+   the include file that contains ``gsl::at()``, e.g. `"gsl/gsl.h"`.
+
+.. option:: IncludeStyle
+
+   A string specifying which include-style is used, `llvm` or `google`. Default
+   is `llvm`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-bounds-pointer-arithmetic.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-bounds-pointer-arithmetic.rst
new file mode 100644
index 0000000..e0660df
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-bounds-pointer-arithmetic.rst
@@ -0,0 +1,14 @@
+.. title:: clang-tidy - cppcoreguidelines-pro-bounds-pointer-arithmetic
+
+cppcoreguidelines-pro-bounds-pointer-arithmetic
+===============================================
+
+This check flags all usage of pointer arithmetic, because it could lead to an
+invalid pointer. Subtraction of two pointers is not flagged by this check.
+
+Pointers should only refer to single objects, and pointer arithmetic is fragile
+and easy to get wrong. ``span<T>`` is a bounds-checked, safe type for accessing
+arrays of data.
+
+This rule is part of the "Bounds safety" profile of the C++ Core Guidelines, see
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Pro-bounds-arithmetic.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-const-cast.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-const-cast.rst
new file mode 100644
index 0000000..f3f0fb4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-const-cast.rst
@@ -0,0 +1,12 @@
+.. title:: clang-tidy - cppcoreguidelines-pro-type-const-cast
+
+cppcoreguidelines-pro-type-const-cast
+=====================================
+
+This check flags all uses of ``const_cast`` in C++ code.
+
+Modifying a variable that was declared const is undefined behavior, even with
+``const_cast``.
+
+This rule is part of the "Type safety" profile of the C++ Core Guidelines, see
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Pro-type-constcast.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-cstyle-cast.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-cstyle-cast.rst
new file mode 100644
index 0000000..1c21dd0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-cstyle-cast.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - cppcoreguidelines-pro-type-cstyle-cast
+
+cppcoreguidelines-pro-type-cstyle-cast
+======================================
+
+This check flags all use of C-style casts that perform a ``static_cast``
+downcast, ``const_cast``, or ``reinterpret_cast``.
+
+Use of these casts can violate type safety and cause the program to access a
+variable that is actually of type X to be accessed as if it were of an unrelated
+type Z. Note that a C-style ``(T)expression`` cast means to perform the first of
+the following that is possible: a ``const_cast``, a ``static_cast``, a
+``static_cast`` followed by a ``const_cast``, a ``reinterpret_cast``, or a
+``reinterpret_cast`` followed by a ``const_cast``. This rule bans
+``(T)expression`` only when used to perform an unsafe cast.
+
+This rule is part of the "Type safety" profile of the C++ Core Guidelines, see
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Pro-type-cstylecast.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst
new file mode 100644
index 0000000..2fdb4e3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst
@@ -0,0 +1,38 @@
+.. title:: clang-tidy - cppcoreguidelines-pro-type-member-init
+
+cppcoreguidelines-pro-type-member-init
+======================================
+
+The check flags user-defined constructor definitions that do not
+initialize all fields that would be left in an undefined state by
+default construction, e.g. builtins, pointers and record types without
+user-provided default constructors containing at least one such
+type. If these fields aren't initialized, the constructor will leave
+some of the memory in an undefined state.
+
+For C++11 it suggests fixes to add in-class field initializers. For
+older versions it inserts the field initializers into the constructor
+initializer list. It will also initialize any direct base classes that
+need to be zeroed in the constructor initializer list.
+
+The check takes assignment of fields in the constructor body into
+account but generates false positives for fields initialized in
+methods invoked in the constructor body.
+
+The check also flags variables with automatic storage duration that have record
+types without a user-provided constructor and are not initialized. The suggested
+fix is to zero initialize the variable via ``{}`` for C++11 and beyond or ``=
+{}`` for older language versions.
+
+Options
+-------
+
+.. option:: IgnoreArrays
+
+   If set to non-zero, the check will not warn about array members that are not
+   zero-initialized during construction. For performance critical code, it may
+   be important to not initialize fixed-size array members. Default is `0`.
+
+This rule is part of the "Type safety" profile of the C++ Core
+Guidelines, corresponding to rule Type.6. See
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Pro-type-memberinit.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-reinterpret-cast.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-reinterpret-cast.rst
new file mode 100644
index 0000000..2ef76f2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-reinterpret-cast.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - cppcoreguidelines-pro-type-reinterpret-cast
+
+cppcoreguidelines-pro-type-reinterpret-cast
+===========================================
+
+This check flags all uses of ``reinterpret_cast`` in C++ code.
+
+Use of these casts can violate type safety and cause the program to access a
+variable that is actually of type ``X`` to be accessed as if it were of an
+unrelated type ``Z``.
+
+This rule is part of the "Type safety" profile of the C++ Core Guidelines, see
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Pro-type-reinterpretcast.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-static-cast-downcast.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-static-cast-downcast.rst
new file mode 100644
index 0000000..880b8b0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-static-cast-downcast.rst
@@ -0,0 +1,15 @@
+.. title:: clang-tidy - cppcoreguidelines-pro-type-static-cast-downcast
+
+cppcoreguidelines-pro-type-static-cast-downcast
+===============================================
+
+This check flags all usages of ``static_cast``, where a base class is casted to
+a derived class. In those cases, a fix-it is provided to convert the cast to a
+``dynamic_cast``.
+
+Use of these casts can violate type safety and cause the program to access a
+variable that is actually of type ``X`` to be accessed as if it were of an
+unrelated type ``Z``.
+
+This rule is part of the "Type safety" profile of the C++ Core Guidelines, see
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Pro-type-downcast.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-union-access.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-union-access.rst
new file mode 100644
index 0000000..cdcf713
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-union-access.rst
@@ -0,0 +1,16 @@
+.. title:: clang-tidy - cppcoreguidelines-pro-type-union-access
+
+cppcoreguidelines-pro-type-union-access
+=======================================
+
+This check flags all access to members of unions. Passing unions as a whole is
+not flagged.
+
+Reading from a union member assumes that member was the last one written, and
+writing to a union member assumes another member with a nontrivial destructor
+had its destructor called. This is fragile because it cannot generally be
+enforced to be safe in the language and so relies on programmer discipline to
+get it right.
+
+This rule is part of the "Type safety" profile of the C++ Core Guidelines, see
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Pro-type-unions.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-vararg.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-vararg.rst
new file mode 100644
index 0000000..26fcd0c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-vararg.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - cppcoreguidelines-pro-type-vararg
+
+cppcoreguidelines-pro-type-vararg
+=================================
+
+This check flags all calls to c-style vararg functions and all use of
+``va_arg``.
+
+To allow for SFINAE use of vararg functions, a call is not flagged if a literal
+0 is passed as the only vararg argument.
+
+Passing to varargs assumes the correct type will be read. This is fragile
+because it cannot generally be enforced to be safe in the language and so relies
+on programmer discipline to get it right.
+
+This rule is part of the "Type safety" profile of the C++ Core Guidelines, see
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Pro-type-varargs.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-slicing.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
new file mode 100644
index 0000000..44f3dca
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
@@ -0,0 +1,25 @@
+.. title:: clang-tidy - cppcoreguidelines-slicing
+
+cppcoreguidelines-slicing
+=========================
+
+Flags slicing of member variables or vtable. Slicing happens when copying a
+derived object into a base object: the members of the derived object (both
+member variables and virtual member functions) will be discarded. This can be
+misleading especially for member function slicing, for example:
+
+.. code-block:: c++
+
+  struct B { int a; virtual int f(); };
+  struct D : B { int b; int f() override; };
+
+  void use(B b) {  // Missing reference, intended?
+    b.f();  // Calls B::f.
+  }
+
+  D d;
+  use(d);  // Slice.
+
+See the relevant C++ Core Guidelines sections for details:
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es63-dont-slice
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c145-access-polymorphic-objects-through-pointers-and-references
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-special-member-functions.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-special-member-functions.rst
new file mode 100644
index 0000000..28a5e8e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-special-member-functions.rst
@@ -0,0 +1,49 @@
+.. title:: clang-tidy - cppcoreguidelines-special-member-functions
+
+cppcoreguidelines-special-member-functions
+==========================================
+
+The check finds classes where some but not all of the special member functions
+are defined.
+
+By default the compiler defines a copy constructor, copy assignment operator,
+move constructor, move assignment operator and destructor. The default can be
+suppressed by explicit user-definitions. The relationship between which
+functions will be suppressed by definitions of other functions is complicated
+and it is advised that all five are defaulted or explicitly defined.
+
+Note that defining a function with ``= delete`` is considered to be a
+definition.
+
+This rule is part of the "Constructors, assignments, and destructors" profile of the C++ Core
+Guidelines, corresponding to rule C.21. See
+
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c21-if-you-define-or-delete-any-default-operation-define-or-delete-them-all.
+
+Options
+-------
+
+.. option:: AllowSoleDefaultDtor
+
+   When set to `1` (default is `0`), this check doesn't flag classes with a sole, explicitly
+   defaulted destructor. An example for such a class is:
+   
+   .. code-block:: c++
+   
+     struct A {
+       virtual ~A() = default;
+     };
+   
+.. option:: AllowMissingMoveFunctions
+
+   When set to `1` (default is `0`), this check doesn't flag classes which define no move
+   operations at all. It still flags classes which define only one of either
+   move constructor or move assignment operator. With this option enabled, the following class won't be flagged:
+   
+   .. code-block:: c++
+   
+     struct A {
+       A(const A&);
+       A& operator=(const A&);
+       ~A();
+     }
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-default-arguments.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-default-arguments.rst
new file mode 100644
index 0000000..ab011bf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-default-arguments.rst
@@ -0,0 +1,24 @@
+.. title:: clang-tidy - fuchsia-default-arguments
+
+fuchsia-default-arguments
+=========================
+
+Warns if a function or method is declared or called with default arguments.
+
+For example, the declaration:
+
+.. code-block:: c++
+
+  int foo(int value = 5) { return value; }
+
+will cause a warning.
+
+A function call expression that uses a default argument will be diagnosed.
+Calling it without defaults will not cause a warning:
+
+.. code-block:: c++
+
+  foo();  // warning
+  foo(0); // no warning
+
+See the features disallowed in Fuchsia at https://fuchsia.googlesource.com/zircon/+/master/docs/cxx.md
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-header-anon-namespaces.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-header-anon-namespaces.rst
new file mode 100644
index 0000000..42b5753
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-header-anon-namespaces.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - fuchsia-header-anon-namespaces
+.. meta::
+   :http-equiv=refresh: 5;URL=google-build-namespaces.html
+
+fuchsia-header-anon-namespaces
+==============================
+
+The fuchsia-header-anon-namespaces check is an alias, please see
+`google-build-namespace <google-build-namespaces.html>`_
+for more information.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-multiple-inheritance.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-multiple-inheritance.rst
new file mode 100644
index 0000000..b52ec2b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-multiple-inheritance.rst
@@ -0,0 +1,46 @@
+.. title:: clang-tidy - fuchsia-multiple-inheritance
+
+fuchsia-multiple-inheritance
+============================
+
+Warns if a class inherits from multiple classes that are not pure virtual.
+
+For example, declaring a class that inherits from multiple concrete classes is
+disallowed:
+
+.. code-block:: c++
+
+  class Base_A {
+  public:
+    virtual int foo() { return 0; }
+  };
+
+  class Base_B {
+  public:
+    virtual int bar() { return 0; }
+  };
+
+  // Warning
+  class Bad_Child1 : public Base_A, Base_B {};
+
+A class that inherits from a pure virtual is allowed:
+
+.. code-block:: c++
+
+  class Interface_A {
+  public:
+    virtual int foo() = 0;
+  };
+
+  class Interface_B {
+  public:
+    virtual int bar() = 0;
+  };
+
+  // No warning
+  class Good_Child1 : public Interface_A, Interface_B {
+    virtual int foo() override { return 0; }
+    virtual int bar() override { return 0; }
+  };
+
+See the features disallowed in Fuchsia at https://fuchsia.googlesource.com/zircon/+/master/docs/cxx.md
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-overloaded-operator.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-overloaded-operator.rst
new file mode 100644
index 0000000..070780f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-overloaded-operator.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - fuchsia-overloaded-operator
+
+fuchsia-overloaded-operator
+===========================
+
+Warns if an operator is overloaded, except for the assignment (copy and move) 
+operators.
+
+For example:
+
+.. code-block:: c++
+
+  int operator+(int);     // Warning
+
+  B &operator=(const B &Other);  // No warning
+  B &operator=(B &&Other) // No warning
+
+See the features disallowed in Fuchsia at https://fuchsia.googlesource.com/zircon/+/master/docs/cxx.md
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-restrict-system-includes.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-restrict-system-includes.rst
new file mode 100644
index 0000000..622e025
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-restrict-system-includes.rst
@@ -0,0 +1,32 @@
+.. title:: clang-tidy - fuchsia-restrict-system-includes
+
+fuchsia-restrict-system-includes
+================================
+
+Checks for allowed system includes and suggests removal of any others.
+
+It is important to note that running this check with fixes may break code, as
+the fix removes headers. Fixes are applied to source and header files, but not
+to system headers.
+
+For example, given the allowed system includes 'a.h,b*':
+
+.. code-block:: c++
+
+  #include <a.h>
+  #include <b.h>
+  #include <bar.h>
+  #include <c.h>    // Warning, as c.h is not explicitly allowed
+  
+All system includes can be allowed with '*', and all can be disallowed with an
+empty string ('').
+  
+Options
+-------
+
+.. option:: Includes
+
+   A string containing a comma separated glob list of allowed include filenames.
+   Similar to the -checks glob list for running clang-tidy itself, the two
+   wildcard characters are '*' and '-', to include and exclude globs,
+   respectively.The default is '*', which allows all includes.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-statically-constructed-objects.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-statically-constructed-objects.rst
new file mode 100644
index 0000000..7c1c0ae
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-statically-constructed-objects.rst
@@ -0,0 +1,43 @@
+.. title:: clang-tidy - fuchsia-statically-constructed-objects
+
+fuchsia-statically-constructed-objects
+======================================
+
+Warns if global, non-trivial objects with static storage are constructed, unless 
+the object is statically initialized with a ``constexpr`` constructor or has no 
+explicit constructor.
+
+For example:
+
+.. code-block:: c++
+
+  class A {};
+
+  class B {
+  public:
+    B(int Val) : Val(Val) {}
+  private:
+    int Val;
+  };
+
+  class C {
+  public:
+    C(int Val) : Val(Val) {}
+    constexpr C() : Val(0) {}
+
+  private:
+    int Val;
+  };
+
+  static A a;         // No warning, as there is no explicit constructor
+  static C c(0);      // No warning, as constructor is constexpr
+
+  static B b(0);      // Warning, as constructor is not constexpr
+  static C c2(0, 1);  // Warning, as constructor is not constexpr
+  
+  static int i;       // No warning, as it is trivial
+  
+  extern int get_i();
+  static C(get_i())   // Warning, as the constructor is dynamically initialized
+
+See the features disallowed in Fuchsia at https://fuchsia.googlesource.com/zircon/+/master/docs/cxx.md
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-trailing-return.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-trailing-return.rst
new file mode 100644
index 0000000..e67f477
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-trailing-return.rst
@@ -0,0 +1,35 @@
+.. title:: clang-tidy - fuchsia-trailing-return
+
+fuchsia-trailing-return
+=======================
+
+Functions that have trailing returns are disallowed, except for those using 
+``decltype`` specifiers and lambda with otherwise unutterable return types.
+
+For example:
+
+.. code-block:: c++
+
+  // No warning
+  int add_one(const int arg) { return arg; }
+
+  // Warning
+  auto get_add_one() -> int (*)(const int) {
+    return add_one;
+  }
+
+Exceptions are made for lambdas and ``decltype`` specifiers:
+
+.. code-block:: c++
+  
+  // No warning
+  auto lambda = [](double x, double y) -> double {return x + y;};
+  
+  // No warning
+  template <typename T1, typename T2>
+  auto fn(const T1 &lhs, const T2 &rhs) -> decltype(lhs + rhs) {
+    return lhs + rhs;
+  }
+
+
+See the features disallowed in Fuchsia at https://fuchsia.googlesource.com/zircon/+/master/docs/cxx.md
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-virtual-inheritance.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-virtual-inheritance.rst
new file mode 100644
index 0000000..f73a49b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/fuchsia-virtual-inheritance.rst
@@ -0,0 +1,14 @@
+.. title:: clang-tidy - fuchsia-virtual-inheritance
+
+fuchsia-virtual-inheritance
+===========================
+
+Warns if classes are defined with virtual inheritance.
+
+For example, classes should not be defined with virtual inheritance:
+
+.. code-block:: c++
+
+  class B : public virtual A {};   // warning
+
+See the features disallowed in Fuchsia at https://fuchsia.googlesource.com/zircon/+/master/docs/cxx.md
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-build-explicit-make-pair.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-build-explicit-make-pair.rst
new file mode 100644
index 0000000..e3e9eeb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-build-explicit-make-pair.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - google-build-explicit-make-pair
+
+google-build-explicit-make-pair
+===============================
+
+Check that ``make_pair``'s template arguments are deduced.
+
+G++ 4.6 in C++11 mode fails badly if ``make_pair``'s template arguments are
+specified explicitly, and such use isn't intended in any case.
+
+Corresponding cpplint.py check name: `build/explicit_make_pair`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-build-namespaces.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-build-namespaces.rst
new file mode 100644
index 0000000..69c01d3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-build-namespaces.rst
@@ -0,0 +1,24 @@
+.. title:: clang-tidy - google-build-namespaces
+
+google-build-namespaces
+=======================
+
+`cert-dcl59-cpp` redirects here as an alias for this check.
+`fuchsia-header-anon-namespaces` redirects here as an alias for this check.
+
+Finds anonymous namespaces in headers.
+
+https://google.github.io/styleguide/cppguide.html#Namespaces
+
+Corresponding cpplint.py check name: `build/namespaces`.
+
+Options
+-------
+
+.. option:: HeaderFileExtensions
+
+   A comma-separated list of filename extensions of header files (the filename
+   extensions should not include "." prefix). Default is "h,hh,hpp,hxx".
+   For header files without an extension, use an empty string (if there are no
+   other desired extensions) or leave an empty element in the list. e.g.,
+   "h,hh,hpp,hxx," (note the trailing comma).
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-build-using-namespace.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-build-using-namespace.rst
new file mode 100644
index 0000000..f01bfed
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-build-using-namespace.rst
@@ -0,0 +1,19 @@
+.. title:: clang-tidy - google-build-using-namespace
+
+google-build-using-namespace
+============================
+
+Finds ``using namespace`` directives.
+
+The check implements the following rule of the
+`Google C++ Style Guide <https://google.github.io/styleguide/cppguide.html#Namespaces>`_:
+
+  You may not use a using-directive to make all names from a namespace
+  available.
+
+  .. code-block:: c++
+
+    // Forbidden -- This pollutes the namespace.
+    using namespace foo;
+
+Corresponding cpplint.py check name: `build/namespaces`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-default-arguments.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-default-arguments.rst
new file mode 100644
index 0000000..c02099c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-default-arguments.rst
@@ -0,0 +1,8 @@
+.. title:: clang-tidy - google-default-arguments
+
+google-default-arguments
+========================
+
+Checks that default arguments are not given for virtual methods.
+
+See https://google.github.io/styleguide/cppguide.html#Default_Arguments
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-explicit-constructor.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-explicit-constructor.rst
new file mode 100644
index 0000000..acafc1a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-explicit-constructor.rst
@@ -0,0 +1,56 @@
+.. title:: clang-tidy - google-explicit-constructor
+
+google-explicit-constructor
+===========================
+
+
+Checks that constructors callable with a single argument and conversion
+operators are marked explicit to avoid the risk of unintentional implicit
+conversions.
+
+Consider this example:
+
+.. code-block:: c++
+
+  struct S {
+    int x;
+    operator bool() const { return true; }
+  };
+
+  bool f() {
+    S a{1};
+    S b{2};
+    return a == b;
+  }
+
+The function will return ``true``, since the objects are implicitly converted to
+``bool`` before comparison, which is unlikely to be the intent.
+
+The check will suggest inserting ``explicit`` before the constructor or
+conversion operator declaration. However, copy and move constructors should not
+be explicit, as well as constructors taking a single ``initializer_list``
+argument.
+
+This code:
+
+.. code-block:: c++
+
+  struct S {
+    S(int a);
+    explicit S(const S&);
+    operator bool() const;
+    ...
+
+will become
+
+.. code-block:: c++
+
+  struct S {
+    explicit S(int a);
+    S(const S&);
+    explicit operator bool() const;
+    ...
+
+
+
+See https://google.github.io/styleguide/cppguide.html#Explicit_Constructors
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-global-names-in-headers.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-global-names-in-headers.rst
new file mode 100644
index 0000000..88ba906
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-global-names-in-headers.rst
@@ -0,0 +1,21 @@
+.. title:: clang-tidy - google-global-names-in-headers
+
+google-global-names-in-headers
+==============================
+
+Flag global namespace pollution in header files. Right now it only triggers on
+``using`` declarations and directives.
+
+The relevant style guide section is
+https://google.github.io/styleguide/cppguide.html#Namespaces.
+
+Options
+-------
+
+.. option:: HeaderFileExtensions
+
+   A comma-separated list of filename extensions of header files (the filename
+   extensions should not contain "." prefix). Default is "h".
+   For header files without an extension, use an empty string (if there are no
+   other desired extensions) or leave an empty element in the list. e.g.,
+   "h,hh,hpp,hxx," (note the trailing comma).
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-throwing-exception.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-throwing-exception.rst
new file mode 100644
index 0000000..39b0217
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-throwing-exception.rst
@@ -0,0 +1,39 @@
+.. title:: clang-tidy - google-objc-avoid-throwing-exception
+
+google-objc-avoid-throwing-exception
+====================================
+
+Finds uses of throwing exceptions usages in Objective-C files.
+
+For the same reason as the Google C++ style guide, we prefer not throwing 
+exceptions from Objective-C code.
+
+The corresponding C++ style guide rule:
+https://google.github.io/styleguide/cppguide.html#Exceptions
+
+Instead, prefer passing in ``NSError **`` and return ``BOOL`` to indicate success or failure.
+
+A counterexample:
+
+.. code-block:: objc
+
+  - (void)readFile {
+    if ([self isError]) {
+      @throw [NSException exceptionWithName:...];
+    }
+  }
+
+Instead, returning an error via ``NSError **`` is preferred:
+
+.. code-block:: objc
+
+  - (BOOL)readFileWithError:(NSError **)error {
+    if ([self isError]) {
+      *error = [NSError errorWithDomain:...];
+      return NO;
+    }
+    return YES;
+  }
+
+The corresponding style guide rule:
+http://google.github.io/styleguide/objcguide.html#avoid-throwing-exceptions
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-objc-global-variable-declaration.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-objc-global-variable-declaration.rst
new file mode 100644
index 0000000..d470370
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-objc-global-variable-declaration.rst
@@ -0,0 +1,47 @@
+.. title:: clang-tidy - google-objc-global-variable-declaration
+
+google-objc-global-variable-declaration
+=======================================
+
+Finds global variable declarations in Objective-C files that do not follow the
+pattern of variable names in Google's Objective-C Style Guide.
+
+The corresponding style guide rule:
+http://google.github.io/styleguide/objcguide.html#variable-names
+
+All the global variables should follow the pattern of `g[A-Z].*` (variables) or
+`k[A-Z].*` (constants). The check will suggest a variable name that follows the
+pattern if it can be inferred from the original name.
+
+For code:
+
+.. code-block:: objc
+
+  static NSString* myString = @"hello";
+
+The fix will be:
+
+.. code-block:: objc
+
+  static NSString* gMyString = @"hello";
+
+Another example of constant:
+
+.. code-block:: objc
+
+  static NSString* const myConstString = @"hello";
+
+The fix will be:
+
+.. code-block:: objc
+
+  static NSString* const kMyConstString = @"hello";
+
+However for code that prefixed with non-alphabetical characters like:
+
+.. code-block:: objc
+
+  static NSString* __anotherString = @"world";
+
+The check will give a warning message but will not be able to suggest a fix. The
+user need to fix it on his own.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-readability-braces-around-statements.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-readability-braces-around-statements.rst
new file mode 100644
index 0000000..e5c8eb6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-readability-braces-around-statements.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - google-readability-braces-around-statements
+.. meta::
+   :http-equiv=refresh: 5;URL=readability-braces-around-statements.html
+
+google-readability-braces-around-statements
+===========================================
+
+The google-readability-braces-around-statements check is an alias, please see
+`readability-braces-around-statements <readability-braces-around-statements.html>`_
+for more information.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-readability-casting.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-readability-casting.rst
new file mode 100644
index 0000000..4c9d1bc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-readability-casting.rst
@@ -0,0 +1,14 @@
+.. title:: clang-tidy - google-readability-casting
+
+google-readability-casting
+==========================
+
+Finds usages of C-style casts.
+
+https://google.github.io/styleguide/cppguide.html#Casting
+
+Corresponding cpplint.py check name: `readability/casting`.
+
+This check is similar to `-Wold-style-cast`, but it suggests automated fixes
+in some cases. The reported locations should not be different from the
+ones generated by `-Wold-style-cast`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-readability-function-size.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-readability-function-size.rst
new file mode 100644
index 0000000..b454628
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-readability-function-size.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - google-readability-function-size
+.. meta::
+   :http-equiv=refresh: 5;URL=readability-function-size.html
+
+google-readability-function-size
+================================
+
+The google-readability-function-size check is an alias, please see
+`readability-function-size <readability-function-size.html>`_ for more
+information.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-readability-namespace-comments.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-readability-namespace-comments.rst
new file mode 100644
index 0000000..258a305
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-readability-namespace-comments.rst
@@ -0,0 +1,9 @@
+.. title:: clang-tidy - google-readability-namespace-comments
+.. meta::
+   :http-equiv=refresh: 5;URL=llvm-namespace-comment.html
+
+google-readability-namespace-comments
+=====================================
+
+The google-readability-namespace-comments check is an alias, please see
+`llvm-namespace-comment <llvm-namespace-comment.html>`_ for more information.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-readability-todo.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-readability-todo.rst
new file mode 100644
index 0000000..159d2b4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-readability-todo.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - google-readability-todo
+
+google-readability-todo
+=======================
+
+Finds TODO comments without a username or bug number.
+
+The relevant style guide section is
+https://google.github.io/styleguide/cppguide.html#TODO_Comments.
+
+Corresponding cpplint.py check: `readability/todo`
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-runtime-int.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-runtime-int.rst
new file mode 100644
index 0000000..5e878a4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-runtime-int.rst
@@ -0,0 +1,27 @@
+.. title:: clang-tidy - google-runtime-int
+
+google-runtime-int
+==================
+
+Finds uses of ``short``, ``long`` and ``long long`` and suggest replacing them
+with ``u?intXX(_t)?``.
+
+The corresponding style guide rule:
+https://google.github.io/styleguide/cppguide.html#Integer_Types.
+
+Correspondig cpplint.py check: `runtime/int`.
+
+Options
+-------
+
+.. option:: UnsignedTypePrefix
+
+   A string specifying the unsigned type prefix. Default is `uint`.
+
+.. option:: SignedTypePrefix
+
+   A string specifying the signed type prefix. Default is `int`.
+
+.. option:: TypeSuffix
+
+   A string specifying the type suffix. Default is an empty string.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-runtime-operator.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-runtime-operator.rst
new file mode 100644
index 0000000..67f2993
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-runtime-operator.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - google-runtime-operator
+
+google-runtime-operator
+=======================
+
+Finds overloads of unary ``operator &``.
+
+https://google.github.io/styleguide/cppguide.html#Operator_Overloading
+
+Corresponding cpplint.py check name: `runtime/operator`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-runtime-references.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-runtime-references.rst
new file mode 100644
index 0000000..a210ccc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/google-runtime-references.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - google-runtime-references
+
+google-runtime-references
+=========================
+
+Checks the usage of non-constant references in function parameters.
+
+The corresponding style guide rule:
+https://google.github.io/styleguide/cppguide.html#Reference_Arguments
+
+
+Options
+-------
+
+.. option:: WhiteListTypes
+
+   A semicolon-separated list of names of whitelist types. Default is empty.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-avoid-goto.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-avoid-goto.rst
new file mode 100644
index 0000000..f689bec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-avoid-goto.rst
@@ -0,0 +1,12 @@
+.. title:: clang-tidy - hicpp-avoid-goto
+
+hicpp-avoid-goto
+================
+
+The `hicpp-avoid-goto` check is an alias to 
+`cppcoreguidelines-avoid-goto <cppcoreguidelines-avoid-goto.html>`_.
+Rule `6.3.1 High Integrity C++ <http://www.codingstandard.com/rule/6-3-1-ensure-that-the-labels-for-a-jump-statement-or-a-switch-condition-appear-later-in-the-same-or-an-enclosing-block/>`_
+requires that ``goto`` only skips parts of a block and is not used for other 
+reasons.
+
+Both coding guidelines implement the same exception to the usage of ``goto``.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-braces-around-statements.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-braces-around-statements.rst
new file mode 100644
index 0000000..2931aa8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-braces-around-statements.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - hicpp-braces-around-statements
+.. meta::
+   :http-equiv=refresh: 5;URL=readability-braces-around-statements.html
+
+hicpp-braces-around-statements
+==============================
+
+The `hicpp-braces-around-statements` check is an alias, please see
+`readability-braces-around-statements <readability-braces-around-statements.html>`_
+for more information.
+It enforces the `rule 6.1.1 <http://www.codingstandard.com/rule/6-1-1-enclose-the-body-of-a-selection-or-an-iteration-statement-in-a-compound-statement/>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-deprecated-headers.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-deprecated-headers.rst
new file mode 100644
index 0000000..960d918
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-deprecated-headers.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - hicpp-deprecated-headers
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-deprecated-headers.html
+
+hicpp-deprecated-headers
+========================
+
+The `hicpp-deprecated-headers` check is an alias, please see
+`modernize-deprecated-headers <modernize-deprecated-headers.html>`_
+for more information.
+It enforces the `rule 1.3.3 <http://www.codingstandard.com/rule/1-3-3-do-not-use-the-c-standard-library-h-headers/>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-exception-baseclass.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-exception-baseclass.rst
new file mode 100644
index 0000000..42563ae
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-exception-baseclass.rst
@@ -0,0 +1,30 @@
+.. title:: clang-tidy - hicpp-exception-baseclass
+
+hicpp-exception-baseclass
+=========================
+
+Ensure that every value that in a ``throw`` expression is an instance of 
+``std::exception``.
+
+This enforces `rule 15.1 <http://www.codingstandard.com/section/15-1-throwing-an-exception/>`_
+of the High Integrity C++ Coding Standard.
+
+.. code-block:: c++
+
+  class custom_exception {};
+
+  void throwing() noexcept(false) {
+    // Problematic throw expressions.
+    throw int(42);
+    throw custom_exception();
+  }
+
+  class mathematical_error : public std::exception {};
+
+  void throwing2() noexcept(false) {
+    // These kind of throws are ok.
+    throw mathematical_error();
+    throw std::runtime_error();
+    throw std::exception();
+  }
+  
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-explicit-conversions.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-explicit-conversions.rst
new file mode 100644
index 0000000..3ee0b78
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-explicit-conversions.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - hicpp-explicit-conversions
+.. meta::
+   :http-equiv=refresh: 5;URL=google-explicit-constructor.html
+
+hicpp-explicit-conversions
+==========================
+
+This check is an alias for `google-explicit-constructor <google-explicit-constructor.html>`_.
+Used to enforce parts of `rule 5.4.1 <http://www.codingstandard.com/rule/5-4-1-only-use-casting-forms-static_cast-excl-void-dynamic_cast-or-explicit-constructor-call/>`_.
+This check will enforce that constructors and conversion operators are marked `explicit`.
+Other forms of casting checks are implemented in other places.
+The following checks can be used to check for more forms of casting:
+
+- `cppcoreguidelines-pro-type-static-cast-downcast <cppcoreguidelines-pro-type-static-cast-downcast.html>`_
+- `cppcoreguidelines-pro-type-reinterpret-cast <cppcoreguidelines-pro-type-reinterpret-cast.html>`_
+- `cppcoreguidelines-pro-type-const-cast <cppcoreguidelines-pro-type-const-cast.html>`_ 
+- `cppcoreguidelines-pro-type-cstyle-cast <cppcoreguidelines-pro-type-cstyle-cast.html>`_
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-function-size.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-function-size.rst
new file mode 100644
index 0000000..4b1f616
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-function-size.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - hicpp-function-size
+.. meta::
+   :http-equiv=refresh: 5;URL=readability-function-size.html
+
+hicpp-function-size
+===================
+
+This check is an alias for `readability-function-size <readability-function-size.html>`_.
+Useful to enforce multiple sections on function complexity.
+
+- `rule 8.2.2 <http://www.codingstandard.com/rule/8-2-2-do-not-declare-functions-with-an-excessive-number-of-parameters/>`_
+- `rule 8.3.1 <http://www.codingstandard.com/rule/8-3-1-do-not-write-functions-with-an-excessive-mccabe-cyclomatic-complexity/>`_
+- `rule 8.3.2 <http://www.codingstandard.com/rule/8-3-2-do-not-write-functions-with-a-high-static-program-path-count/>`_
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-invalid-access-moved.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-invalid-access-moved.rst
new file mode 100644
index 0000000..4fac3f5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-invalid-access-moved.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-invalid-access-moved
+.. meta::
+   :http-equiv=refresh: 5;URL=bugprone-use-after-move.html
+
+hicpp-invalid-access-moved
+==========================
+
+This check is an alias for `bugprone-use-after-move <bugprone-use-after-move.html>`_.
+
+Implements parts of the `rule 8.4.1 <http://www.codingstandard.com/rule/8-4-1-do-not-access-an-invalid-object-or-an-object-with-indeterminate-value/>`_ to check if moved-from objects are accessed.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-member-init.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-member-init.rst
new file mode 100644
index 0000000..7f985e2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-member-init.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - hicpp-member-init
+.. meta::
+   :http-equiv=refresh: 5;URL=cppcoreguidelines-pro-type-member-init.html
+
+hicpp-member-init
+=================
+
+This check is an alias for `cppcoreguidelines-pro-type-member-init <cppcoreguidelines-pro-type-member-init.html>`_.
+Implements the check for 
+`rule 12.4.2 <http://www.codingstandard.com/rule/12-4-2-ensure-that-a-constructor-initializes-explicitly-all-base-classes-and-non-static-data-members/>`_ 
+to initialize class members in the right order.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-move-const-arg.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-move-const-arg.rst
new file mode 100644
index 0000000..c8d34d0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-move-const-arg.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-move-const-arg
+.. meta::
+   :http-equiv=refresh: 5;URL=performance-move-const-arg.html
+
+hicpp-move-const-arg
+====================
+
+The `hicpp-move-const-arg` check is an alias, please see
+`performance-move-const-arg <performance-move-const-arg.html>`_ for more information.
+It enforces the `rule 17.3.1 <http://www.codingstandard.com/rule/17-3-1-do-not-use-stdmove-on-objects-declared-with-const-or-const-type/>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-multiway-paths-covered.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-multiway-paths-covered.rst
new file mode 100644
index 0000000..2cace63
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-multiway-paths-covered.rst
@@ -0,0 +1,96 @@
+.. title:: clang-tidy - hicpp-multiway-paths-covered
+
+hicpp-multiway-paths-covered
+============================
+
+This check discovers situations where code paths are not fully-covered.
+It furthermore suggests using ``if`` instead of ``switch`` if the code will be more clear.
+The `rule 6.1.2 <http://www.codingstandard.com/rule/6-1-2-explicitly-cover-all-paths-through-multi-way-selection-statements/>`_
+and `rule 6.1.4 <http://www.codingstandard.com/rule/6-1-4-ensure-that-a-switch-statement-has-at-least-two-case-labels-distinct-from-the-default-label/>`_
+of the High Integrity C++ Coding Standard are enforced.
+
+``if-else if`` chains that miss a final ``else`` branch might lead to unexpected 
+program execution and be the result of a logical error.
+If the missing ``else`` branch is intended you can leave it empty with a clarifying
+comment.
+This warning can be noisy on some code bases, so it is disabled by default.
+
+.. code-block:: c++
+
+  void f1() {
+    int i = determineTheNumber();
+
+     if(i > 0) { 
+       // Some Calculation 
+     } else if (i < 0) { 
+       // Precondition violated or something else. 
+     }
+     // ...
+  }
+
+Similar arguments hold for ``switch`` statements which do not cover all possible code paths.
+
+.. code-block:: c++
+
+  // The missing default branch might be a logical error. It can be kept empty
+  // if there is nothing to do, making it explicit.
+  void f2(int i) {
+    switch (i) {
+    case 0: // something
+      break;
+    case 1: // something else
+      break;
+    }
+    // All other numbers?
+  }
+
+  // Violates this rule as well, but already emits a compiler warning (-Wswitch).
+  enum Color { Red, Green, Blue, Yellow };
+  void f3(enum Color c) {
+    switch (c) {
+    case Red: // We can't drive for now.
+      break;
+    case Green:  // We are allowed to drive.
+      break;
+    }
+    // Other cases missing
+  }
+
+
+The `rule 6.1.4 <http://www.codingstandard.com/rule/6-1-4-ensure-that-a-switch-statement-has-at-least-two-case-labels-distinct-from-the-default-label/>`_
+requires every ``switch`` statement to have at least two ``case`` labels other than a `default` label.
+Otherwise, the ``switch`` could be better expressed with an ``if`` statement.
+Degenerated ``switch`` statements without any labels are caught as well.
+
+.. code-block:: c++
+
+  // Degenerated switch that could be better written as `if`
+  int i = 42;
+  switch(i) {
+    case 1: // do something here
+    default: // do somethe else here
+  }
+
+  // Should rather be the following:
+  if (i == 1) { 
+    // do something here 
+  }
+  else { 
+    // do something here 
+  }
+
+
+.. code-block:: c++
+  
+  // A completly degenerated switch will be diagnosed.
+  int i = 42;
+  switch(i) {}
+
+
+Options
+-------
+
+.. option:: WarnOnMissingElse
+
+  Boolean flag that activates a warning for missing ``else`` branches.
+  Default is `0`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-named-parameter.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-named-parameter.rst
new file mode 100644
index 0000000..4bb8505
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-named-parameter.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-named-parameter
+.. meta::
+   :http-equiv=refresh: 5;URL=readability-named-parameter.html
+
+hicpp-named-parameter
+=====================
+
+This check is an alias for `readability-named-parameter <readability-named-parameter.html>`_.
+
+Implements `rule 8.2.1 <http://www.codingstandard.com/rule/8-2-1-make-parameter-names-absent-or-identical-in-all-declarations/>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-new-delete-operators.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-new-delete-operators.rst
new file mode 100644
index 0000000..88c26ad
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-new-delete-operators.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-new-delete-operators
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-new-delete-overloads.html
+
+hicpp-new-delete-operators
+==========================
+
+This check is an alias for `misc-new-delete-overloads <misc-new-delete-overloads.html>`_.
+Implements `rule 12.3.1 <http://www.codingstandard.com/section/12-3-free-store/>`_ to ensure
+the `new` and `delete` operators have the correct signature.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-no-array-decay.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-no-array-decay.rst
new file mode 100644
index 0000000..01f140e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-no-array-decay.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - hicpp-no-array-decay
+.. meta::
+   :http-equiv=refresh: 5;URL=cppcoreguidelines-pro-bounds-array-to-pointer-decay.html
+
+hicpp-no-array-decay
+====================
+
+The `hicpp-no-array-decay` check is an alias, please see
+`cppcoreguidelines-pro-bounds-array-to-pointer-decay <cppcoreguidelines-pro-bounds-array-to-pointer-decay.html>`_
+for more information.
+It enforces the `rule 4.1.1 <http://www.codingstandard.com/section/4-1-array-to-pointer-conversion/>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-no-assembler.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-no-assembler.rst
new file mode 100644
index 0000000..8295895
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-no-assembler.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-no-assembler
+
+hicpp-no-assembler
+===================
+
+Check for assembler statements. No fix is offered.
+
+Inline assembler is forbidden by the `High Intergrity C++ Coding Standard
+<http://www.codingstandard.com/section/7-5-the-asm-declaration/>`_ 
+as it restricts the portability of code.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-no-malloc.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-no-malloc.rst
new file mode 100644
index 0000000..768342f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-no-malloc.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - hicpp-no-malloc
+.. meta::
+   :http-equiv=refresh: 5;URL=cppcoreguidelines-no-malloc.html
+
+hicpp-no-malloc
+===============
+
+The `hicpp-no-malloc` check is an alias, please see
+`cppcoreguidelines-no-malloc <cppcoreguidelines-no-malloc.html>`_
+for more information.
+It enforces the `rule 5.3.2 <http://www.codingstandard.com/rule/5-3-2-allocate-memory-using-new-and-release-it-using-delete/>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-noexcept-move.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-noexcept-move.rst
new file mode 100644
index 0000000..10573ec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-noexcept-move.rst
@@ -0,0 +1,9 @@
+.. title:: clang-tidy - hicpp-noexcept-move
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-noexcept-moveconstructor.html
+
+hicpp-noexcept-move
+===================
+
+This check is an alias for `misc-noexcept-moveconstructor <misc-noexcept-moveconstructor.html>`_.
+Checks `rule 12.5.4 <http://www.codingstandard.com/rule/12-5-4-declare-noexcept-the-move-constructor-and-move-assignment-operator>`_ to mark move assignment and move construction `noexcept`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-signed-bitwise.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-signed-bitwise.rst
new file mode 100644
index 0000000..59b19b6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-signed-bitwise.rst
@@ -0,0 +1,9 @@
+.. title:: clang-tidy - hicpp-signed-bitwise
+
+hicpp-signed-bitwise
+====================
+
+Finds uses of bitwise operations on signed integer types, which may lead to 
+undefined or implementation defined behaviour.
+
+The according rule is defined in the `High Integrity C++ Standard, Section 5.6.1 <http://www.codingstandard.com/section/5-6-shift-operators/>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-special-member-functions.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-special-member-functions.rst
new file mode 100644
index 0000000..4173177
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-special-member-functions.rst
@@ -0,0 +1,9 @@
+.. title:: clang-tidy - hicpp-special-member-functions
+.. meta::
+   :http-equiv=refresh: 5;URL=cppcoreguidelines-special-member-functions.html
+
+hicpp-special-member-functions
+==============================
+
+This check is an alias for `cppcoreguidelines-special-member-functions <cppcoreguidelines-special-member-functions.html>`_.
+Checks that special member functions have the correct signature, according to `rule 12.5.7 <http://www.codingstandard.com/rule/12-5-7-declare-assignment-operators-with-the-ref-qualifier/>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-static-assert.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-static-assert.rst
new file mode 100644
index 0000000..b5d4e41
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-static-assert.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-static-assert
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-static-assert.html
+
+hicpp-static-assert
+===================
+
+The `hicpp-static-assert` check is an alias, please see
+`misc-static-assert <misc-static-assert.html>`_ for more information.
+It enforces the `rule 7.1.10 <http://www.codingstandard.com/rule/6-1-1-enclose-the-body-of-a-selection-or-an-iteration-statement-in-a-compound-statement/>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-undelegated-constructor.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-undelegated-constructor.rst
new file mode 100644
index 0000000..db521c5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-undelegated-constructor.rst
@@ -0,0 +1,25 @@
+.. title:: clang-tidy - hicpp-undelegated-construtor
+.. meta::
+   :http-equiv=refresh: 5;URL=bugprone-undelegated-constructor.html
+
+hicpp-undelegated-constructor
+=============================
+
+This check is an alias for `bugprone-undelegated-constructor <bugprone-undelegated-constructor.html>`_.
+Partially implements `rule 12.4.5 <http://www.codingstandard.com/rule/12-4-5-use-delegating-constructors-to-reduce-code-duplication/>`_ 
+to find misplaced constructor calls inside a constructor.
+
+.. code-block:: c++
+
+  struct Ctor {
+    Ctor();
+    Ctor(int);
+    Ctor(int, int);
+    Ctor(Ctor *i) {
+      // All Ctor() calls result in a temporary object
+      Ctor(); // did you intend to call a delegated constructor? 
+      Ctor(0); // did you intend to call a delegated constructor?
+      Ctor(1, 2); // did you intend to call a delegated constructor?
+      foo();
+    }
+  };
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-auto.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-auto.rst
new file mode 100644
index 0000000..23d0067
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-auto.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-use-auto
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-use-auto.html
+
+hicpp-use-auto
+==============
+
+The `hicpp-use-auto` check is an alias, please see
+`modernize-use-auto <modernize-use-auto.html>`_ for more information.
+It enforces the `rule 7.1.8 <http://www.codingstandard.com/rule/7-1-8-use-auto-id-expr-when-declaring-a-variable-to-have-the-same-type-as-its-initializer-function-call/>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-emplace.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-emplace.rst
new file mode 100644
index 0000000..07853c8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-emplace.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-use-emplace
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-use-emplace.html
+
+hicpp-use-emplace
+=================
+
+The `hicpp-use-emplace` check is an alias, please see
+`modernize-use-emplace <modernize-use-emplace.html>`_ for more information.
+It enforces the `rule 17.4.2 <http://www.codingstandard.com/rule/17-4-2-use-api-calls-that-construct-objects-in-place/>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-equals-default.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-equals-default.rst
new file mode 100644
index 0000000..1dcf581
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-equals-default.rst
@@ -0,0 +1,9 @@
+.. title:: clang-tidy - hicpp-use-equals-defaults
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-use-equals-default.html
+
+hicpp-use-equals-default
+========================
+
+This check is an alias for `modernize-use-equals-default <modernize-use-equals-default.html>`_.
+Implements `rule 12.5.1 <http://www.codingstandard.com/rule/12-5-1-define-explicitly-default-or-delete-implicit-special-member-functions-of-concrete-classes/>`_ to explicitly default special member functions.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-equals-delete.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-equals-delete.rst
new file mode 100644
index 0000000..4d98786
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-equals-delete.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-use-equals-delete
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-use-equals-delete.html
+
+hicpp-use-equals-delete
+=======================
+
+This check is an alias for `modernize-use-equals-delete <modernize-use-equals-delete.html>`_.
+Implements `rule 12.5.1 <http://www.codingstandard.com/rule/12-5-1-define-explicitly-default-or-delete-implicit-special-member-functions-of-concrete-classes/>`_ 
+to explicitly default or delete special member functions.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-noexcept.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-noexcept.rst
new file mode 100644
index 0000000..1a30ddf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-noexcept.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-use-noexcept
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-use-noexcept.html
+
+hicpp-use-noexcept
+==================
+
+The `hicpp-use-noexcept` check is an alias, please see
+`modernize-use-noexcept <modernize-use-noexcept.html>`_ for more information.
+It enforces the `rule 1.3.5 <http://www.codingstandard.com/rule/1-3-5-do-not-use-throw-exception-specifications/>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-nullptr.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-nullptr.rst
new file mode 100644
index 0000000..9bd9051
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-nullptr.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-use-nullptr
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-use-nullptr.html
+
+hicpp-use-nullptr
+=================
+
+The `hicpp-use-nullptr` check is an alias, please see
+`modernize-use-nullptr <modernize-use-nullptr.html>`_ for more information.
+It enforces the `rule 2.5.3 <http://www.codingstandard.com/rule/2-5-3-use-nullptr-for-the-null-pointer-constant/>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-override.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-override.rst
new file mode 100644
index 0000000..62541fa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-use-override.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-use-override
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-use-override.html
+
+hicpp-use-override
+==================
+
+This check is an alias for `modernize-use-override <modernize-use-override.html>`_.
+Implements `rule 10.2.1 <http://www.codingstandard.com/section/10-2-virtual-functions/>`_ to 
+declare a virtual function `override` when overriding.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-vararg.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-vararg.rst
new file mode 100644
index 0000000..92562e4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/hicpp-vararg.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - hicpp-vararg
+.. meta::
+   :http-equiv=refresh: 5;URL=cppcoreguidelines-pro-type-vararg.html
+
+hicpp-vararg
+============
+
+The `hicpp-vararg` check is an alias, please see
+`cppcoreguidelines-pro-type-vararg <cppcoreguidelines-pro-type-vararg.html>`_
+for more information.
+It enforces the `rule 14.1.1 <http://www.codingstandard.com/section/14-1-template-declarations/>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/list.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/list.rst
new file mode 100644
index 0000000..9bb68bc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -0,0 +1,238 @@
+.. title:: clang-tidy - Clang-Tidy Checks
+
+Clang-Tidy Checks
+=================
+
+.. toctree::
+   abseil-string-find-startswith
+   android-cloexec-accept
+   android-cloexec-accept4
+   android-cloexec-creat
+   android-cloexec-dup
+   android-cloexec-epoll-create
+   android-cloexec-epoll-create1
+   android-cloexec-fopen
+   android-cloexec-inotify-init
+   android-cloexec-inotify-init1
+   android-cloexec-memfd-create
+   android-cloexec-open
+   android-cloexec-socket
+   android-comparison-in-temp-failure-retry
+   boost-use-to-string
+   bugprone-argument-comment
+   bugprone-assert-side-effect
+   bugprone-bool-pointer-implicit-conversion
+   bugprone-copy-constructor-init
+   bugprone-dangling-handle
+   bugprone-exception-escape
+   bugprone-fold-init-type
+   bugprone-forward-declaration-namespace
+   bugprone-forwarding-reference-overload
+   bugprone-inaccurate-erase
+   bugprone-incorrect-roundings
+   bugprone-integer-division
+   bugprone-lambda-function-name
+   bugprone-macro-parentheses
+   bugprone-macro-repeated-side-effects
+   bugprone-misplaced-operator-in-strlen-in-alloc
+   bugprone-misplaced-widening-cast
+   bugprone-move-forwarding-reference
+   bugprone-multiple-statement-macro
+   bugprone-parent-virtual-call
+   bugprone-sizeof-container
+   bugprone-sizeof-expression
+   bugprone-string-constructor
+   bugprone-string-integer-assignment
+   bugprone-string-literal-with-embedded-nul
+   bugprone-suspicious-enum-usage
+   bugprone-suspicious-memset-usage
+   bugprone-suspicious-missing-comma
+   bugprone-suspicious-semicolon
+   bugprone-suspicious-string-compare
+   bugprone-swapped-arguments
+   bugprone-terminating-continue
+   bugprone-throw-keyword-missing
+   bugprone-undefined-memory-manipulation
+   bugprone-undelegated-constructor
+   bugprone-unused-raii
+   bugprone-unused-return-value
+   bugprone-use-after-move
+   bugprone-virtual-near-miss
+   cert-dcl03-c (redirects to misc-static-assert) <cert-dcl03-c>
+   cert-dcl21-cpp
+   cert-dcl50-cpp
+   cert-dcl54-cpp (redirects to misc-new-delete-overloads) <cert-dcl54-cpp>
+   cert-dcl58-cpp
+   cert-dcl59-cpp (redirects to google-build-namespaces) <cert-dcl59-cpp>
+   cert-env33-c
+   cert-err09-cpp (redirects to misc-throw-by-value-catch-by-reference) <cert-err09-cpp>
+   cert-err34-c
+   cert-err52-cpp
+   cert-err58-cpp
+   cert-err60-cpp
+   cert-err61-cpp (redirects to misc-throw-by-value-catch-by-reference) <cert-err61-cpp>
+   cert-fio38-c (redirects to misc-non-copyable-objects) <cert-fio38-c>
+   cert-flp30-c
+   cert-msc30-c (redirects to cert-msc50-cpp) <cert-msc30-c>
+   cert-msc32-c (redirects to cert-msc51-cpp) <cert-msc32-c>
+   cert-msc50-cpp
+   cert-msc51-cpp
+   cert-oop11-cpp (redirects to performance-move-constructor-init) <cert-oop11-cpp>
+   cppcoreguidelines-avoid-goto
+   cppcoreguidelines-c-copy-assignment-signature (redirects to misc-unconventional-assign-operator) <cppcoreguidelines-c-copy-assignment-signature>
+   cppcoreguidelines-interfaces-global-init
+   cppcoreguidelines-narrowing-conversions
+   cppcoreguidelines-no-malloc
+   cppcoreguidelines-owning-memory
+   cppcoreguidelines-pro-bounds-array-to-pointer-decay
+   cppcoreguidelines-pro-bounds-constant-array-index
+   cppcoreguidelines-pro-bounds-pointer-arithmetic
+   cppcoreguidelines-pro-type-const-cast
+   cppcoreguidelines-pro-type-cstyle-cast
+   cppcoreguidelines-pro-type-member-init
+   cppcoreguidelines-pro-type-reinterpret-cast
+   cppcoreguidelines-pro-type-static-cast-downcast
+   cppcoreguidelines-pro-type-union-access
+   cppcoreguidelines-pro-type-vararg
+   cppcoreguidelines-slicing
+   cppcoreguidelines-special-member-functions
+   fuchsia-default-arguments
+   fuchsia-header-anon-namespaces (redirects to google-build-namespaces) <fuchsia-header-anon-namespaces>
+   fuchsia-multiple-inheritance
+   fuchsia-overloaded-operator
+   fuchsia-restrict-system-includes
+   fuchsia-statically-constructed-objects
+   fuchsia-trailing-return
+   fuchsia-virtual-inheritance
+   google-build-explicit-make-pair
+   google-build-namespaces
+   google-build-using-namespace
+   google-default-arguments
+   google-explicit-constructor
+   google-global-names-in-headers
+   google-objc-avoid-throwing-exception
+   google-objc-global-variable-declaration
+   google-readability-braces-around-statements (redirects to readability-braces-around-statements) <google-readability-braces-around-statements>
+   google-readability-casting
+   google-readability-function-size (redirects to readability-function-size) <google-readability-function-size>
+   google-readability-namespace-comments (redirects to llvm-namespace-comment) <google-readability-namespace-comments>
+   google-readability-todo
+   google-runtime-int
+   google-runtime-operator
+   google-runtime-references
+   hicpp-avoid-goto
+   hicpp-braces-around-statements (redirects to readability-braces-around-statements) <hicpp-braces-around-statements>
+   hicpp-deprecated-headers (redirects to modernize-deprecated-headers) <hicpp-deprecated-headers>
+   hicpp-exception-baseclass
+   hicpp-explicit-conversions (redirects to google-explicit-constructor) <hicpp-explicit-conversions>
+   hicpp-function-size (redirects to readability-function-size) <hicpp-function-size>
+   hicpp-invalid-access-moved (redirects to bugprone-use-after-move) <hicpp-invalid-access-moved>
+   hicpp-member-init (redirects to cppcoreguidelines-pro-type-member-init) <hicpp-member-init>
+   hicpp-move-const-arg (redirects to performance-move-const-arg) <hicpp-move-const-arg>
+   hicpp-multiway-paths-covered
+   hicpp-named-parameter (redirects to readability-named-parameter) <hicpp-named-parameter>
+   hicpp-new-delete-operators (redirects to misc-new-delete-overloads) <hicpp-new-delete-operators>
+   hicpp-no-array-decay (redirects to cppcoreguidelines-pro-bounds-array-to-pointer-decay) <hicpp-no-array-decay>
+   hicpp-no-assembler
+   hicpp-no-malloc (redirects to cppcoreguidelines-no-malloc) <hicpp-no-malloc>
+   hicpp-noexcept-move (redirects to misc-noexcept-moveconstructor) <hicpp-noexcept-move>
+   hicpp-signed-bitwise
+   hicpp-special-member-functions (redirects to cppcoreguidelines-special-member-functions) <hicpp-special-member-functions>
+   hicpp-static-assert (redirects to misc-static-assert) <hicpp-static-assert>
+   hicpp-undelegated-constructor (redirects to bugprone-undelegated-constructor) <hicpp-undelegated-constructor>
+   hicpp-use-auto (redirects to modernize-use-auto) <hicpp-use-auto>
+   hicpp-use-emplace (redirects to modernize-use-emplace) <hicpp-use-emplace>
+   hicpp-use-equals-default (redirects to modernize-use-equals-default) <hicpp-use-equals-default>
+   hicpp-use-equals-delete (redirects to modernize-use-equals-delete) <hicpp-use-equals-delete>
+   hicpp-use-noexcept (redirects to modernize-use-noexcept) <hicpp-use-noexcept>
+   hicpp-use-nullptr (redirects to modernize-use-nullptr) <hicpp-use-nullptr>
+   hicpp-use-override (redirects to modernize-use-override) <hicpp-use-override>
+   hicpp-vararg (redirects to cppcoreguidelines-pro-type-vararg) <hicpp-vararg>
+   llvm-header-guard
+   llvm-include-order
+   llvm-namespace-comment
+   llvm-twine-local
+   misc-definitions-in-headers
+   misc-misplaced-const
+   misc-new-delete-overloads
+   misc-non-copyable-objects
+   misc-redundant-expression
+   misc-static-assert
+   misc-throw-by-value-catch-by-reference
+   misc-unconventional-assign-operator
+   misc-uniqueptr-reset-release
+   misc-unused-alias-decls
+   misc-unused-parameters
+   misc-unused-using-decls
+   modernize-avoid-bind
+   modernize-deprecated-headers
+   modernize-loop-convert
+   modernize-make-shared
+   modernize-make-unique
+   modernize-pass-by-value
+   modernize-raw-string-literal
+   modernize-redundant-void-arg
+   modernize-replace-auto-ptr
+   modernize-replace-random-shuffle
+   modernize-return-braced-init-list
+   modernize-shrink-to-fit
+   modernize-unary-static-assert
+   modernize-use-auto
+   modernize-use-bool-literals
+   modernize-use-default-member-init
+   modernize-use-emplace
+   modernize-use-equals-default
+   modernize-use-equals-delete
+   modernize-use-noexcept
+   modernize-use-nullptr
+   modernize-use-override
+   modernize-use-transparent-functors
+   modernize-use-uncaught-exceptions
+   modernize-use-using
+   mpi-buffer-deref
+   mpi-type-mismatch
+   objc-avoid-nserror-init
+   objc-avoid-spinlock
+   objc-forbidden-subclassing
+   objc-property-declaration
+   performance-faster-string-find
+   performance-for-range-copy
+   performance-implicit-conversion-in-loop
+   performance-inefficient-algorithm
+   performance-inefficient-string-concatenation
+   performance-inefficient-vector-operation
+   performance-move-const-arg
+   performance-move-constructor-init
+   performance-noexcept-move-constructor
+   performance-type-promotion-in-math-fn
+   performance-unnecessary-copy-initialization
+   performance-unnecessary-value-param
+   portability-simd-intrinsics
+   readability-avoid-const-params-in-decls
+   readability-braces-around-statements
+   readability-container-size-empty
+   readability-delete-null-pointer
+   readability-deleted-default
+   readability-else-after-return
+   readability-function-size
+   readability-identifier-naming
+   readability-implicit-bool-conversion
+   readability-inconsistent-declaration-parameter-name
+   readability-misleading-indentation
+   readability-misplaced-array-index
+   readability-named-parameter
+   readability-non-const-parameter
+   readability-redundant-control-flow
+   readability-redundant-declaration
+   readability-redundant-function-ptr-dereference
+   readability-redundant-member-init
+   readability-redundant-smartptr-get
+   readability-redundant-string-cstr
+   readability-redundant-string-init
+   readability-simplify-boolean-expr
+   readability-simplify-subscript-expr
+   readability-static-accessed-through-instance
+   readability-static-definition-in-anonymous-namespace
+   readability-string-compare
+   readability-uniqueptr-delete-release
+   zircon-temporary-objects
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/llvm-header-guard.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/llvm-header-guard.rst
new file mode 100644
index 0000000..58233ec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/llvm-header-guard.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - llvm-header-guard
+
+llvm-header-guard
+=================
+
+Finds and fixes header guards that do not adhere to LLVM style.
+
+Options
+-------
+
+.. option:: HeaderFileExtensions
+
+   A comma-separated list of filename extensions of header files (the filename
+   extensions should not include "." prefix). Default is "h,hh,hpp,hxx".
+   For header files without an extension, use an empty string (if there are no
+   other desired extensions) or leave an empty element in the list. e.g.,
+   "h,hh,hpp,hxx," (note the trailing comma).
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/llvm-include-order.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/llvm-include-order.rst
new file mode 100644
index 0000000..dba9837
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/llvm-include-order.rst
@@ -0,0 +1,9 @@
+.. title:: clang-tidy - llvm-include-order
+
+llvm-include-order
+==================
+
+
+Checks the correct order of ``#includes``.
+
+See http://llvm.org/docs/CodingStandards.html#include-style
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/llvm-namespace-comment.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/llvm-namespace-comment.rst
new file mode 100644
index 0000000..f6bc598
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/llvm-namespace-comment.rst
@@ -0,0 +1,41 @@
+.. title:: clang-tidy - llvm-namespace-comment
+
+llvm-namespace-comment
+======================
+
+`google-readability-namespace-comments` redirects here as an alias for this
+check.
+
+Checks that long namespaces have a closing comment.
+
+http://llvm.org/docs/CodingStandards.html#namespace-indentation
+
+https://google.github.io/styleguide/cppguide.html#Namespaces
+
+.. code-block:: c++
+
+  namespace n1 {
+  void f();
+  }
+
+  // becomes
+
+  namespace n1 {
+  void f();
+  }  // namespace n1
+
+
+Options
+-------
+
+.. option:: ShortNamespaceLines
+
+   Requires the closing brace of the namespace definition to be followed by a
+   closing comment if the body of the namespace has more than
+   `ShortNamespaceLines` lines of code. The value is an unsigned integer that
+   defaults to `1U`.
+
+.. option:: SpacesBeforeComments
+
+   An unsigned integer specifying the number of spaces before the comment
+   closing a namespace definition. Default is `1U`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/llvm-twine-local.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/llvm-twine-local.rst
new file mode 100644
index 0000000..ec9ef1c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/llvm-twine-local.rst
@@ -0,0 +1,16 @@
+.. title:: clang-tidy - llvm-twine-local
+
+llvm-twine-local
+================
+
+
+Looks for local ``Twine`` variables which are prone to use after frees and
+should be generally avoided.
+
+.. code-block:: c++
+
+  static Twine Moo = Twine("bark") + "bah";
+
+  // becomes
+
+  static std::string Moo = (Twine("bark") + "bah").str();
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-definitions-in-headers.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-definitions-in-headers.rst
new file mode 100644
index 0000000..1b6c2cd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-definitions-in-headers.rst
@@ -0,0 +1,100 @@
+.. title:: clang-tidy - misc-definitions-in-headers
+
+misc-definitions-in-headers
+===========================
+
+Finds non-extern non-inline function and variable definitions in header files,
+which can lead to potential ODR violations in case these headers are included
+from multiple translation units.
+
+.. code-block:: c++
+
+   // Foo.h
+   int a = 1; // Warning: variable definition.
+   extern int d; // OK: extern variable.
+
+   namespace N {
+     int e = 2; // Warning: variable definition.
+   }
+
+   // Warning: variable definition.
+   const char* str = "foo";
+
+   // OK: internal linkage variable definitions are ignored for now.
+   // Although these might also cause ODR violations, we can be less certain and
+   // should try to keep the false-positive rate down.
+   static int b = 1;
+   const int c = 1;
+   const char* const str2 = "foo";
+   constexpr int k = 1;
+
+   // Warning: function definition.
+   int g() {
+     return 1;
+   }
+
+   // OK: inline function definition is allowed to be defined multiple times.
+   inline int e() {
+     return 1;
+   }
+
+   class A {
+   public:
+     int f1() { return 1; } // OK: implicitly inline member function definition is allowed.
+     int f2();
+
+     static int d;
+   };
+
+   // Warning: not an inline member function definition.
+   int A::f2() { return 1; }
+
+   // OK: class static data member declaration is allowed.
+   int A::d = 1;
+
+   // OK: function template is allowed.
+   template<typename T>
+   T f3() {
+     T a = 1;
+     return a;
+   }
+
+   // Warning: full specialization of a function template is not allowed.
+   template <>
+   int f3() {
+     int a = 1;
+     return a;
+   }
+
+   template <typename T>
+   struct B {
+     void f1();
+   };
+
+   // OK: member function definition of a class template is allowed.
+   template <typename T>
+   void B<T>::f1() {}
+
+   class CE {
+     constexpr static int i = 5; // OK: inline variable definition.
+   };
+
+   inline int i = 5; // OK: inline variable definition.
+
+   constexpr int f10() { return 0; } // OK: constexpr function implies inline.
+
+Options
+-------
+
+.. option:: HeaderFileExtensions
+
+   A comma-separated list of filename extensions of header files (the filename
+   extensions should not include "." prefix). Default is "h,hh,hpp,hxx".
+   For header files without an extension, use an empty string (if there are no
+   other desired extensions) or leave an empty element in the list. e.g.,
+   "h,hh,hpp,hxx," (note the trailing comma).
+
+.. option:: UseHeaderFileExtension
+
+   When non-zero, the check will use the file extension to distinguish header
+   files. Default is `1`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-misplaced-const.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-misplaced-const.rst
new file mode 100644
index 0000000..ee1549f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-misplaced-const.rst
@@ -0,0 +1,22 @@
+.. title:: clang-tidy - misc-misplaced-const
+
+misc-misplaced-const
+====================
+
+This check diagnoses when a ``const`` qualifier is applied to a ``typedef`` to a
+pointer type rather than to the pointee, because such constructs are often
+misleading to developers because the ``const`` applies to the pointer rather
+than the pointee.
+
+For instance, in the following code, the resulting type is ``int *`` ``const``
+rather than ``const int *``:
+
+.. code-block:: c++
+
+  typedef int *int_ptr;
+  void f(const int_ptr ptr);
+
+The check does not diagnose when the underlying ``typedef`` type is a pointer to
+a ``const`` type or a function pointer type. This is because the ``const``
+qualifier is less likely to be mistaken because it would be redundant (or
+disallowed) on the underlying pointee type.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-new-delete-overloads.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-new-delete-overloads.rst
new file mode 100644
index 0000000..727436d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-new-delete-overloads.rst
@@ -0,0 +1,19 @@
+.. title:: clang-tidy - misc-new-delete-overloads
+
+misc-new-delete-overloads
+=========================
+
+`cert-dcl54-cpp` redirects here as an alias for this check.
+
+The check flags overloaded operator ``new()`` and operator ``delete()``
+functions that do not have a corresponding free store function defined within
+the same scope.
+For instance, the check will flag a class implementation of a non-placement
+operator ``new()`` when the class does not also define a non-placement operator
+``delete()`` function as well.
+
+The check does not flag implicitly-defined operators, deleted or private
+operators, or placement operators.
+
+This check corresponds to CERT C++ Coding Standard rule `DCL54-CPP. Overload allocation and deallocation functions as a pair in the same scope
+<https://www.securecoding.cert.org/confluence/display/cplusplus/DCL54-CPP.+Overload+allocation+and+deallocation+functions+as+a+pair+in+the+same+scope>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-non-copyable-objects.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-non-copyable-objects.rst
new file mode 100644
index 0000000..d1f7bba
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-non-copyable-objects.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - misc-non-copyable-objects
+
+misc-non-copyable-objects
+=========================
+
+`cert-fio38-c` redirects here as an alias for this check.
+
+The check flags dereferences and non-pointer declarations of objects that are
+not meant to be passed by value, such as C FILE objects or POSIX
+``pthread_mutex_t`` objects.
+
+This check corresponds to CERT C++ Coding Standard rule `FIO38-C. Do not copy a FILE object
+<https://www.securecoding.cert.org/confluence/display/c/FIO38-C.+Do+not+copy+a+FILE+object>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-redundant-expression.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-redundant-expression.rst
new file mode 100644
index 0000000..83c29bd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-redundant-expression.rst
@@ -0,0 +1,25 @@
+.. title:: clang-tidy - misc-redundant-expression
+
+misc-redundant-expression
+=========================
+
+Detect redundant expressions which are typically errors due to copy-paste.
+
+Depending on the operator expressions may be
+
+- redundant,
+
+- always ``true``,
+
+- always ``false``,
+
+- always a constant (zero or one).
+
+Examples:
+
+.. code-block:: c++
+
+  ((x+1) | (x+1))             // (x+1) is redundant
+  (p->x == p->x)              // always true
+  (p->x < p->x)               // always false
+  (speed - speed + 1 == 12)   // speed - speed is always zero
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-static-assert.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-static-assert.rst
new file mode 100644
index 0000000..cf0cc2d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-static-assert.rst
@@ -0,0 +1,12 @@
+.. title:: clang-tidy - misc-static-assert
+
+misc-static-assert
+==================
+
+`cert-dcl03-c` redirects here as an alias for this check.
+
+Replaces ``assert()`` with ``static_assert()`` if the condition is evaluatable
+at compile time.
+
+The condition of ``static_assert()`` is evaluated at compile time which is
+safer and more efficient.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst
new file mode 100644
index 0000000..1a6d6b3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst
@@ -0,0 +1,34 @@
+.. title:: clang-tidy - misc-throw-by-value-catch-by-reference
+
+misc-throw-by-value-catch-by-reference
+======================================
+
+"cert-err09-cpp" redirects here as an alias for this check.
+"cert-err61-cpp" redirects here as an alias for this check.
+
+Finds violations of the rule "Throw by value, catch by reference" presented for
+example in "C++ Coding Standards" by H. Sutter and A. Alexandrescu.
+
+Exceptions:
+  * Throwing string literals will not be flagged despite being a pointer. They
+    are not susceptible to slicing and the usage of string literals is idomatic.
+  * Catching character pointers (``char``, ``wchar_t``, unicode character types)
+    will not be flagged to allow catching sting literals.
+  * Moved named values will not be flagged as not throwing an anonymous
+    temporary. In this case we can be sure that the user knows that the object
+    can't be accessed outside catch blocks handling the error.
+  * Throwing function parameters will not be flagged as not throwing an
+    anonymous temporary. This allows helper functions for throwing.
+  * Re-throwing caught exception variables will not be flragged as not throwing
+    an anonymous temporary. Although this can usually be done by just writing
+    ``throw;`` it happens often enough in real code.
+
+Options
+-------
+
+.. option:: CheckThrowTemporaries
+
+   Triggers detection of violations of the rule `Throw anonymous temporaries
+   <https://www.securecoding.cert.org/confluence/display/cplusplus/ERR09-CPP.+Throw+anonymous+temporaries>`_.
+   Default is `1`.
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-unconventional-assign-operator.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-unconventional-assign-operator.rst
new file mode 100644
index 0000000..8b85332
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-unconventional-assign-operator.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - misc-unconventional-assign-operator
+
+misc-unconventional-assign-operator
+===================================
+
+
+Finds declarations of assign operators with the wrong return and/or argument
+types and definitions with good return type but wrong ``return`` statements.
+
+  * The return type must be ``Class&``.
+  * Works with move-assign and assign by value.
+  * Private and deleted operators are ignored.
+  * The operator must always return ``*this``.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-uniqueptr-reset-release.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-uniqueptr-reset-release.rst
new file mode 100644
index 0000000..858fbe7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-uniqueptr-reset-release.rst
@@ -0,0 +1,16 @@
+.. title:: clang-tidy - misc-uniqueptr-reset-release
+
+misc-uniqueptr-reset-release
+============================
+
+Find and replace ``unique_ptr::reset(release())`` with ``std::move()``.
+
+Example:
+
+.. code-block:: c++
+
+  std::unique_ptr<Foo> x, y;
+  x.reset(y.release()); -> x = std::move(y);
+
+If ``y`` is already rvalue, ``std::move()`` is not added. ``x`` and ``y`` can
+also be ``std::unique_ptr<Foo>*``.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-unused-alias-decls.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-unused-alias-decls.rst
new file mode 100644
index 0000000..d0e8c71
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-unused-alias-decls.rst
@@ -0,0 +1,7 @@
+.. title:: clang-tidy - misc-unused-alias-decls
+
+misc-unused-alias-decls
+=======================
+
+
+Finds unused namespace alias declarations.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-unused-parameters.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-unused-parameters.rst
new file mode 100644
index 0000000..3dfeb29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-unused-parameters.rst
@@ -0,0 +1,42 @@
+.. title:: clang-tidy - misc-unused-parameters
+
+misc-unused-parameters
+======================
+
+Finds unused function parameters. Unused parameters may signify a bug in the
+code (e.g. when a different parameter is used instead). The suggested fixes
+either comment parameter name out or remove the parameter completely, if all
+callers of the function are in the same translation unit and can be updated.
+
+The check is similar to the `-Wunused-parameter` compiler diagnostic and can be
+used to prepare a codebase to enabling of that diagnostic. By default the check
+is more permissive (see :option:`StrictMode`).
+
+.. code-block:: c++
+
+  void a(int i) { /*some code that doesn't use `i`*/ }
+
+  // becomes
+
+  void a(int  /*i*/) { /*some code that doesn't use `i`*/ }
+
+.. code-block:: c++
+
+  static void staticFunctionA(int i);
+  static void staticFunctionA(int i) { /*some code that doesn't use `i`*/ }
+
+  // becomes
+
+  static void staticFunctionA()
+  static void staticFunctionA() { /*some code that doesn't use `i`*/ }
+
+Options
+-------
+
+.. option:: StrictMode
+
+   When zero (default value), the check will ignore trivially unused parameters,
+   i.e. when the corresponding function has an empty body (and in case of
+   constructors - no constructor initializers). When the function body is empty,
+   an unused parameter is unlikely to be unnoticed by a human reader, and
+   there's basically no place for a bug to hide.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-unused-using-decls.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-unused-using-decls.rst
new file mode 100644
index 0000000..9de1cb2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/misc-unused-using-decls.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - misc-unused-using-decls
+
+misc-unused-using-decls
+=======================
+
+Finds unused ``using`` declarations.
+
+Example:
+
+.. code-block:: c++
+
+  namespace n { class C; }
+  using n::C;  // Never actually used.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-avoid-bind.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-avoid-bind.rst
new file mode 100644
index 0000000..7ea9bec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-avoid-bind.rst
@@ -0,0 +1,37 @@
+.. title:: clang-tidy - modernize-avoid-bind
+
+modernize-avoid-bind
+====================
+
+The check finds uses of ``std::bind`` and replaces simple uses with lambdas.
+Lambdas will use value-capture where required.
+
+Right now it only handles free functions, not member functions.
+
+Given:
+
+.. code-block:: c++
+
+  int add(int x, int y) { return x + y; }
+
+Then:
+
+.. code-block:: c++
+
+  void f() {
+    int x = 2;
+    auto clj = std::bind(add, x, _1);
+  }
+
+is replaced by:
+
+.. code-block:: c++
+
+  void f() {
+    int x = 2;
+    auto clj = [=](auto && arg1) { return add(x, arg1); };
+  }
+
+``std::bind`` can be hard to read and can result in larger object files and
+binaries due to type information that will not be produced by equivalent
+lambdas.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-deprecated-headers.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-deprecated-headers.rst
new file mode 100644
index 0000000..4c4750a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-deprecated-headers.rst
@@ -0,0 +1,49 @@
+.. title:: clang-tidy - modernize-deprecated-headers
+
+modernize-deprecated-headers
+============================
+
+Some headers from C library were deprecated in C++ and are no longer welcome in
+C++ codebases. Some have no effect in C++. For more details refer to the C++ 14
+Standard [depr.c.headers] section.
+
+This check replaces C standard library headers with their C++ alternatives and
+removes redundant ones.
+
+Improtant note: the Standard doesn't guarantee that the C++ headers declare all
+the same functions in the global namespace. The check in its current form can
+break the code that uses library symbols from the global namespace.
+
+* `<assert.h>`
+* `<complex.h>`
+* `<ctype.h>`
+* `<errno.h>`
+* `<fenv.h>`     // deprecated since C++11
+* `<float.h>`
+* `<inttypes.h>`
+* `<limits.h>`
+* `<locale.h>`
+* `<math.h>`
+* `<setjmp.h>`
+* `<signal.h>`
+* `<stdarg.h>`
+* `<stddef.h>`
+* `<stdint.h>`
+* `<stdio.h>`
+* `<stdlib.h>`
+* `<string.h>`
+* `<tgmath.h>`   // deprecated since C++11
+* `<time.h>`
+* `<uchar.h>`    // deprecated since C++11
+* `<wchar.h>`
+* `<wctype.h>`
+
+If the specified standard is older than C++11 the check will only replace
+headers deprecated before C++11, otherwise -- every header that appeared in
+the previous list.
+
+These headers don't have effect in C++:
+
+* `<iso646.h>`
+* `<stdalign.h>`
+* `<stdbool.h>`
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-loop-convert.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-loop-convert.rst
new file mode 100644
index 0000000..bad574f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-loop-convert.rst
@@ -0,0 +1,255 @@
+.. title:: clang-tidy - modernize-loop-convert
+
+modernize-loop-convert
+======================
+
+This check converts ``for(...; ...; ...)`` loops to use the new range-based
+loops in C++11.
+
+Three kinds of loops can be converted:
+
+-  Loops over statically allocated arrays.
+-  Loops over containers, using iterators.
+-  Loops over array-like containers, using ``operator[]`` and ``at()``.
+
+MinConfidence option
+--------------------
+
+risky
+^^^^^
+
+In loops where the container expression is more complex than just a
+reference to a declared expression (a variable, function, enum, etc.),
+and some part of it appears elsewhere in the loop, we lower our confidence
+in the transformation due to the increased risk of changing semantics.
+Transformations for these loops are marked as `risky`, and thus will only
+be converted if the minimum required confidence level is set to `risky`.
+
+.. code-block:: c++
+
+  int arr[10][20];
+  int l = 5;
+
+  for (int j = 0; j < 20; ++j)
+    int k = arr[l][j] + l; // using l outside arr[l] is considered risky
+
+  for (int i = 0; i < obj.getVector().size(); ++i)
+    obj.foo(10); // using 'obj' is considered risky
+
+See
+:ref:`Range-based loops evaluate end() only once<IncorrectRiskyTransformation>`
+for an example of an incorrect transformation when the minimum required confidence
+level is set to `risky`.
+
+reasonable (Default)
+^^^^^^^^^^^^^^^^^^^^
+
+If a loop calls ``.end()`` or ``.size()`` after each iteration, the
+transformation for that loop is marked as `reasonable`, and thus will
+be converted if the required confidence level is set to `reasonable`
+(default) or lower.
+
+.. code-block:: c++
+
+  // using size() is considered reasonable
+  for (int i = 0; i < container.size(); ++i)
+    cout << container[i];
+
+safe
+^^^^
+
+Any other loops that do not match the above criteria to be marked as
+`risky` or `reasonable` are marked `safe`, and thus will be converted
+if the required confidence level is set to `safe` or lower.
+
+.. code-block:: c++
+
+  int arr[] = {1,2,3};
+
+  for (int i = 0; i < 3; ++i)
+    cout << arr[i];
+
+Example
+-------
+
+Original:
+
+.. code-block:: c++
+
+  const int N = 5;
+  int arr[] = {1,2,3,4,5};
+  vector<int> v;
+  v.push_back(1);
+  v.push_back(2);
+  v.push_back(3);
+
+  // safe conversion
+  for (int i = 0; i < N; ++i)
+    cout << arr[i];
+
+  // reasonable conversion
+  for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
+    cout << *it;
+
+  // reasonable conversion
+  for (int i = 0; i < v.size(); ++i)
+    cout << v[i];
+
+After applying the check with minimum confidence level set to `reasonable` (default):
+
+.. code-block:: c++
+
+  const int N = 5;
+  int arr[] = {1,2,3,4,5};
+  vector<int> v;
+  v.push_back(1);
+  v.push_back(2);
+  v.push_back(3);
+
+  // safe conversion
+  for (auto & elem : arr)
+    cout << elem;
+
+  // reasonable conversion
+  for (auto & elem : v)
+    cout << elem;
+
+  // reasonable conversion
+  for (auto & elem : v)
+    cout << elem;
+
+Limitations
+-----------
+
+There are certain situations where the tool may erroneously perform
+transformations that remove information and change semantics. Users of the tool
+should be aware of the behaviour and limitations of the check outlined by
+the cases below.
+
+Comments inside loop headers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Comments inside the original loop header are ignored and deleted when
+transformed.
+
+.. code-block:: c++
+
+  for (int i = 0; i < N; /* This will be deleted */ ++i) { }
+
+Range-based loops evaluate end() only once
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The C++11 range-based for loop calls ``.end()`` only once during the
+initialization of the loop. If in the original loop ``.end()`` is called after
+each iteration the semantics of the transformed loop may differ.
+
+.. code-block:: c++
+
+  // The following is semantically equivalent to the C++11 range-based for loop,
+  // therefore the semantics of the header will not change.
+  for (iterator it = container.begin(), e = container.end(); it != e; ++it) { }
+
+  // Instead of calling .end() after each iteration, this loop will be
+  // transformed to call .end() only once during the initialization of the loop,
+  // which may affect semantics.
+  for (iterator it = container.begin(); it != container.end(); ++it) { }
+
+.. _IncorrectRiskyTransformation:
+
+As explained above, calling member functions of the container in the body
+of the loop is considered `risky`. If the called member function modifies the
+container the semantics of the converted loop will differ due to ``.end()``
+being called only once.
+
+.. code-block:: c++
+
+  bool flag = false;
+  for (vector<T>::iterator it = vec.begin(); it != vec.end(); ++it) {
+    // Add a copy of the first element to the end of the vector.
+    if (!flag) {
+      // This line makes this transformation 'risky'.
+      vec.push_back(*it);
+      flag = true;
+    }
+    cout << *it;
+  }
+
+The original code above prints out the contents of the container including the
+newly added element while the converted loop, shown below, will only print the
+original contents and not the newly added element.
+
+.. code-block:: c++
+
+  bool flag = false;
+  for (auto & elem : vec) {
+    // Add a copy of the first element to the end of the vector.
+    if (!flag) {
+      // This line makes this transformation 'risky'
+      vec.push_back(elem);
+      flag = true;
+    }
+    cout << elem;
+  }
+
+Semantics will also be affected if ``.end()`` has side effects. For example, in
+the case where calls to ``.end()`` are logged the semantics will change in the
+transformed loop if ``.end()`` was originally called after each iteration.
+
+.. code-block:: c++
+
+  iterator end() {
+    num_of_end_calls++;
+    return container.end();
+  }
+
+Overloaded operator->() with side effects
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Similarly, if ``operator->()`` was overloaded to have side effects, such as
+logging, the semantics will change. If the iterator's ``operator->()`` was used
+in the original loop it will be replaced with ``<container element>.<member>``
+instead due to the implicit dereference as part of the range-based for loop.
+Therefore any side effect of the overloaded ``operator->()`` will no longer be
+performed.
+
+.. code-block:: c++
+
+  for (iterator it = c.begin(); it != c.end(); ++it) {
+    it->func(); // Using operator->()
+  }
+  // Will be transformed to:
+  for (auto & elem : c) {
+    elem.func(); // No longer using operator->()
+  }
+
+Pointers and references to containers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+While most of the check's risk analysis is dedicated to determining whether
+the iterator or container was modified within the loop, it is possible to
+circumvent the analysis by accessing and modifying the container through a
+pointer or reference.
+
+If the container were directly used instead of using the pointer or reference
+the following transformation would have only been applied at the `risky`
+level since calling a member function of the container is considered `risky`.
+The check cannot identify expressions associated with the container that are
+different than the one used in the loop header, therefore the transformation
+below ends up being performed at the `safe` level.
+
+.. code-block:: c++
+
+  vector<int> vec;
+
+  vector<int> *ptr = &vec;
+  vector<int> &ref = vec;
+
+  for (vector<int>::iterator it = vec.begin(), e = vec.end(); it != e; ++it) {
+    if (!flag) {
+      // Accessing and modifying the container is considered risky, but the risk
+      // level is not raised here.
+      ptr->push_back(*it);
+      ref.push_back(*it);
+      flag = true;
+    }
+  }
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-make-shared.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-make-shared.rst
new file mode 100644
index 0000000..e73b320
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-make-shared.rst
@@ -0,0 +1,50 @@
+.. title:: clang-tidy - modernize-make-shared
+
+modernize-make-shared
+=====================
+
+This check finds the creation of ``std::shared_ptr`` objects by explicitly
+calling the constructor and a ``new`` expression, and replaces it with a call
+to ``std::make_shared``.
+
+.. code-block:: c++
+
+  auto my_ptr = std::shared_ptr<MyPair>(new MyPair(1, 2));
+
+  // becomes
+
+  auto my_ptr = std::make_shared<MyPair>(1, 2);
+
+This check also finds calls to ``std::shared_ptr::reset()`` with a ``new``
+expression, and replaces it with a call to ``std::make_shared``.
+
+.. code-block:: c++
+
+  my_ptr.reset(new MyPair(1, 2));
+
+  // becomes
+
+  my_ptr = std::make_shared<MyPair>(1, 2);
+
+Options
+-------
+
+.. option:: MakeSmartPtrFunction
+
+   A string specifying the name of make-shared-ptr function. Default is
+   `std::make_shared`.
+
+.. option:: MakeSmartPtrFunctionHeader
+
+   A string specifying the corresponding header of make-shared-ptr function.
+   Default is `memory`.
+
+.. option:: IncludeStyle
+
+   A string specifying which include-style is used, `llvm` or `google`. Default
+   is `llvm`.
+
+.. option:: IgnoreMacros
+
+   If set to non-zero, the check will not give warnings inside macros. Default
+   is `1`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-make-unique.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-make-unique.rst
new file mode 100644
index 0000000..1961f05
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-make-unique.rst
@@ -0,0 +1,50 @@
+.. title:: clang-tidy - modernize-make-unique
+
+modernize-make-unique
+=====================
+
+This check finds the creation of ``std::unique_ptr`` objects by explicitly
+calling the constructor and a ``new`` expression, and replaces it with a call
+to ``std::make_unique``, introduced in C++14.
+
+.. code-block:: c++
+
+  auto my_ptr = std::unique_ptr<MyPair>(new MyPair(1, 2));
+
+  // becomes
+
+  auto my_ptr = std::make_unique<MyPair>(1, 2);
+
+This check also finds calls to ``std::unique_ptr::reset()`` with a ``new``
+expression, and replaces it with a call to ``std::make_unique``.
+
+.. code-block:: c++
+
+  my_ptr.reset(new MyPair(1, 2));
+
+  // becomes
+
+  my_ptr = std::make_unique<MyPair>(1, 2);
+
+Options
+-------
+
+.. option:: MakeSmartPtrFunction
+
+   A string specifying the name of make-unique-ptr function. Default is
+   `std::make_unique`.
+
+.. option:: MakeSmartPtrFunctionHeader
+
+   A string specifying the corresponding header of make-unique-ptr function.
+   Default is `memory`.
+
+.. option:: IncludeStyle
+
+   A string specifying which include-style is used, `llvm` or `google`. Default
+   is `llvm`.
+
+.. option:: IgnoreMacros
+
+   If set to non-zero, the check will not give warnings inside macros. Default
+   is `1`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-pass-by-value.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-pass-by-value.rst
new file mode 100644
index 0000000..1dfbf95
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-pass-by-value.rst
@@ -0,0 +1,166 @@
+.. title:: clang-tidy - modernize-pass-by-value
+
+modernize-pass-by-value
+=======================
+
+With move semantics added to the language and the standard library updated with
+move constructors added for many types it is now interesting to take an
+argument directly by value, instead of by const-reference, and then copy. This
+check allows the compiler to take care of choosing the best way to construct
+the copy.
+
+The transformation is usually beneficial when the calling code passes an
+*rvalue* and assumes the move construction is a cheap operation. This short
+example illustrates how the construction of the value happens:
+
+  .. code-block:: c++
+
+    void foo(std::string s);
+    std::string get_str();
+
+    void f(const std::string &str) {
+      foo(str);       // lvalue  -> copy construction
+      foo(get_str()); // prvalue -> move construction
+    }
+
+.. note::
+
+   Currently, only constructors are transformed to make use of pass-by-value.
+   Contributions that handle other situations are welcome!
+
+
+Pass-by-value in constructors
+-----------------------------
+
+Replaces the uses of const-references constructor parameters that are copied
+into class fields. The parameter is then moved with `std::move()`.
+
+Since ``std::move()`` is a library function declared in `<utility>` it may be
+necessary to add this include. The check will add the include directive when
+necessary.
+
+  .. code-block:: c++
+
+     #include <string>
+
+     class Foo {
+     public:
+    -  Foo(const std::string &Copied, const std::string &ReadOnly)
+    -    : Copied(Copied), ReadOnly(ReadOnly)
+    +  Foo(std::string Copied, const std::string &ReadOnly)
+    +    : Copied(std::move(Copied)), ReadOnly(ReadOnly)
+       {}
+
+     private:
+       std::string Copied;
+       const std::string &ReadOnly;
+     };
+
+     std::string get_cwd();
+
+     void f(const std::string &Path) {
+       // The parameter corresponding to 'get_cwd()' is move-constructed. By
+       // using pass-by-value in the Foo constructor we managed to avoid a
+       // copy-construction.
+       Foo foo(get_cwd(), Path);
+     }
+
+
+If the parameter is used more than once no transformation is performed since
+moved objects have an undefined state. It means the following code will be left
+untouched:
+
+.. code-block:: c++
+
+  #include <string>
+
+  void pass(const std::string &S);
+
+  struct Foo {
+    Foo(const std::string &S) : Str(S) {
+      pass(S);
+    }
+
+    std::string Str;
+  };
+
+
+Known limitations
+^^^^^^^^^^^^^^^^^
+
+A situation where the generated code can be wrong is when the object referenced
+is modified before the assignment in the init-list through a "hidden" reference.
+
+Example:
+
+.. code-block:: c++
+
+   std::string s("foo");
+
+   struct Base {
+     Base() {
+       s = "bar";
+     }
+   };
+
+   struct Derived : Base {
+  -  Derived(const std::string &S) : Field(S)
+  +  Derived(std::string S) : Field(std::move(S))
+     { }
+
+     std::string Field;
+   };
+
+   void f() {
+  -  Derived d(s); // d.Field holds "bar"
+  +  Derived d(s); // d.Field holds "foo"
+   }
+
+
+Note about delayed template parsing
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+When delayed template parsing is enabled, constructors part of templated
+contexts; templated constructors, constructors in class templates, constructors
+of inner classes of template classes, etc., are not transformed. Delayed
+template parsing is enabled by default on Windows as a Microsoft extension:
+`Clang Compiler User’s Manual - Microsoft extensions`_.
+
+Delayed template parsing can be enabled using the `-fdelayed-template-parsing`
+flag and disabled using `-fno-delayed-template-parsing`.
+
+Example:
+
+.. code-block:: c++
+
+   template <typename T> class C {
+     std::string S;
+
+   public:
+ =  // using -fdelayed-template-parsing (default on Windows)
+ =  C(const std::string &S) : S(S) {}
+
+ +  // using -fno-delayed-template-parsing (default on non-Windows systems)
+ +  C(std::string S) : S(std::move(S)) {}
+   };
+
+.. _Clang Compiler User’s Manual - Microsoft extensions: http://clang.llvm.org/docs/UsersManual.html#microsoft-extensions
+
+.. seealso::
+
+  For more information about the pass-by-value idiom, read: `Want Speed? Pass by Value`_.
+
+  .. _Want Speed? Pass by Value: https://web.archive.org/web/20140205194657/http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
+
+Options
+-------
+
+.. option:: IncludeStyle
+
+   A string specifying which include-style is used, `llvm` or `google`. Default
+   is `llvm`.
+
+.. option:: ValuesOnly
+
+   When non-zero, the check only warns about copied parameters that are already
+   passed by value. Default is `0`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-raw-string-literal.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-raw-string-literal.rst
new file mode 100644
index 0000000..3525d57
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-raw-string-literal.rst
@@ -0,0 +1,46 @@
+.. title:: clang-tidy - modernize-raw-string-literal
+
+modernize-raw-string-literal
+============================
+
+This check selectively replaces string literals containing escaped characters
+with raw string literals.
+
+Example:
+
+.. code-blocK:: c++
+
+  const char *const Quotes{"embedded \"quotes\""};
+  const char *const Paragraph{"Line one.\nLine two.\nLine three.\n"};
+  const char *const SingleLine{"Single line.\n"};
+  const char *const TrailingSpace{"Look here -> \n"};
+  const char *const Tab{"One\tTwo\n"};
+  const char *const Bell{"Hello!\a  And welcome!"};
+  const char *const Path{"C:\\Program Files\\Vendor\\Application.exe"};
+  const char *const RegEx{"\\w\\([a-z]\\)"};
+
+becomes
+
+.. code-block:: c++
+
+  const char *const Quotes{R"(embedded "quotes")"};
+  const char *const Paragraph{"Line one.\nLine two.\nLine three.\n"};
+  const char *const SingleLine{"Single line.\n"};
+  const char *const TrailingSpace{"Look here -> \n"};
+  const char *const Tab{"One\tTwo\n"};
+  const char *const Bell{"Hello!\a  And welcome!"};
+  const char *const Path{R"(C:\Program Files\Vendor\Application.exe)"};
+  const char *const RegEx{R"(\w\([a-z]\))"};
+
+The presence of any of the following escapes can cause the string to be
+converted to a raw string literal: ``\\``, ``\'``, ``\"``, ``\?``,
+and octal or hexadecimal escapes for printable ASCII characters.
+
+A string literal containing only escaped newlines is a common way of
+writing lines of text output. Introducing physical newlines with raw
+string literals in this case is likely to impede readability. These
+string literals are left unchanged.
+
+An escaped horizontal tab, form feed, or vertical tab prevents the string
+literal from being converted. The presence of a horizontal tab, form feed or
+vertical tab in source code is not visually obvious.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-redundant-void-arg.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-redundant-void-arg.rst
new file mode 100644
index 0000000..d1a03e3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-redundant-void-arg.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - modernize-redundant-void-arg
+
+modernize-redundant-void-arg
+============================
+
+Find and remove redundant ``void`` argument lists.
+
+Examples:
+  ===================================  ===========================
+  Initial code                         Code with applied fixes
+  ===================================  ===========================
+  ``int f(void);``                     ``int f();``
+  ``int (*f(void))(void);``            ``int (*f())();``
+  ``typedef int (*f_t(void))(void);``  ``typedef int (*f_t())();``
+  ``void (C::*p)(void);``              ``void (C::*p)();``
+  ``C::C(void) {}``                    ``C::C() {}``
+  ``C::~C(void) {}``                   ``C::~C() {}``
+  ===================================  ===========================
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-replace-auto-ptr.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-replace-auto-ptr.rst
new file mode 100644
index 0000000..1cbd68c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-replace-auto-ptr.rst
@@ -0,0 +1,79 @@
+.. title:: clang-tidy - modernize-replace-auto-ptr
+
+modernize-replace-auto-ptr
+==========================
+
+This check replaces the uses of the deprecated class ``std::auto_ptr`` by
+``std::unique_ptr`` (introduced in C++11). The transfer of ownership, done
+by the copy-constructor and the assignment operator, is changed to match
+``std::unique_ptr`` usage by using explicit calls to ``std::move()``.
+
+Migration example:
+
+.. code-block:: c++
+
+  -void take_ownership_fn(std::auto_ptr<int> int_ptr);
+  +void take_ownership_fn(std::unique_ptr<int> int_ptr);
+
+   void f(int x) {
+  -  std::auto_ptr<int> a(new int(x));
+  -  std::auto_ptr<int> b;
+  +  std::unique_ptr<int> a(new int(x));
+  +  std::unique_ptr<int> b;
+
+  -  b = a;
+  -  take_ownership_fn(b);
+  +  b = std::move(a);
+  +  take_ownership_fn(std::move(b));
+   }
+
+Since ``std::move()`` is a library function declared in ``<utility>`` it may be
+necessary to add this include. The check will add the include directive when
+necessary.
+
+Known Limitations
+-----------------
+* If headers modification is not activated or if a header is not allowed to be
+  changed this check will produce broken code (compilation error), where the
+  headers' code will stay unchanged while the code using them will be changed.
+
+* Client code that declares a reference to an ``std::auto_ptr`` coming from
+  code that can't be migrated (such as a header coming from a 3\ :sup:`rd`
+  party library) will produce a compilation error after migration. This is
+  because the type of the reference will be changed to ``std::unique_ptr`` but
+  the type returned by the library won't change, binding a reference to
+  ``std::unique_ptr`` from an ``std::auto_ptr``. This pattern doesn't make much
+  sense and usually ``std::auto_ptr`` are stored by value (otherwise what is
+  the point in using them instead of a reference or a pointer?).
+
+  .. code-block:: c++
+
+     // <3rd-party header...>
+     std::auto_ptr<int> get_value();
+     const std::auto_ptr<int> & get_ref();
+
+     // <calling code (with migration)...>
+    -std::auto_ptr<int> a(get_value());
+    +std::unique_ptr<int> a(get_value()); // ok, unique_ptr constructed from auto_ptr
+
+    -const std::auto_ptr<int> & p = get_ptr();
+    +const std::unique_ptr<int> & p = get_ptr(); // won't compile
+
+* Non-instantiated templates aren't modified.
+
+  .. code-block:: c++
+
+     template <typename X>
+     void f() {
+         std::auto_ptr<X> p;
+     }
+
+     // only 'f<int>()' (or similar) will trigger the replacement.
+
+Options
+-------
+
+.. option:: IncludeStyle
+
+   A string specifying which include-style is used, `llvm` or `google`. Default
+   is `llvm`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-replace-random-shuffle.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-replace-random-shuffle.rst
new file mode 100644
index 0000000..50674d4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-replace-random-shuffle.rst
@@ -0,0 +1,41 @@
+.. title:: clang-tidy - modernize-replace-random-shuffle
+
+modernize-replace-random-shuffle
+================================
+
+This check will find occurrences of ``std::random_shuffle`` and replace it with ``std::shuffle``. In C++17 ``std::random_shuffle`` will no longer be available and thus we need to replace it.
+
+Below are two examples of what kind of occurrences will be found and two examples of what it will be replaced with.
+
+.. code-block:: c++
+
+  std::vector<int> v;
+
+  // First example
+  std::random_shuffle(vec.begin(), vec.end());
+
+  // Second example
+  std::random_shuffle(vec.begin(), vec.end(), randomFunc);
+
+Both of these examples will be replaced with:
+
+.. code-block:: c++
+
+  std::shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()()));
+
+The second example will also receive a warning that ``randomFunc`` is no longer supported in the same way as before so if the user wants the same functionality, the user will need to change the implementation of the ``randomFunc``.
+
+One thing to be aware of here is that ``std::random_device`` is quite expensive to initialize. So if you are using the code in a performance critical place, you probably want to initialize it elsewhere. 
+Another thing is that the seeding quality of the suggested fix is quite poor: ``std::mt19937`` has an internal state of 624 32-bit integers, but is only seeded with a single integer. So if you require
+higher quality randomness, you should consider seeding better, for example:
+
+.. code-block:: c++
+
+  std::shuffle(v.begin(), v.end(), []() {
+    std::mt19937::result_type seeds[std::mt19937::state_size];
+    std::random_device device;
+    std::uniform_int_distribution<typename std::mt19937::result_type> dist;
+    std::generate(std::begin(seeds), std::end(seeds), [&] { return dist(device); });
+    std::seed_seq seq(std::begin(seeds), std::end(seeds));
+    return std::mt19937(seq);
+  }());
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-return-braced-init-list.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-return-braced-init-list.rst
new file mode 100644
index 0000000..2631d90
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-return-braced-init-list.rst
@@ -0,0 +1,22 @@
+.. title:: clang-tidy - modernize-return-braced-init-list
+
+modernize-return-braced-init-list
+=================================
+
+Replaces explicit calls to the constructor in a return with a braced
+initializer list. This way the return type is not needlessly duplicated in the
+function definition and the return statement.
+
+.. code:: c++
+
+  Foo bar() {
+    Baz baz;
+    return Foo(baz);
+  }
+
+  // transforms to:
+
+  Foo bar() {
+    Baz baz;
+    return {baz};
+  }
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-shrink-to-fit.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-shrink-to-fit.rst
new file mode 100644
index 0000000..4d7ffaf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-shrink-to-fit.rst
@@ -0,0 +1,12 @@
+.. title:: clang-tidy - modernize-shrink-to-fit
+
+modernize-shrink-to-fit
+=======================
+
+
+Replace copy and swap tricks on shrinkable containers with the
+``shrink_to_fit()`` method call.
+
+The ``shrink_to_fit()`` method is more readable and more effective than
+the copy and swap trick to reduce the capacity of a shrinkable container.
+Note that, the ``shrink_to_fit()`` method is only available in C++11 and up.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-unary-static-assert.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-unary-static-assert.rst
new file mode 100644
index 0000000..31ece10
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-unary-static-assert.rst
@@ -0,0 +1,25 @@
+.. title:: clang-tidy - modernize-unary-static-assert
+
+modernize-unary-static-assert
+=============================
+
+The check diagnoses any ``static_assert`` declaration with an empty string literal
+and provides a fix-it to replace the declaration with a single-argument ``static_assert`` declaration.
+
+The check is only applicable for C++17 and later code.
+
+The following code:
+
+.. code-block:: c++
+
+  void f_textless(int a) {
+    static_assert(sizeof(a) <= 10, "");
+  }
+
+is replaced by:
+
+.. code-block:: c++
+
+  void f_textless(int a) {
+    static_assert(sizeof(a) <= 10);
+  }
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-auto.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-auto.rst
new file mode 100644
index 0000000..a73e86e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-auto.rst
@@ -0,0 +1,233 @@
+.. title:: clang-tidy - modernize-use-auto
+
+modernize-use-auto
+==================
+
+This check is responsible for using the ``auto`` type specifier for variable
+declarations to *improve code readability and maintainability*. For example:
+
+.. code-block:: c++
+
+  std::vector<int>::iterator I = my_container.begin();
+
+  // transforms to:
+
+  auto I = my_container.begin();
+
+The ``auto`` type specifier will only be introduced in situations where the
+variable type matches the type of the initializer expression. In other words
+``auto`` should deduce the same type that was originally spelled in the source.
+However, not every situation should be transformed:
+
+.. code-block:: c++
+
+  int val = 42;
+  InfoStruct &I = SomeObject.getInfo();
+
+  // Should not become:
+
+  auto val = 42;
+  auto &I = SomeObject.getInfo();
+
+In this example using ``auto`` for builtins doesn't improve readability. In
+other situations it makes the code less self-documenting impairing readability
+and maintainability. As a result, ``auto`` is used only introduced in specific
+situations described below.
+
+Iterators
+---------
+
+Iterator type specifiers tend to be long and used frequently, especially in
+loop constructs. Since the functions generating iterators have a common format,
+the type specifier can be replaced without obscuring the meaning of code while
+improving readability and maintainability.
+
+.. code-block:: c++
+
+  for (std::vector<int>::iterator I = my_container.begin(),
+                                  E = my_container.end();
+       I != E; ++I) {
+  }
+
+  // becomes
+
+  for (auto I = my_container.begin(), E = my_container.end(); I != E; ++I) {
+  }
+
+The check will only replace iterator type-specifiers when all of the following
+conditions are satisfied:
+
+* The iterator is for one of the standard container in ``std`` namespace:
+
+  * ``array``
+  * ``deque``
+  * ``forward_list``
+  * ``list``
+  * ``vector``
+  * ``map``
+  * ``multimap``
+  * ``set``
+  * ``multiset``
+  * ``unordered_map``
+  * ``unordered_multimap``
+  * ``unordered_set``
+  * ``unordered_multiset``
+  * ``queue``
+  * ``priority_queue``
+  * ``stack``
+
+* The iterator is one of the possible iterator types for standard containers:
+
+  * ``iterator``
+  * ``reverse_iterator``
+  * ``const_iterator``
+  * ``const_reverse_iterator``
+
+* In addition to using iterator types directly, typedefs or other ways of
+  referring to those types are also allowed. However, implementation-specific
+  types for which a type like ``std::vector<int>::iterator`` is itself a
+  typedef will not be transformed. Consider the following examples:
+
+.. code-block:: c++
+
+  // The following direct uses of iterator types will be transformed.
+  std::vector<int>::iterator I = MyVec.begin();
+  {
+    using namespace std;
+    list<int>::iterator I = MyList.begin();
+  }
+
+  // The type specifier for J would transform to auto since it's a typedef
+  // to a standard iterator type.
+  typedef std::map<int, std::string>::const_iterator map_iterator;
+  map_iterator J = MyMap.begin();
+
+  // The following implementation-specific iterator type for which
+  // std::vector<int>::iterator could be a typedef would not be transformed.
+  __gnu_cxx::__normal_iterator<int*, std::vector> K = MyVec.begin();
+
+* The initializer for the variable being declared is not a braced initializer
+  list. Otherwise, use of ``auto`` would cause the type of the variable to be
+  deduced as ``std::initializer_list``.
+
+New expressions
+---------------
+
+Frequently, when a pointer is declared and initialized with ``new``, the
+pointee type is written twice: in the declaration type and in the
+``new`` expression. In this cases, the declaration type can be replaced with
+``auto`` improving readability and maintainability.
+
+.. code-block:: c++
+
+  TypeName *my_pointer = new TypeName(my_param);
+
+  // becomes
+
+  auto *my_pointer = new TypeName(my_param);
+
+The check will also replace the declaration type in multiple declarations, if
+the following conditions are satisfied:
+
+* All declared variables have the same type (i.e. all of them are pointers to
+  the same type).
+* All declared variables are initialized with a ``new`` expression.
+* The types of all the new expressions are the same than the pointee of the
+  declaration type.
+
+.. code-block:: c++
+
+  TypeName *my_first_pointer = new TypeName, *my_second_pointer = new TypeName;
+
+  // becomes
+
+  auto *my_first_pointer = new TypeName, *my_second_pointer = new TypeName;
+
+Cast expressions
+----------------
+
+Frequently, when a variable is declared and initialized with a cast, the
+variable type is written twice: in the declaration type and in the
+cast expression. In this cases, the declaration type can be replaced with
+``auto`` improving readability and maintainability.
+
+.. code-block:: c++
+
+  TypeName *my_pointer = static_cast<TypeName>(my_param);
+
+  // becomes
+
+  auto *my_pointer = static_cast<TypeName>(my_param);
+
+The check handles ``static_cast``, ``dynamic_cast``, ``const_cast``,
+``reinterpret_cast``, functional casts, C-style casts and function templates
+that behave as casts, such as ``llvm::dyn_cast``, ``boost::lexical_cast`` and
+``gsl::narrow_cast``.  Calls to function templates are considered to behave as
+casts if the first template argument is explicit and is a type, and the function
+returns that type, or a pointer or reference to it.
+
+Known Limitations
+-----------------
+
+* If the initializer is an explicit conversion constructor, the check will not
+  replace the type specifier even though it would be safe to do so.
+
+* User-defined iterators are not handled at this time.
+
+Options
+-------
+
+.. option:: MinTypeNameLength
+
+   If the option is set to non-zero (default `5`), the check will ignore type
+   names having a length less than the option value. The option affects
+   expressions only, not iterators.
+   Spaces between multi-lexeme type names (``long int``) are considered as one.
+   If ``RemoveStars`` option (see below) is set to non-zero, then ``*s`` in
+   the type are also counted as a part of the type name.
+
+.. code-block:: c++
+
+  // MinTypeNameLength = 0, RemoveStars=0
+
+  int a = static_cast<int>(foo());            // ---> auto a = ...
+  // length(bool *) = 4
+  bool *b = new bool;                         // ---> auto *b = ...
+  unsigned c = static_cast<unsigned>(foo());  // ---> auto c = ...
+
+  // MinTypeNameLength = 5, RemoveStars=0
+
+  int a = static_cast<int>(foo());                 // ---> int  a = ...
+  bool b = static_cast<bool>(foo());               // ---> bool b = ...
+  bool *pb = static_cast<bool*>(foo());            // ---> bool *pb = ...
+  unsigned c = static_cast<unsigned>(foo());       // ---> auto c = ...
+  // length(long <on-or-more-spaces> int) = 8
+  long int d = static_cast<long int>(foo());       // ---> auto d = ...
+
+  // MinTypeNameLength = 5, RemoveStars=1
+
+  int a = static_cast<int>(foo());                 // ---> int  a = ...
+  // length(int * * ) = 5
+  int **pa = static_cast<int**>(foo());            // ---> auto pa = ...
+  bool b = static_cast<bool>(foo());               // ---> bool b = ...
+  bool *pb = static_cast<bool*>(foo());            // ---> auto pb = ...
+  unsigned c = static_cast<unsigned>(foo());       // ---> auto c = ...
+  long int d = static_cast<long int>(foo());       // ---> auto d = ...
+
+.. option:: RemoveStars
+
+   If the option is set to non-zero (default is `0`), the check will remove
+   stars from the non-typedef pointer types when replacing type names with
+   ``auto``. Otherwise, the check will leave stars. For example:
+
+.. code-block:: c++
+
+  TypeName *my_first_pointer = new TypeName, *my_second_pointer = new TypeName;
+
+  // RemoveStars = 0
+
+  auto *my_first_pointer = new TypeName, *my_second_pointer = new TypeName;
+
+  // RemoveStars = 1
+
+  auto my_first_pointer = new TypeName, my_second_pointer = new TypeName;
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-bool-literals.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-bool-literals.rst
new file mode 100644
index 0000000..792d3a4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-bool-literals.rst
@@ -0,0 +1,28 @@
+.. title:: clang-tidy - modernize-use-bool-literals
+
+modernize-use-bool-literals
+===========================
+
+Finds integer literals which are cast to ``bool``.
+
+.. code-block:: c++
+
+  bool p = 1;
+  bool f = static_cast<bool>(1);
+  std::ios_base::sync_with_stdio(0);
+  bool x = p ? 1 : 0;
+
+  // transforms to
+
+  bool p = true;
+  bool f = true;
+  std::ios_base::sync_with_stdio(false);
+  bool x = p ? true : false;
+
+Options
+-------
+
+.. option:: IgnoreMacros
+
+   If set to non-zero, the check will not give warnings inside macros. Default
+   is `1`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-default-member-init.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-default-member-init.rst
new file mode 100644
index 0000000..6a199ec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-default-member-init.rst
@@ -0,0 +1,54 @@
+.. title:: clang-tidy - modernize-use-default-member-init
+
+modernize-use-default-member-init
+=================================
+
+This check converts a default constructor's member initializers into the new
+default member initializers in C++11. Other member initializers that match the
+default member initializer are removed. This can reduce repeated code or allow
+use of '= default'.
+
+.. code-block:: c++
+
+  struct A {
+    A() : i(5), j(10.0) {}
+    A(int i) : i(i), j(10.0) {}
+    int i;
+    double j;
+  };
+
+  // becomes
+
+  struct A {
+    A() {}
+    A(int i) : i(i) {}
+    int i{5};
+    double j{10.0};
+  };
+
+.. note::
+  Only converts member initializers for built-in types, enums, and pointers.
+  The `readability-redundant-member-init` check will remove redundant member
+  initializers for classes.
+
+Options
+-------
+
+.. option:: UseAssignment
+
+   If this option is set to non-zero (default is `0`), the check will initialise
+   members with an assignment. For example:
+
+.. code-block:: c++
+
+  struct A {
+    A() {}
+    A(int i) : i(i) {}
+    int i = 5;
+    double j = 10.0;
+  };
+
+.. option:: IgnoreMacros
+
+   If this option is set to non-zero (default is `1`), the check will not warn
+   about members declared inside macros.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-default.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-default.rst
new file mode 100644
index 0000000..ce58706
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-default.rst
@@ -0,0 +1,11 @@
+:orphan:
+
+.. title:: clang-tidy - modernize-use-default
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-use-equals-default.html
+
+modernize-use-default
+=====================
+
+This check has been renamed to
+`modernize-use-equals-default <modernize-use-equals-default.html>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-emplace.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-emplace.rst
new file mode 100644
index 0000000..533125e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-emplace.rst
@@ -0,0 +1,147 @@
+.. title:: clang-tidy - modernize-use-emplace
+
+modernize-use-emplace
+=====================
+
+The check flags insertions to an STL-style container done by calling the
+``push_back`` method with an explicitly-constructed temporary of the container
+element type. In this case, the corresponding ``emplace_back`` method
+results in less verbose and potentially more efficient code.
+Right now the check doesn't support ``push_front`` and ``insert``.
+It also doesn't support ``insert`` functions for associative containers
+because replacing ``insert`` with ``emplace`` may result in
+`speed regression <http://htmlpreview.github.io/?https://github.com/HowardHinnant/papers/blob/master/insert_vs_emplace.html>`_, but it might get support with some addition flag in the future.
+
+By default only ``std::vector``, ``std::deque``, ``std::list`` are considered.
+This list can be modified using the :option:`ContainersWithPushBack` option.
+
+Before:
+
+.. code-block:: c++
+
+    std::vector<MyClass> v;
+    v.push_back(MyClass(21, 37));
+
+    std::vector<std::pair<int, int>> w;
+
+    w.push_back(std::pair<int, int>(21, 37));
+    w.push_back(std::make_pair(21L, 37L));
+
+After:
+
+.. code-block:: c++
+
+    std::vector<MyClass> v;
+    v.emplace_back(21, 37);
+
+    std::vector<std::pair<int, int>> w;
+    w.emplace_back(21, 37);
+    w.emplace_back(21L, 37L);
+
+By default, the check is able to remove unnecessary ``std::make_pair`` and
+``std::make_tuple`` calls from ``push_back`` calls on containers of
+``std::pair`` and ``std::tuple``. Custom tuple-like types can be modified by
+the :option:`TupleTypes` option; custom make functions can be modified by the
+:option:`TupleMakeFunctions` option.
+
+The other situation is when we pass arguments that will be converted to a type
+inside a container.
+
+Before:
+
+.. code-block:: c++
+
+    std::vector<boost::optional<std::string> > v;
+    v.push_back("abc");
+
+After:
+
+.. code-block:: c++
+
+    std::vector<boost::optional<std::string> > v;
+    v.emplace_back("abc");
+
+
+In some cases the transformation would be valid, but the code wouldn't be
+exception safe. In this case the calls of ``push_back`` won't be replaced.
+
+.. code-block:: c++
+
+    std::vector<std::unique_ptr<int>> v;
+    v.push_back(std::unique_ptr<int>(new int(0)));
+    auto *ptr = new int(1);
+    v.push_back(std::unique_ptr<int>(ptr));
+
+This is because replacing it with ``emplace_back`` could cause a leak of this
+pointer if ``emplace_back`` would throw exception before emplacement (e.g. not
+enough memory to add a new element).
+
+For more info read item 42 - "Consider emplacement instead of insertion." of
+Scott Meyers "Effective Modern C++".
+
+The default smart pointers that are considered are ``std::unique_ptr``,
+``std::shared_ptr``, ``std::auto_ptr``. To specify other smart pointers or
+other classes use the :option:`SmartPointers` option.
+
+
+Check also doesn't fire if any argument of the constructor call would be:
+
+  - a bit-field (bit-fields can't bind to rvalue/universal reference)
+
+  - a ``new`` expression (to avoid leak)
+
+  - if the argument would be converted via derived-to-base cast.
+
+This check requires C++11 or higher to run.
+
+Options
+-------
+
+.. option:: ContainersWithPushBack
+
+   Semicolon-separated list of class names of custom containers that support
+   ``push_back``.
+
+.. option:: IgnoreImplicitConstructors
+
+    When non-zero, the check will ignore implicitly constructed arguments of
+    ``push_back``, e.g.
+
+    .. code-block:: c++
+
+        std::vector<std::string> v;
+        v.push_back("a"); // Ignored when IgnoreImplicitConstructors is ``1``.
+
+    Default is ``0``.
+
+.. option:: SmartPointers
+
+   Semicolon-separated list of class names of custom smart pointers.
+
+.. option:: TupleTypes
+
+    Semicolon-separated list of ``std::tuple``-like class names.
+
+.. option:: TupleMakeFunctions
+
+    Semicolon-separated list of ``std::make_tuple``-like function names. Those
+    function calls will be removed from ``push_back`` calls and turned into
+    ``emplace_back``.
+
+Example
+^^^^^^^
+
+.. code-block:: c++
+
+  std::vector<MyTuple<int, bool, char>> x;
+  x.push_back(MakeMyTuple(1, false, 'x'));
+
+transforms to:
+
+.. code-block:: c++
+
+  std::vector<MyTuple<int, bool, char>> x;
+  x.emplace_back(1, false, 'x');
+
+when :option:`TupleTypes` is set to ``MyTuple`` and :option:`TupleMakeFunctions`
+is set to ``MakeMyTuple``.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-equals-default.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-equals-default.rst
new file mode 100644
index 0000000..4b2368c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-equals-default.rst
@@ -0,0 +1,36 @@
+.. title:: clang-tidy - modernize-use-equals-default
+
+modernize-use-equals-default
+============================
+
+This check replaces default bodies of special member functions with ``=
+default;``. The explicitly defaulted function declarations enable more
+opportunities in optimization, because the compiler might treat explicitly
+defaulted functions as trivial.
+
+.. code-block:: c++
+
+  struct A {
+    A() {}
+    ~A();
+  };
+  A::~A() {}
+
+  // becomes
+
+  struct A {
+    A() = default;
+    ~A();
+  };
+  A::~A() = default;
+
+.. note::
+  Move-constructor and move-assignment operator are not supported yet.
+
+Options
+-------
+
+.. option:: IgnoreMacros
+
+   If set to non-zero, the check will not give warnings inside macros. Default
+   is `1`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-equals-delete.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-equals-delete.rst
new file mode 100644
index 0000000..bfa54e4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-equals-delete.rst
@@ -0,0 +1,25 @@
+.. title:: clang-tidy - modernize-use-equals-delete
+
+modernize-use-equals-delete
+===========================
+
+This check marks unimplemented private special member functions with ``= delete``.
+To avoid false-positives, this check only applies in a translation unit that has
+all other member functions implemented.
+
+.. code-block:: c++
+
+  struct A {
+  private:
+    A(const A&);
+    A& operator=(const A&);
+  };
+
+  // becomes
+
+  struct A {
+  private:
+    A(const A&) = delete;
+    A& operator=(const A&) = delete;
+  };
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-noexcept.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-noexcept.rst
new file mode 100644
index 0000000..084dad7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-noexcept.rst
@@ -0,0 +1,90 @@
+.. title:: clang-tidy - modernize-use-noexcept
+
+modernize-use-noexcept
+======================
+
+This check replaces deprecated dynamic exception specifications with
+the appropriate noexcept specification (introduced in C++11).  By
+default this check will replace ``throw()`` with ``noexcept``,
+and ``throw(<exception>[,...])`` or ``throw(...)`` with
+``noexcept(false)``.
+
+Example
+-------
+
+.. code-block:: c++
+
+  void foo() throw();
+	void bar() throw(int) {}
+
+transforms to:
+
+.. code-block:: c++
+
+  void foo() noexcept;
+	void bar() noexcept(false) {}
+
+Options
+-------
+
+.. option:: ReplacementString
+
+Users can use :option:`ReplacementString` to specify a macro to use
+instead of ``noexcept``.  This is useful when maintaining source code
+that uses custom exception specification marking other than
+``noexcept``.  Fix-it hints will only be generated for non-throwing
+specifications.
+
+Example
+^^^^^^^
+
+.. code-block:: c++
+
+  void bar() throw(int);
+  void foo() throw();
+
+transforms to:
+
+.. code-block:: c++
+
+  void bar() throw(int);  // No fix-it generated.
+  void foo() NOEXCEPT;
+
+if the :option:`ReplacementString` option is set to `NOEXCEPT`.
+
+.. option:: UseNoexceptFalse
+
+Enabled by default, disabling will generate fix-it hints that remove
+throwing dynamic exception specs, e.g., ``throw(<something>)``,
+completely without providing a replacement text, except for
+destructors and delete operators that are ``noexcept(true)`` by
+default.
+
+Example
+^^^^^^^
+
+.. code-block:: c++
+
+  void foo() throw(int) {}
+
+  struct bar {
+    void foobar() throw(int);
+    void operator delete(void *ptr) throw(int);
+    void operator delete[](void *ptr) throw(int);
+    ~bar() throw(int);
+  }
+
+transforms to:
+
+.. code-block:: c++
+
+  void foo() {}
+
+  struct bar {
+    void foobar();
+    void operator delete(void *ptr) noexcept(false);
+    void operator delete[](void *ptr) noexcept(false);
+    ~bar() noexcept(false);
+  }
+
+if the :option:`UseNoexceptFalse` option is set to `0`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-nullptr.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-nullptr.rst
new file mode 100644
index 0000000..e65b65b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-nullptr.rst
@@ -0,0 +1,67 @@
+.. title:: clang-tidy - modernize-use-nullptr
+
+modernize-use-nullptr
+=====================
+
+The check converts the usage of null pointer constants (eg. ``NULL``, ``0``)
+to use the new C++11 ``nullptr`` keyword.
+
+Example
+-------
+
+.. code-block:: c++
+
+  void assignment() {
+    char *a = NULL;
+    char *b = 0;
+    char c = 0;
+  }
+
+  int *ret_ptr() {
+    return 0;
+  }
+
+
+transforms to:
+
+.. code-block:: c++
+
+  void assignment() {
+    char *a = nullptr;
+    char *b = nullptr;
+    char c = 0;
+  }
+
+  int *ret_ptr() {
+    return nullptr;
+  }
+
+Options
+-------
+
+.. option:: NullMacros
+
+   Comma-separated list of macro names that will be transformed along with
+   ``NULL``. By default this check will only replace the ``NULL`` macro and will
+   skip any similar user-defined macros.
+
+Example
+^^^^^^^
+
+.. code-block:: c++
+
+  #define MY_NULL (void*)0
+  void assignment() {
+    void *p = MY_NULL;
+  }
+
+transforms to:
+
+.. code-block:: c++
+
+  #define MY_NULL NULL
+  void assignment() {
+    int *p = nullptr;
+  }
+
+if the :option:`NullMacros` option is set to ``MY_NULL``.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-override.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-override.rst
new file mode 100644
index 0000000..f2c778a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-override.rst
@@ -0,0 +1,7 @@
+.. title:: clang-tidy - modernize-use-override
+
+modernize-use-override
+======================
+
+
+Use C++11's ``override`` and remove ``virtual`` where applicable.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-transparent-functors.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-transparent-functors.rst
new file mode 100644
index 0000000..8887275
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-transparent-functors.rst
@@ -0,0 +1,39 @@
+.. title:: clang-tidy - modernize-use-transparent-functors
+
+modernize-use-transparent-functors
+==================================
+
+Prefer transparent functors to non-transparent ones. When using transparent
+functors, the type does not need to be repeated. The code is easier to read,
+maintain and less prone to errors. It is not possible to introduce unwanted
+conversions.
+
+  .. code-block:: c++
+
+    // Non-transparent functor
+    std::map<int, std::string, std::greater<int>> s;
+
+    // Transparent functor.
+    std::map<int, std::string, std::greater<>> s;
+
+    // Non-transparent functor
+    using MyFunctor = std::less<MyType>;
+
+It is not always a safe transformation though. The following case will be
+untouched to preserve the semantics.
+
+  .. code-block:: c++
+
+    // Non-transparent functor
+    std::map<const char *, std::string, std::greater<std::string>> s;
+
+Options
+-------
+
+.. option:: SafeMode
+
+  If the option is set to non-zero, the check will not diagnose cases where
+  using a transparent functor cannot be guaranteed to produce identical results
+  as the original code. The default value for this option is `0`.
+
+This check requires using C++14 or higher to run.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-uncaught-exceptions.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-uncaught-exceptions.rst
new file mode 100644
index 0000000..615f2e3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-uncaught-exceptions.rst
@@ -0,0 +1,64 @@
+.. title:: clang-tidy - modernize-use-uncaught-exceptions
+
+modernize-use-uncaught-exceptions
+====================================
+
+This check will warn on calls to ``std::uncaught_exception`` and replace them
+with calls to ``std::uncaught_exceptions``, since ``std::uncaught_exception``
+was deprecated in C++17.
+
+Below are a few examples of what kind of occurrences will be found and what
+they will be replaced with.
+
+.. code-block:: c++
+
+	#define MACRO1 std::uncaught_exception
+	#define MACRO2 std::uncaught_exception
+
+	int uncaught_exception() {
+		return 0;
+	}
+
+	int main() {
+		int res;
+
+	  res = uncaught_exception();
+	  // No warning, since it is not the deprecated function from namespace std
+	  
+	  res = MACRO2();
+	  // Warning, but will not be replaced
+	  
+	  res = std::uncaught_exception();
+	  // Warning and replaced
+	  
+	  using std::uncaught_exception;
+	  // Warning and replaced
+	  
+	  res = uncaught_exception();
+	  // Warning and replaced
+	}
+
+After applying the fixes the code will look like the following:
+
+.. code-block:: c++
+
+	#define MACRO1 std::uncaught_exception
+	#define MACRO2 std::uncaught_exception
+
+	int uncaught_exception() {
+		return 0;
+	}
+
+	int main() {
+	  int res;
+	  
+	  res = uncaught_exception();
+	  
+	  res = MACRO2();
+	  
+	  res = std::uncaught_exceptions();
+	  
+	  using std::uncaught_exceptions;
+	  
+	  res = uncaught_exceptions();
+	}
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-using.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-using.rst
new file mode 100644
index 0000000..1456a91
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize-use-using.rst
@@ -0,0 +1,34 @@
+.. title:: clang-tidy - modernize-use-using
+
+modernize-use-using
+===================
+
+The check converts the usage of ``typedef`` with ``using`` keyword.
+
+Before:
+
+.. code-block:: c++
+
+  typedef int variable;
+
+  class Class{};
+  typedef void (Class::* MyPtrType)() const;
+
+After:
+
+.. code-block:: c++
+
+  using variable = int;
+
+  class Class{};
+  using MyPtrType = void (Class::*)() const;
+
+This check requires using C++11 or higher to run.
+
+Options
+-------
+
+.. option:: IgnoreMacros
+
+   If set to non-zero, the check will not give warnings inside macros. Default
+   is `1`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/mpi-buffer-deref.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/mpi-buffer-deref.rst
new file mode 100644
index 0000000..ef9f391
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/mpi-buffer-deref.rst
@@ -0,0 +1,26 @@
+.. title:: clang-tidy - mpi-buffer-deref
+
+mpi-buffer-deref
+================
+
+This check verifies if a buffer passed to an MPI (Message Passing Interface)
+function is sufficiently dereferenced. Buffers should be passed as a single
+pointer or array. As MPI function signatures specify ``void *`` for their buffer
+types, insufficiently dereferenced buffers can be passed, like for example as
+double pointers or multidimensional arrays, without a compiler warning emitted.
+
+Examples:
+
+.. code-block:: c++
+
+   // A double pointer is passed to the MPI function.
+   char *buf;
+   MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+
+   // A multidimensional array is passed to the MPI function.
+   short buf[1][1];
+   MPI_Send(buf, 1, MPI_SHORT, 0, 0, MPI_COMM_WORLD);
+
+   // A pointer to an array is passed to the MPI function.
+   short *buf[1];
+   MPI_Send(buf, 1, MPI_SHORT, 0, 0, MPI_COMM_WORLD);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/mpi-type-mismatch.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/mpi-type-mismatch.rst
new file mode 100644
index 0000000..10752ef
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/mpi-type-mismatch.rst
@@ -0,0 +1,21 @@
+.. title:: clang-tidy - mpi-type-mismatch
+
+mpi-type-mismatch
+=================
+
+This check verifies if buffer type and MPI (Message Passing Interface) datatype
+pairs match for used MPI functions. All MPI datatypes defined by the MPI
+standard (3.1) are verified by this check. User defined typedefs, custom MPI
+datatypes and null pointer constants are skipped, in the course of verification.
+
+Example:
+
+.. code-block:: c++
+
+  // In this case, the buffer type matches MPI datatype.
+  char buf;
+  MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+
+  // In the following case, the buffer type does not match MPI datatype.
+  int buf;
+  MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/objc-avoid-nserror-init.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/objc-avoid-nserror-init.rst
new file mode 100644
index 0000000..265794c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/objc-avoid-nserror-init.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - objc-avoid-nserror-init
+
+objc-avoid-nserror-init
+=======================
+
+Finds improper initialization of ``NSError`` objects.
+
+According to Apple developer document, we should always use factory method 
+``errorWithDomain:code:userInfo:`` to create new NSError objects instead
+of ``[NSError alloc] init]``. Otherwise it will lead to a warning message
+during runtime.
+
+The corresponding information about ``NSError`` creation: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/CreateCustomizeNSError/CreateCustomizeNSError.html
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/objc-avoid-spinlock.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/objc-avoid-spinlock.rst
new file mode 100644
index 0000000..d1b11fc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/objc-avoid-spinlock.rst
@@ -0,0 +1,15 @@
+.. title:: clang-tidy - objc-avoid-spinlock
+
+objc-avoid-spinlock
+===================
+
+Finds usages of ``OSSpinlock``, which is deprecated due to potential livelock
+problems. 
+
+This check will detect following function invocations:
+
+- ``OSSpinlockLock``
+- ``OSSpinlockTry``
+- ``OSSpinlockUnlock``
+
+The corresponding information about the problem of ``OSSpinlock``: https://blog.postmates.com/why-spinlocks-are-bad-on-ios-b69fc5221058
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/objc-forbidden-subclassing.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/objc-forbidden-subclassing.rst
new file mode 100644
index 0000000..4bb023c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/objc-forbidden-subclassing.rst
@@ -0,0 +1,28 @@
+.. title:: clang-tidy - objc-forbidden-subclassing
+
+objc-forbidden-subclassing
+==========================
+
+Finds Objective-C classes which are subclasses of classes which are not designed
+to be subclassed.
+
+By default, includes a list of Objective-C classes which are publicly documented
+as not supporting subclassing.
+
+.. note::
+
+   Instead of using this check, for code under your control, you should add
+   ``__attribute__((objc_subclassing_restricted))`` before your ``@interface``
+   declarations to ensure the compiler prevents others from subclassing your
+   Objective-C classes.
+   See https://clang.llvm.org/docs/AttributeReference.html#objc-subclassing-restricted
+
+Options
+-------
+
+.. option:: ForbiddenSuperClassNames
+
+   Semicolon-separated list of names of Objective-C classes which
+   do not support subclassing.
+
+   Defaults to `ABNewPersonViewController;ABPeoplePickerNavigationController;ABPersonViewController;ABUnknownPersonViewController;NSHashTable;NSMapTable;NSPointerArray;NSPointerFunctions;NSTimer;UIActionSheet;UIAlertView;UIImagePickerController;UITextInputMode;UIWebView`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/objc-property-declaration.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/objc-property-declaration.rst
new file mode 100644
index 0000000..f851056
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/objc-property-declaration.rst
@@ -0,0 +1,69 @@
+.. title:: clang-tidy - objc-property-declaration
+
+objc-property-declaration
+=========================
+
+Finds property declarations in Objective-C files that do not follow the pattern
+of property names in Apple's programming guide. The property name should be
+in the format of Lower Camel Case.
+
+For code:
+
+.. code-block:: objc
+
+   @property(nonatomic, assign) int LowerCamelCase;
+
+The fix will be:
+
+.. code-block:: objc
+
+   @property(nonatomic, assign) int lowerCamelCase;
+
+The check will only fix 'CamelCase' to 'camelCase'. In some other cases we will
+only provide warning messages since the property name could be complicated.
+Users will need to come up with a proper name by their own.
+
+This check also accepts special acronyms as prefixes or suffixes. Such prefixes or suffixes
+will suppress the Lower Camel Case check according to the guide:
+https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingBasics.html#//apple_ref/doc/uid/20001281-1002931-BBCFHEAB
+
+For a full list of well-known acronyms:
+https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/APIAbbreviations.html#//apple_ref/doc/uid/20001285-BCIHCGAE
+
+The corresponding style rule: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingIvarsAndTypes.html#//apple_ref/doc/uid/20001284-1001757
+
+The check will also accept property declared in category with a prefix of
+lowercase letters followed by a '_' to avoid naming conflict. For example:
+
+.. code-block:: objc
+
+   @property(nonatomic, assign) int abc_lowerCamelCase;
+
+The corresponding style rule: https://developer.apple.com/library/content/qa/qa1908/_index.html
+
+
+Options
+-------
+
+.. option:: Acronyms
+
+   Semicolon-separated list of custom acronyms that can be used as a prefix
+   or a suffix of property names.
+
+   By default, appends to the list of default acronyms (
+   ``IncludeDefaultAcronyms`` set to ``1``).
+   If ``IncludeDefaultAcronyms`` is set to ``0``, instead replaces the
+   default list of acronyms.
+
+.. option:: IncludeDefaultAcronyms
+
+   Integer value (defaults to ``1``) to control whether the default
+   acronyms are included in the list of acronyms.
+
+   If set to ``1``, the value in ``Acronyms`` is appended to the
+   default list of acronyms:
+
+   ``ACL;API;ARGB;ASCII;BGRA;CMYK;DNS;FPS;FTP;GIF;GPS;HD;HDR;HTML;HTTP;HTTPS;HUD;ID;JPG;JS;LAN;LZW;MDNS;MIDI;OS;PDF;PIN;PNG;POI;PSTN;PTR;QA;QOS;RGB;RGBA;RGBX;ROM;RPC;RTF;RTL;SDK;SSO;TCP;TIFF;TTS;UI;URI;URL;VC;VOIP;VPN;VR;WAN;XML``.
+
+   If set to ``0``, the value in ``Acronyms`` replaces the default list
+   of acronyms.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-faster-string-find.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-faster-string-find.rst
new file mode 100644
index 0000000..8d7265e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-faster-string-find.rst
@@ -0,0 +1,28 @@
+.. title:: clang-tidy - performance-faster-string-find
+
+performance-faster-string-find
+==============================
+
+Optimize calls to ``std::string::find()`` and friends when the needle passed is
+a single character string literal. The character literal overload is more
+efficient.
+
+Examples:
+
+.. code-block:: c++
+
+  str.find("A");
+
+  // becomes
+
+  str.find('A');
+
+Options
+-------
+
+.. option:: StringLikeClasses
+
+   Semicolon-separated list of names of string-like classes. By default only
+   ``std::basic_string`` is considered. The list of methods to consired is
+   fixed.
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-for-range-copy.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-for-range-copy.rst
new file mode 100644
index 0000000..2e7db98
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-for-range-copy.rst
@@ -0,0 +1,27 @@
+.. title:: clang-tidy - performance-for-range-copy
+
+performance-for-range-copy
+==========================
+
+Finds C++11 for ranges where the loop variable is copied in each iteration but
+it would suffice to obtain it by const reference.
+
+The check is only applied to loop variables of types that are expensive to copy
+which means they are not trivially copyable or have a non-trivial copy
+constructor or destructor.
+
+To ensure that it is safe to replace the copy with a const reference the
+following heuristic is employed:
+
+1. The loop variable is const qualified.
+2. The loop variable is not const, but only const methods or operators are
+   invoked on it, or it is used as const reference or value argument in
+   constructors or function calls.
+
+Options
+-------
+
+.. option:: WarnOnAllAutoCopies
+
+   When non-zero, warns on any use of `auto` as the type of the range-based for
+   loop variable. Default is `0`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-implicit-cast-in-loop.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-implicit-cast-in-loop.rst
new file mode 100644
index 0000000..280e7c0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-implicit-cast-in-loop.rst
@@ -0,0 +1,12 @@
+:orphan:
+
+.. title:: clang-tidy - performance-implicit-cast-in-loop
+.. meta::
+   :http-equiv=refresh: 5;URL=performance-implicit-conversion-in-loop.html
+
+performance-implicit-cast-in-loop
+=================================
+
+This check has been renamed to `performance-implicit-conversion-in-loop
+<performance-implicit-conversion-in-loop.html>`_.
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-implicit-conversion-in-loop.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-implicit-conversion-in-loop.rst
new file mode 100644
index 0000000..14e4d31
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-implicit-conversion-in-loop.rst
@@ -0,0 +1,21 @@
+.. title:: clang-tidy - performance-implicit-conversion-in-loop
+
+performance-implicit-conversion-in-loop
+=======================================
+
+This warning appears in a range-based loop with a loop variable of const ref
+type where the type of the variable does not match the one returned by the
+iterator. This means that an implicit conversion happens, which can for example
+result in expensive deep copies.
+
+Example:
+
+.. code-block:: c++
+
+  map<int, vector<string>> my_map;
+  for (const pair<int, vector<string>>& p : my_map) {}
+  // The iterator type is in fact pair<const int, vector<string>>, which means
+  // that the compiler added a conversion, resulting in a copy of the vectors.
+
+The easiest solution is usually to use ``const auto&`` instead of writing the
+type manually.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-algorithm.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-algorithm.rst
new file mode 100644
index 0000000..7002744
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-algorithm.rst
@@ -0,0 +1,29 @@
+.. title:: clang-tidy - performance-inefficient-algorithm
+
+performance-inefficient-algorithm
+=================================
+
+
+Warns on inefficient use of STL algorithms on associative containers.
+
+Associative containers implements some of the algorithms as methods which
+should be preferred to the algorithms in the algorithm header. The methods
+can take advanatage of the order of the elements.
+
+.. code-block:: c++
+
+  std::set<int> s;
+  auto it = std::find(s.begin(), s.end(), 43);
+
+  // becomes
+
+  auto it = s.find(43);
+
+.. code-block:: c++
+
+  std::set<int> s;
+  auto c = std::count(s.begin(), s.end(), 43);
+
+  // becomes
+
+  auto c = s.count(43);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-string-concatenation.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-string-concatenation.rst
new file mode 100644
index 0000000..60910c6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-string-concatenation.rst
@@ -0,0 +1,59 @@
+.. title:: clang-tidy - performance-inefficient-string-concatenation
+
+performance-inefficient-string-concatenation
+============================================
+
+This check warns about the performance overhead arising from concatenating
+strings using the ``operator+``, for instance:
+
+.. code-block:: c++
+
+    std::string a("Foo"), b("Bar");
+    a = a + b;
+
+Instead of this structure you should use ``operator+=`` or ``std::string``'s
+(``std::basic_string``) class member function ``append()``. For instance:
+
+.. code-block:: c++
+
+   std::string a("Foo"), b("Baz");
+   for (int i = 0; i < 20000; ++i) {
+       a = a + "Bar" + b;
+   }
+
+Could be rewritten in a greatly more efficient way like:
+
+.. code-block:: c++
+
+   std::string a("Foo"), b("Baz");
+   for (int i = 0; i < 20000; ++i) {
+       a.append("Bar").append(b);
+   }
+
+And this can be rewritten too:
+
+.. code-block:: c++
+
+   void f(const std::string&) {}
+   std::string a("Foo"), b("Baz");
+   void g() {
+       f(a + "Bar" + b);
+   }
+
+In a slightly more efficient way like:
+
+.. code-block:: c++
+
+   void f(const std::string&) {}
+   std::string a("Foo"), b("Baz");
+   void g() {
+       f(std::string(a).append("Bar").append(b));
+   }
+
+Options
+-------
+
+.. option:: StrictMode
+
+   When zero, the check will only check the string usage in ``while``, ``for``
+   and ``for-range`` statements. Default is `0`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-vector-operation.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
new file mode 100644
index 0000000..8cf9318
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
@@ -0,0 +1,49 @@
+.. title:: clang-tidy - performance-inefficient-vector-operation
+
+performance-inefficient-vector-operation
+========================================
+
+Finds possible inefficient ``std::vector`` operations (e.g. ``push_back``,
+``emplace_back``) that may cause unnecessary memory reallocations.
+
+Currently, the check only detects following kinds of loops with a single
+statement body:
+
+* Counter-based for loops start with 0:
+
+.. code-block:: c++
+
+  std::vector<int> v;
+  for (int i = 0; i < n; ++i) {
+    v.push_back(n);
+    // This will trigger the warning since the push_back may cause multiple
+    // memory reallocations in v. This can be avoid by inserting a 'reserve(n)'
+    // statement before the for statement.
+  }
+
+
+* For-range loops like ``for (range-declaration : range_expression)``, the type
+  of ``range_expression`` can be ``std::vector``, ``std::array``,
+  ``std::deque``, ``std::set``, ``std::unordered_set``, ``std::map``,
+  ``std::unordered_set``:
+
+.. code-block:: c++
+
+  std::vector<int> data;
+  std::vector<int> v;
+
+  for (auto element : data) {
+    v.push_back(element);
+    // This will trigger the warning since the 'push_back' may cause multiple
+    // memory reallocations in v. This can be avoid by inserting a
+    // 'reserve(data.size())' statement before the for statement.
+  }
+
+
+Options
+-------
+
+.. option:: VectorLikeClasses
+
+   Semicolon-separated list of names of vector-like classes. By default only
+   ``::std::vector`` is considered.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-move-const-arg.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-move-const-arg.rst
new file mode 100644
index 0000000..39e1ca4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-move-const-arg.rst
@@ -0,0 +1,37 @@
+.. title:: clang-tidy - performance-move-const-arg
+
+performance-move-const-arg
+==========================
+
+The check warns
+
+- if ``std::move()`` is called with a constant argument,
+
+- if ``std::move()`` is called with an argument of a trivially-copyable type,
+
+- if the result of ``std::move()`` is passed as a const reference argument.
+
+In all three cases, the check will suggest a fix that removes the
+``std::move()``.
+
+Here are examples of each of the three cases:
+
+.. code-block:: c++
+
+  const string s;
+  return std::move(s);  // Warning: std::move of the const variable has no effect
+
+  int x;
+  return std::move(x);  // Warning: std::move of the variable of a trivially-copyable type has no effect
+
+  void f(const string &s);
+  string s;
+  f(std::move(s));  // Warning: passing result of std::move as a const reference argument; no move will actually happen
+
+Options
+-------
+
+.. option:: CheckTriviallyCopyableMove
+
+   If non-zero, enables detection of trivially copyable types that do not
+   have a move constructor. Default is non-zero.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-move-constructor-init.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-move-constructor-init.rst
new file mode 100644
index 0000000..a193b9e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-move-constructor-init.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - performance-move-constructor-init
+
+performance-move-constructor-init
+=================================
+
+"cert-oop11-cpp" redirects here as an alias for this check.
+
+The check flags user-defined move constructors that have a ctor-initializer
+initializing a member or base class through a copy constructor instead of a
+move constructor.
+
+Options
+-------
+
+.. option:: IncludeStyle
+
+   A string specifying which include-style is used, `llvm` or `google`. Default
+   is `llvm`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-noexcept-move-constructor.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-noexcept-move-constructor.rst
new file mode 100644
index 0000000..05f1d85
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-noexcept-move-constructor.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - performance-noexcept-move-constructor
+
+performance-noexcept-move-constructor
+=====================================
+
+
+The check flags user-defined move constructors and assignment operators not
+marked with ``noexcept`` or marked with ``noexcept(expr)`` where ``expr``
+evaluates to ``false`` (but is not a ``false`` literal itself).
+
+Move constructors of all the types used with STL containers, for example,
+need to be declared ``noexcept``. Otherwise STL will choose copy constructors
+instead. The same is valid for move assignment operations.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-type-promotion-in-math-fn.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-type-promotion-in-math-fn.rst
new file mode 100644
index 0000000..a27a482
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-type-promotion-in-math-fn.rst
@@ -0,0 +1,21 @@
+.. title:: clang-tidy - performance-type-promotion-in-math-fn
+
+performance-type-promotion-in-math-fn
+=====================================
+
+Finds calls to C math library functions (from ``math.h`` or, in C++, ``cmath``)
+with implicit ``float`` to ``double`` promotions.
+
+For example, warns on ``::sin(0.f)``, because this funciton's parameter is a
+double. You probably meant to call ``std::sin(0.f)`` (in C++), or ``sinf(0.f)``
+(in C).
+
+.. code-block:: c++
+
+  float a;
+  asin(a);
+
+  // becomes
+
+  float a;
+  std::asin(a);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-unnecessary-copy-initialization.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-unnecessary-copy-initialization.rst
new file mode 100644
index 0000000..2bd7755
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-unnecessary-copy-initialization.rst
@@ -0,0 +1,37 @@
+.. title:: clang-tidy - performance-unnecessary-copy-initialization
+
+performance-unnecessary-copy-initialization
+===========================================
+
+Finds local variable declarations that are initialized using the copy
+constructor of a non-trivially-copyable type but it would suffice to obtain a
+const reference.
+
+The check is only applied if it is safe to replace the copy by a const
+reference. This is the case when the variable is const qualified or when it is
+only used as a const, i.e. only const methods or operators are invoked on it, or
+it is used as const reference or value argument in constructors or function
+calls.
+
+Example:
+
+.. code-block:: c++
+
+  const string& constReference();
+  void Function() {
+    // The warning will suggest making this a const reference.
+    const string UnnecessaryCopy = constReference();
+  }
+
+  struct Foo {
+    const string& name() const;
+  };
+  void Function(const Foo& foo) {
+    // The warning will suggest making this a const reference.
+    string UnnecessaryCopy1 = foo.name();
+    UnnecessaryCopy1.find("bar");
+
+    // The warning will suggest making this a const reference.
+    string UnnecessaryCopy2 = UnnecessaryCopy1;
+    UnnecessaryCopy2.find("bar");
+  }
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-unnecessary-value-param.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-unnecessary-value-param.rst
new file mode 100644
index 0000000..e69610e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/performance-unnecessary-value-param.rst
@@ -0,0 +1,63 @@
+.. title:: clang-tidy - performance-unnecessary-value-param
+
+performance-unnecessary-value-param
+===================================
+
+Flags value parameter declarations of expensive to copy types that are copied
+for each invocation but it would suffice to pass them by const reference.
+
+The check is only applied to parameters of types that are expensive to copy
+which means they are not trivially copyable or have a non-trivial copy
+constructor or destructor.
+
+To ensure that it is safe to replace the value parameter with a const reference
+the following heuristic is employed:
+
+1. the parameter is const qualified;
+2. the parameter is not const, but only const methods or operators are invoked
+   on it, or it is used as const reference or value argument in constructors or
+   function calls.
+
+Example:
+
+.. code-block:: c++
+
+  void f(const string Value) {
+    // The warning will suggest making Value a reference.
+  }
+
+  void g(ExpensiveToCopy Value) {
+    // The warning will suggest making Value a const reference.
+    Value.ConstMethd();
+    ExpensiveToCopy Copy(Value);
+  }
+
+If the parameter is not const, only copied or assigned once and has a
+non-trivial move-constructor or move-assignment operator respectively the check
+will suggest to move it.
+
+Example:
+
+.. code-block:: c++
+
+  void setValue(string Value) {
+    Field = Value;
+  }
+
+Will become:
+
+.. code-block:: c++
+
+  #include <utility>
+
+  void setValue(string Value) {
+    Field = std::move(Value);
+  }
+
+Options
+-------
+
+.. option:: IncludeStyle
+
+   A string specifying which include-style is used, `llvm` or `google`. Default
+   is `llvm`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/portability-simd-intrinsics.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/portability-simd-intrinsics.rst
new file mode 100644
index 0000000..2cd9d9f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/portability-simd-intrinsics.rst
@@ -0,0 +1,49 @@
+.. title:: clang-tidy - portability-simd-intrinsics
+
+portability-simd-intrinsics
+===========================
+
+Finds SIMD intrinsics calls and suggests ``std::experimental::simd`` (`P0214`_)
+alternatives.
+
+If the option ``Suggest`` is set to non-zero, for
+
+.. code-block:: c++
+
+  _mm_add_epi32(a, b); // x86
+  vec_add(a, b);       // Power
+
+the check suggests an alternative: ``operator+`` on ``std::experimental::simd``
+objects.
+
+Otherwise, it just complains the intrinsics are non-portable (and there are
+`P0214`_ alternatives).
+
+Many architectures provide SIMD operations (e.g. x86 SSE/AVX, Power AltiVec/VSX,
+ARM NEON). It is common that SIMD code implementing the same algorithm, is
+written in multiple target-dispatching pieces to optimize for different
+architectures or micro-architectures.
+
+The C++ standard proposal `P0214`_ and its extensions cover many common SIMD
+operations. By migrating from target-dependent intrinsics to `P0214`_
+operations, the SIMD code can be simplified and pieces for different targets can
+be unified.
+
+Refer to `P0214`_ for introduction and motivation for the data-parallel standard
+library.
+
+Options
+-------
+
+.. option:: Suggest
+
+   If this option is set to non-zero (default is `0`), the check will suggest
+   `P0214`_ alternatives, otherwise it only points out the intrinsic function is
+   non-portable.
+
+.. option:: Std
+
+   The namespace used to suggest `P0214`_ alternatives. If not specified, `std::`
+   for `-std=c++2a` and `std::experimental::` for `-std=c++11`.
+
+.. _P0214: http://wg21.link/p0214
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-avoid-const-params-in-decls.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-avoid-const-params-in-decls.rst
new file mode 100644
index 0000000..3aea5d0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-avoid-const-params-in-decls.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - readability-avoid-const-params-in-decls
+
+readability-avoid-const-params-in-decls
+=======================================
+
+Checks whether a function declaration has parameters that are top level
+``const``.
+
+``const`` values in declarations do not affect the signature of a function, so
+they should not be put there.
+
+Examples:
+
+.. code-block:: c++
+
+  void f(const string);   // Bad: const is top level.
+  void f(const string&);  // Good: const is not top level.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-braces-around-statements.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-braces-around-statements.rst
new file mode 100644
index 0000000..2c08165
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-braces-around-statements.rst
@@ -0,0 +1,38 @@
+.. title:: clang-tidy - readability-braces-around-statements
+
+readability-braces-around-statements
+====================================
+
+`google-readability-braces-around-statements` redirects here as an alias for
+this check.
+
+Checks that bodies of ``if`` statements and loops (``for``, ``do while``, and
+``while``) are inside braces.
+
+Before:
+
+.. code-block:: c++
+
+  if (condition)
+    statement;
+
+After:
+
+.. code-block:: c++
+
+  if (condition) {
+    statement;
+  }
+
+Options
+-------
+
+.. option:: ShortStatementLines
+
+   Defines the minimal number of lines that the statement should have in order
+   to trigger this check.
+
+   The number of lines is counted from the end of condition or initial keyword
+   (``do``/``else``) until the last line of the inner statement. Default value
+   `0` means that braces will be added to all statements (not having them
+   already).
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-container-size-empty.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-container-size-empty.rst
new file mode 100644
index 0000000..541320c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-container-size-empty.rst
@@ -0,0 +1,26 @@
+.. title:: clang-tidy - readability-container-size-empty
+
+readability-container-size-empty
+================================
+
+
+Checks whether a call to the ``size()`` method can be replaced with a call to
+``empty()``.
+
+The emptiness of a container should be checked using the ``empty()`` method
+instead of the ``size()`` method. It is not guaranteed that ``size()`` is a
+constant-time function, and it is generally more efficient and also shows
+clearer intent to use ``empty()``. Furthermore some containers may implement
+the ``empty()`` method but not implement the ``size()`` method. Using
+``empty()`` whenever possible makes it easier to switch to another container in
+the future.
+
+The check issues warning if a container has ``size()`` and ``empty()`` methods
+matching following signatures:
+
+.. code-block:: c++
+
+  size_type size() const;
+  bool empty() const;
+
+`size_type` can be any kind of integer type.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-delete-null-pointer.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-delete-null-pointer.rst
new file mode 100644
index 0000000..21c91b4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-delete-null-pointer.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - readability-delete-null-pointer
+
+readability-delete-null-pointer
+===============================
+
+Checks the ``if`` statements where a pointer's existence is checked and then deletes the pointer.
+The check is unnecessary as deleting a null pointer has no effect.
+
+.. code:: c++
+
+  int *p;
+  if (p)
+    delete p;
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-deleted-default.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-deleted-default.rst
new file mode 100644
index 0000000..00134eb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-deleted-default.rst
@@ -0,0 +1,22 @@
+.. title:: clang-tidy - readability-deleted-default
+
+readability-deleted-default
+===========================
+
+Checks that constructors and assignment operators marked as ``= default`` are
+not actually deleted by the compiler.
+
+.. code-block:: c++
+
+  class Example {
+  public:
+    // This constructor is deleted because I is missing a default value.
+    Example() = default;
+    // This is fine.
+    Example(const Example& Other) = default;
+    // This operator is deleted because I cannot be assigned (it is const).
+    Example& operator=(const Example& Other) = default;
+
+  private:
+    const int I;
+  };
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-else-after-return.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-else-after-return.rst
new file mode 100644
index 0000000..949b5bb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-else-after-return.rst
@@ -0,0 +1,64 @@
+.. title:: clang-tidy - readability-else-after-return
+
+readability-else-after-return
+=============================
+
+`LLVM Coding Standards <http://llvm.org/docs/CodingStandards.html>`_ advises to
+reduce indentation where possible and where it makes understanding code easier.
+Early exit is one of the suggested enforcements of that. Please do not use
+``else`` or ``else if`` after something that interrupts control flow - like
+``return``, ``break``, ``continue``, ``throw``.
+
+The following piece of code illustrates how the check works. This piece of code:
+
+.. code-block:: c++
+
+    void foo(int Value) {
+      int Local = 0;
+      for (int i = 0; i < 42; i++) {
+        if (Value == 1) {
+          return;
+        } else {
+          Local++;
+        }
+
+        if (Value == 2)
+          continue;
+        else
+          Local++;
+
+        if (Value == 3) {
+          throw 42;
+        } else {
+          Local++;
+        }
+      }
+    }
+
+
+Would be transformed into:
+
+.. code-block:: c++
+
+    void foo(int Value) {
+      int Local = 0;
+      for (int i = 0; i < 42; i++) {
+        if (Value == 1) {
+          return;
+        }
+        Local++;
+
+        if (Value == 2)
+          continue;
+        Local++;
+
+        if (Value == 3) {
+          throw 42;
+        }
+        Local++;
+      }
+    }
+
+
+This check helps to enforce this `LLVM Coding Standards recommendation
+<http://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-function-size.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-function-size.rst
new file mode 100644
index 0000000..3360fbd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-function-size.rst
@@ -0,0 +1,45 @@
+.. title:: clang-tidy - readability-function-size
+
+readability-function-size
+=========================
+
+`google-readability-function-size` redirects here as an alias for this check.
+
+Checks for large functions based on various metrics.
+
+Options
+-------
+
+.. option:: LineThreshold
+
+   Flag functions exceeding this number of lines. The default is `-1` (ignore
+   the number of lines).
+
+.. option:: StatementThreshold
+
+   Flag functions exceeding this number of statements. This may differ
+   significantly from the number of lines for macro-heavy code. The default is
+   `800`.
+
+.. option:: BranchThreshold
+
+   Flag functions exceeding this number of control statements. The default is
+   `-1` (ignore the number of branches).
+
+.. option:: ParameterThreshold
+
+   Flag functions that exceed a specified number of parameters. The default
+   is `-1` (ignore the number of parameters).
+
+.. option:: NestingThreshold
+
+    Flag compound statements which create next nesting level after
+    `NestingThreshold`. This may differ significantly from the expected value
+    for macro-heavy code. The default is `-1` (ignore the nesting level).
+
+.. option:: VariableThreshold
+
+   Flag functions exceeding this number of variables declared in the body.
+   The default is `-1` (ignore the number of variables).
+   Please note that function parameters and variables declared in lambdas,
+   GNU Statement Expressions, and nested class inline functions are not counted.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-identifier-naming.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-identifier-naming.rst
new file mode 100644
index 0000000..30408c1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-identifier-naming.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - readability-identifier-naming
+
+readability-identifier-naming
+=============================
+
+Checks for identifiers naming style mismatch.
+
+This check will try to enforce coding guidelines on the identifiers naming.
+It supports `lower_case`, `UPPER_CASE`, `camelBack` and `CamelCase` casing and
+tries to convert from one to another if a mismatch is detected.
+
+It also supports a fixed prefix and suffix that will be prepended or
+appended to the identifiers, regardless of the casing.
+
+Many configuration options are available, in order to be able to create
+different rules for different kind of identifier. In general, the
+rules are falling back to a more generic rule if the specific case is not
+configured.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-implicit-bool-cast.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-implicit-bool-cast.rst
new file mode 100644
index 0000000..a6a3492
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-implicit-bool-cast.rst
@@ -0,0 +1,11 @@
+:orphan:
+
+.. title:: clang-tidy - readability-implicit-bool-cast
+.. meta::
+   :http-equiv=refresh: 5;URL=readability-implicit-bool-conversion.html
+
+readability-implicit-bool-cast
+==============================
+
+This check has been renamed to `readability-implicit-bool-conversion
+<readability-implicit-bool-conversion.html>`_.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-implicit-bool-conversion.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-implicit-bool-conversion.rst
new file mode 100644
index 0000000..64f3f73
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-implicit-bool-conversion.rst
@@ -0,0 +1,132 @@
+.. title:: clang-tidy - readability-implicit-bool-conversion
+
+readability-implicit-bool-conversion
+====================================
+
+This check can be used to find implicit conversions between built-in types and
+booleans. Depending on use case, it may simply help with readability of the code,
+or in some cases, point to potential bugs which remain unnoticed due to implicit
+conversions.
+
+The following is a real-world example of bug which was hiding behind implicit
+``bool`` conversion:
+
+.. code-block:: c++
+
+  class Foo {
+    int m_foo;
+
+  public:
+    void setFoo(bool foo) { m_foo = foo; } // warning: implicit conversion bool -> int
+    int getFoo() { return m_foo; }
+  };
+
+  void use(Foo& foo) {
+    bool value = foo.getFoo(); // warning: implicit conversion int -> bool
+  }
+
+This code is the result of unsuccessful refactoring, where type of ``m_foo``
+changed from ``bool`` to ``int``. The programmer forgot to change all
+occurrences of ``bool``, and the remaining code is no longer correct, yet it
+still compiles without any visible warnings.
+
+In addition to issuing warnings, fix-it hints are provided to help solve the
+reported issues. This can be used for improving readability of code, for
+example:
+
+.. code-block:: c++
+
+  void conversionsToBool() {
+    float floating;
+    bool boolean = floating;
+    // ^ propose replacement: bool boolean = floating != 0.0f;
+
+    int integer;
+    if (integer) {}
+    // ^ propose replacement: if (integer != 0) {}
+
+    int* pointer;
+    if (!pointer) {}
+    // ^ propose replacement: if (pointer == nullptr) {}
+
+    while (1) {}
+    // ^ propose replacement: while (true) {}
+  }
+
+  void functionTakingInt(int param);
+
+  void conversionsFromBool() {
+    bool boolean;
+    functionTakingInt(boolean);
+    // ^ propose replacement: functionTakingInt(static_cast<int>(boolean));
+
+    functionTakingInt(true);
+    // ^ propose replacement: functionTakingInt(1);
+  }
+
+In general, the following conversion types are checked:
+
+- integer expression/literal to boolean,
+
+- floating expression/literal to boolean,
+
+- pointer/pointer to member/``nullptr``/``NULL`` to boolean,
+
+- boolean expression/literal to integer,
+
+- boolean expression/literal to floating.
+
+The rules for generating fix-it hints are:
+
+- in case of conversions from other built-in type to bool, an explicit
+  comparison is proposed to make it clear what exaclty is being compared:
+
+  - ``bool boolean = floating;`` is changed to
+    ``bool boolean = floating == 0.0f;``,
+
+  - for other types, appropriate literals are used (``0``, ``0u``, ``0.0f``,
+    ``0.0``, ``nullptr``),
+
+- in case of negated expressions conversion to bool, the proposed replacement
+  with comparison is simplified:
+
+  - ``if (!pointer)`` is changed to ``if (pointer == nullptr)``,
+
+- in case of conversions from bool to other built-in types, an explicit
+  ``static_cast`` is proposed to make it clear that a conversion is taking
+  place:
+
+  - ``int integer = boolean;`` is changed to
+    ``int integer = static_cast<int>(boolean);``,
+
+- if the conversion is performed on type literals, an equivalent literal is
+  proposed, according to what type is actually expected, for example:
+
+  - ``functionTakingBool(0);`` is changed to ``functionTakingBool(false);``,
+
+  - ``functionTakingInt(true);`` is changed to ``functionTakingInt(1);``,
+
+  - for other types, appropriate literals are used (``false``, ``true``, ``0``,
+    ``1``, ``0u``, ``1u``, ``0.0f``, ``1.0f``, ``0.0``, ``1.0f``).
+
+Some additional accommodations are made for pre-C++11 dialects:
+
+- ``false`` literal conversion to pointer is detected,
+
+- instead of ``nullptr`` literal, ``0`` is proposed as replacement.
+
+Occurrences of implicit conversions inside macros and template instantiations
+are deliberately ignored, as it is not clear how to deal with such cases.
+
+Options
+-------
+
+.. option::  AllowIntegerConditions
+
+   When non-zero, the check will allow conditional integer conversions. Default
+   is `0`.
+
+.. option::  AllowPointerConditions
+
+   When non-zero, the check will allow conditional pointer conversions. Default
+   is `0`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-inconsistent-declaration-parameter-name.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-inconsistent-declaration-parameter-name.rst
new file mode 100644
index 0000000..a47bb41
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-inconsistent-declaration-parameter-name.rst
@@ -0,0 +1,63 @@
+.. title:: clang-tidy - readability-inconsistent-declaration-parameter-name
+
+readability-inconsistent-declaration-parameter-name
+===================================================
+
+Find function declarations which differ in parameter names.
+
+Example:
+
+.. code-block:: c++
+
+  // in foo.hpp:
+  void foo(int a, int b, int c);
+
+  // in foo.cpp:
+  void foo(int d, int e, int f); // warning
+
+This check should help to enforce consistency in large projects, where it often
+happens that a definition of function is refactored, changing the parameter
+names, but its declaration in header file is not updated. With this check, we
+can easily find and correct such inconsistencies, keeping declaration and
+definition always in sync.
+
+Unnamed parameters are allowed and are not taken into account when comparing
+function declarations, for example:
+
+.. code-block:: c++
+
+  void foo(int a);
+  void foo(int); // no warning
+
+One name is also allowed to be a case-insensitive prefix/suffix of the other:
+
+.. code-block:: c++
+
+  void foo(int count);
+  void foo(int count_input) { // no warning
+    int count = adjustCount(count_input);
+  }
+
+To help with refactoring, in some cases fix-it hints are generated to align
+parameter names to a single naming convention. This works with the assumption
+that the function definition is the most up-to-date version, as it directly
+references parameter names in its body. Example:
+
+.. code-block:: c++
+
+  void foo(int a); // warning and fix-it hint (replace "a" to "b")
+  int foo(int b) { return b + 2; } // definition with use of "b"
+
+In the case of multiple redeclarations or function template specializations,
+a warning is issued for every redeclaration or specialization inconsistent with
+the definition or the first declaration seen in a translation unit.
+
+.. option:: IgnoreMacros
+
+   If this option is set to non-zero (default is `1`), the check will not warn
+   about names declared inside macros.
+
+.. option:: Strict
+
+   If this option is set to non-zero (default is `0`), then names must match
+   exactly (or be absent).
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-misleading-indentation.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-misleading-indentation.rst
new file mode 100644
index 0000000..5d52c77
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-misleading-indentation.rst
@@ -0,0 +1,38 @@
+.. title:: clang-tidy - readability-misleading-indentation
+
+readability-misleading-indentation
+==================================
+
+Correct indentation helps to understand code. Mismatch of the syntactical
+structure and the indentation of the code may hide serious problems.
+Missing braces can also make it significantly harder to read the code,
+therefore it is important to use braces. 
+
+The way to avoid dangling else is to always check that an ``else`` belongs
+to the ``if`` that begins in the same column.
+
+You can omit braces when your inner part of e.g. an ``if`` statement has only
+one statement in it. Although in that case you should begin the next statement
+in the same column with the ``if``.
+
+Examples:
+
+.. code-block:: c++
+
+  // Dangling else:
+  if (cond1)
+    if (cond2)
+      foo1();
+  else
+    foo2();  // Wrong indentation: else belongs to if(cond2) statement.
+
+  // Missing braces:
+  if (cond1)
+    foo1();
+    foo2();  // Not guarded by if(cond1).
+
+Limitations
+-----------
+
+Note that this check only works as expected when the tabs or spaces are used
+consistently and not mixed.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-misplaced-array-index.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-misplaced-array-index.rst
new file mode 100644
index 0000000..26a5af7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-misplaced-array-index.rst
@@ -0,0 +1,27 @@
+.. title:: clang-tidy - readability-misplaced-array-index
+
+readability-misplaced-array-index
+=================================
+
+This check warns for unusual array index syntax.
+
+The following code has unusual array index syntax:
+
+.. code-block:: c++
+
+  void f(int *X, int Y) {
+    Y[X] = 0;
+  }
+
+becomes
+
+.. code-block:: c++
+
+  void f(int *X, int Y) {
+    X[Y] = 0;
+  }
+
+The check warns about such unusual syntax for readability reasons:
+ * There are programmers that are not familiar with this unusual syntax.
+ * It is possible that variables are mixed up.
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-named-parameter.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-named-parameter.rst
new file mode 100644
index 0000000..8d28c0a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-named-parameter.rst
@@ -0,0 +1,16 @@
+.. title:: clang-tidy - readability-named-parameter
+
+readability-named-parameter
+===========================
+
+Find functions with unnamed arguments.
+
+The check implements the following rule originating in the Google C++ Style
+Guide:
+
+https://google.github.io/styleguide/cppguide.html#Function_Declarations_and_Definitions
+
+All parameters should be named, with identical names in the declaration and
+implementation.
+
+Corresponding cpplint.py check name: `readability/function`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-non-const-parameter.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-non-const-parameter.rst
new file mode 100644
index 0000000..0729470
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-non-const-parameter.rst
@@ -0,0 +1,46 @@
+.. title:: clang-tidy - readability-non-const-parameter
+
+readability-non-const-parameter
+===============================
+
+The check finds function parameters of a pointer type that could be changed to
+point to a constant type instead.
+
+When ``const`` is used properly, many mistakes can be avoided. Advantages when
+using ``const`` properly:
+
+- prevent unintentional modification of data;
+
+- get additional warnings such as using uninitialized data;
+
+- make it easier for developers to see possible side effects.
+
+This check is not strict about constness, it only warns when the constness will
+make the function interface safer.
+
+.. code-block:: c++
+
+  // warning here; the declaration "const char *p" would make the function
+  // interface safer.
+  char f1(char *p) {
+    return *p;
+  }
+
+  // no warning; the declaration could be more const "const int * const p" but
+  // that does not make the function interface safer.
+  int f2(const int *p) {
+    return *p;
+  }
+
+  // no warning; making x const does not make the function interface safer
+  int f3(int x) {
+    return x;
+  }
+
+  // no warning; Technically, *p can be const ("const struct S *p"). But making
+  // *p const could be misleading. People might think that it's safe to pass
+  // const data to this function.
+  struct S { int *a; int *b; };
+  int f3(struct S *p) {
+    *(p->a) = 0;
+  }
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-control-flow.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-control-flow.rst
new file mode 100644
index 0000000..aeaf345
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-control-flow.rst
@@ -0,0 +1,50 @@
+.. title:: clang-tidy - readability-redundant-control-flow
+
+readability-redundant-control-flow
+==================================
+
+This check looks for procedures (functions returning no value) with ``return``
+statements at the end of the function. Such ``return`` statements are redundant.
+
+Loop statements (``for``, ``while``, ``do while``) are checked for redundant
+``continue`` statements at the end of the loop body.
+
+Examples:
+
+The following function `f` contains a redundant ``return`` statement:
+
+.. code-block:: c++
+
+  extern void g();
+  void f() {
+    g();
+    return;
+  }
+
+becomes
+
+.. code-block:: c++
+
+  extern void g();
+  void f() {
+    g();
+  }
+
+The following function `k` contains a redundant ``continue`` statement:
+
+.. code-block:: c++
+
+  void k() {
+    for (int i = 0; i < 10; ++i) {
+      continue;
+    }
+  }
+
+becomes
+
+.. code-block:: c++
+
+  void k() {
+    for (int i = 0; i < 10; ++i) {
+    }
+  }
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-declaration.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-declaration.rst
new file mode 100644
index 0000000..8ce7aac
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-declaration.rst
@@ -0,0 +1,37 @@
+.. title:: clang-tidy - readability-redundant-declaration
+
+readability-redundant-declaration
+=================================
+
+Finds redundant variable and function declarations.
+
+.. code-block:: c++
+
+  extern int X;
+  extern int X;
+
+becomes
+
+.. code-block:: c++
+
+  extern int X;
+
+Such redundant declarations can be removed without changing program behaviour.
+They can for instance be unintentional left overs from previous refactorings
+when code has been moved around. Having redundant declarations could in worst
+case mean that there are typos in the code that cause bugs.
+
+Normally the code can be automatically fixed, :program:`clang-tidy` can remove
+the second declaration. However there are 2 cases when you need to fix the code
+manually:
+
+* When the declarations are in different header files;
+* When multiple variables are declared together.
+
+Options
+-------
+
+.. option:: IgnoreMacros
+
+   If set to non-zero, the check will not give warnings inside macros. Default
+   is `1`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-function-ptr-dereference.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-function-ptr-dereference.rst
new file mode 100644
index 0000000..d8c7ec7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-function-ptr-dereference.rst
@@ -0,0 +1,24 @@
+.. title:: clang-tidy - readability-redundant-function-ptr-dereference
+
+readability-redundant-function-ptr-dereference
+==============================================
+
+Finds redundant dereferences of a function pointer.
+
+Before:
+
+.. code-block:: c++
+
+  int f(int,int);
+  int (*p)(int, int) = &f;
+
+  int i = (**p)(10, 50);
+
+After:
+
+.. code-block:: c++
+
+  int f(int,int);
+  int (*p)(int, int) = &f;
+
+  int i = (*p)(10, 50);
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
new file mode 100644
index 0000000..a640e16
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
@@ -0,0 +1,20 @@
+.. title:: clang-tidy - readability-redundant-member-init
+
+readability-redundant-member-init
+=================================
+
+Finds member initializations that are unnecessary because the same default
+constructor would be called if they were not present.
+
+Example:
+
+.. code-block:: c++
+
+  // Explicitly initializing the member s is unnecessary.
+  class Foo {
+  public:
+    Foo() : s() {}
+
+  private:
+    std::string s;
+  };
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-smartptr-get.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-smartptr-get.rst
new file mode 100644
index 0000000..3fc77c5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-smartptr-get.rst
@@ -0,0 +1,16 @@
+.. title:: clang-tidy - readability-redundant-smartptr-get
+
+readability-redundant-smartptr-get
+==================================
+
+Find and remove redundant calls to smart pointer's ``.get()`` method.
+
+Examples:
+
+.. code-block:: c++
+
+  ptr.get()->Foo()  ==>  ptr->Foo()
+  *ptr.get()  ==>  *ptr
+  *ptr->get()  ==>  **ptr
+  if (ptr.get() == nullptr) ... => if (ptr == nullptr) ...
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-cstr.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-cstr.rst
new file mode 100644
index 0000000..e6760a4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-cstr.rst
@@ -0,0 +1,7 @@
+.. title:: clang-tidy - readability-redundant-string-cstr
+
+readability-redundant-string-cstr
+=================================
+
+
+Finds unnecessary calls to ``std::string::c_str()`` and ``std::string::data()``.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
new file mode 100644
index 0000000..e4136ea
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
@@ -0,0 +1,19 @@
+.. title:: clang-tidy - readability-redundant-string-init
+
+readability-redundant-string-init
+=================================
+
+Finds unnecessary string initializations.
+
+Examples:
+
+.. code-block:: c++
+
+  // Initializing string with empty string literal is unnecessary.
+  std::string a = "";
+  std::string b("");
+
+  // becomes
+
+  std::string a;
+  std::string b;
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-simplify-boolean-expr.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-simplify-boolean-expr.rst
new file mode 100644
index 0000000..b333e18
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-simplify-boolean-expr.rst
@@ -0,0 +1,86 @@
+.. title:: clang-tidy - readability-simplify-boolean-expr
+
+readability-simplify-boolean-expr
+=================================
+
+Looks for boolean expressions involving boolean constants and simplifies
+them to use the appropriate boolean expression directly.
+
+Examples:
+
+===========================================  ================
+Initial expression                           Result
+-------------------------------------------  ----------------
+``if (b == true)``                             ``if (b)``
+``if (b == false)``                            ``if (!b)``
+``if (b && true)``                             ``if (b)``
+``if (b && false)``                            ``if (false)``
+``if (b || true)``                             ``if (true)``
+``if (b || false)``                            ``if (b)``
+``e ? true : false``                           ``e``
+``e ? false : true``                           ``!e``
+``if (true) t(); else f();``                   ``t();``
+``if (false) t(); else f();``                  ``f();``
+``if (e) return true; else return false;``     ``return e;``
+``if (e) return false; else return true;``     ``return !e;``
+``if (e) b = true; else b = false;``           ``b = e;``
+``if (e) b = false; else b = true;``           ``b = !e;``
+``if (e) return true; return false;``          ``return e;``
+``if (e) return false; return true;``          ``return !e;``
+===========================================  ================
+
+The resulting expression ``e`` is modified as follows:
+  1. Unnecessary parentheses around the expression are removed.
+  2. Negated applications of ``!`` are eliminated.
+  3. Negated applications of comparison operators are changed to use the
+     opposite condition.
+  4. Implicit conversions of pointers, including pointers to members, to
+     ``bool`` are replaced with explicit comparisons to ``nullptr`` in C++11
+     or ``NULL`` in C++98/03.
+  5. Implicit casts to ``bool`` are replaced with explicit casts to ``bool``.
+  6. Object expressions with ``explicit operator bool`` conversion operators
+     are replaced with explicit casts to ``bool``.
+  7. Implicit conversions of integral types to ``bool`` are replaced with
+     explicit comparisons to ``0``.
+
+Examples:
+  1. The ternary assignment ``bool b = (i < 0) ? true : false;`` has redundant
+     parentheses and becomes ``bool b = i < 0;``.
+
+  2. The conditional return ``if (!b) return false; return true;`` has an
+     implied double negation and becomes ``return b;``.
+
+  3. The conditional return ``if (i < 0) return false; return true;`` becomes
+     ``return i >= 0;``.
+
+     The conditional return ``if (i != 0) return false; return true;`` becomes
+     ``return i == 0;``.
+
+  4. The conditional return ``if (p) return true; return false;`` has an
+     implicit conversion of a pointer to ``bool`` and becomes
+     ``return p != nullptr;``.
+
+     The ternary assignment ``bool b = (i & 1) ? true : false;`` has an
+     implicit conversion of ``i & 1`` to ``bool`` and becomes
+     ``bool b = (i & 1) != 0;``.
+
+  5. The conditional return ``if (i & 1) return true; else return false;`` has
+     an implicit conversion of an integer quantity ``i & 1`` to ``bool`` and
+     becomes ``return (i & 1) != 0;``
+
+  6. Given ``struct X { explicit operator bool(); };``, and an instance ``x`` of
+     ``struct X``, the conditional return ``if (x) return true; return false;``
+     becomes ``return static_cast<bool>(x);``
+
+Options
+-------
+
+.. option:: ChainedConditionalReturn
+
+   If non-zero, conditional boolean return statements at the end of an
+   ``if/else if`` chain will be transformed. Default is `0`.
+
+.. option:: ChainedConditionalAssignment
+
+   If non-zero, conditional boolean assignments at the end of an ``if/else
+   if`` chain will be transformed. Default is `0`.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-simplify-subscript-expr.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-simplify-subscript-expr.rst
new file mode 100644
index 0000000..f3f44be
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-simplify-subscript-expr.rst
@@ -0,0 +1,23 @@
+.. title:: clang-tidy - readability-simplify-subscript-expr
+
+readability-simplify-subscript-expr
+===================================
+
+This check simplifies subscript expressions. Currently this covers calling
+``.data()`` and immediately doing an array subscript operation to obtain a
+single element, in which case simply calling ``operator[]`` suffice.
+
+Examples:
+
+.. code-block:: c++
+
+  std::string s = ...;
+  char c = s.data()[i];  // char c = s[i];
+
+Options
+-------
+
+.. option:: Types
+
+   The list of type(s) that triggers this check. Default is
+   `::std::basic_string;::std::basic_string_view;::std::vector;::std::array`
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-static-accessed-through-instance.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-static-accessed-through-instance.rst
new file mode 100644
index 0000000..879b87c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-static-accessed-through-instance.rst
@@ -0,0 +1,31 @@
+.. title:: clang-tidy - readability-static-accessed-through-instance
+
+readability-static-accessed-through-instance
+============================================
+
+Checks for member expressions that access static members through instances, and
+replaces them with uses of the appropriate qualified-id.
+
+Example:
+
+The following code:
+
+.. code-block:: c++
+
+  struct C {
+    static void foo();
+    static int x;
+  };
+
+  C *c1 = new C();
+  c1->foo();
+  c1->x;
+
+is changed to:
+
+.. code-block:: c++
+
+  C *c1 = new C();
+  C::foo();
+  C::x;
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-static-definition-in-anonymous-namespace.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-static-definition-in-anonymous-namespace.rst
new file mode 100644
index 0000000..c1803d4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-static-definition-in-anonymous-namespace.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - readability-static-definition-in-anonymous-namespace
+
+readability-static-definition-in-anonymous-namespace
+====================================================
+
+Finds static function and variable definitions in anonymous namespace.
+
+In this case, ``static`` is redundant, because anonymous namespace limits the
+visibility of definitions to a single translation unit.
+
+.. code-block:: c++
+
+  namespace {
+    static int a = 1; // Warning.
+    static const b = 1; // Warning.
+  }
+
+The check will apply a fix by removing the redundant ``static`` qualifier.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-string-compare.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-string-compare.rst
new file mode 100644
index 0000000..58d01d5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-string-compare.rst
@@ -0,0 +1,54 @@
+.. title:: clang-tidy - readability-string-compare
+
+readability-string-compare
+==========================
+
+Finds string comparisons using the compare method.
+
+A common mistake is to use the string's ``compare`` method instead of using the 
+equality or inequality operators. The compare method is intended for sorting
+functions and thus returns a negative number, a positive number or 
+zero depending on the lexicographical relationship between the strings compared. 
+If an equality or inequality check can suffice, that is recommended. This is 
+recommended to avoid the risk of incorrect interpretation of the return value
+and to simplify the code. The string equality and inequality operators can
+also be faster than the ``compare`` method due to early termination.
+
+Examples:
+
+.. code-block:: c++
+
+  std::string str1{"a"};
+  std::string str2{"b"};
+
+  // use str1 != str2 instead.
+  if (str1.compare(str2)) {
+  }
+
+  // use str1 == str2 instead.
+  if (!str1.compare(str2)) {
+  }
+
+  // use str1 == str2 instead.
+  if (str1.compare(str2) == 0) {
+  }
+
+  // use str1 != str2 instead.
+  if (str1.compare(str2) != 0) {
+  }
+
+  // use str1 == str2 instead.
+  if (0 == str1.compare(str2)) {
+  }
+
+  // use str1 != str2 instead.
+  if (0 != str1.compare(str2)) {
+  }
+
+  // Use str1 == "foo" instead.
+  if (str1.compare("foo") == 0) {
+  }
+
+The above code examples shows the list of if-statements that this check will
+give a warning for. All of them uses ``compare`` to check if equality or 
+inequality of two strings instead of using the correct operators.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-uniqueptr-delete-release.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-uniqueptr-delete-release.rst
new file mode 100644
index 0000000..beec1d5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/readability-uniqueptr-delete-release.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - readability-uniqueptr-delete-release
+
+readability-uniqueptr-delete-release
+====================================
+
+Replace ``delete <unique_ptr>.release()`` with ``<unique_ptr> = nullptr``.
+The latter is shorter, simpler and does not require use of raw pointer APIs.
+
+.. code-block:: c++
+
+  std::unique_ptr<int> P;
+  delete P.release();
+
+  // becomes
+
+  std::unique_ptr<int> P;
+  P = nullptr;
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/zircon-temporary-objects.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/zircon-temporary-objects.rst
new file mode 100644
index 0000000..7491f77
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/checks/zircon-temporary-objects.rst
@@ -0,0 +1,53 @@
+.. title:: clang-tidy - zircon-temporary-objects
+
+zircon-temporary-objects
+========================
+
+Warns on construction of specific temporary objects in the Zircon kernel. 
+If the object should be flagged, If the object should be flagged, the fully 
+qualified type name must be explicitly passed to the check.
+
+For example, given the list of classes "Foo" and "NS::Bar", all of the 
+following will trigger the warning: 
+
+.. code-block:: c++
+
+  Foo();
+  Foo F = Foo();
+  func(Foo());
+
+  namespace NS {
+
+  Bar();
+
+  }
+
+With the same list, the following will not trigger the warning:
+
+.. code-block:: c++
+
+  Foo F;				         // Non-temporary construction okay
+  Foo F(param);			     // Non-temporary construction okay
+  Foo *F = new Foo();	   // New construction okay
+
+  Bar(); 				         // Not NS::Bar, so okay
+  NS::Bar B;			       // Non-temporary construction okay
+
+Note that objects must be explicitly specified in order to be flagged, 
+and so objects that inherit a specified object will not be flagged.
+
+This check matches temporary objects without regard for inheritance and so a
+prohibited base class type does not similarly prohibit derived class types.
+
+.. code-block:: c++
+
+  class Derived : Foo {} // Derived is not explicitly disallowed
+  Derived();             // and so temporary construction is okay
+
+Options
+-------
+
+.. option:: Names
+
+   A semi-colon-separated list of fully-qualified names of C++ classes that 
+   should not be constructed as temporaries. Default is empty.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/index.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/index.rst
new file mode 100644
index 0000000..ec6c24f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clang-tidy/index.rst
@@ -0,0 +1,810 @@
+==========
+Clang-Tidy
+==========
+
+.. contents::
+
+See also:
+
+.. toctree::
+   :maxdepth: 1
+
+   The list of clang-tidy checks <checks/list>
+
+:program:`clang-tidy` is a clang-based C++ "linter" tool. Its purpose is to
+provide an extensible framework for diagnosing and fixing typical programming
+errors, like style violations, interface misuse, or bugs that can be deduced via
+static analysis. :program:`clang-tidy` is modular and provides a convenient
+interface for writing new checks.
+
+
+Using clang-tidy
+================
+
+:program:`clang-tidy` is a `LibTooling`_-based tool, and it's easier to work
+with if you set up a compile command database for your project (for an example
+of how to do this see `How To Setup Tooling For LLVM`_). You can also specify
+compilation options on the command line after ``--``:
+
+.. code-block:: console
+
+  $ clang-tidy test.cpp -- -Imy_project/include -DMY_DEFINES ...
+
+:program:`clang-tidy` has its own checks and can also run Clang static analyzer
+checks. Each check has a name and the checks to run can be chosen using the
+``-checks=`` option, which specifies a comma-separated list of positive and
+negative (prefixed with ``-``) globs. Positive globs add subsets of checks,
+negative globs remove them. For example,
+
+.. code-block:: console
+
+  $ clang-tidy test.cpp -checks=-*,clang-analyzer-*,-clang-analyzer-cplusplus*
+
+will disable all default checks (``-*``) and enable all ``clang-analyzer-*``
+checks except for ``clang-analyzer-cplusplus*`` ones.
+
+The ``-list-checks`` option lists all the enabled checks. When used without
+``-checks=``, it shows checks enabled by default. Use ``-checks=*`` to see all
+available checks or with any other value of ``-checks=`` to see which checks are
+enabled by this value.
+
+.. _checks-groups-table:
+
+There are currently the following groups of checks:
+
+====================== =========================================================
+Name prefix            Description
+====================== =========================================================
+``android-``           Checks related to Android.
+``boost-``             Checks related to Boost library.
+``bugprone-``          Checks that target bugprone code constructs.
+``cert-``              Checks related to CERT Secure Coding Guidelines.
+``cppcoreguidelines-`` Checks related to C++ Core Guidelines.
+``clang-analyzer-``    Clang Static Analyzer checks.
+``fuchsia-``           Checks related to Fuchsia coding conventions.
+``google-``            Checks related to Google coding conventions.
+``hicpp-``             Checks related to High Integrity C++ Coding Standard.
+``llvm-``              Checks related to the LLVM coding conventions.
+``misc-``              Checks that we didn't have a better category for.
+``modernize-``         Checks that advocate usage of modern (currently "modern"
+                       means "C++11") language constructs.
+``mpi-``               Checks related to MPI (Message Passing Interface).
+``objc-``              Checks related to Objective-C coding conventions.
+``performance-``       Checks that target performance-related issues.
+``portability-``       Checks that target portability-related issues that don't
+                       relate to any particular coding style.
+``readability-``       Checks that target readability-related issues that don't
+                       relate to any particular coding style.
+``zircon-``            Checks related to Zircon kernel coding conventions.
+====================== =========================================================
+
+Clang diagnostics are treated in a similar way as check diagnostics. Clang
+diagnostics are displayed by :program:`clang-tidy` and can be filtered out using
+``-checks=`` option. However, the ``-checks=`` option does not affect
+compilation arguments, so it can not turn on Clang warnings which are not
+already turned on in build configuration. The ``-warnings-as-errors=`` option
+upgrades any warnings emitted under the ``-checks=`` flag to errors (but it
+does not enable any checks itself).
+
+Clang diagnostics have check names starting with ``clang-diagnostic-``.
+Diagnostics which have a corresponding warning option, are named
+``clang-diagnostic-<warning-option>``, e.g. Clang warning controlled by
+``-Wliteral-conversion`` will be reported with check name
+``clang-diagnostic-literal-conversion``.
+
+The ``-fix`` flag instructs :program:`clang-tidy` to fix found errors if
+supported by corresponding checks.
+
+An overview of all the command-line options:
+
+.. code-block:: console
+
+  $ clang-tidy --help
+  USAGE: clang-tidy [options] <source0> [... <sourceN>]
+
+  OPTIONS:
+
+  Generic Options:
+
+    -help                         - Display available options (-help-hidden for more)
+    -help-list                    - Display list of available options (-help-list-hidden for more)
+    -version                      - Display the version of this program
+
+  clang-tidy options:
+
+    -checks=<string>              -
+                                    Comma-separated list of globs with optional '-'
+                                    prefix. Globs are processed in order of
+                                    appearance in the list. Globs without '-'
+                                    prefix add checks with matching names to the
+                                    set, globs with the '-' prefix remove checks
+                                    with matching names from the set of enabled
+                                    checks. This option's value is appended to the
+                                    value of the 'Checks' option in .clang-tidy
+                                    file, if any.
+    -config=<string>              -
+                                    Specifies a configuration in YAML/JSON format:
+                                      -config="{Checks: '*',
+                                                CheckOptions: [{key: x,
+                                                                value: y}]}"
+                                    When the value is empty, clang-tidy will
+                                    attempt to find a file named .clang-tidy for
+                                    each source file in its parent directories.
+    -dump-config                  -
+                                    Dumps configuration in the YAML format to
+                                    stdout. This option can be used along with a
+                                    file name (and '--' if the file is outside of a
+                                    project with configured compilation database).
+                                    The configuration used for this file will be
+                                    printed.
+                                    Use along with -checks=* to include
+                                    configuration of all checks.
+    -enable-check-profile         -
+                                    Enable per-check timing profiles, and print a
+                                    report to stderr.
+    -explain-config               -
+                                    For each enabled check explains, where it is
+                                    enabled, i.e. in clang-tidy binary, command
+                                    line or a specific configuration file.
+    -export-fixes=<filename>      -
+                                    YAML file to store suggested fixes in. The
+                                    stored fixes can be applied to the input source
+                                    code with clang-apply-replacements.
+    -extra-arg=<string>           - Additional argument to append to the compiler command line
+    -extra-arg-before=<string>    - Additional argument to prepend to the compiler command line
+    -fix                          -
+                                    Apply suggested fixes. Without -fix-errors
+                                    clang-tidy will bail out if any compilation
+                                    errors were found.
+    -fix-errors                   -
+                                    Apply suggested fixes even if compilation
+                                    errors were found. If compiler errors have
+                                    attached fix-its, clang-tidy will apply them as
+                                    well.
+    -format-style=<string>        -
+                                    Style for formatting code around applied fixes:
+                                      - 'none' (default) turns off formatting
+                                      - 'file' (literally 'file', not a placeholder)
+                                        uses .clang-format file in the closest parent
+                                        directory
+                                      - '{ <json> }' specifies options inline, e.g.
+                                        -format-style='{BasedOnStyle: llvm, IndentWidth: 8}'
+                                      - 'llvm', 'google', 'webkit', 'mozilla'
+                                    See clang-format documentation for the up-to-date
+                                    information about formatting styles and options.
+                                    This option overrides the 'FormatStyle` option in
+                                    .clang-tidy file, if any.
+    -header-filter=<string>       -
+                                    Regular expression matching the names of the
+                                    headers to output diagnostics from. Diagnostics
+                                    from the main file of each translation unit are
+                                    always displayed.
+                                    Can be used together with -line-filter.
+                                    This option overrides the 'HeaderFilter' option
+                                    in .clang-tidy file, if any.
+    -line-filter=<string>         -
+                                    List of files with line ranges to filter the
+                                    warnings. Can be used together with
+                                    -header-filter. The format of the list is a
+                                    JSON array of objects:
+                                      [
+                                        {"name":"file1.cpp","lines":[[1,3],[5,7]]},
+                                        {"name":"file2.h"}
+                                      ]
+    -list-checks                  -
+                                    List all enabled checks and exit. Use with
+                                    -checks=* to list all available checks.
+    -p=<string>                   - Build path
+    -quiet                        -
+                                    Run clang-tidy in quiet mode. This suppresses
+                                    printing statistics about ignored warnings and
+                                    warnings treated as errors if the respective
+                                    options are specified.
+    -store-check-profile=<prefix> -
+                                    By default reports are printed in tabulated
+                                    format to stderr. When this option is passed,
+                                    these per-TU profiles are instead stored as JSON.
+    -system-headers               - Display the errors from system headers.
+    -vfsoverlay=<filename>        -
+                                    Overlay the virtual filesystem described by file
+                                    over the real file system.
+    -warnings-as-errors=<string>  -
+                                    Upgrades warnings to errors. Same format as
+                                    '-checks'.
+                                    This option's value is appended to the value of
+                                    the 'WarningsAsErrors' option in .clang-tidy
+                                    file, if any.
+
+  -p <build-path> is used to read a compile command database.
+
+          For example, it can be a CMake build directory in which a file named
+          compile_commands.json exists (use -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
+          CMake option to get this output). When no build path is specified,
+          a search for compile_commands.json will be attempted through all
+          parent paths of the first input file . See:
+          http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html for an
+          example of setting up Clang Tooling on a source tree.
+
+  <source0> ... specify the paths of source files. These paths are
+          looked up in the compile command database. If the path of a file is
+          absolute, it needs to point into CMake's source tree. If the path is
+          relative, the current working directory needs to be in the CMake
+          source tree and the file must be in a subdirectory of the current
+          working directory. "./" prefixes in the relative files will be
+          automatically removed, but the rest of a relative path must be a
+          suffix of a path in the compile command database.
+
+
+  Configuration files:
+    clang-tidy attempts to read configuration for each source file from a
+    .clang-tidy file located in the closest parent directory of the source
+    file. If any configuration options have a corresponding command-line
+    option, command-line option takes precedence. The effective
+    configuration can be inspected using -dump-config:
+
+      $ clang-tidy -dump-config
+      ---
+      Checks:          '-*,some-check'
+      WarningsAsErrors: ''
+      HeaderFilterRegex: ''
+      FormatStyle:     none
+      User:            user
+      CheckOptions:
+        - key:             some-check.SomeOption
+          value:           'some value'
+      ...
+
+:program:`clang-tidy` diagnostics are intended to call out code that does
+not adhere to a coding standard, or is otherwise problematic in some way.
+However, if it is known that the code is correct, the check-specific ways
+to silence the diagnostics could be used, if they are available (e.g. 
+bugprone-use-after-move can be silenced by re-initializing the variable after 
+it has been moved out, misc-string-integer-assignment can be suppressed by 
+explicitly casting the integer to char, readability-implicit-bool-conversion
+can also be suppressed by using explicit casts, etc.). If they are not 
+available or if changing the semantics of the code is not desired, 
+the ``NOLINT`` or ``NOLINTNEXTLINE`` comments can be used instead. For example:
+
+.. code-block:: c++
+
+  class Foo
+  {
+    // Silent all the diagnostics for the line
+    Foo(int param); // NOLINT
+
+    // Silent only the specified checks for the line
+    Foo(double param); // NOLINT(google-explicit-constructor, google-runtime-int)
+
+    // Silent only the specified diagnostics for the next line
+    // NOLINTNEXTLINE(google-explicit-constructor, google-runtime-int)
+    Foo(bool param); 
+  };
+
+The formal syntax of ``NOLINT``/``NOLINTNEXTLINE`` is the following:
+
+.. parsed-literal::
+
+  lint-comment:
+    lint-command
+    lint-command lint-args
+
+  lint-args:
+    **(** check-name-list **)**
+
+  check-name-list:
+    *check-name*
+    check-name-list **,** *check-name*
+
+  lint-command:
+    **NOLINT**
+    **NOLINTNEXTLINE**
+
+Note that whitespaces between ``NOLINT``/``NOLINTNEXTLINE`` and the opening
+parenthesis are not allowed (in this case the comment will be treated just as
+``NOLINT``/``NOLINTNEXTLINE``), whereas in check names list (inside
+the parenthesis) whitespaces can be used and will be ignored.
+
+.. _LibTooling: http://clang.llvm.org/docs/LibTooling.html
+.. _How To Setup Tooling For LLVM: http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
+
+
+Getting Involved
+================
+
+:program:`clang-tidy` has several own checks and can run Clang static analyzer
+checks, but its power is in the ability to easily write custom checks.
+
+Checks are organized in modules, which can be linked into :program:`clang-tidy`
+with minimal or no code changes in :program:`clang-tidy`.
+
+Checks can plug into the analysis on the preprocessor level using `PPCallbacks`_
+or on the AST level using `AST Matchers`_. When an error is found, checks can
+report them in a way similar to how Clang diagnostics work. A fix-it hint can be
+attached to a diagnostic message.
+
+The interface provided by :program:`clang-tidy` makes it easy to write useful
+and precise checks in just a few lines of code. If you have an idea for a good
+check, the rest of this document explains how to do this.
+
+There are a few tools particularly useful when developing clang-tidy checks:
+  * ``add_new_check.py`` is a script to automate the process of adding a new
+    check, it will create the check, update the CMake file and create a test;
+  * ``rename_check.py`` does what the script name suggests, renames an existing
+    check;
+  * :program:`clang-query` is invaluable for interactive prototyping of AST
+    matchers and exploration of the Clang AST;
+  * `clang-check`_ with the ``-ast-dump`` (and optionally ``-ast-dump-filter``)
+    provides a convenient way to dump AST of a C++ program.
+
+
+.. _AST Matchers: http://clang.llvm.org/docs/LibASTMatchers.html
+.. _PPCallbacks: http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html
+.. _clang-check: http://clang.llvm.org/docs/ClangCheck.html
+
+
+Choosing the Right Place for your Check
+---------------------------------------
+
+If you have an idea of a check, you should decide whether it should be
+implemented as a:
+
++ *Clang diagnostic*: if the check is generic enough, targets code patterns that
+  most probably are bugs (rather than style or readability issues), can be
+  implemented effectively and with extremely low false positive rate, it may
+  make a good Clang diagnostic.
+
++ *Clang static analyzer check*: if the check requires some sort of control flow
+  analysis, it should probably be implemented as a static analyzer check.
+
++ *clang-tidy check* is a good choice for linter-style checks, checks that are
+  related to a certain coding style, checks that address code readability, etc.
+
+
+Preparing your Workspace
+------------------------
+
+If you are new to LLVM development, you should read the `Getting Started with
+the LLVM System`_, `Using Clang Tools`_ and `How To Setup Tooling For LLVM`_
+documents to check out and build LLVM, Clang and Clang Extra Tools with CMake.
+
+Once you are done, change to the ``llvm/tools/clang/tools/extra`` directory, and
+let's start!
+
+.. _Getting Started with the LLVM System: http://llvm.org/docs/GettingStarted.html
+.. _Using Clang Tools: http://clang.llvm.org/docs/ClangTools.html
+
+
+The Directory Structure
+-----------------------
+
+:program:`clang-tidy` source code resides in the
+``llvm/tools/clang/tools/extra`` directory and is structured as follows:
+
+::
+
+  clang-tidy/                       # Clang-tidy core.
+  |-- ClangTidy.h                   # Interfaces for users and checks.
+  |-- ClangTidyModule.h             # Interface for clang-tidy modules.
+  |-- ClangTidyModuleRegistry.h     # Interface for registering of modules.
+     ...
+  |-- google/                       # Google clang-tidy module.
+  |-+
+    |-- GoogleTidyModule.cpp
+    |-- GoogleTidyModule.h
+          ...
+  |-- llvm/                         # LLVM clang-tidy module.
+  |-+
+    |-- LLVMTidyModule.cpp
+    |-- LLVMTidyModule.h
+          ...
+  |-- objc/                         # Objective-C clang-tidy module.
+  |-+
+    |-- ObjCTidyModule.cpp
+    |-- ObjCTidyModule.h
+          ...
+  |-- tool/                         # Sources of the clang-tidy binary.
+          ...
+  test/clang-tidy/                  # Integration tests.
+      ...
+  unittests/clang-tidy/             # Unit tests.
+  |-- ClangTidyTest.h
+  |-- GoogleModuleTest.cpp
+  |-- LLVMModuleTest.cpp
+  |-- ObjCModuleTest.cpp
+      ...
+
+
+Writing a clang-tidy Check
+--------------------------
+
+So you have an idea of a useful check for :program:`clang-tidy`.
+
+First, if you're not familiar with LLVM development, read through the `Getting
+Started with LLVM`_ document for instructions on setting up your workflow and
+the `LLVM Coding Standards`_ document to familiarize yourself with the coding
+style used in the project. For code reviews we mostly use `LLVM Phabricator`_.
+
+.. _Getting Started with LLVM: http://llvm.org/docs/GettingStarted.html
+.. _LLVM Coding Standards: http://llvm.org/docs/CodingStandards.html
+.. _LLVM Phabricator: http://llvm.org/docs/Phabricator.html
+
+Next, you need to decide which module the check belongs to. Modules
+are located in subdirectories of `clang-tidy/
+<http://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/clang-tidy/>`_
+and contain checks targeting a certain aspect of code quality (performance,
+readability, etc.), certain coding style or standard (Google, LLVM, CERT, etc.)
+or a widely used API (e.g. MPI). Their names are same as user-facing check
+groups names described :ref:`above <checks-groups-table>`.
+
+After choosing the module and the name for the check, run the
+``clang-tidy/add_new_check.py`` script to create the skeleton of the check and
+plug it to :program:`clang-tidy`. It's the recommended way of adding new checks.
+
+If we want to create a `readability-awesome-function-names`, we would run:
+
+.. code-block:: console
+
+  $ clang-tidy/add_new_check.py readability awesome-function-names
+
+
+The ``add_new_check.py`` script will:
+  * create the class for your check inside the specified module's directory and
+    register it in the module and in the build system;
+  * create a lit test file in the ``test/clang-tidy/`` directory;
+  * create a documentation file and include it into the
+    ``docs/clang-tidy/checks/list.rst``.
+
+Let's see in more detail at the check class definition:
+
+.. code-block:: c++
+
+  ...
+
+  #include "../ClangTidy.h"
+
+  namespace clang {
+  namespace tidy {
+  namespace readability {
+
+  ...
+  class AwesomeFunctionNamesCheck : public ClangTidyCheck {
+  public:
+    AwesomeFunctionNamesCheck(StringRef Name, ClangTidyContext *Context)
+        : ClangTidyCheck(Name, Context) {}
+    void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+    void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  };
+
+  } // namespace readability
+  } // namespace tidy
+  } // namespace clang
+
+  ...
+
+Constructor of the check receives the ``Name`` and ``Context`` parameters, and
+must forward them to the ``ClangTidyCheck`` constructor.
+
+In our case the check needs to operate on the AST level and it overrides the
+``registerMatchers`` and ``check`` methods. If we wanted to analyze code on the
+preprocessor level, we'd need instead to override the ``registerPPCallbacks``
+method.
+
+In the ``registerMatchers`` method we create an AST Matcher (see `AST Matchers`_
+for more information) that will find the pattern in the AST that we want to
+inspect. The results of the matching are passed to the ``check`` method, which
+can further inspect them and report diagnostics.
+
+.. code-block:: c++
+
+  using namespace ast_matchers;
+
+  void AwesomeFunctionNamesCheck::registerMatchers(MatchFinder *Finder) {
+    Finder->addMatcher(functionDecl().bind("x"), this);
+  }
+
+  void AwesomeFunctionNamesCheck::check(const MatchFinder::MatchResult &Result) {
+    const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>("x");
+    if (MatchedDecl->getName().startswith("awesome_"))
+      return;
+    diag(MatchedDecl->getLocation(), "function %0 is insufficiently awesome")
+        << MatchedDecl
+        << FixItHint::CreateInsertion(MatchedDecl->getLocation(), "awesome_");
+  }
+
+(If you want to see an example of a useful check, look at
+`clang-tidy/google/ExplicitConstructorCheck.h
+<http://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/clang-tidy/google/ExplicitConstructorCheck.h>`_
+and `clang-tidy/google/ExplicitConstructorCheck.cpp
+<http://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/clang-tidy/google/ExplicitConstructorCheck.cpp>`_).
+
+
+Registering your Check
+----------------------
+
+(The ``add_new_check.py`` takes care of registering the check in an existing
+module. If you want to create a new module or know the details, read on.)
+
+The check should be registered in the corresponding module with a distinct name:
+
+.. code-block:: c++
+
+  class MyModule : public ClangTidyModule {
+   public:
+    void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+      CheckFactories.registerCheck<ExplicitConstructorCheck>(
+          "my-explicit-constructor");
+    }
+  };
+
+Now we need to register the module in the ``ClangTidyModuleRegistry`` using a
+statically initialized variable:
+
+.. code-block:: c++
+
+  static ClangTidyModuleRegistry::Add<MyModule> X("my-module",
+                                                  "Adds my lint checks.");
+
+
+When using LLVM build system, we need to use the following hack to ensure the
+module is linked into the :program:`clang-tidy` binary:
+
+Add this near the ``ClangTidyModuleRegistry::Add<MyModule>`` variable:
+
+.. code-block:: c++
+
+  // This anchor is used to force the linker to link in the generated object file
+  // and thus register the MyModule.
+  volatile int MyModuleAnchorSource = 0;
+
+And this to the main translation unit of the :program:`clang-tidy` binary (or
+the binary you link the ``clang-tidy`` library in)
+``clang-tidy/tool/ClangTidyMain.cpp``:
+
+.. code-block:: c++
+
+  // This anchor is used to force the linker to link the MyModule.
+  extern volatile int MyModuleAnchorSource;
+  static int MyModuleAnchorDestination = MyModuleAnchorSource;
+
+
+Configuring Checks
+------------------
+
+If a check needs configuration options, it can access check-specific options
+using the ``Options.get<Type>("SomeOption", DefaultValue)`` call in the check
+constructor. In this case the check should also override the
+``ClangTidyCheck::storeOptions`` method to make the options provided by the
+check discoverable. This method lets :program:`clang-tidy` know which options
+the check implements and what the current values are (e.g. for the
+``-dump-config`` command line option).
+
+.. code-block:: c++
+
+  class MyCheck : public ClangTidyCheck {
+    const unsigned SomeOption1;
+    const std::string SomeOption2;
+
+  public:
+    MyCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context),
+        SomeOption(Options.get("SomeOption1", -1U)),
+        SomeOption(Options.get("SomeOption2", "some default")) {}
+
+    void storeOptions(ClangTidyOptions::OptionMap &Opts) override {
+      Options.store(Opts, "SomeOption1", SomeOption1);
+      Options.store(Opts, "SomeOption2", SomeOption2);
+    }
+    ...
+
+Assuming the check is registered with the name "my-check", the option can then
+be set in a ``.clang-tidy`` file in the following way:
+
+.. code-block:: yaml
+
+  CheckOptions:
+    - key: my-check.SomeOption1
+      value: 123
+    - key: my-check.SomeOption2
+      value: 'some other value'
+
+If you need to specify check options on a command line, you can use the inline
+YAML format:
+
+.. code-block:: console
+
+  $ clang-tidy -config="{CheckOptions: [{key: a, value: b}, {key: x, value: y}]}" ...
+
+
+Testing Checks
+--------------
+
+To run tests for :program:`clang-tidy` use the command:
+
+.. code-block:: console
+
+  $ ninja check-clang-tools
+
+:program:`clang-tidy` checks can be tested using either unit tests or
+`lit`_ tests. Unit tests may be more convenient to test complex replacements
+with strict checks. `Lit`_ tests allow using partial text matching and regular
+expressions which makes them more suitable for writing compact tests for
+diagnostic messages.
+
+The ``check_clang_tidy.py`` script provides an easy way to test both
+diagnostic messages and fix-its. It filters out ``CHECK`` lines from the test
+file, runs :program:`clang-tidy` and verifies messages and fixes with two
+separate `FileCheck`_ invocations: once with FileCheck's directive
+prefix set to ``CHECK-MESSAGES``, validating the diagnostic messages,
+and once with the directive prefix set to ``CHECK-FIXES``, running
+against the fixed code (i.e., the code after generated fix-its are
+applied). In particular, ``CHECK-FIXES:`` can be used to check
+that code was not modified by fix-its, by checking that it is present
+unchanged in the fixed code. The full set of `FileCheck`_ directives
+is available (e.g., ``CHECK-MESSAGES-SAME:``, ``CHECK-MESSAGES-NOT:``), though
+typically the basic ``CHECK`` forms (``CHECK-MESSAGES`` and ``CHECK-FIXES``)
+are sufficient for clang-tidy tests. Note that the `FileCheck`_
+documentation mostly assumes the default prefix (``CHECK``), and hence
+describes the directive as ``CHECK:``, ``CHECK-SAME:``, ``CHECK-NOT:``, etc.
+Replace ``CHECK`` by either ``CHECK-FIXES`` or ``CHECK-MESSAGES`` for
+clang-tidy tests.
+
+An additional check enabled by ``check_clang_tidy.py`` ensures that
+if `CHECK-MESSAGES:` is used in a file then every warning or error
+must have an associated CHECK in that file.
+
+To use the ``check_clang_tidy.py`` script, put a .cpp file with the
+appropriate ``RUN`` line in the ``test/clang-tidy`` directory. Use
+``CHECK-MESSAGES:`` and ``CHECK-FIXES:`` lines to write checks against
+diagnostic messages and fixed code.
+
+It's advised to make the checks as specific as possible to avoid checks matching
+to incorrect parts of the input. Use ``[[@LINE+X]]``/``[[@LINE-X]]``
+substitutions and distinct function and variable names in the test code.
+
+Here's an example of a test using the ``check_clang_tidy.py`` script (the full
+source code is at `test/clang-tidy/google-readability-casting.cpp`_):
+
+.. code-block:: c++
+
+  // RUN: %check_clang_tidy %s google-readability-casting %t
+
+  void f(int a) {
+    int b = (int)a;
+    // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant cast to the same type [google-readability-casting]
+    // CHECK-FIXES: int b = a;
+  }
+
+To check more than one scenario in the same test file use 
+``-check-suffix=SUFFIX-NAME`` on ``check_clang_tidy.py`` command line.
+With ``-check-suffix=SUFFIX-NAME`` you need to replace your ``CHECK-*`` 
+directives with ``CHECK-MESSAGES-SUFFIX-NAME`` and ``CHECK-FIXES-SUFFIX-NAME``.
+
+Here's an example:
+
+.. code-block:: c++
+
+   // RUN: %check_clang_tidy -check-suffix=USING-A %s misc-unused-using-decls %t -- -- -DUSING_A
+   // RUN: %check_clang_tidy -check-suffix=USING-B %s misc-unused-using-decls %t -- -- -DUSING_B
+   // RUN: %check_clang_tidy %s misc-unused-using-decls %t
+   ...
+   // CHECK-MESSAGES-USING-A: :[[@LINE-8]]:10: warning: using decl 'A' {{.*}}
+   // CHECK-MESSAGES-USING-B: :[[@LINE-7]]:10: warning: using decl 'B' {{.*}}
+   // CHECK-MESSAGES: :[[@LINE-6]]:10: warning: using decl 'C' {{.*}}
+   // CHECK-FIXES-USING-A-NOT: using a::A;$
+   // CHECK-FIXES-USING-B-NOT: using a::B;$
+   // CHECK-FIXES-NOT: using a::C;$
+
+
+There are many dark corners in the C++ language, and it may be difficult to make
+your check work perfectly in all cases, especially if it issues fix-it hints. The
+most frequent pitfalls are macros and templates:
+
+1. code written in a macro body/template definition may have a different meaning
+   depending on the macro expansion/template instantiation;
+2. multiple macro expansions/template instantiations may result in the same code
+   being inspected by the check multiple times (possibly, with different
+   meanings, see 1), and the same warning (or a slightly different one) may be
+   issued by the check multiple times; :program:`clang-tidy` will deduplicate
+   _identical_ warnings, but if the warnings are slightly different, all of them
+   will be shown to the user (and used for applying fixes, if any);
+3. making replacements to a macro body/template definition may be fine for some
+   macro expansions/template instantiations, but easily break some other
+   expansions/instantiations.
+
+.. _lit: http://llvm.org/docs/CommandGuide/lit.html
+.. _FileCheck: http://llvm.org/docs/CommandGuide/FileCheck.html
+.. _test/clang-tidy/google-readability-casting.cpp: http://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/test/clang-tidy/google-readability-casting.cpp
+
+
+Running clang-tidy on LLVM
+--------------------------
+
+To test a check it's best to try it out on a larger code base. LLVM and Clang
+are the natural targets as you already have the source code around. The most
+convenient way to run :program:`clang-tidy` is with a compile command database;
+CMake can automatically generate one, for a description of how to enable it see
+`How To Setup Tooling For LLVM`_. Once ``compile_commands.json`` is in place and
+a working version of :program:`clang-tidy` is in ``PATH`` the entire code base
+can be analyzed with ``clang-tidy/tool/run-clang-tidy.py``. The script executes
+:program:`clang-tidy` with the default set of checks on every translation unit
+in the compile command database and displays the resulting warnings and errors.
+The script provides multiple configuration flags.
+
+* The default set of checks can be overridden using the ``-checks`` argument,
+  taking the identical format as :program:`clang-tidy` does. For example
+  ``-checks=-*,modernize-use-override`` will run the ``modernize-use-override``
+  check only.
+
+* To restrict the files examined you can provide one or more regex arguments
+  that the file names are matched against.
+  ``run-clang-tidy.py clang-tidy/.*Check\.cpp`` will only analyze clang-tidy
+  checks. It may also be necessary to restrict the header files warnings are
+  displayed from using the ``-header-filter`` flag. It has the same behavior
+  as the corresponding :program:`clang-tidy` flag.
+
+* To apply suggested fixes ``-fix`` can be passed as an argument. This gathers
+  all changes in a temporary directory and applies them. Passing ``-format``
+  will run clang-format over changed lines.
+
+
+On checks profiling
+-------------------
+
+:program:`clang-tidy` can collect per-check profiling info, and output it
+for each processed source file (translation unit).
+
+To enable profiling info collection, use the ``-enable-check-profile`` argument.
+The timings will be output to ``stderr`` as a table. Example output:
+
+.. code-block:: console
+
+  $ clang-tidy -enable-check-profile -checks=-*,readability-function-size source.cpp
+  ===-------------------------------------------------------------------------===
+                            clang-tidy checks profiling
+  ===-------------------------------------------------------------------------===
+    Total Execution Time: 1.0282 seconds (1.0258 wall clock)
+
+     ---User Time---   --System Time--   --User+System--   ---Wall Time---  --- Name ---
+     0.9136 (100.0%)   0.1146 (100.0%)   1.0282 (100.0%)   1.0258 (100.0%)  readability-function-size
+     0.9136 (100.0%)   0.1146 (100.0%)   1.0282 (100.0%)   1.0258 (100.0%)  Total
+
+It can also store that data as JSON files for further processing. Example output:
+
+.. code-block:: console
+
+  $ clang-tidy -enable-check-profile -store-check-profile=.  -checks=-*,readability-function-size source.cpp
+  $ # Note that there won't be timings table printed to the console.
+  $ ls /tmp/out/
+  20180516161318717446360-source.cpp.json
+  $ cat 20180516161318717446360-source.cpp.json
+  {
+  "file": "/path/to/source.cpp",
+  "timestamp": "2018-05-16 16:13:18.717446360",
+  "profile": {
+    "time.clang-tidy.readability-function-size.wall": 1.0421266555786133e+00,
+    "time.clang-tidy.readability-function-size.user": 9.2088400000005421e-01,
+    "time.clang-tidy.readability-function-size.sys": 1.2418899999999974e-01
+  }
+  }
+
+There is only one argument that controls profile storage:
+
+* ``-store-check-profile=<prefix>``
+
+  By default reports are printed in tabulated format to stderr. When this option
+  is passed, these per-TU profiles are instead stored as JSON.
+  If the prefix is not an absolute path, it is considered to be relative to the
+  directory from where you have run :program:`clang-tidy`. All ``.`` and ``..``
+  patterns in the path are collapsed, and symlinks are resolved.
+
+  Example:
+  Let's suppose you have a source file named ``example.cpp``, located in the
+  ``/source`` directory. Only the input filename is used, not the full path
+  to the source file. Additionally, it is prefixed with the current timestamp.
+
+  * If you specify ``-store-check-profile=/tmp``, then the profile will be saved
+    to ``/tmp/<ISO8601-like timestamp>-example.cpp.json``
+
+  * If you run :program:`clang-tidy` from within ``/foo`` directory, and specify
+    ``-store-check-profile=.``, then the profile will still be saved to
+    ``/foo/<ISO8601-like timestamp>-example.cpp.json``
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/clangd.rst b/src/third_party/llvm-project/clang-tools-extra/docs/clangd.rst
new file mode 100644
index 0000000..97736ef
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/clangd.rst
@@ -0,0 +1,123 @@
+============
+Clangd
+============
+
+.. contents::
+
+.. toctree::
+   :maxdepth: 1
+
+:program:`Clangd` is an implementation of the `Language Server Protocol
+<https://github.com/Microsoft/language-server-protocol>`_ leveraging Clang.
+Clangd's goal is to provide language "smartness" features like code completion,
+find references, etc. for clients such as C/C++ Editors.
+
+Using Clangd
+==================
+
+:program:`Clangd` is not meant to be used by C/C++ developers directly but
+rather from a client implementing the protocol. A client would be typically
+implemented in an IDE or an editor.
+
+At the moment, `Visual Studio Code <https://code.visualstudio.com/>`_ is mainly
+used in order to test :program:`Clangd` but more clients are likely to make
+use of :program:`Clangd` in the future as it matures and becomes a production
+quality tool. If you are interested in trying :program:`Clangd` in combination
+with Visual Studio Code, you can start by `installing Clangd`_ or
+`building Clangd`_, then open Visual Studio Code in the clangd-vscode folder and
+launch the extension.
+
+Installing Clangd
+==================
+
+Packages are available for debian-based distributions, see the `LLVM packages
+page <http://apt.llvm.org/>`_. :program:`Clangd` is included in the
+`clang-tools` package.
+However, it is a good idea to check your distribution's packaging system first
+as it might already be available.
+
+Otherwise, you can install :program:`Clangd` by `building Clangd`_ first.
+
+Building Clangd
+==================
+
+You can follow the instructions for `building Clang
+<https://clang.llvm.org/get_started.html>`_ but "extra Clang tools" is **not**
+optional.
+
+Current Status
+==================
+
+Many features could be implemented in :program:`Clangd`.
+Here is a list of features that could be useful with the status of whether or
+not they are already implemented in :program:`Clangd` and specified in the
+Language Server Protocol. Note that for some of the features, it is not clear
+whether or not they should be part of the Language Server Protocol, so those
+features might be eventually developed outside :program:`Clangd` or as an
+extension to the protocol.
+
++-------------------------------------+------------+----------+
+| C/C++ Editor feature                |  LSP       |  Clangd  |
++=====================================+============+==========+
+| Formatting                          | Yes        |   Yes    |
++-------------------------------------+------------+----------+
+| Completion                          | Yes        |   Yes    |
++-------------------------------------+------------+----------+
+| Diagnostics                         | Yes        |   Yes    |
++-------------------------------------+------------+----------+ 
+| Fix-its                             | Yes        |   Yes    |
++-------------------------------------+------------+----------+
+| Go to Definition                    | Yes        |   Yes    |
++-------------------------------------+------------+----------+
+| Signature Help                      | Yes        |   Yes    |
++-------------------------------------+------------+----------+
+| Document Highlights                 | Yes        |   Yes    |
++-------------------------------------+------------+----------+
+| Rename                              | Yes        |   Yes    |
++-------------------------------------+------------+----------+
+| Source hover                        | Yes        |   Yes    |
++-------------------------------------+------------+----------+
+| Find References                     | Yes        |   No     |
++-------------------------------------+------------+----------+
+| Code Lens                           | Yes        |   No     |
++-------------------------------------+------------+----------+
+| Document Symbols                    | Yes        |   Yes    |
++-------------------------------------+------------+----------+
+| Workspace Symbols                   | Yes        |   No     |
++-------------------------------------+------------+----------+
+| Syntax and Semantic Coloring        | No         |   No     |
++-------------------------------------+------------+----------+
+| Code folding                        | No         |   No     |
++-------------------------------------+------------+----------+
+| Call hierarchy                      | No         |   No     |
++-------------------------------------+------------+----------+
+| Type hierarchy                      | No         |   No     |
++-------------------------------------+------------+----------+
+| Organize Includes                   | No         |   No     |
++-------------------------------------+------------+----------+
+| Quick Assist                        | No         |   No     |
++-------------------------------------+------------+----------+
+| Extract Local Variable              | No         |   No     |
++-------------------------------------+------------+----------+
+| Extract Function/Method             | No         |   No     |
++-------------------------------------+------------+----------+
+| Hide Method                         | No         |   No     |
++-------------------------------------+------------+----------+
+| Implement Method                    | No         |   No     |
++-------------------------------------+------------+----------+
+| Gen. Getters/Setters                | No         |   No     |
++-------------------------------------+------------+----------+
+
+Getting Involved
+==================
+
+A good place for interested contributors is the `Clang developer mailing list
+<http://lists.llvm.org/mailman/listinfo/cfe-dev>`_.
+If you're also interested in contributing patches to :program:`Clangd`, take a
+look at the `LLVM Developer Policy
+<http://llvm.org/docs/DeveloperPolicy.html>`_ and `Code Reviews
+<http://llvm.org/docs/Phabricator.html>`_ page. Contributions of new features
+to the `Language Server Protocol
+<https://github.com/Microsoft/language-server-protocol>`_ itself would also be
+very useful, so that :program:`Clangd` can eventually implement them in a
+conforming way.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/conf.py b/src/third_party/llvm-project/clang-tools-extra/docs/conf.py
new file mode 100644
index 0000000..5ac1821
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/conf.py
@@ -0,0 +1,243 @@
+# -*- coding: utf-8 -*-
+#
+# Extra Clang Tools documentation build configuration file, created by
+# sphinx-quickstart on Wed Feb 13 10:00:18 2013.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+from datetime import date
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.todo', 'sphinx.ext.mathjax']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Extra Clang Tools'
+copyright = u'2007-%d, The Clang Team' % date.today().year
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short version.
+version = '7'
+# The full version, including alpha/beta/rc tags.
+release = '7'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'friendly'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'haiku'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'ExtraClangToolsdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'ExtraClangTools.tex', u'Extra Clang Tools Documentation',
+   u'The Clang Team', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'extraclangtools', u'Extra Clang Tools Documentation',
+     [u'The Clang Team'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  ('index', 'ExtraClangTools', u'Extra Clang Tools Documentation',
+   u'The Clang Team', 'ExtraClangTools', 'One line description of project.',
+   'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/cpp11-migrate.rst b/src/third_party/llvm-project/clang-tools-extra/docs/cpp11-migrate.rst
new file mode 100644
index 0000000..0a42961
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/cpp11-migrate.rst
@@ -0,0 +1,4 @@
+:orphan:
+
+All :program:`clang-modernize` transforms have moved to :doc:`clang-tidy/index`
+(see the ``modernize`` module).
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/doxygen-mainpage.dox b/src/third_party/llvm-project/clang-tools-extra/docs/doxygen-mainpage.dox
new file mode 100644
index 0000000..a4527b8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/doxygen-mainpage.dox
@@ -0,0 +1,9 @@
+/// \mainpage clang-tools
+///
+/// \section main_intro Introduction
+/// Welcome to clang tools.
+///
+/// This documentation describes the **internal** software that makes
+/// up clang tools, not the **external** use of clang tools. For
+/// usage instructions, please see the programmer's guide or reference
+/// manual.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/doxygen.cfg.in b/src/third_party/llvm-project/clang-tools-extra/docs/doxygen.cfg.in
new file mode 100644
index 0000000..8809588
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/doxygen.cfg.in
@@ -0,0 +1,2305 @@
+# Doxyfile 1.8.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = clang-tools
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         = @PACKAGE_VERSION@
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = @abs_builddir@/doxygen
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = NO
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        = ../..
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 2
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 2
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. Do not use file names with spaces, bibtex cannot handle them. See
+# also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = NO
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = NO
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  =  \
+                          @abs_srcdir@/../change-namespace \
+                          @abs_srcdir@/../clang-apply-replacements \
+                          @abs_srcdir@/../clang-doc \
+                          @abs_srcdir@/../clang-move \
+                          @abs_srcdir@/../clang-query \
+                          @abs_srcdir@/../clang-reorder-fields \
+                          @abs_srcdir@/../clang-tidy \
+                          @abs_srcdir@/../clangd \
+                          @abs_srcdir@/../include-fixer \
+                          @abs_srcdir@/../modularize \
+                          @abs_srcdir@/../pp-trace \
+                          @abs_srcdir@/../tool-template \
+                          @abs_srcdir@/doxygen-mainpage.dox
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS          =
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = YES
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX    = 4
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          = clang::
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
+# defined cascading style sheet that is included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet file to the output directory. For an example
+# see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = @clang_tools_doxygen_generate_qhp@
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               = @clang_tools_doxygen_qch_filename@
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = @clang_tools_doxygen_qhp_namespace@
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   = @clang_tools_doxygen_qhp_cust_filter_name@
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  = @clang_tools_doxygen_qhp_cust_filter_attrs@
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           = @clang_tools_doxygen_qhelpgenerator_path@
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = @enable_searchengine@
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavours of web server based searching depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools. See
+# the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = @enable_server_based_search@
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = @enable_external_search@
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       = @searchengine_url@
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     = clang-tools
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  = @extra_search_mappings@
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
+# replace them by respectively the title of the page, the current date and time,
+# only the current date, the version number of doxygen, the project name (see
+# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = YES
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           = @abs_srcdir@/../../../include \
+                         @abs_srcdir@/../../../../../include
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             = LLVM_ALIGNAS(x)=
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have an
+# all uppercase name, and do not end with a semicolon. Such function macros are
+# typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have an unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = YES
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = NO
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font n the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = YES
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = @DOT_IMAGE_FORMAT@
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               = @DOT@
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = YES
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP            = YES
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/include-fixer.rst b/src/third_party/llvm-project/clang-tools-extra/docs/include-fixer.rst
new file mode 100644
index 0000000..fcd2998
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/include-fixer.rst
@@ -0,0 +1,155 @@
+===================
+Clang-Include-Fixer
+===================
+
+.. contents::
+
+One of the major nuisances of C++ compared to other languages is the manual
+management of ``#include`` directives in any file.
+:program:`clang-include-fixer` addresses one aspect of this problem by providing
+an automated way of adding ``#include`` directives for missing symbols in one
+translation unit.
+
+While inserting missing ``#include``, :program:`clang-include-fixer` adds
+missing namespace qualifiers to all instances of an unidentified symbol if
+the symbol is missing some prefix namespace qualifiers.
+
+Setup
+=====
+
+To use :program:`clang-include-fixer` two databases are required. Both can be
+generated with existing tools.
+
+- Compilation database. Contains the compiler commands for any given file in a
+  project and can be generated by CMake, see `How To Setup Tooling For LLVM`_.
+- Symbol index. Contains all symbol information in a project to match a given
+  identifier to a header file.
+
+Ideally both databases (``compile_commands.json`` and
+``find_all_symbols_db.yaml``) are linked into the root of the source tree they
+correspond to. Then the :program:`clang-include-fixer` can automatically pick
+them up if called with a source file from that tree. Note that by default
+``compile_commands.json`` as generated by CMake does not include header files,
+so only implementation files can be handled by tools.
+
+.. _How To Setup Tooling For LLVM: http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
+
+Creating a Symbol Index From a Compilation Database
+---------------------------------------------------
+
+The include fixer contains :program:`find-all-symbols`, a tool to create a
+symbol database in YAML format from a compilation database by parsing all
+source files listed in it. The following list of commands shows how to set up a
+database for LLVM, any project built by CMake should follow similar steps.
+
+.. code-block:: console
+
+  $ cd path/to/llvm-build
+  $ ninja find-all-symbols // build find-all-symbols tool.
+  $ ninja clang-include-fixer // build clang-include-fixer tool.
+  $ ls compile_commands.json # Make sure compile_commands.json exists.
+    compile_commands.json
+  $ path/to/llvm/source/tools/clang/tools/extra/include-fixer/find-all-symbols/tool/run-find-all-symbols.py
+    ... wait as clang indexes the code base ...
+  $ ln -s $PWD/find_all_symbols_db.yaml path/to/llvm/source/ # Link database into the source tree.
+  $ ln -s $PWD/compile_commands.json path/to/llvm/source/ # Also link compilation database if it's not there already.
+  $ cd path/to/llvm/source
+  $ /path/to/clang-include-fixer -db=yaml path/to/file/with/missing/include.cpp
+    Added #include "foo.h"
+
+Integrate with Vim
+------------------
+To run `clang-include-fixer` on a potentially unsaved buffer in Vim. Add the
+following key binding to your ``.vimrc``:
+
+.. code-block:: console
+
+  noremap <leader>cf :pyf path/to/llvm/source/tools/clang/tools/extra/include-fixer/tool/clang-include-fixer.py<cr>
+
+This enables `clang-include-fixer` for NORMAL and VISUAL mode. Change
+`<leader>cf` to another binding if you need clang-include-fixer on a different
+key. The `<leader> key
+<http://vim.wikia.com/wiki/Mapping_keys_in_Vim_-_Tutorial_(Part_3)#Map_leader>`_
+is a reference to a specific key defined by the mapleader variable and is bound
+to backslash by default.
+
+Make sure vim can find :program:`clang-include-fixer`:
+
+- Add the path to :program:`clang-include-fixer` to the PATH environment variable.
+- Or set ``g:clang_include_fixer_path`` in vimrc: ``let g:clang_include_fixer_path=path/to/clang-include-fixer``
+
+You can customize the number of headers being shown by setting
+``let g:clang_include_fixer_maximum_suggested_headers=5``
+
+Customized settings in `.vimrc`:
+
+- ``let g:clang_include_fixer_path = "clang-include-fixer"``
+
+  Set clang-include-fixer binary file path.
+
+- ``let g:clang_include_fixer_maximum_suggested_headers = 3``
+
+  Set the maximum number of ``#includes`` to show. Default is 3.
+
+- ``let g:clang_include_fixer_increment_num = 5``
+
+  Set the increment number of #includes to show every time when pressing ``m``.
+  Default is 5.
+
+- ``let g:clang_include_fixer_jump_to_include = 0``
+
+  Set to 1 if you want to jump to the new inserted ``#include`` line. Default is
+  0.
+
+- ``let g:clang_include_fixer_query_mode = 0``
+
+  Set to 1 if you want to insert ``#include`` for the symbol under the cursor.
+  Default is 0. Compared to normal mode, this mode won't parse the source file
+  and only search the sysmbol from database, which is faster than normal mode.
+
+See ``clang-include-fixer.py`` for more details.
+
+Integrate with Emacs
+--------------------
+To run `clang-include-fixer` on a potentially unsaved buffer in Emacs.
+Ensure that Emacs finds ``clang-include-fixer.el`` by adding the directory
+containing the file to the ``load-path`` and requiring the `clang-include-fixer`
+in your ``.emacs``:
+
+.. code-block:: console
+
+ (add-to-list 'load-path "path/to/llvm/source/tools/clang/tools/extra/include-fixer/tool/"
+ (require 'clang-include-fixer)
+
+Within Emacs the tool can be invoked with the command
+``M-x clang-include-fixer``. This will insert the header that defines the
+first undefined symbol; if there is more than one header that would define the
+symbol, the user is prompted to select one.
+
+To include the header that defines the symbol at point, run
+``M-x clang-include-fixer-at-point``.
+
+Make sure Emacs can find :program:`clang-include-fixer`:
+
+- Either add the parent directory of :program:`clang-include-fixer` to the PATH
+  environment variable, or customize the Emacs user option
+  ``clang-include-fixer-executable`` to point to the file name of the program.
+
+How it Works
+============
+
+To get the most information out of Clang at parse time,
+:program:`clang-include-fixer` runs in tandem with the parse and receives
+callbacks from Clang's semantic analysis. In particular it reuses the existing
+support for typo corrections. Whenever Clang tries to correct a potential typo
+it emits a callback to the include fixer which then looks for a corresponding
+file. At this point rich lookup information is still available, which is not
+available in the AST at a later stage.
+
+The identifier that should be typo corrected is then sent to the database, if a
+header file is returned it is added as an include directive at the top of the
+file.
+
+Currently :program:`clang-include-fixer` only inserts a single include at a
+time to avoid getting caught in follow-up errors. If multiple `#include`
+additions are desired the program can be rerun until a fix-point is reached.
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/index.rst b/src/third_party/llvm-project/clang-tools-extra/docs/index.rst
new file mode 100644
index 0000000..55fd1a6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/index.rst
@@ -0,0 +1,36 @@
+.. Extra Clang Tools documentation master file, created by
+   sphinx-quickstart on Wed Feb 13 10:00:18 2013.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+.. title:: Welcome to Extra Clang Tools's documentation!
+
+Introduction
+============
+Welcome to the clang-tools-extra project which contains extra tools built using
+Clang's tooling API's.
+
+.. toctree::
+   :maxdepth: 1
+
+   ReleaseNotes
+
+Contents
+========
+.. toctree::
+   :maxdepth: 2
+
+   clang-tidy/index
+   include-fixer
+   modularize
+   pp-trace
+   clang-rename
+   clangd
+   clang-doc
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`search`
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/make.bat b/src/third_party/llvm-project/clang-tools-extra/docs/make.bat
new file mode 100644
index 0000000..09b798c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/make.bat
@@ -0,0 +1,190 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+	set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+	:help
+	echo.Please use `make ^<target^>` where ^<target^> is one of
+	echo.  html       to make standalone HTML files
+	echo.  dirhtml    to make HTML files named index.html in directories
+	echo.  singlehtml to make a single large HTML file
+	echo.  pickle     to make pickle files
+	echo.  json       to make JSON files
+	echo.  htmlhelp   to make HTML files and a HTML help project
+	echo.  qthelp     to make HTML files and a qthelp project
+	echo.  devhelp    to make HTML files and a Devhelp project
+	echo.  epub       to make an epub
+	echo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+	echo.  text       to make text files
+	echo.  man        to make manual pages
+	echo.  texinfo    to make Texinfo files
+	echo.  gettext    to make PO message catalogs
+	echo.  changes    to make an overview over all changed/added/deprecated items
+	echo.  linkcheck  to check all external links for integrity
+	echo.  doctest    to run all doctests embedded in the documentation if enabled
+	goto end
+)
+
+if "%1" == "clean" (
+	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+	del /q /s %BUILDDIR%\*
+	goto end
+)
+
+if "%1" == "html" (
+	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+	goto end
+)
+
+if "%1" == "dirhtml" (
+	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+	goto end
+)
+
+if "%1" == "singlehtml" (
+	%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+	goto end
+)
+
+if "%1" == "pickle" (
+	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the pickle files.
+	goto end
+)
+
+if "%1" == "json" (
+	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the JSON files.
+	goto end
+)
+
+if "%1" == "htmlhelp" (
+	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+	goto end
+)
+
+if "%1" == "qthelp" (
+	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\ExtraClangTools.qhcp
+	echo.To view the help file:
+	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\ExtraClangTools.ghc
+	goto end
+)
+
+if "%1" == "devhelp" (
+	%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished.
+	goto end
+)
+
+if "%1" == "epub" (
+	%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The epub file is in %BUILDDIR%/epub.
+	goto end
+)
+
+if "%1" == "latex" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "text" (
+	%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The text files are in %BUILDDIR%/text.
+	goto end
+)
+
+if "%1" == "man" (
+	%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The manual pages are in %BUILDDIR%/man.
+	goto end
+)
+
+if "%1" == "texinfo" (
+	%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+	goto end
+)
+
+if "%1" == "gettext" (
+	%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+	goto end
+)
+
+if "%1" == "changes" (
+	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.The overview file is in %BUILDDIR%/changes.
+	goto end
+)
+
+if "%1" == "linkcheck" (
+	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+	goto end
+)
+
+if "%1" == "doctest" (
+	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+	goto end
+)
+
+:end
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/modularize.rst b/src/third_party/llvm-project/clang-tools-extra/docs/modularize.rst
new file mode 100644
index 0000000..6fe49b4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/modularize.rst
@@ -0,0 +1,265 @@
+.. index:: modularize
+
+==================================
+Modularize User's Manual
+==================================
+
+.. toctree::
+   :hidden:
+
+   ModularizeUsage
+
+:program:`modularize` is a standalone tool that checks whether a set of headers
+provides the consistent definitions required to use modules. For example, it
+detects whether the same entity (say, a NULL macro or size_t typedef) is
+defined in multiple headers or whether a header produces different definitions
+under different circumstances. These conditions cause modules built from the
+headers to behave poorly, and should be fixed before introducing a module
+map.
+
+:program:`modularize` also has an assistant mode option for generating
+a module map file based on the provided header list. The generated file
+is a functional module map that can be used as a starting point for a
+module.map file.
+
+Getting Started
+===============
+
+To build from source:
+
+1. Read `Getting Started with the LLVM System`_ and `Clang Tools
+   Documentation`_ for information on getting sources for LLVM, Clang, and
+   Clang Extra Tools.
+
+2. `Getting Started with the LLVM System`_ and `Building LLVM with CMake`_ give
+   directions for how to build. With sources all checked out into the
+   right place the LLVM build will build Clang Extra Tools and their
+   dependencies automatically.
+
+   * If using CMake, you can also use the ``modularize`` target to build
+     just the modularize tool and its dependencies.
+
+Before continuing, take a look at :doc:`ModularizeUsage` to see how to invoke
+modularize.
+
+.. _Getting Started with the LLVM System: http://llvm.org/docs/GettingStarted.html
+.. _Building LLVM with CMake: http://llvm.org/docs/CMake.html
+.. _Clang Tools Documentation: http://clang.llvm.org/docs/ClangTools.html
+
+What Modularize Checks
+======================
+
+Modularize will check for the following:
+
+* Duplicate global type and variable definitions
+* Duplicate macro definitions
+* Macro instances, 'defined(macro)', or #if, #elif, #ifdef, #ifndef conditions
+  that evaluate differently in a header
+* #include directives inside 'extern "C/C++" {}' or 'namespace (name) {}' blocks
+* Module map header coverage completeness (in the case of a module map input
+  only)
+
+Modularize will do normal C/C++ parsing, reporting normal errors and warnings,
+but will also report special error messages like the following::
+
+  error: '(symbol)' defined at multiple locations:
+     (file):(row):(column)
+     (file):(row):(column)
+
+  error: header '(file)' has different contents depending on how it was included
+
+The latter might be followed by messages like the following::
+
+  note: '(symbol)' in (file) at (row):(column) not always provided
+
+Checks will also be performed for macro expansions, defined(macro)
+expressions, and preprocessor conditional directives that evaluate
+inconsistently, and can produce error messages like the following::
+
+   (...)/SubHeader.h:11:5:
+  #if SYMBOL == 1
+      ^
+  error: Macro instance 'SYMBOL' has different values in this header,
+         depending on how it was included.
+    'SYMBOL' expanded to: '1' with respect to these inclusion paths:
+      (...)/Header1.h
+        (...)/SubHeader.h
+  (...)/SubHeader.h:3:9:
+  #define SYMBOL 1
+          ^
+  Macro defined here.
+    'SYMBOL' expanded to: '2' with respect to these inclusion paths:
+      (...)/Header2.h
+          (...)/SubHeader.h
+  (...)/SubHeader.h:7:9:
+  #define SYMBOL 2
+          ^
+  Macro defined here.
+
+Checks will also be performed for '#include' directives that are
+nested inside 'extern "C/C++" {}' or 'namespace (name) {}' blocks,
+and can produce error message like the following::
+
+  IncludeInExtern.h:2:3:
+  #include "Empty.h"
+  ^
+  error: Include directive within extern "C" {}.
+  IncludeInExtern.h:1:1:
+  extern "C" {
+  ^
+  The "extern "C" {}" block is here.
+
+.. _module-map-coverage:
+
+Module Map Coverage Check
+=========================
+
+The coverage check uses the Clang library to read and parse the
+module map file. Starting at the module map file directory, or just the
+include paths, if specified, it will collect the names of all the files it
+considers headers (no extension, .h, or .inc--if you need more, modify the
+isHeader function). It then compares the headers against those referenced
+in the module map, either explicitly named, or implicitly named via an
+umbrella directory or umbrella file, as parsed by the ModuleMap object.
+If headers are found which are not referenced or covered by an umbrella
+directory or file, warning messages will be produced, and this program
+will return an error code of 1. If no problems are found, an error code of
+0 is returned.
+
+Note that in the case of umbrella headers, this tool invokes the compiler
+to preprocess the file, and uses a callback to collect the header files
+included by the umbrella header or any of its nested includes. If any
+front end options are needed for these compiler invocations, these
+can be included on the command line after the module map file argument.
+
+Warning message have the form:
+
+  warning: module.modulemap does not account for file: Level3A.h
+
+Note that for the case of the module map referencing a file that does
+not exist, the module map parser in Clang will (at the time of this
+writing) display an error message.
+
+To limit the checks :program:`modularize` does to just the module
+map coverage check, use the ``-coverage-check-only option``.
+
+For example::
+
+  modularize -coverage-check-only module.modulemap
+
+.. _module-map-generation:
+
+Module Map Generation
+=====================
+
+If you specify the ``-module-map-path=<module map file>``,
+:program:`modularize` will output a module map based on the input header list.
+A module will be created for each header. Also, if the header in the header
+list is a partial path, a nested module hierarchy will be created in which a
+module will be created for each subdirectory component in the header path,
+with the header itself represented by the innermost module. If other headers
+use the same subdirectories, they will be enclosed in these same modules also.
+
+For example, for the header list::
+
+  SomeTypes.h
+  SomeDecls.h
+  SubModule1/Header1.h
+  SubModule1/Header2.h
+  SubModule2/Header3.h
+  SubModule2/Header4.h
+  SubModule2.h
+
+The following module map will be generated::
+
+  // Output/NoProblemsAssistant.txt
+  // Generated by: modularize -module-map-path=Output/NoProblemsAssistant.txt \
+       -root-module=Root NoProblemsAssistant.modularize
+  
+  module SomeTypes {
+    header "SomeTypes.h"
+    export *
+  }
+  module SomeDecls {
+    header "SomeDecls.h"
+    export *
+  }
+  module SubModule1 {
+    module Header1 {
+      header "SubModule1/Header1.h"
+      export *
+    }
+    module Header2 {
+      header "SubModule1/Header2.h"
+      export *
+    }
+  }
+  module SubModule2 {
+    module Header3 {
+      header "SubModule2/Header3.h"
+      export *
+    }
+    module Header4 {
+      header "SubModule2/Header4.h"
+      export *
+    }
+    header "SubModule2.h"
+    export *
+  }
+
+An optional ``-root-module=<root-name>`` option can be used to cause a root module
+to be created which encloses all the modules.
+
+An optional ``-problem-files-list=<problem-file-name>`` can be used to input
+a list of files to be excluded, perhaps as a temporary stop-gap measure until
+problem headers can be fixed.
+
+For example, with the same header list from above::
+
+  // Output/NoProblemsAssistant.txt
+  // Generated by: modularize -module-map-path=Output/NoProblemsAssistant.txt \
+       -root-module=Root NoProblemsAssistant.modularize
+  
+  module Root {
+    module SomeTypes {
+      header "SomeTypes.h"
+      export *
+    }
+    module SomeDecls {
+      header "SomeDecls.h"
+      export *
+    }
+    module SubModule1 {
+      module Header1 {
+        header "SubModule1/Header1.h"
+        export *
+      }
+      module Header2 {
+        header "SubModule1/Header2.h"
+        export *
+      }
+    }
+    module SubModule2 {
+      module Header3 {
+        header "SubModule2/Header3.h"
+        export *
+      }
+      module Header4 {
+        header "SubModule2/Header4.h"
+        export *
+      }
+      header "SubModule2.h"
+      export *
+    }
+  }
+
+Note that headers with dependents will be ignored with a warning, as the
+Clang module mechanism doesn't support headers the rely on other headers
+to be included first.
+
+The module map format defines some keywords which can't be used in module
+names. If a header has one of these names, an underscore ('_') will be
+prepended to the name. For example, if the header name is ``header.h``,
+because ``header`` is a keyword, the module name will be ``_header``.
+For a list of the module map keywords, please see:
+`Lexical structure <http://clang.llvm.org/docs/Modules.html#lexical-structure>`_
diff --git a/src/third_party/llvm-project/clang-tools-extra/docs/pp-trace.rst b/src/third_party/llvm-project/clang-tools-extra/docs/pp-trace.rst
new file mode 100644
index 0000000..b8768ed
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/docs/pp-trace.rst
@@ -0,0 +1,825 @@
+.. index:: pp-trace
+
+==================================
+pp-trace User's Manual
+==================================
+
+.. toctree::
+   :hidden:
+
+:program:`pp-trace` is a standalone tool that traces preprocessor
+activity. It's also used as a test of Clang's PPCallbacks interface.
+It runs a given source file through the Clang preprocessor, displaying
+selected information from callback functions overridden in a
+`PPCallbacks <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html>`_
+derivation. The output is in a high-level YAML format, described in
+:ref:`OutputFormat`.
+
+.. _Usage:
+
+pp-trace Usage
+==============
+
+Command Line Format
+-------------------
+
+``pp-trace [<pp-trace-options>] <source-file> [<front-end-options>]``
+
+``<pp-trace-options>`` is a place-holder for options
+specific to pp-trace, which are described below in
+:ref:`CommandLineOptions`.
+
+``<source-file>`` specifies the source file to run through the preprocessor.
+
+``<front-end-options>`` is a place-holder for regular
+`Clang Compiler Options <http://clang.llvm.org/docs/UsersManual.html#command-line-options>`_,
+which must follow the <source-file>.
+
+.. _CommandLineOptions:
+
+Command Line Options
+--------------------
+
+.. option:: -ignore <callback-name-list>
+
+  This option specifies a comma-separated list of names of callbacks
+  that shouldn't be traced. It can be used to eliminate unwanted
+  trace output. The callback names are the name of the actual
+  callback function names in the PPCallbacks class:
+
+  * FileChanged
+  * FileSkipped
+  * FileNotFound
+  * InclusionDirective
+  * moduleImport
+  * EndOfMainFile
+  * Ident
+  * PragmaDirective
+  * PragmaComment
+  * PragmaDetectMismatch
+  * PragmaDebug
+  * PragmaMessage
+  * PragmaDiagnosticPush
+  * PragmaDiagnosticPop
+  * PragmaDiagnostic
+  * PragmaOpenCLExtension
+  * PragmaWarning
+  * PragmaWarningPush
+  * PragmaWarningPop
+  * MacroExpands
+  * MacroDefined
+  * MacroUndefined
+  * Defined
+  * SourceRangeSkipped
+  * If
+  * Elif
+  * Ifdef
+  * Ifndef
+  * Else
+  * Endif
+
+.. option:: -output <output-file>
+
+  By default, pp-trace outputs the trace information to stdout. Use this
+  option to output the trace information to a file.
+
+.. _OutputFormat:
+
+pp-trace Output Format
+======================
+
+The pp-trace output is formatted as YAML. See http://yaml.org/ for general
+YAML information. It's arranged as a sequence of information about the
+callback call, including the callback name and argument information, for
+example:::
+
+  ---
+  - Callback: Name
+    Argument1: Value1
+    Argument2: Value2
+  (etc.)
+  ...
+
+With real data:::
+
+  ---
+  - Callback: FileChanged
+    Loc: "c:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-include.cpp:1:1"
+    Reason: EnterFile
+    FileType: C_User
+    PrevFID: (invalid)
+    (etc.)
+  - Callback: FileChanged
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-include.cpp:5:1"
+    Reason: ExitFile
+    FileType: C_User
+    PrevFID: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/Input/Level1B.h"
+  - Callback: EndOfMainFile
+  ...
+
+In all but one case (MacroDirective) the "Argument" scalars have the same
+name as the argument in the corresponding PPCallbacks callback function.
+
+Callback Details
+----------------
+
+The following sections describe the pupose and output format for each callback.
+
+Click on the callback name in the section heading to see the Doxygen
+documentation for the callback.
+
+The argument descriptions table describes the callback argument information
+displayed.
+
+The Argument Name field in most (but not all) cases is the same name as the
+callback function parameter.
+
+The Argument Value Syntax field describes the values that will be displayed
+for the argument value. It uses an ad hoc representation that mixes literal
+and symbolic representations. Enumeration member symbols are shown as the
+actual enum member in a (member1|member2|...) form. A name in parentheses
+can either represent a place holder for the described value, or confusingly,
+it might be a literal, such as (null), for a null pointer.
+Locations are shown as quoted only to avoid confusing the documentation generator.
+
+The Clang C++ Type field is the type from the callback function declaration.
+
+The description describes the argument or what is displayed for it.
+
+Note that in some cases, such as when a structure pointer is an argument
+value, only some key member or members are shown to represent the value,
+instead of trying to display all members of the structure.
+
+`FileChanged <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a7cc8cfaf34114fc65e92af621cd6464e>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+FileChanged is called when the preprocessor enters or exits a file, both the
+top level file being compiled, as well as any #include directives. It will
+also be called as a result of a system header pragma or in internal renaming
+of a file.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==============================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==============================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+Reason           (EnterFile|ExitFile|SystemHeaderPragma|RenameFile)   PPCallbacks::FileChangeReason  Reason for change.
+FileType         (C_User|C_System|C_ExternCSystem)                    SrcMgr::CharacteristicKind     Include type.
+PrevFID          ((file)|(invalid))                                   FileID                         Previous file, if any.
+==============   ==================================================   ============================== ==============================
+
+Example:::
+
+  - Callback: FileChanged
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-include.cpp:1:1"
+    Reason: EnterFile
+    FileType: C_User
+    PrevFID: (invalid)
+
+`FileSkipped <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ab5b338a0670188eb05fa7685bbfb5128>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+FileSkipped is called when a source file is skipped as the result of header
+guard optimization.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ========================================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ========================================================
+ParentFile       ("(file)" or (null))                                 const FileEntry                The file that #included the skipped file.
+FilenameTok      (token)                                              const Token                    The token in ParentFile that indicates the skipped file.
+FileType         (C_User|C_System|C_ExternCSystem)                    SrcMgr::CharacteristicKind     The file type.
+==============   ==================================================   ============================== ========================================================
+
+Example:::
+
+  - Callback: FileSkipped
+    ParentFile: "/path/filename.h"
+    FilenameTok: "filename.h"
+    FileType: C_User
+
+`FileNotFound <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a3045151545f987256bfa8d978916ef00>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+FileNotFound is called when an inclusion directive results in a file-not-found error.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== =====================================================================================================================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== =====================================================================================================================================
+FileName         "(file)"                                             StringRef                      The name of the file being included, as written in the source code.
+RecoveryPath     (path)                                               SmallVectorImpl<char>          If this client indicates that it can recover from this missing file, the client should set this as an additional header search patch.
+==============   ==================================================   ============================== =====================================================================================================================================
+
+Example:::
+
+  - Callback: FileNotFound
+    FileName: "/path/filename.h"
+    RecoveryPath:
+
+`InclusionDirective <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a557d9738c329793513a6f57d6b60de52>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+InclusionDirective is called when an inclusion directive of any kind (#include</code>, #import</code>, etc.) has been processed, regardless of whether the inclusion will actually result in an inclusion.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ============================================================================================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ============================================================================================================
+HashLoc          "(file):(line):(col)"                                SourceLocation                 The location of the '#' that starts the inclusion directive.
+IncludeTok       (token)                                              const Token                    The token that indicates the kind of inclusion directive, e.g., 'include' or 'import'.
+FileName         "(file)"                                             StringRef                      The name of the file being included, as written in the source code.
+IsAngled         (true|false)                                         bool                           Whether the file name was enclosed in angle brackets; otherwise, it was enclosed in quotes.
+FilenameRange    "(file)"                                             CharSourceRange                The character range of the quotes or angle brackets for the written file name.
+File             "(file)"                                             const FileEntry                The actual file that may be included by this inclusion directive.
+SearchPath       "(path)"                                             StringRef                      Contains the search path which was used to find the file in the file system.
+RelativePath     "(path)"                                             StringRef                      The path relative to SearchPath, at which the include file was found.
+Imported         ((module name)|(null))                               const Module                   The module, whenever an inclusion directive was automatically turned into a module import or null otherwise.
+==============   ==================================================   ============================== ============================================================================================================
+
+Example:::
+
+  - Callback: InclusionDirective
+    IncludeTok: include
+    FileName: "Input/Level1B.h"
+    IsAngled: false
+    FilenameRange: "Input/Level1B.h"
+    File: "D:/Clang/llvmnewmod/tools/clang/tools/extra/test/pp-trace/Input/Level1B.h"
+    SearchPath: "D:/Clang/llvmnewmod/tools/clang/tools/extra/test/pp-trace"
+    RelativePath: "Input/Level1B.h"
+    Imported: (null)
+
+`moduleImport <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#af32dcf1b8b7c179c7fcd3e24e89830fe>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+moduleImport is called when there was an explicit module-import syntax.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ===========================================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ===========================================================
+ImportLoc        "(file):(line):(col)"                                SourceLocation                 The location of import directive token.
+Path             "(path)"                                             ModuleIdPath                   The identifiers (and their locations) of the module "path".
+Imported         ((module name)|(null))                               const Module                   The imported module; can be null if importing failed.
+==============   ==================================================   ============================== ===========================================================
+
+Example:::
+
+  - Callback: moduleImport
+    ImportLoc: "d:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-modules.cpp:4:2"
+    Path: [{Name: Level1B, Loc: "d:/Clang/llvmnewmod/tools/clang/tools/extra/test/pp-trace/pp-trace-modules.cpp:4:9"}, {Name: Level2B, Loc: "d:/Clang/llvmnewmod/tools/clang/tools/extra/test/pp-trace/pp-trace-modules.cpp:4:17"}]
+    Imported: Level2B
+
+`EndOfMainFile <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a63e170d069e99bc1c9c7ea0f3bed8bcc>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+EndOfMainFile is called when the end of the main file is reached.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ======================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ======================
+(no arguments)
+==============   ==================================================   ============================== ======================
+
+Example:::
+
+  - Callback: EndOfMainFile
+
+`Ident <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a3683f1d1fa513e9b6193d446a5cc2b66>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Ident is called when a #ident or #sccs directive is read.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==============================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==============================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+str              (name)                                               const std::string              The text of the directive.
+==============   ==================================================   ============================== ==============================
+
+Example:::
+
+  - Callback: Ident
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-ident.cpp:3:1"
+    str: "$Id$"
+
+`PragmaDirective <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a0a2d7a72c62184b3cbde31fb62c6f2f7>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PragmaDirective is called when start reading any pragma directive.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== =================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== =================================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+Introducer       (PIK_HashPragma|PIK__Pragma|PIK___pragma)            PragmaIntroducerKind           The type of the pragma directive.
+==============   ==================================================   ============================== =================================
+
+Example:::
+
+  - Callback: PragmaDirective
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
+    Introducer: PIK_HashPragma
+
+`PragmaComment <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ace0d940fc2c12ab76441466aab58dc37>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PragmaComment is called when a #pragma comment directive is read.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==============================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==============================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+Kind             ((name)|(null))                                      const IdentifierInfo           The comment kind symbol.
+Str              (message directive)                                  const std::string              The comment message directive.
+==============   ==================================================   ============================== ==============================
+
+Example:::
+
+  - Callback: PragmaComment
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
+    Kind: library
+    Str: kernel32.lib
+
+`PragmaDetectMismatch <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ab11158c9149fb8ad8af1903f4a6cd65d>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PragmaDetectMismatch is called when a #pragma detect_mismatch directive is read.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==============================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==============================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+Name             "(name)"                                             const std::string              The name.
+Value            (string)                                             const std::string              The value.
+==============   ==================================================   ============================== ==============================
+
+Example:::
+
+  - Callback: PragmaDetectMismatch
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
+    Name: name
+    Value: value
+
+`PragmaDebug <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a57cdccb6dcc07e926513ac3d5b121466>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PragmaDebug is called when a #pragma clang __debug directive is read.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ================================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+DebugType        (string)                                             StringRef                      Indicates type of debug message.
+==============   ==================================================   ============================== ================================
+
+Example:::
+
+  - Callback: PragmaDebug
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
+    DebugType: warning
+
+`PragmaMessage <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#abb42935d9a9fd8e2c4f51cfdc4ea2ae1>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PragmaMessage is called when a #pragma message directive is read.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== =======================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== =======================================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+Namespace        (name)                                               StringRef                      The namespace of the message directive.
+Kind             (PMK_Message|PMK_Warning|PMK_Error)                  PPCallbacks::PragmaMessageKind The type of the message directive.
+Str              (string)                                             StringRef                      The text of the message directive.
+==============   ==================================================   ============================== =======================================
+
+Example:::
+
+  - Callback: PragmaMessage
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
+    Namespace: "GCC"
+    Kind: PMK_Message
+    Str: The message text.
+
+`PragmaDiagnosticPush <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a0f3ff19762baa38fe6c5c58022d32979>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PragmaDiagnosticPush is called when a #pragma gcc dianostic push directive is read.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==============================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==============================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+Namespace        (name)                                               StringRef                      Namespace name.
+==============   ==================================================   ============================== ==============================
+
+Example:::
+
+  - Callback: PragmaDiagnosticPush
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
+    Namespace: "GCC"
+
+`PragmaDiagnosticPop <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ac94d789873122221fba8d76f6c5ea45e>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PragmaDiagnosticPop is called when a #pragma gcc dianostic pop directive is read.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==============================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==============================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+Namespace        (name)                                               StringRef                      Namespace name.
+==============   ==================================================   ============================== ==============================
+
+Example:::
+
+  - Callback: PragmaDiagnosticPop
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
+    Namespace: "GCC"
+
+`PragmaDiagnostic <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#afe7938f38a83cb7b4b25a13edfdd7bdd>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PragmaDiagnostic is called when a #pragma gcc dianostic directive is read.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==============================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==============================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+Namespace        (name)                                               StringRef                      Namespace name.
+mapping          (0|MAP_IGNORE|MAP_WARNING|MAP_ERROR|MAP_FATAL)       diag::Severity                 Mapping type.
+Str              (string)                                             StringRef                      Warning/error name.
+==============   ==================================================   ============================== ==============================
+
+Example:::
+
+  - Callback: PragmaDiagnostic
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
+    Namespace: "GCC"
+    mapping: MAP_WARNING
+    Str: WarningName
+
+`PragmaOpenCLExtension <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a92a20a21fadbab4e2c788f4e27fe07e7>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PragmaOpenCLExtension is called when OpenCL extension is either disabled or enabled with a pragma.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==========================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==========================
+NameLoc          "(file):(line):(col)"                                SourceLocation                 The location of the name.
+Name             (name)                                               const IdentifierInfo           Name symbol.
+StateLoc         "(file):(line):(col)"                                SourceLocation                 The location of the state.
+State            (1|0)                                                unsigned                       Enabled/disabled state.
+==============   ==================================================   ============================== ==========================
+
+Example:::
+
+  - Callback: PragmaOpenCLExtension
+    NameLoc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:10"
+    Name: Name
+    StateLoc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:18"
+    State: 1
+
+`PragmaWarning <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#aa17169d25fa1cf0a6992fc944d1d8730>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PragmaWarning is called when a #pragma warning directive is read.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==============================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==============================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+WarningSpec      (string)                                             StringRef                      The warning specifier.
+Ids              [(number)[, ...]]                                    ArrayRef<int>                  The warning numbers.
+==============   ==================================================   ============================== ==============================
+
+Example:::
+
+  - Callback: PragmaWarning
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
+    WarningSpec: disable
+    Ids: 1,2,3
+
+`PragmaWarningPush <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ae5626ef70502687a859f323a809ed0b6>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PragmaWarningPush is called when a #pragma warning(push) directive is read.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==============================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==============================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+Level            (number)                                             int                            Warning level.
+==============   ==================================================   ============================== ==============================
+
+Example:::
+
+  - Callback: PragmaWarningPush
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
+    Level: 1
+
+`PragmaWarningPop <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ac98d502af8811b8a6e7342d7cd2b3b95>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PragmaWarningPop is called when a #pragma warning(pop) directive is read.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==============================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==============================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+==============   ==================================================   ============================== ==============================
+
+Example:::
+
+  - Callback: PragmaWarningPop
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
+
+`MacroExpands <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a9bc725209d3a071ea649144ab996d515>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+MacroExpands is called when ::HandleMacroExpandedIdentifier when a macro invocation is found.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ======================================================================================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ======================================================================================================
+MacroNameTok     (token)                                              const Token                    The macro name token.
+MacroDirective   (MD_Define|MD_Undefine|MD_Visibility)                const MacroDirective           The kind of macro directive from the MacroDirective structure.
+Range            ["(file):(line):(col)", "(file):(line):(col)"]       SourceRange                    The source range for the expansion.
+Args             [(name)|(number)|<(token name)>[, ...]]              const MacroArgs                The argument tokens. Names and numbers are literal, everything else is of the form '<' tokenName '>'.
+==============   ==================================================   ============================== ======================================================================================================
+
+Example:::
+
+  - Callback: MacroExpands
+    MacroNameTok: X_IMPL
+    MacroDirective: MD_Define
+    Range: [(nonfile), (nonfile)]
+    Args: [a <plus> y, b]
+
+`MacroDefined <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a8448fc9f96f22ad1b93ff393cffc5a76>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+MacroDefined is called when a macro definition is seen.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==============================================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==============================================================
+MacroNameTok     (token)                                              const Token                    The macro name token.
+MacroDirective   (MD_Define|MD_Undefine|MD_Visibility)                const MacroDirective           The kind of macro directive from the MacroDirective structure.
+==============   ==================================================   ============================== ==============================================================
+
+Example:::
+
+  - Callback: MacroDefined
+    MacroNameTok: X_IMPL
+    MacroDirective: MD_Define
+
+`MacroUndefined <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#acb80fc6171a839db8e290945bf2c9d7a>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+MacroUndefined is called when a macro #undef is seen.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==============================================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==============================================================
+MacroNameTok     (token)                                              const Token                    The macro name token.
+MacroDirective   (MD_Define|MD_Undefine|MD_Visibility)                const MacroDirective           The kind of macro directive from the MacroDirective structure.
+==============   ==================================================   ============================== ==============================================================
+
+Example:::
+
+  - Callback: MacroUndefined
+    MacroNameTok: X_IMPL
+    MacroDirective: MD_Define
+
+`Defined <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a3cc2a644533d0e4088a13d2baf90db94>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Defined is called when the 'defined' operator is seen.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==============================================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==============================================================
+MacroNameTok     (token)                                              const Token                    The macro name token.
+MacroDirective   (MD_Define|MD_Undefine|MD_Visibility)                const MacroDirective           The kind of macro directive from the MacroDirective structure.
+Range            ["(file):(line):(col)", "(file):(line):(col)"]       SourceRange                    The source range for the directive.
+==============   ==================================================   ============================== ==============================================================
+
+Example:::
+
+  - Callback: Defined
+    MacroNameTok: MACRO
+    MacroDirective: (null)
+    Range: ["D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:8:5", "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:8:19"]
+
+`SourceRangeSkipped <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#abdb4ebe11610f079ac33515965794b46>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+SourceRangeSkipped is called when a source range is skipped.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== =========================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== =========================
+Range            ["(file):(line):(col)", "(file):(line):(col)"]       SourceRange                    The source range skipped.
+==============   ==================================================   ============================== =========================
+
+Example:::
+
+  - Callback: SourceRangeSkipped
+    Range: [":/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:8:2", ":/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:9:2"]
+
+`If <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a645edcb0d6becbc6f256f02fd1287778>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If is called when an #if is seen.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ===================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ===================================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+ConditionRange   ["(file):(line):(col)", "(file):(line):(col)"]       SourceRange                    The source range for the condition.
+ConditionValue   (true|false)                                         bool                           The condition value.
+==============   ==================================================   ============================== ===================================
+
+Example:::
+
+  - Callback: If
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:8:2"
+    ConditionRange: ["D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:8:4", "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:9:1"]
+    ConditionValue: false
+
+`Elif <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a180c9e106a28d60a6112e16b1bb8302a>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Elif is called when an #elif is seen.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ===================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ===================================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+ConditionRange   ["(file):(line):(col)", "(file):(line):(col)"]       SourceRange                    The source range for the condition.
+ConditionValue   (true|false)                                         bool                           The condition value.
+IfLoc            "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+==============   ==================================================   ============================== ===================================
+
+Example:::
+
+  - Callback: Elif
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:10:2"
+    ConditionRange: ["D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:10:4", "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:11:1"]
+    ConditionValue: false
+    IfLoc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:8:2"
+
+`Ifdef <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a0ce79575dda307784fd51a6dd4eec33d>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Ifdef is called when an #ifdef is seen.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==============================================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==============================================================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+MacroNameTok     (token)                                              const Token                    The macro name token.
+MacroDirective   (MD_Define|MD_Undefine|MD_Visibility)                const MacroDirective           The kind of macro directive from the MacroDirective structure.
+==============   ==================================================   ============================== ==============================================================
+
+Example:::
+
+  - Callback: Ifdef
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-conditional.cpp:3:1"
+    MacroNameTok: MACRO
+    MacroDirective: MD_Define
+
+`Ifndef <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a767af69f1cdcc4cd880fa2ebf77ad3ad>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Ifndef is called when an #ifndef is seen.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ==============================================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ==============================================================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the directive.
+MacroNameTok     (token)                                              const Token                    The macro name token.
+MacroDirective   (MD_Define|MD_Undefine|MD_Visibility)                const MacroDirective           The kind of macro directive from the MacroDirective structure.
+==============   ==================================================   ============================== ==============================================================
+
+Example:::
+
+  - Callback: Ifndef
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-conditional.cpp:3:1"
+    MacroNameTok: MACRO
+    MacroDirective: MD_Define
+
+`Else <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ad57f91b6d9c3cbcca326a2bfb49e0314>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Else is called when an #else is seen.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ===================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ===================================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the else directive.
+IfLoc            "(file):(line):(col)"                                SourceLocation                 The location of the if directive.
+==============   ==================================================   ============================== ===================================
+
+Example:::
+
+  - Callback: Else
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:10:2"
+    IfLoc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:8:2"
+
+`Endif <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#afc62ca1401125f516d58b1629a2093ce>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Endif is called when an #endif is seen.
+
+Argument descriptions:
+
+==============   ==================================================   ============================== ====================================
+Argument Name    Argument Value Syntax                                Clang C++ Type                 Description           
+==============   ==================================================   ============================== ====================================
+Loc              "(file):(line):(col)"                                SourceLocation                 The location of the endif directive.
+IfLoc            "(file):(line):(col)"                                SourceLocation                 The location of the if directive.
+==============   ==================================================   ============================== ====================================
+
+Example:::
+
+  - Callback: Endif
+    Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:10:2"
+    IfLoc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:8:2"
+
+Building pp-trace
+=================
+
+To build from source:
+
+1. Read `Getting Started with the LLVM System`_ and `Clang Tools
+   Documentation`_ for information on getting sources for LLVM, Clang, and
+   Clang Extra Tools.
+
+2. `Getting Started with the LLVM System`_ and `Building LLVM with CMake`_ give
+   directions for how to build. With sources all checked out into the
+   right place the LLVM build will build Clang Extra Tools and their
+   dependencies automatically.
+
+   * If using CMake, you can also use the ``pp-trace`` target to build
+     just the pp-trace tool and its dependencies.
+
+.. _Getting Started with the LLVM System: http://llvm.org/docs/GettingStarted.html
+.. _Building LLVM with CMake: http://llvm.org/docs/CMake.html
+.. _Clang Tools Documentation: http://clang.llvm.org/docs/ClangTools.html
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/include-fixer/CMakeLists.txt
new file mode 100644
index 0000000..3981fcd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/CMakeLists.txt
@@ -0,0 +1,28 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  )
+
+add_clang_library(clangIncludeFixer
+  IncludeFixer.cpp
+  IncludeFixerContext.cpp
+  InMemorySymbolIndex.cpp
+  FuzzySymbolIndex.cpp
+  SymbolIndexManager.cpp
+  YamlSymbolIndex.cpp
+
+  LINK_LIBS
+  clangAST
+  clangBasic
+  clangFormat
+  clangFrontend
+  clangLex
+  clangParse
+  clangSema
+  clangTooling
+  clangToolingCore
+  findAllSymbols
+  )
+
+add_subdirectory(plugin)
+add_subdirectory(tool)
+add_subdirectory(find-all-symbols)
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/FuzzySymbolIndex.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/FuzzySymbolIndex.cpp
new file mode 100644
index 0000000..d91f455
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/FuzzySymbolIndex.cpp
@@ -0,0 +1,143 @@
+//===--- FuzzySymbolIndex.cpp - Lookup symbols for autocomplete -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "FuzzySymbolIndex.h"
+#include "llvm/Support/Regex.h"
+
+using clang::find_all_symbols::SymbolAndSignals;
+using llvm::StringRef;
+
+namespace clang {
+namespace include_fixer {
+namespace {
+
+class MemSymbolIndex : public FuzzySymbolIndex {
+public:
+  MemSymbolIndex(std::vector<SymbolAndSignals> Symbols) {
+    for (auto &Symbol : Symbols) {
+      auto Tokens = tokenize(Symbol.Symbol.getName());
+      this->Symbols.emplace_back(
+          StringRef(llvm::join(Tokens.begin(), Tokens.end(), " ")),
+          std::move(Symbol));
+    }
+  }
+
+  std::vector<SymbolAndSignals> search(StringRef Query) override {
+    auto Tokens = tokenize(Query);
+    llvm::Regex Pattern("^" + queryRegexp(Tokens));
+    std::vector<SymbolAndSignals> Results;
+    for (const Entry &E : Symbols)
+      if (Pattern.match(E.first))
+        Results.push_back(E.second);
+    return Results;
+  }
+
+private:
+  using Entry = std::pair<llvm::SmallString<32>, SymbolAndSignals>;
+  std::vector<Entry> Symbols;
+};
+
+// Helpers for tokenize state machine.
+enum TokenizeState {
+  EMPTY,      // No pending characters.
+  ONE_BIG,    // Read one uppercase letter, could be WORD or Word.
+  BIG_WORD,   // Reading an uppercase WORD.
+  SMALL_WORD, // Reading a lowercase word.
+  NUMBER      // Reading a number.
+};
+
+enum CharType { UPPER, LOWER, DIGIT, MISC };
+CharType classify(char c) {
+  if (isupper(c))
+    return UPPER;
+  if (islower(c))
+    return LOWER;
+  if (isdigit(c))
+    return DIGIT;
+  return MISC;
+}
+
+} // namespace
+
+std::vector<std::string> FuzzySymbolIndex::tokenize(StringRef Text) {
+  std::vector<std::string> Result;
+  // State describes the treatment of text from Start to I.
+  // Once text is Flush()ed into Result, we're done with it and advance Start.
+  TokenizeState State = EMPTY;
+  size_t Start = 0;
+  auto Flush = [&](size_t End) {
+    if (State != EMPTY) {
+      Result.push_back(Text.substr(Start, End - Start).lower());
+      State = EMPTY;
+    }
+    Start = End;
+  };
+  for (size_t I = 0; I < Text.size(); ++I) {
+    CharType Type = classify(Text[I]);
+    if (Type == MISC)
+      Flush(I);
+    else if (Type == LOWER)
+      switch (State) {
+      case BIG_WORD:
+        Flush(I - 1); // FOOBar: first token is FOO, not FOOB.
+        LLVM_FALLTHROUGH;
+      case ONE_BIG:
+        State = SMALL_WORD;
+        LLVM_FALLTHROUGH;
+      case SMALL_WORD:
+        break;
+      default:
+        Flush(I);
+        State = SMALL_WORD;
+      }
+    else if (Type == UPPER)
+      switch (State) {
+      case ONE_BIG:
+        State = BIG_WORD;
+        LLVM_FALLTHROUGH;
+      case BIG_WORD:
+        break;
+      default:
+        Flush(I);
+        State = ONE_BIG;
+      }
+    else if (Type == DIGIT && State != NUMBER) {
+      Flush(I);
+      State = NUMBER;
+    }
+  }
+  Flush(Text.size());
+  return Result;
+}
+
+std::string
+FuzzySymbolIndex::queryRegexp(const std::vector<std::string> &Tokens) {
+  std::string Result;
+  for (size_t I = 0; I < Tokens.size(); ++I) {
+    if (I)
+      Result.append("[[:alnum:]]* ");
+    for (size_t J = 0; J < Tokens[I].size(); ++J) {
+      if (J)
+        Result.append("([[:alnum:]]* )?");
+      Result.push_back(Tokens[I][J]);
+    }
+  }
+  return Result;
+}
+
+llvm::Expected<std::unique_ptr<FuzzySymbolIndex>>
+FuzzySymbolIndex::createFromYAML(StringRef FilePath) {
+  auto Buffer = llvm::MemoryBuffer::getFile(FilePath);
+  if (!Buffer)
+    return llvm::errorCodeToError(Buffer.getError());
+  return llvm::make_unique<MemSymbolIndex>(
+      find_all_symbols::ReadSymbolInfosFromYAML(Buffer.get()->getBuffer()));
+}
+
+} // namespace include_fixer
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/FuzzySymbolIndex.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/FuzzySymbolIndex.h
new file mode 100644
index 0000000..245191e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/FuzzySymbolIndex.h
@@ -0,0 +1,55 @@
+//===--- FuzzySymbolIndex.h - Lookup symbols for autocomplete ---*- 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_INCLUDE_FIXER_FUZZY_SYMBOL_INDEX_H
+#define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FUZZY_SYMBOL_INDEX_H
+
+#include "SymbolIndex.h"
+#include "find-all-symbols/SymbolInfo.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace include_fixer {
+
+// A FuzzySymbolIndex retrieves top-level symbols matching a query string.
+//
+// It refines the contract of SymbolIndex::search to do fuzzy matching:
+// - symbol names are tokenized: "unique ptr", "string ref".
+// - query must match prefixes of symbol tokens: [upt]
+// - if the query has multiple tokens, splits must match: [StR], not [STr].
+// Helpers for tokenization and regex matching are provided.
+//
+// Implementations may choose to truncate results, refuse short queries, etc.
+class FuzzySymbolIndex : public SymbolIndex {
+public:
+  // Loads the specified include-fixer database and returns an index serving it.
+  static llvm::Expected<std::unique_ptr<FuzzySymbolIndex>>
+  createFromYAML(llvm::StringRef File);
+
+  // Helpers for implementing indexes:
+
+  // Transforms a symbol name or query into a sequence of tokens.
+  // - URLHandlerCallback --> [url, handler, callback]
+  // - snake_case11 --> [snake, case, 11]
+  // - _WTF$ --> [wtf]
+  static std::vector<std::string> tokenize(llvm::StringRef Text);
+
+  // Transforms query tokens into an unanchored regexp to match symbol tokens.
+  // - [fe f] --> /f(\w* )?e\w* f/, matches [fee fie foe].
+  static std::string queryRegexp(const std::vector<std::string> &Tokens);
+};
+
+} // namespace include_fixer
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FUZZY_SYMBOL_INDEX_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/InMemorySymbolIndex.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/InMemorySymbolIndex.cpp
new file mode 100644
index 0000000..14753bd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/InMemorySymbolIndex.cpp
@@ -0,0 +1,32 @@
+//===-- InMemorySymbolIndex.cpp--------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InMemorySymbolIndex.h"
+
+using clang::find_all_symbols::SymbolAndSignals;
+
+namespace clang {
+namespace include_fixer {
+
+InMemorySymbolIndex::InMemorySymbolIndex(
+    const std::vector<SymbolAndSignals> &Symbols) {
+  for (const auto &Symbol : Symbols)
+    LookupTable[Symbol.Symbol.getName()].push_back(Symbol);
+}
+
+std::vector<SymbolAndSignals>
+InMemorySymbolIndex::search(llvm::StringRef Identifier) {
+  auto I = LookupTable.find(Identifier);
+  if (I != LookupTable.end())
+    return I->second;
+  return {};
+}
+
+} // namespace include_fixer
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/InMemorySymbolIndex.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/InMemorySymbolIndex.h
new file mode 100644
index 0000000..0e1310e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/InMemorySymbolIndex.h
@@ -0,0 +1,38 @@
+//===-- InMemorySymbolIndex.h -----------------------------------*- 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_INCLUDE_FIXER_INMEMORYSYMBOLINDEX_H
+#define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_INMEMORYSYMBOLINDEX_H
+
+#include "SymbolIndex.h"
+#include <map>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace include_fixer {
+
+/// Xref database with fixed content.
+class InMemorySymbolIndex : public SymbolIndex {
+public:
+  InMemorySymbolIndex(
+      const std::vector<find_all_symbols::SymbolAndSignals> &Symbols);
+
+  std::vector<find_all_symbols::SymbolAndSignals>
+  search(llvm::StringRef Identifier) override;
+
+private:
+  std::map<std::string, std::vector<find_all_symbols::SymbolAndSignals>>
+      LookupTable;
+};
+
+} // namespace include_fixer
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_INMEMORYSYMBOLINDEX_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/IncludeFixer.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/IncludeFixer.cpp
new file mode 100644
index 0000000..c6dfd7f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/IncludeFixer.cpp
@@ -0,0 +1,445 @@
+//===-- IncludeFixer.cpp - Include inserter based on sema callbacks -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IncludeFixer.h"
+#include "clang/Format/Format.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/ParseAST.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+#define DEBUG_TYPE "include-fixer"
+
+using namespace clang;
+
+namespace clang {
+namespace include_fixer {
+namespace {
+/// Manages the parse, gathers include suggestions.
+class Action : public clang::ASTFrontendAction {
+public:
+  explicit Action(SymbolIndexManager &SymbolIndexMgr, bool MinimizeIncludePaths)
+      : SemaSource(SymbolIndexMgr, MinimizeIncludePaths,
+                   /*GenerateDiagnostics=*/false) {}
+
+  std::unique_ptr<clang::ASTConsumer>
+  CreateASTConsumer(clang::CompilerInstance &Compiler,
+                    StringRef InFile) override {
+    SemaSource.setFilePath(InFile);
+    return llvm::make_unique<clang::ASTConsumer>();
+  }
+
+  void ExecuteAction() override {
+    clang::CompilerInstance *Compiler = &getCompilerInstance();
+    assert(!Compiler->hasSema() && "CI already has Sema");
+
+    // Set up our hooks into sema and parse the AST.
+    if (hasCodeCompletionSupport() &&
+        !Compiler->getFrontendOpts().CodeCompletionAt.FileName.empty())
+      Compiler->createCodeCompletionConsumer();
+
+    clang::CodeCompleteConsumer *CompletionConsumer = nullptr;
+    if (Compiler->hasCodeCompletionConsumer())
+      CompletionConsumer = &Compiler->getCodeCompletionConsumer();
+
+    Compiler->createSema(getTranslationUnitKind(), CompletionConsumer);
+    SemaSource.setCompilerInstance(Compiler);
+    Compiler->getSema().addExternalSource(&SemaSource);
+
+    clang::ParseAST(Compiler->getSema(), Compiler->getFrontendOpts().ShowStats,
+                    Compiler->getFrontendOpts().SkipFunctionBodies);
+  }
+
+  IncludeFixerContext
+  getIncludeFixerContext(const clang::SourceManager &SourceManager,
+                         clang::HeaderSearch &HeaderSearch) const {
+    return SemaSource.getIncludeFixerContext(SourceManager, HeaderSearch,
+                                             SemaSource.getMatchedSymbols());
+  }
+
+private:
+  IncludeFixerSemaSource SemaSource;
+};
+
+} // namespace
+
+IncludeFixerActionFactory::IncludeFixerActionFactory(
+    SymbolIndexManager &SymbolIndexMgr,
+    std::vector<IncludeFixerContext> &Contexts, StringRef StyleName,
+    bool MinimizeIncludePaths)
+    : SymbolIndexMgr(SymbolIndexMgr), Contexts(Contexts),
+      MinimizeIncludePaths(MinimizeIncludePaths) {}
+
+IncludeFixerActionFactory::~IncludeFixerActionFactory() = default;
+
+bool IncludeFixerActionFactory::runInvocation(
+    std::shared_ptr<clang::CompilerInvocation> Invocation,
+    clang::FileManager *Files,
+    std::shared_ptr<clang::PCHContainerOperations> PCHContainerOps,
+    clang::DiagnosticConsumer *Diagnostics) {
+  assert(Invocation->getFrontendOpts().Inputs.size() == 1);
+
+  // Set up Clang.
+  clang::CompilerInstance Compiler(PCHContainerOps);
+  Compiler.setInvocation(std::move(Invocation));
+  Compiler.setFileManager(Files);
+
+  // Create the compiler's actual diagnostics engine. We want to drop all
+  // diagnostics here.
+  Compiler.createDiagnostics(new clang::IgnoringDiagConsumer,
+                             /*ShouldOwnClient=*/true);
+  Compiler.createSourceManager(*Files);
+
+  // We abort on fatal errors so don't let a large number of errors become
+  // fatal. A missing #include can cause thousands of errors.
+  Compiler.getDiagnostics().setErrorLimit(0);
+
+  // Run the parser, gather missing includes.
+  auto ScopedToolAction =
+      llvm::make_unique<Action>(SymbolIndexMgr, MinimizeIncludePaths);
+  Compiler.ExecuteAction(*ScopedToolAction);
+
+  Contexts.push_back(ScopedToolAction->getIncludeFixerContext(
+      Compiler.getSourceManager(),
+      Compiler.getPreprocessor().getHeaderSearchInfo()));
+
+  // Technically this should only return true if we're sure that we have a
+  // parseable file. We don't know that though. Only inform users of fatal
+  // errors.
+  return !Compiler.getDiagnostics().hasFatalErrorOccurred();
+}
+
+static bool addDiagnosticsForContext(TypoCorrection &Correction,
+                                     const IncludeFixerContext &Context,
+                                     StringRef Code, SourceLocation StartOfFile,
+                                     ASTContext &Ctx) {
+  auto Reps = createIncludeFixerReplacements(
+      Code, Context, format::getLLVMStyle(), /*AddQualifiers=*/false);
+  if (!Reps || Reps->size() != 1)
+    return false;
+
+  unsigned DiagID = Ctx.getDiagnostics().getCustomDiagID(
+      DiagnosticsEngine::Note, "Add '#include %0' to provide the missing "
+                               "declaration [clang-include-fixer]");
+
+  // FIXME: Currently we only generate a diagnostic for the first header. Give
+  // the user choices.
+  const tooling::Replacement &Placed = *Reps->begin();
+
+  auto Begin = StartOfFile.getLocWithOffset(Placed.getOffset());
+  auto End = Begin.getLocWithOffset(std::max(0, (int)Placed.getLength() - 1));
+  PartialDiagnostic PD(DiagID, Ctx.getDiagAllocator());
+  PD << Context.getHeaderInfos().front().Header
+     << FixItHint::CreateReplacement(CharSourceRange::getCharRange(Begin, End),
+                                     Placed.getReplacementText());
+  Correction.addExtraDiagnostic(std::move(PD));
+  return true;
+}
+
+/// Callback for incomplete types. If we encounter a forward declaration we
+/// have the fully qualified name ready. Just query that.
+bool IncludeFixerSemaSource::MaybeDiagnoseMissingCompleteType(
+    clang::SourceLocation Loc, clang::QualType T) {
+  // Ignore spurious callbacks from SFINAE contexts.
+  if (CI->getSema().isSFINAEContext())
+    return false;
+
+  clang::ASTContext &context = CI->getASTContext();
+  std::string QueryString = QualType(T->getUnqualifiedDesugaredType(), 0)
+                                .getAsString(context.getPrintingPolicy());
+  LLVM_DEBUG(llvm::dbgs() << "Query missing complete type '" << QueryString
+                          << "'");
+  // Pass an empty range here since we don't add qualifier in this case.
+  std::vector<find_all_symbols::SymbolInfo> MatchedSymbols =
+      query(QueryString, "", tooling::Range());
+
+  if (!MatchedSymbols.empty() && GenerateDiagnostics) {
+    TypoCorrection Correction;
+    FileID FID = CI->getSourceManager().getFileID(Loc);
+    StringRef Code = CI->getSourceManager().getBufferData(FID);
+    SourceLocation StartOfFile =
+        CI->getSourceManager().getLocForStartOfFile(FID);
+    addDiagnosticsForContext(
+        Correction,
+        getIncludeFixerContext(CI->getSourceManager(),
+                               CI->getPreprocessor().getHeaderSearchInfo(),
+                               MatchedSymbols),
+        Code, StartOfFile, CI->getASTContext());
+    for (const PartialDiagnostic &PD : Correction.getExtraDiagnostics())
+      CI->getSema().Diag(Loc, PD);
+  }
+  return true;
+}
+
+/// Callback for unknown identifiers. Try to piece together as much
+/// qualification as we can get and do a query.
+clang::TypoCorrection IncludeFixerSemaSource::CorrectTypo(
+    const DeclarationNameInfo &Typo, int LookupKind, Scope *S, CXXScopeSpec *SS,
+    CorrectionCandidateCallback &CCC, DeclContext *MemberContext,
+    bool EnteringContext, const ObjCObjectPointerType *OPT) {
+  // Ignore spurious callbacks from SFINAE contexts.
+  if (CI->getSema().isSFINAEContext())
+    return clang::TypoCorrection();
+
+  // We currently ignore the unidentified symbol which is not from the
+  // main file.
+  //
+  // However, this is not always true due to templates in a non-self contained
+  // header, consider the case:
+  //
+  //   // header.h
+  //   template <typename T>
+  //   class Foo {
+  //     T t;
+  //   };
+  //
+  //   // test.cc
+  //   // We need to add <bar.h> in test.cc instead of header.h.
+  //   class Bar;
+  //   Foo<Bar> foo;
+  //
+  // FIXME: Add the missing header to the header file where the symbol comes
+  // from.
+  if (!CI->getSourceManager().isWrittenInMainFile(Typo.getLoc()))
+    return clang::TypoCorrection();
+
+  std::string TypoScopeString;
+  if (S) {
+    // FIXME: Currently we only use namespace contexts. Use other context
+    // types for query.
+    for (const auto *Context = S->getEntity(); Context;
+         Context = Context->getParent()) {
+      if (const auto *ND = dyn_cast<NamespaceDecl>(Context)) {
+        if (!ND->getName().empty())
+          TypoScopeString = ND->getNameAsString() + "::" + TypoScopeString;
+      }
+    }
+  }
+
+  auto ExtendNestedNameSpecifier = [this](CharSourceRange Range) {
+    StringRef Source =
+        Lexer::getSourceText(Range, CI->getSourceManager(), CI->getLangOpts());
+
+    // Skip forward until we find a character that's neither identifier nor
+    // colon. This is a bit of a hack around the fact that we will only get a
+    // single callback for a long nested name if a part of the beginning is
+    // unknown. For example:
+    //
+    // llvm::sys::path::parent_path(...)
+    // ^~~~  ^~~
+    //    known
+    //            ^~~~
+    //      unknown, last callback
+    //                  ^~~~~~~~~~~
+    //                  no callback
+    //
+    // With the extension we get the full nested name specifier including
+    // parent_path.
+    // FIXME: Don't rely on source text.
+    const char *End = Source.end();
+    while (isIdentifierBody(*End) || *End == ':')
+      ++End;
+
+    return std::string(Source.begin(), End);
+  };
+
+  /// If we have a scope specification, use that to get more precise results.
+  std::string QueryString;
+  tooling::Range SymbolRange;
+  const auto &SM = CI->getSourceManager();
+  auto CreateToolingRange = [&QueryString, &SM](SourceLocation BeginLoc) {
+    return tooling::Range(SM.getDecomposedLoc(BeginLoc).second,
+                          QueryString.size());
+  };
+  if (SS && SS->getRange().isValid()) {
+    auto Range = CharSourceRange::getTokenRange(SS->getRange().getBegin(),
+                                                Typo.getLoc());
+
+    QueryString = ExtendNestedNameSpecifier(Range);
+    SymbolRange = CreateToolingRange(Range.getBegin());
+  } else if (Typo.getName().isIdentifier() && !Typo.getLoc().isMacroID()) {
+    auto Range =
+        CharSourceRange::getTokenRange(Typo.getBeginLoc(), Typo.getEndLoc());
+
+    QueryString = ExtendNestedNameSpecifier(Range);
+    SymbolRange = CreateToolingRange(Range.getBegin());
+  } else {
+    QueryString = Typo.getAsString();
+    SymbolRange = CreateToolingRange(Typo.getLoc());
+  }
+
+  LLVM_DEBUG(llvm::dbgs() << "TypoScopeQualifiers: " << TypoScopeString
+                          << "\n");
+  std::vector<find_all_symbols::SymbolInfo> MatchedSymbols =
+      query(QueryString, TypoScopeString, SymbolRange);
+
+  if (!MatchedSymbols.empty() && GenerateDiagnostics) {
+    TypoCorrection Correction(Typo.getName());
+    Correction.setCorrectionRange(SS, Typo);
+    FileID FID = SM.getFileID(Typo.getLoc());
+    StringRef Code = SM.getBufferData(FID);
+    SourceLocation StartOfFile = SM.getLocForStartOfFile(FID);
+    if (addDiagnosticsForContext(
+            Correction, getIncludeFixerContext(
+                            SM, CI->getPreprocessor().getHeaderSearchInfo(),
+                            MatchedSymbols),
+            Code, StartOfFile, CI->getASTContext()))
+      return Correction;
+  }
+  return TypoCorrection();
+}
+
+/// Get the minimal include for a given path.
+std::string IncludeFixerSemaSource::minimizeInclude(
+    StringRef Include, const clang::SourceManager &SourceManager,
+    clang::HeaderSearch &HeaderSearch) const {
+  if (!MinimizeIncludePaths)
+    return Include;
+
+  // Get the FileEntry for the include.
+  StringRef StrippedInclude = Include.trim("\"<>");
+  const FileEntry *Entry =
+      SourceManager.getFileManager().getFile(StrippedInclude);
+
+  // If the file doesn't exist return the path from the database.
+  // FIXME: This should never happen.
+  if (!Entry)
+    return Include;
+
+  bool IsSystem;
+  std::string Suggestion =
+      HeaderSearch.suggestPathToFileForDiagnostics(Entry, &IsSystem);
+
+  return IsSystem ? '<' + Suggestion + '>' : '"' + Suggestion + '"';
+}
+
+/// Get the include fixer context for the queried symbol.
+IncludeFixerContext IncludeFixerSemaSource::getIncludeFixerContext(
+    const clang::SourceManager &SourceManager,
+    clang::HeaderSearch &HeaderSearch,
+    ArrayRef<find_all_symbols::SymbolInfo> MatchedSymbols) const {
+  std::vector<find_all_symbols::SymbolInfo> SymbolCandidates;
+  for (const auto &Symbol : MatchedSymbols) {
+    std::string FilePath = Symbol.getFilePath().str();
+    std::string MinimizedFilePath = minimizeInclude(
+        ((FilePath[0] == '"' || FilePath[0] == '<') ? FilePath
+                                                    : "\"" + FilePath + "\""),
+        SourceManager, HeaderSearch);
+    SymbolCandidates.emplace_back(Symbol.getName(), Symbol.getSymbolKind(),
+                                  MinimizedFilePath, Symbol.getContexts());
+  }
+  return IncludeFixerContext(FilePath, QuerySymbolInfos, SymbolCandidates);
+}
+
+std::vector<find_all_symbols::SymbolInfo>
+IncludeFixerSemaSource::query(StringRef Query, StringRef ScopedQualifiers,
+                              tooling::Range Range) {
+  assert(!Query.empty() && "Empty query!");
+
+  // Save all instances of an unidentified symbol.
+  //
+  // We use conservative behavior for detecting the same unidentified symbol
+  // here. The symbols which have the same ScopedQualifier and RawIdentifier
+  // are considered equal. So that include-fixer avoids false positives, and
+  // always adds missing qualifiers to correct symbols.
+  if (!GenerateDiagnostics && !QuerySymbolInfos.empty()) {
+    if (ScopedQualifiers == QuerySymbolInfos.front().ScopedQualifiers &&
+        Query == QuerySymbolInfos.front().RawIdentifier) {
+      QuerySymbolInfos.push_back({Query.str(), ScopedQualifiers, Range});
+    }
+    return {};
+  }
+
+  LLVM_DEBUG(llvm::dbgs() << "Looking up '" << Query << "' at ");
+  LLVM_DEBUG(CI->getSourceManager()
+                 .getLocForStartOfFile(CI->getSourceManager().getMainFileID())
+                 .getLocWithOffset(Range.getOffset())
+                 .print(llvm::dbgs(), CI->getSourceManager()));
+  LLVM_DEBUG(llvm::dbgs() << " ...");
+  llvm::StringRef FileName = CI->getSourceManager().getFilename(
+      CI->getSourceManager().getLocForStartOfFile(
+          CI->getSourceManager().getMainFileID()));
+
+  QuerySymbolInfos.push_back({Query.str(), ScopedQualifiers, Range});
+
+  // Query the symbol based on C++ name Lookup rules.
+  // Firstly, lookup the identifier with scoped namespace contexts;
+  // If that fails, falls back to look up the identifier directly.
+  //
+  // For example:
+  //
+  // namespace a {
+  // b::foo f;
+  // }
+  //
+  // 1. lookup a::b::foo.
+  // 2. lookup b::foo.
+  std::string QueryString = ScopedQualifiers.str() + Query.str();
+  // It's unsafe to do nested search for the identifier with scoped namespace
+  // context, it might treat the identifier as a nested class of the scoped
+  // namespace.
+  std::vector<find_all_symbols::SymbolInfo> MatchedSymbols =
+      SymbolIndexMgr.search(QueryString, /*IsNestedSearch=*/false, FileName);
+  if (MatchedSymbols.empty())
+    MatchedSymbols =
+        SymbolIndexMgr.search(Query, /*IsNestedSearch=*/true, FileName);
+  LLVM_DEBUG(llvm::dbgs() << "Having found " << MatchedSymbols.size()
+                          << " symbols\n");
+  // We store a copy of MatchedSymbols in a place where it's globally reachable.
+  // This is used by the standalone version of the tool.
+  this->MatchedSymbols = MatchedSymbols;
+  return MatchedSymbols;
+}
+
+llvm::Expected<tooling::Replacements> createIncludeFixerReplacements(
+    StringRef Code, const IncludeFixerContext &Context,
+    const clang::format::FormatStyle &Style, bool AddQualifiers) {
+  if (Context.getHeaderInfos().empty())
+    return tooling::Replacements();
+  StringRef FilePath = Context.getFilePath();
+  std::string IncludeName =
+      "#include " + Context.getHeaderInfos().front().Header + "\n";
+  // Create replacements for the new header.
+  clang::tooling::Replacements Insertions;
+  auto Err =
+      Insertions.add(tooling::Replacement(FilePath, UINT_MAX, 0, IncludeName));
+  if (Err)
+    return std::move(Err);
+
+  auto CleanReplaces = cleanupAroundReplacements(Code, Insertions, Style);
+  if (!CleanReplaces)
+    return CleanReplaces;
+
+  auto Replaces = std::move(*CleanReplaces);
+  if (AddQualifiers) {
+    for (const auto &Info : Context.getQuerySymbolInfos()) {
+      // Ignore the empty range.
+      if (Info.Range.getLength() > 0) {
+        auto R = tooling::Replacement(
+            {FilePath, Info.Range.getOffset(), Info.Range.getLength(),
+             Context.getHeaderInfos().front().QualifiedName});
+        auto Err = Replaces.add(R);
+        if (Err) {
+          llvm::consumeError(std::move(Err));
+          R = tooling::Replacement(
+              R.getFilePath(), Replaces.getShiftedCodePosition(R.getOffset()),
+              R.getLength(), R.getReplacementText());
+          Replaces = Replaces.merge(tooling::Replacements(R));
+        }
+      }
+    }
+  }
+  return formatReplacements(Code, Replaces, Style);
+}
+
+} // namespace include_fixer
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/IncludeFixer.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/IncludeFixer.h
new file mode 100644
index 0000000..13092a3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/IncludeFixer.h
@@ -0,0 +1,158 @@
+//===-- IncludeFixer.h - Include inserter -----------------------*- 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_INCLUDE_FIXER_INCLUDEFIXER_H
+#define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_INCLUDEFIXER_H
+
+#include "IncludeFixerContext.h"
+#include "SymbolIndexManager.h"
+#include "clang/Format/Format.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "clang/Tooling/Tooling.h"
+#include <memory>
+#include <vector>
+
+namespace clang {
+
+class CompilerInvocation;
+class DiagnosticConsumer;
+class FileManager;
+class PCHContainerOperations;
+
+namespace include_fixer {
+
+class IncludeFixerActionFactory : public clang::tooling::ToolAction {
+public:
+  /// \param SymbolIndexMgr A source for matching symbols to header files.
+  /// \param Contexts The contexts for the symbols being queried.
+  /// \param StyleName Fallback style for reformatting.
+  /// \param MinimizeIncludePaths whether inserted include paths are optimized.
+  IncludeFixerActionFactory(SymbolIndexManager &SymbolIndexMgr,
+                            std::vector<IncludeFixerContext> &Contexts,
+                            StringRef StyleName,
+                            bool MinimizeIncludePaths = true);
+
+  ~IncludeFixerActionFactory() override;
+
+  bool
+  runInvocation(std::shared_ptr<clang::CompilerInvocation> Invocation,
+                clang::FileManager *Files,
+                std::shared_ptr<clang::PCHContainerOperations> PCHContainerOps,
+                clang::DiagnosticConsumer *Diagnostics) override;
+
+private:
+  /// The client to use to find cross-references.
+  SymbolIndexManager &SymbolIndexMgr;
+
+  /// Multiple contexts for files being processed.
+  std::vector<IncludeFixerContext> &Contexts;
+
+  /// Whether inserted include paths should be optimized.
+  bool MinimizeIncludePaths;
+
+  /// The fallback format style for formatting after insertion if no
+  /// clang-format config file was found.
+  std::string FallbackStyle;
+};
+
+/// Create replacements, which are generated by clang-format, for the
+/// missing header and mising qualifiers insertions. The function uses the
+/// first header for insertion.
+///
+/// \param Code The source code.
+/// \param Context The context which contains all information for creating
+/// include-fixer replacements.
+/// \param Style clang-format style being used.
+/// \param AddQualifiers  Whether we should add qualifiers to all instances of
+/// an unidentified symbol.
+///
+/// \return Formatted replacements for inserting, sorting headers and adding
+/// qualifiers on success; otherwise, an llvm::Error carrying llvm::StringError
+/// is returned.
+llvm::Expected<tooling::Replacements> createIncludeFixerReplacements(
+    StringRef Code, const IncludeFixerContext &Context,
+    const format::FormatStyle &Style = format::getLLVMStyle(),
+    bool AddQualifiers = true);
+
+/// Handles callbacks from sema, does the include lookup and turns it into an
+/// IncludeFixerContext.
+class IncludeFixerSemaSource : public clang::ExternalSemaSource {
+public:
+  explicit IncludeFixerSemaSource(SymbolIndexManager &SymbolIndexMgr,
+                                  bool MinimizeIncludePaths,
+                                  bool GenerateDiagnostics)
+      : SymbolIndexMgr(SymbolIndexMgr),
+        MinimizeIncludePaths(MinimizeIncludePaths),
+        GenerateDiagnostics(GenerateDiagnostics) {}
+
+  void setCompilerInstance(CompilerInstance *CI) { this->CI = CI; }
+  void setFilePath(StringRef FilePath) { this->FilePath = FilePath; }
+
+  /// Callback for incomplete types. If we encounter a forward declaration we
+  /// have the fully qualified name ready. Just query that.
+  bool MaybeDiagnoseMissingCompleteType(clang::SourceLocation Loc,
+                                        clang::QualType T) override;
+
+  /// Callback for unknown identifiers. Try to piece together as much
+  /// qualification as we can get and do a query.
+  clang::TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
+                                    int LookupKind, Scope *S, CXXScopeSpec *SS,
+                                    CorrectionCandidateCallback &CCC,
+                                    DeclContext *MemberContext,
+                                    bool EnteringContext,
+                                    const ObjCObjectPointerType *OPT) override;
+
+  /// Get the minimal include for a given path.
+  std::string minimizeInclude(StringRef Include,
+                              const clang::SourceManager &SourceManager,
+                              clang::HeaderSearch &HeaderSearch) const;
+
+  /// Get the include fixer context for the queried symbol.
+  IncludeFixerContext getIncludeFixerContext(
+      const clang::SourceManager &SourceManager,
+      clang::HeaderSearch &HeaderSearch,
+      ArrayRef<find_all_symbols::SymbolInfo> MatchedSymbols) const;
+
+  /// Get the global matched symbols.
+  ArrayRef<find_all_symbols::SymbolInfo> getMatchedSymbols() const {
+    return MatchedSymbols;
+  }
+
+private:
+  /// Query the database for a given identifier.
+  std::vector<find_all_symbols::SymbolInfo>
+  query(StringRef Query, StringRef ScopedQualifiers, tooling::Range Range);
+
+  CompilerInstance *CI;
+
+  /// The client to use to find cross-references.
+  SymbolIndexManager &SymbolIndexMgr;
+
+  /// The information of the symbols being queried.
+  std::vector<IncludeFixerContext::QuerySymbolInfo> QuerySymbolInfos;
+
+  /// All symbol candidates which match QuerySymbol. We only include the first
+  /// discovered identifier to avoid getting caught in results from error
+  /// recovery.
+  std::vector<find_all_symbols::SymbolInfo> MatchedSymbols;
+
+  /// The file path to the file being processed.
+  std::string FilePath;
+
+  /// Whether we should use the smallest possible include path.
+  bool MinimizeIncludePaths = true;
+
+  /// Whether we should generate diagnostics with fixits for missing symbols.
+  bool GenerateDiagnostics = false;
+};
+} // namespace include_fixer
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_INCLUDEFIXER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/IncludeFixerContext.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/IncludeFixerContext.cpp
new file mode 100644
index 0000000..8106e20
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/IncludeFixerContext.cpp
@@ -0,0 +1,116 @@
+//===-- IncludeFixerContext.cpp - Include fixer context ---------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IncludeFixerContext.h"
+#include <algorithm>
+
+namespace clang {
+namespace include_fixer {
+
+namespace {
+
+// Splits a multiply qualified names (e.g. a::b::c).
+llvm::SmallVector<llvm::StringRef, 8>
+SplitQualifiers(llvm::StringRef StringQualifiers) {
+  llvm::SmallVector<llvm::StringRef, 8> Qualifiers;
+  StringQualifiers.split(Qualifiers, "::");
+  return Qualifiers;
+}
+
+std::string createQualifiedNameForReplacement(
+    llvm::StringRef RawSymbolName,
+    llvm::StringRef SymbolScopedQualifiersName,
+    const find_all_symbols::SymbolInfo &MatchedSymbol) {
+  // No need to add missing qualifiers if SymbolIndentifer has a global scope
+  // operator "::".
+  if (RawSymbolName.startswith("::"))
+    return RawSymbolName;
+
+  std::string QualifiedName = MatchedSymbol.getQualifiedName();
+
+  // For nested classes, the qualified name constructed from database misses
+  // some stripped qualifiers, because when we search a symbol in database,
+  // we strip qualifiers from the end until we find a result. So append the
+  // missing stripped qualifiers here.
+  //
+  // Get stripped qualifiers.
+  auto SymbolQualifiers = SplitQualifiers(RawSymbolName);
+  std::string StrippedQualifiers;
+  while (!SymbolQualifiers.empty() &&
+         !llvm::StringRef(QualifiedName).endswith(SymbolQualifiers.back())) {
+    StrippedQualifiers =
+        "::" + SymbolQualifiers.back().str() + StrippedQualifiers;
+    SymbolQualifiers.pop_back();
+  }
+  // Append the missing stripped qualifiers.
+  std::string FullyQualifiedName = QualifiedName + StrippedQualifiers;
+
+  // Try to find and skip the common prefix qualifiers.
+  auto FullySymbolQualifiers = SplitQualifiers(FullyQualifiedName);
+  auto ScopedQualifiers = SplitQualifiers(SymbolScopedQualifiersName);
+  auto FullySymbolQualifiersIter = FullySymbolQualifiers.begin();
+  auto SymbolScopedQualifiersIter = ScopedQualifiers.begin();
+  while (FullySymbolQualifiersIter != FullySymbolQualifiers.end() &&
+         SymbolScopedQualifiersIter != ScopedQualifiers.end()) {
+    if (*FullySymbolQualifiersIter != *SymbolScopedQualifiersIter)
+      break;
+    ++FullySymbolQualifiersIter;
+    ++SymbolScopedQualifiersIter;
+  }
+  std::string Result;
+  for (; FullySymbolQualifiersIter != FullySymbolQualifiers.end();
+       ++FullySymbolQualifiersIter) {
+    if (!Result.empty())
+      Result += "::";
+    Result += *FullySymbolQualifiersIter;
+  }
+  return Result;
+}
+
+} // anonymous namespace
+
+IncludeFixerContext::IncludeFixerContext(
+    StringRef FilePath, std::vector<QuerySymbolInfo> QuerySymbols,
+    std::vector<find_all_symbols::SymbolInfo> Symbols)
+    : FilePath(FilePath), QuerySymbolInfos(std::move(QuerySymbols)),
+      MatchedSymbols(std::move(Symbols)) {
+  // Remove replicated QuerySymbolInfos with the same range.
+  //
+  // QuerySymbolInfos may contain replicated elements. Because CorrectTypo
+  // callback doesn't always work as we expected. In somecases, it will be
+  // triggered at the same position or unidentified symbol multiple times.
+  std::sort(QuerySymbolInfos.begin(), QuerySymbolInfos.end(),
+            [&](const QuerySymbolInfo &A, const QuerySymbolInfo &B) {
+              return std::make_pair(A.Range.getOffset(), A.Range.getLength()) <
+                     std::make_pair(B.Range.getOffset(), B.Range.getLength());
+            });
+  QuerySymbolInfos.erase(
+      std::unique(QuerySymbolInfos.begin(), QuerySymbolInfos.end(),
+                  [](const QuerySymbolInfo &A, const QuerySymbolInfo &B) {
+                    return A.Range == B.Range;
+                  }),
+      QuerySymbolInfos.end());
+  for (const auto &Symbol : MatchedSymbols) {
+    HeaderInfos.push_back(
+        {Symbol.getFilePath().str(),
+         createQualifiedNameForReplacement(
+             QuerySymbolInfos.front().RawIdentifier,
+             QuerySymbolInfos.front().ScopedQualifiers, Symbol)});
+  }
+  // Deduplicate header infos.
+  HeaderInfos.erase(std::unique(HeaderInfos.begin(), HeaderInfos.end(),
+                                [](const HeaderInfo &A, const HeaderInfo &B) {
+                                  return A.Header == B.Header &&
+                                         A.QualifiedName == B.QualifiedName;
+                                }),
+                    HeaderInfos.end());
+}
+
+} // include_fixer
+} // clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/IncludeFixerContext.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/IncludeFixerContext.h
new file mode 100644
index 0000000..3c44574
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/IncludeFixerContext.h
@@ -0,0 +1,95 @@
+//===-- IncludeFixerContext.h - Include fixer context -----------*- 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_INCLUDE_FIXER_INCLUDEFIXERCONTEXT_H
+#define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_INCLUDEFIXERCONTEXT_H
+
+#include "find-all-symbols/SymbolInfo.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace include_fixer {
+
+/// \brief A context for a file being processed. It includes all query
+/// information, e.g. symbols being queried in database, all header candidates.
+class IncludeFixerContext {
+public:
+  struct HeaderInfo {
+    /// \brief The header where QualifiedName comes from.
+    std::string Header;
+    /// \brief A symbol name with completed namespace qualifiers which will
+    /// replace the original symbol.
+    std::string QualifiedName;
+  };
+
+  struct QuerySymbolInfo {
+    /// \brief The raw symbol name being queried in database. This name might
+    /// miss some namespace qualifiers, and will be replaced by a fully
+    /// qualified one.
+    std::string RawIdentifier;
+
+    /// \brief The qualifiers of the scope in which SymbolIdentifier lookup
+    /// occurs. It is represented as a sequence of names and scope resolution
+    /// operatiors ::, ending with a scope resolution operator (e.g. a::b::).
+    /// Empty if SymbolIdentifier is not in a specific scope.
+    std::string ScopedQualifiers;
+
+    /// \brief The replacement range of RawIdentifier.
+    tooling::Range Range;
+  };
+
+  IncludeFixerContext() = default;
+  IncludeFixerContext(StringRef FilePath,
+                      std::vector<QuerySymbolInfo> QuerySymbols,
+                      std::vector<find_all_symbols::SymbolInfo> Symbols);
+
+  /// \brief Get symbol name.
+  llvm::StringRef getSymbolIdentifier() const {
+    return QuerySymbolInfos.front().RawIdentifier;
+  }
+
+  /// \brief Get replacement range of the symbol.
+  tooling::Range getSymbolRange() const {
+    return QuerySymbolInfos.front().Range;
+  }
+
+  /// \brief Get the file path to the file being processed.
+  StringRef getFilePath() const { return FilePath; }
+
+  /// \brief Get header information.
+  const std::vector<HeaderInfo> &getHeaderInfos() const { return HeaderInfos; }
+
+  /// \brief Get information of symbols being querid.
+  const std::vector<QuerySymbolInfo> &getQuerySymbolInfos() const {
+    return QuerySymbolInfos;
+  }
+
+private:
+  friend struct llvm::yaml::MappingTraits<IncludeFixerContext>;
+
+  /// \brief The file path to the file being processed.
+  std::string FilePath;
+
+  /// \brief All instances of an unidentified symbol being queried.
+  std::vector<QuerySymbolInfo> QuerySymbolInfos;
+
+  /// \brief The symbol candidates which match SymbolIdentifier. The symbols are
+  /// sorted in a descending order based on the popularity info in SymbolInfo.
+  std::vector<find_all_symbols::SymbolInfo> MatchedSymbols;
+
+  /// \brief The header information.
+  std::vector<HeaderInfo> HeaderInfos;
+};
+
+} // namespace include_fixer
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_INCLUDEFIXERCONTEXT_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/SymbolIndex.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/SymbolIndex.h
new file mode 100644
index 0000000..f3e6ecd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/SymbolIndex.h
@@ -0,0 +1,38 @@
+//===-- SymbolIndex.h - Interface for symbol-header matching ----*- 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_INCLUDE_FIXER_SYMBOLINDEX_H
+#define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_SYMBOLINDEX_H
+
+#include "find-all-symbols/SymbolInfo.h"
+#include "llvm/ADT/StringRef.h"
+#include <vector>
+
+namespace clang {
+namespace include_fixer {
+
+/// This class provides an interface for finding all `SymbolInfo`s corresponding
+/// to a symbol name from a symbol database.
+class SymbolIndex {
+public:
+  virtual ~SymbolIndex() = default;
+
+  /// Search for all `SymbolInfo`s corresponding to an identifier.
+  /// \param Identifier The unqualified identifier being searched for.
+  /// \returns A list of `SymbolInfo` candidates.
+  // FIXME: Expose the type name so we can also insert using declarations (or
+  // fix the usage)
+  virtual std::vector<find_all_symbols::SymbolAndSignals>
+  search(llvm::StringRef Identifier) = 0;
+};
+
+} // namespace include_fixer
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_SYMBOLINDEX_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/SymbolIndexManager.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/SymbolIndexManager.cpp
new file mode 100644
index 0000000..e4312bf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/SymbolIndexManager.cpp
@@ -0,0 +1,159 @@
+//===-- SymbolIndexManager.cpp - Managing multiple SymbolIndices-*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolIndexManager.h"
+#include "find-all-symbols/SymbolInfo.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Path.h"
+
+#define DEBUG_TYPE "include-fixer"
+
+namespace clang {
+namespace include_fixer {
+
+using find_all_symbols::SymbolInfo;
+using find_all_symbols::SymbolAndSignals;
+
+// Calculate a score based on whether we think the given header is closely
+// related to the given source file.
+static double similarityScore(llvm::StringRef FileName,
+                              llvm::StringRef Header) {
+  // Compute the maximum number of common path segements between Header and
+  // a suffix of FileName.
+  // We do not do a full longest common substring computation, as Header
+  // specifies the path we would directly #include, so we assume it is rooted
+  // relatively to a subproject of the repository.
+  int MaxSegments = 1;
+  for (auto FileI = llvm::sys::path::begin(FileName),
+            FileE = llvm::sys::path::end(FileName);
+       FileI != FileE; ++FileI) {
+    int Segments = 0;
+    for (auto HeaderI = llvm::sys::path::begin(Header),
+              HeaderE = llvm::sys::path::end(Header), I = FileI;
+         HeaderI != HeaderE && *I == *HeaderI && I != FileE; ++I, ++HeaderI) {
+      ++Segments;
+    }
+    MaxSegments = std::max(Segments, MaxSegments);
+  }
+  return MaxSegments;
+}
+
+static void rank(std::vector<SymbolAndSignals> &Symbols,
+                 llvm::StringRef FileName) {
+  llvm::DenseMap<llvm::StringRef, double> Score;
+  for (const auto &Symbol : Symbols) {
+    // Calculate a score from the similarity of the header the symbol is in
+    // with the current file and the popularity of the symbol.
+    double NewScore = similarityScore(FileName, Symbol.Symbol.getFilePath()) *
+                      (1.0 + std::log2(1 + Symbol.Signals.Seen));
+    double &S = Score[Symbol.Symbol.getFilePath()];
+    S = std::max(S, NewScore);
+  }
+  // Sort by the gathered scores. Use file name as a tie breaker so we can
+  // deduplicate.
+  std::sort(Symbols.begin(), Symbols.end(),
+            [&](const SymbolAndSignals &A, const SymbolAndSignals &B) {
+              auto AS = Score[A.Symbol.getFilePath()];
+              auto BS = Score[B.Symbol.getFilePath()];
+              if (AS != BS)
+                return AS > BS;
+              return A.Symbol.getFilePath() < B.Symbol.getFilePath();
+            });
+}
+
+std::vector<find_all_symbols::SymbolInfo>
+SymbolIndexManager::search(llvm::StringRef Identifier,
+                           bool IsNestedSearch,
+                           llvm::StringRef FileName) const {
+  // The identifier may be fully qualified, so split it and get all the context
+  // names.
+  llvm::SmallVector<llvm::StringRef, 8> Names;
+  Identifier.split(Names, "::");
+
+  bool IsFullyQualified = false;
+  if (Identifier.startswith("::")) {
+    Names.erase(Names.begin()); // Drop first (empty) element.
+    IsFullyQualified = true;
+  }
+
+  // As long as we don't find a result keep stripping name parts from the end.
+  // This is to support nested classes which aren't recorded in the database.
+  // Eventually we will either hit a class (namespaces aren't in the database
+  // either) and can report that result.
+  bool TookPrefix = false;
+  std::vector<SymbolAndSignals> MatchedSymbols;
+  do {
+    std::vector<SymbolAndSignals> Symbols;
+    for (const auto &DB : SymbolIndices) {
+      auto Res = DB.get()->search(Names.back());
+      Symbols.insert(Symbols.end(), Res.begin(), Res.end());
+    }
+
+    LLVM_DEBUG(llvm::dbgs() << "Searching " << Names.back() << "... got "
+                            << Symbols.size() << " results...\n");
+
+    for (auto &SymAndSig : Symbols) {
+      const SymbolInfo &Symbol = SymAndSig.Symbol;
+      // Match the identifier name without qualifier.
+      bool IsMatched = true;
+      auto SymbolContext = Symbol.getContexts().begin();
+      auto IdentiferContext = Names.rbegin() + 1; // Skip identifier name.
+      // Match the remaining context names.
+      while (IdentiferContext != Names.rend() &&
+             SymbolContext != Symbol.getContexts().end()) {
+        if (SymbolContext->second == *IdentiferContext) {
+          ++IdentiferContext;
+          ++SymbolContext;
+        } else if (SymbolContext->first ==
+                   find_all_symbols::SymbolInfo::ContextType::EnumDecl) {
+          // Skip non-scoped enum context.
+          ++SymbolContext;
+        } else {
+          IsMatched = false;
+          break;
+        }
+      }
+
+      // If the name was qualified we only want to add results if we evaluated
+      // all contexts.
+      if (IsFullyQualified)
+        IsMatched &= (SymbolContext == Symbol.getContexts().end());
+
+      // FIXME: Support full match. At this point, we only find symbols in
+      // database which end with the same contexts with the identifier.
+      if (IsMatched && IdentiferContext == Names.rend()) {
+        // If we're in a situation where we took a prefix but the thing we
+        // found couldn't possibly have a nested member ignore it.
+        if (TookPrefix &&
+            (Symbol.getSymbolKind() == SymbolInfo::SymbolKind::Function ||
+             Symbol.getSymbolKind() == SymbolInfo::SymbolKind::Variable ||
+             Symbol.getSymbolKind() ==
+                 SymbolInfo::SymbolKind::EnumConstantDecl ||
+             Symbol.getSymbolKind() == SymbolInfo::SymbolKind::Macro))
+          continue;
+
+        MatchedSymbols.push_back(std::move(SymAndSig));
+      }
+    }
+    Names.pop_back();
+    TookPrefix = true;
+  } while (MatchedSymbols.empty() && !Names.empty() && IsNestedSearch);
+
+  rank(MatchedSymbols, FileName);
+  // Strip signals, they are no longer needed.
+  std::vector<SymbolInfo> Res;
+  for (auto &SymAndSig : MatchedSymbols)
+    Res.push_back(std::move(SymAndSig.Symbol));
+  return Res;
+}
+
+} // namespace include_fixer
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/SymbolIndexManager.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/SymbolIndexManager.h
new file mode 100644
index 0000000..12963dd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/SymbolIndexManager.h
@@ -0,0 +1,66 @@
+//===-- SymbolIndexManager.h - Managing multiple SymbolIndices --*- 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_INCLUDE_FIXER_SYMBOLINDEXMANAGER_H
+#define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_SYMBOLINDEXMANAGER_H
+
+#include "SymbolIndex.h"
+#include "find-all-symbols/SymbolInfo.h"
+#include "llvm/ADT/StringRef.h"
+
+#ifdef _MSC_VER
+// Disable warnings from ppltasks.h transitively included by <future>.
+#pragma warning(push)
+#pragma warning(disable:4530)
+#endif
+
+#include <future>
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+namespace clang {
+namespace include_fixer {
+
+/// This class provides an interface for finding the header files corresponding
+/// to an identifier in the source code from multiple symbol databases.
+class SymbolIndexManager {
+public:
+  void addSymbolIndex(std::function<std::unique_ptr<SymbolIndex>()> F) {
+#if LLVM_ENABLE_THREADS
+    auto Strategy = std::launch::async;
+#else
+    auto Strategy = std::launch::deferred;
+#endif
+    SymbolIndices.push_back(std::async(Strategy, F));
+  }
+
+  /// Search for header files to be included for an identifier.
+  /// \param Identifier The identifier being searched for. May or may not be
+  ///                   fully qualified.
+  /// \param IsNestedSearch Whether searching nested classes. If true, the
+  ///        method tries to strip identifier name parts from the end until it
+  ///        finds the corresponding candidates in database (e.g for identifier
+  ///        "b::foo", the method will try to find "b" if it fails to find
+  ///        "b::foo").
+  ///
+  /// \returns A list of symbol candidates.
+  std::vector<find_all_symbols::SymbolInfo>
+  search(llvm::StringRef Identifier, bool IsNestedSearch = true,
+         llvm::StringRef FileName = "") const;
+
+private:
+  std::vector<std::shared_future<std::unique_ptr<SymbolIndex>>> SymbolIndices;
+};
+
+} // namespace include_fixer
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/YamlSymbolIndex.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/YamlSymbolIndex.cpp
new file mode 100644
index 0000000..f3f2d5a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/YamlSymbolIndex.cpp
@@ -0,0 +1,61 @@
+//===-- YamlSymbolIndex.cpp -----------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "YamlSymbolIndex.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include <string>
+#include <vector>
+
+using clang::find_all_symbols::SymbolInfo;
+using clang::find_all_symbols::SymbolAndSignals;
+
+namespace clang {
+namespace include_fixer {
+
+llvm::ErrorOr<std::unique_ptr<YamlSymbolIndex>>
+YamlSymbolIndex::createFromFile(llvm::StringRef FilePath) {
+  auto Buffer = llvm::MemoryBuffer::getFile(FilePath);
+  if (!Buffer)
+    return Buffer.getError();
+
+  return std::unique_ptr<YamlSymbolIndex>(new YamlSymbolIndex(
+      find_all_symbols::ReadSymbolInfosFromYAML(Buffer.get()->getBuffer())));
+}
+
+llvm::ErrorOr<std::unique_ptr<YamlSymbolIndex>>
+YamlSymbolIndex::createFromDirectory(llvm::StringRef Directory,
+                                     llvm::StringRef Name) {
+  // Walk upwards from Directory, looking for files.
+  for (llvm::SmallString<128> PathStorage = Directory; !Directory.empty();
+       Directory = llvm::sys::path::parent_path(Directory)) {
+    assert(Directory.size() <= PathStorage.size());
+    PathStorage.resize(Directory.size()); // Shrink to parent.
+    llvm::sys::path::append(PathStorage, Name);
+    if (auto DB = createFromFile(PathStorage))
+      return DB;
+  }
+  return llvm::make_error_code(llvm::errc::no_such_file_or_directory);
+}
+
+std::vector<SymbolAndSignals>
+YamlSymbolIndex::search(llvm::StringRef Identifier) {
+  std::vector<SymbolAndSignals> Results;
+  for (const auto &Symbol : Symbols) {
+    if (Symbol.Symbol.getName() == Identifier)
+      Results.push_back(Symbol);
+  }
+  return Results;
+}
+
+} // namespace include_fixer
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/YamlSymbolIndex.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/YamlSymbolIndex.h
new file mode 100644
index 0000000..d5d699a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/YamlSymbolIndex.h
@@ -0,0 +1,46 @@
+//===-- YamlSymbolIndex.h ---------------------------------------*- 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_INCLUDE_FIXER_YAMLSYMBOLINDEX_H
+#define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_YAMLSYMBOLINDEX_H
+
+#include "SymbolIndex.h"
+#include "find-all-symbols/SymbolInfo.h"
+#include "llvm/Support/ErrorOr.h"
+#include <map>
+#include <vector>
+
+namespace clang {
+namespace include_fixer {
+
+/// Yaml format database.
+class YamlSymbolIndex : public SymbolIndex {
+public:
+  /// Create a new Yaml db from a file.
+  static llvm::ErrorOr<std::unique_ptr<YamlSymbolIndex>>
+  createFromFile(llvm::StringRef FilePath);
+  /// Look for a file called \c Name in \c Directory and all parent directories.
+  static llvm::ErrorOr<std::unique_ptr<YamlSymbolIndex>>
+  createFromDirectory(llvm::StringRef Directory, llvm::StringRef Name);
+
+  std::vector<find_all_symbols::SymbolAndSignals>
+  search(llvm::StringRef Identifier) override;
+
+private:
+  explicit YamlSymbolIndex(
+      std::vector<find_all_symbols::SymbolAndSignals> Symbols)
+      : Symbols(std::move(Symbols)) {}
+
+  std::vector<find_all_symbols::SymbolAndSignals> Symbols;
+};
+
+} // namespace include_fixer
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_YAMLSYMBOLINDEX_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/CMakeLists.txt
new file mode 100644
index 0000000..c5fe19b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/CMakeLists.txt
@@ -0,0 +1,24 @@
+set(LLVM_LINK_COMPONENTS
+  Support
+  )
+
+add_clang_library(findAllSymbols
+  FindAllSymbols.cpp
+  FindAllSymbolsAction.cpp
+  FindAllMacros.cpp
+  HeaderMapCollector.cpp
+  PathConfig.cpp
+  PragmaCommentHandler.cpp
+  STLPostfixHeaderMap.cpp
+  SymbolInfo.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFrontend
+  clangLex
+  clangTooling
+  )
+
+add_subdirectory(tool)
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllMacros.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllMacros.cpp
new file mode 100644
index 0000000..3dc2b96
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllMacros.cpp
@@ -0,0 +1,70 @@
+//===-- FindAllMacros.cpp - find all macros ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FindAllMacros.h"
+#include "HeaderMapCollector.h"
+#include "PathConfig.h"
+#include "SymbolInfo.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Token.h"
+#include "llvm/Support/Path.h"
+
+namespace clang {
+namespace find_all_symbols {
+
+llvm::Optional<SymbolInfo>
+FindAllMacros::CreateMacroSymbol(const Token &MacroNameTok,
+                                 const MacroInfo *info) {
+  std::string FilePath =
+      getIncludePath(*SM, info->getDefinitionLoc(), Collector);
+  if (FilePath.empty())
+    return llvm::None;
+  return SymbolInfo(MacroNameTok.getIdentifierInfo()->getName(),
+                    SymbolInfo::SymbolKind::Macro, FilePath, {});
+}
+
+void FindAllMacros::MacroDefined(const Token &MacroNameTok,
+                                 const MacroDirective *MD) {
+  if (auto Symbol = CreateMacroSymbol(MacroNameTok, MD->getMacroInfo()))
+    ++FileSymbols[*Symbol].Seen;
+}
+
+void FindAllMacros::MacroUsed(const Token &Name, const MacroDefinition &MD) {
+  if (!MD || !SM->isInMainFile(SM->getExpansionLoc(Name.getLocation())))
+    return;
+  if (auto Symbol = CreateMacroSymbol(Name, MD.getMacroInfo()))
+    ++FileSymbols[*Symbol].Used;
+}
+
+void FindAllMacros::MacroExpands(const Token &MacroNameTok,
+                                 const MacroDefinition &MD, SourceRange Range,
+                                 const MacroArgs *Args) {
+  MacroUsed(MacroNameTok, MD);
+}
+
+void FindAllMacros::Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+                          const MacroDefinition &MD) {
+  MacroUsed(MacroNameTok, MD);
+}
+
+void FindAllMacros::Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+                           const MacroDefinition &MD) {
+  MacroUsed(MacroNameTok, MD);
+}
+
+void FindAllMacros::EndOfMainFile() {
+  Reporter->reportSymbols(SM->getFileEntryForID(SM->getMainFileID())->getName(),
+                          FileSymbols);
+  FileSymbols.clear();
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllMacros.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllMacros.h
new file mode 100644
index 0000000..10b4a69
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllMacros.h
@@ -0,0 +1,65 @@
+//===-- FindAllMacros.h - find all macros -----------------------*- 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_FIND_ALL_SYMBOLS_FIND_ALL_MACROS_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_FIND_ALL_MACROS_H
+
+#include "SymbolInfo.h"
+#include "SymbolReporter.h"
+#include "clang/Lex/PPCallbacks.h"
+
+namespace clang {
+class MacroInfo;
+namespace find_all_symbols {
+
+class HeaderMapCollector;
+
+/// \brief A preprocessor that collects all macro symbols.
+/// The contexts of a macro will be ignored since they are not available during
+/// preprocessing period.
+class FindAllMacros : public clang::PPCallbacks {
+public:
+  explicit FindAllMacros(SymbolReporter *Reporter, SourceManager *SM,
+                         HeaderMapCollector *Collector = nullptr)
+      : Reporter(Reporter), SM(SM), Collector(Collector) {}
+
+  void MacroDefined(const Token &MacroNameTok,
+                    const MacroDirective *MD) override;
+
+  void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
+                    SourceRange Range, const MacroArgs *Args) override;
+
+  void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+             const MacroDefinition &MD) override;
+
+  void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+              const MacroDefinition &MD) override;
+
+  void EndOfMainFile() override;
+
+private:
+  llvm::Optional<SymbolInfo> CreateMacroSymbol(const Token &MacroNameTok,
+                                               const MacroInfo *MD);
+  // Not a callback, just a common path for all usage types.
+  void MacroUsed(const Token &Name, const MacroDefinition &MD);
+
+  SymbolInfo::SignalMap FileSymbols;
+  // Reporter for SymbolInfo.
+  SymbolReporter *const Reporter;
+  SourceManager *const SM;
+  // A remapping header file collector allowing clients to include a different
+  // header.
+  HeaderMapCollector *const Collector;
+};
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_FIND_ALL_MACROS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.cpp
new file mode 100644
index 0000000..bd5032d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.cpp
@@ -0,0 +1,269 @@
+//===-- FindAllSymbols.cpp - find all symbols--------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FindAllSymbols.h"
+#include "HeaderMapCollector.h"
+#include "PathConfig.h"
+#include "SymbolInfo.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/FileSystem.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace find_all_symbols {
+namespace {
+
+AST_MATCHER(EnumConstantDecl, isInScopedEnum) {
+  if (const auto *ED = dyn_cast<EnumDecl>(Node.getDeclContext()))
+    return ED->isScoped();
+  return false;
+}
+
+AST_POLYMORPHIC_MATCHER(isFullySpecialized,
+                        AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, VarDecl,
+                                                        CXXRecordDecl)) {
+  if (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
+    bool IsPartialSpecialization =
+        llvm::isa<VarTemplatePartialSpecializationDecl>(Node) ||
+        llvm::isa<ClassTemplatePartialSpecializationDecl>(Node);
+    return !IsPartialSpecialization;
+  }
+  return false;
+}
+
+std::vector<SymbolInfo::Context> GetContexts(const NamedDecl *ND) {
+  std::vector<SymbolInfo::Context> Contexts;
+  for (const auto *Context = ND->getDeclContext(); Context;
+       Context = Context->getParent()) {
+    if (llvm::isa<TranslationUnitDecl>(Context) ||
+        llvm::isa<LinkageSpecDecl>(Context))
+      break;
+
+    assert(llvm::isa<NamedDecl>(Context) &&
+           "Expect Context to be a NamedDecl");
+    if (const auto *NSD = dyn_cast<NamespaceDecl>(Context)) {
+      if (!NSD->isInlineNamespace())
+        Contexts.emplace_back(SymbolInfo::ContextType::Namespace,
+                              NSD->getName().str());
+    } else if (const auto *ED = dyn_cast<EnumDecl>(Context)) {
+      Contexts.emplace_back(SymbolInfo::ContextType::EnumDecl,
+                            ED->getName().str());
+    } else {
+      const auto *RD = cast<RecordDecl>(Context);
+      Contexts.emplace_back(SymbolInfo::ContextType::Record,
+                            RD->getName().str());
+    }
+  }
+  return Contexts;
+}
+
+llvm::Optional<SymbolInfo>
+CreateSymbolInfo(const NamedDecl *ND, const SourceManager &SM,
+                 const HeaderMapCollector *Collector) {
+  SymbolInfo::SymbolKind Type;
+  if (llvm::isa<VarDecl>(ND)) {
+    Type = SymbolInfo::SymbolKind::Variable;
+  } else if (llvm::isa<FunctionDecl>(ND)) {
+    Type = SymbolInfo::SymbolKind::Function;
+  } else if (llvm::isa<TypedefNameDecl>(ND)) {
+    Type = SymbolInfo::SymbolKind::TypedefName;
+  } else if (llvm::isa<EnumConstantDecl>(ND)) {
+    Type = SymbolInfo::SymbolKind::EnumConstantDecl;
+  } else if (llvm::isa<EnumDecl>(ND)) {
+    Type = SymbolInfo::SymbolKind::EnumDecl;
+    // Ignore anonymous enum declarations.
+    if (ND->getName().empty())
+      return llvm::None;
+  } else {
+    assert(llvm::isa<RecordDecl>(ND) &&
+           "Matched decl must be one of VarDecl, "
+           "FunctionDecl, TypedefNameDecl, EnumConstantDecl, "
+           "EnumDecl and RecordDecl!");
+    // C-style record decl can have empty name, e.g "struct { ... } var;".
+    if (ND->getName().empty())
+      return llvm::None;
+    Type = SymbolInfo::SymbolKind::Class;
+  }
+
+  SourceLocation Loc = SM.getExpansionLoc(ND->getLocation());
+  if (!Loc.isValid()) {
+    llvm::errs() << "Declaration " << ND->getNameAsString() << "("
+                 << ND->getDeclKindName()
+                 << ") has invalid declaration location.";
+    return llvm::None;
+  }
+
+  std::string FilePath = getIncludePath(SM, Loc, Collector);
+  if (FilePath.empty()) return llvm::None;
+
+  return SymbolInfo(ND->getNameAsString(), Type, FilePath, GetContexts(ND));
+}
+
+} // namespace
+
+void FindAllSymbols::registerMatchers(MatchFinder *MatchFinder) {
+  // FIXME: Handle specialization.
+  auto IsInSpecialization = hasAncestor(
+      decl(anyOf(cxxRecordDecl(isExplicitTemplateSpecialization()),
+                 functionDecl(isExplicitTemplateSpecialization()))));
+
+  // Matchers for both C and C++.
+  // We only match symbols from header files, i.e. not from main files (see
+  // function's comment for detailed explanation).
+  auto CommonFilter =
+      allOf(unless(isImplicit()), unless(isExpansionInMainFile()));
+
+  auto HasNSOrTUCtxMatcher =
+      hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl()));
+
+  // We need seperate rules for C record types and C++ record types since some
+  // template related matchers are inapplicable on C record declarations.
+  //
+  // Matchers specific to C++ code.
+  // All declarations should be in namespace or translation unit.
+  auto CCMatcher =
+      allOf(HasNSOrTUCtxMatcher, unless(IsInSpecialization),
+            unless(ast_matchers::isTemplateInstantiation()),
+            unless(isInstantiated()), unless(isFullySpecialized()));
+
+  // Matchers specific to code in extern "C" {...}.
+  auto ExternCMatcher = hasDeclContext(linkageSpecDecl());
+
+  // Matchers for variable declarations.
+  //
+  // In most cases, `ParmVarDecl` is filtered out by hasDeclContext(...)
+  // matcher since the declaration context is usually `MethodDecl`. However,
+  // this assumption does not hold for parameters of a function pointer
+  // parameter.
+  // For example, consider a function declaration:
+  //        void Func(void (*)(float), int);
+  // The float parameter of the function pointer has an empty name, and its
+  // declaration context is an anonymous namespace; therefore, it won't be
+  // filtered out by our matchers above.
+  auto Vars = varDecl(CommonFilter, anyOf(ExternCMatcher, CCMatcher),
+                      unless(parmVarDecl()));
+
+  // Matchers for C-style record declarations in extern "C" {...}.
+  auto CRecords = recordDecl(CommonFilter, ExternCMatcher, isDefinition());
+  // Matchers for C++ record declarations.
+  auto CXXRecords = cxxRecordDecl(CommonFilter, CCMatcher, isDefinition());
+
+  // Matchers for function declarations.
+  // We want to exclude friend declaration, but the `DeclContext` of a friend
+  // function declaration is not the class in which it is declared, so we need
+  // to explicitly check if the parent is a `friendDecl`.
+  auto Functions = functionDecl(CommonFilter, unless(hasParent(friendDecl())),
+                                anyOf(ExternCMatcher, CCMatcher));
+
+  // Matcher for typedef and type alias declarations.
+  //
+  // typedef and type alias can come from C-style headers and C++ headers.
+  // For C-style headers, `DeclContxet` can be either `TranslationUnitDecl`
+  // or `LinkageSpecDecl`.
+  // For C++ headers, `DeclContext ` can be either `TranslationUnitDecl`
+  // or `NamespaceDecl`.
+  // With the following context matcher, we can match `typedefNameDecl` from
+  // both C-style headers and C++ headers (except for those in classes).
+  // "cc_matchers" are not included since template-related matchers are not
+  // applicable on `TypedefNameDecl`.
+  auto Typedefs =
+      typedefNameDecl(CommonFilter, anyOf(HasNSOrTUCtxMatcher,
+                                          hasDeclContext(linkageSpecDecl())));
+
+  // Matchers for enum declarations.
+  auto Enums = enumDecl(CommonFilter, isDefinition(),
+                        anyOf(HasNSOrTUCtxMatcher, ExternCMatcher));
+
+  // Matchers for enum constant declarations.
+  // We only match the enum constants in non-scoped enum declarations which are
+  // inside toplevel translation unit or a namespace.
+  auto EnumConstants = enumConstantDecl(
+      CommonFilter, unless(isInScopedEnum()),
+      anyOf(hasDeclContext(enumDecl(HasNSOrTUCtxMatcher)), ExternCMatcher));
+
+  // Most of the time we care about all matchable decls, or all types.
+  auto Types = namedDecl(anyOf(CRecords, CXXRecords, Enums));
+  auto Decls = namedDecl(anyOf(CRecords, CXXRecords, Enums, Typedefs, Vars,
+                               EnumConstants, Functions));
+
+  // We want eligible decls bound to "decl"...
+  MatchFinder->addMatcher(Decls.bind("decl"), this);
+
+  // ... and all uses of them bound to "use". These have many cases:
+  // Uses of values/functions: these generate a declRefExpr.
+  MatchFinder->addMatcher(
+      declRefExpr(isExpansionInMainFile(), to(Decls.bind("use"))), this);
+  // Uses of function templates:
+  MatchFinder->addMatcher(
+      declRefExpr(isExpansionInMainFile(),
+                  to(functionDecl(hasParent(
+                      functionTemplateDecl(has(Functions.bind("use"))))))),
+      this);
+
+  // Uses of most types: just look at what the typeLoc refers to.
+  MatchFinder->addMatcher(
+      typeLoc(isExpansionInMainFile(),
+              loc(qualType(hasDeclaration(Types.bind("use"))))),
+      this);
+  // Uses of typedefs: these are often transparent to hasDeclaration, so we need
+  // to handle them explicitly.
+  MatchFinder->addMatcher(
+      typeLoc(isExpansionInMainFile(),
+              loc(typedefType(hasDeclaration(Typedefs.bind("use"))))),
+      this);
+  // Uses of class templates:
+  // The typeLoc names the templateSpecializationType. Its declaration is the
+  // ClassTemplateDecl, which contains the CXXRecordDecl we want.
+  MatchFinder->addMatcher(
+      typeLoc(isExpansionInMainFile(),
+              loc(templateSpecializationType(hasDeclaration(
+                  classTemplateSpecializationDecl(hasSpecializedTemplate(
+                      classTemplateDecl(has(CXXRecords.bind("use"))))))))),
+      this);
+}
+
+void FindAllSymbols::run(const MatchFinder::MatchResult &Result) {
+  // Ignore Results in failing TUs.
+  if (Result.Context->getDiagnostics().hasErrorOccurred()) {
+    return;
+  }
+
+  SymbolInfo::Signals Signals;
+  const NamedDecl *ND;
+  if ((ND = Result.Nodes.getNodeAs<NamedDecl>("use")))
+    Signals.Used = 1;
+  else if ((ND = Result.Nodes.getNodeAs<NamedDecl>("decl")))
+    Signals.Seen = 1;
+  else
+    assert(false && "Must match a NamedDecl!");
+
+  const SourceManager *SM = Result.SourceManager;
+  if (auto Symbol = CreateSymbolInfo(ND, *SM, Collector)) {
+    Filename = SM->getFileEntryForID(SM->getMainFileID())->getName();
+    FileSymbols[*Symbol] += Signals;
+  }
+}
+
+void FindAllSymbols::onEndOfTranslationUnit() {
+  if (Filename != "") {
+    Reporter->reportSymbols(Filename, FileSymbols);
+    FileSymbols.clear();
+    Filename = "";
+  }
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.h
new file mode 100644
index 0000000..fca849f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.h
@@ -0,0 +1,63 @@
+//===-- FindAllSymbols.h - find all symbols----------------------*- 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_FIND_ALL_SYMBOLS_SYMBOL_MATCHER_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_MATCHER_H
+
+#include "SymbolInfo.h"
+#include "SymbolReporter.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include <string>
+
+namespace clang {
+namespace find_all_symbols {
+
+class HeaderMapCollector;
+
+/// \brief FindAllSymbols collects all classes, free standing functions and
+/// global variables with some extra information such as the path of the header
+/// file, the namespaces they are contained in, the type of variables and the
+/// parameter types of functions.
+///
+/// NOTE:
+///   - Symbols declared in main files are not collected since they can not be
+///   included.
+///   - Member functions are not collected because accessing them must go
+///   through the class. #include fixer only needs the class name to find
+///   headers.
+///
+class FindAllSymbols : public ast_matchers::MatchFinder::MatchCallback {
+public:
+  explicit FindAllSymbols(SymbolReporter *Reporter,
+                          HeaderMapCollector *Collector = nullptr)
+      : Reporter(Reporter), Collector(Collector) {}
+
+  void registerMatchers(ast_matchers::MatchFinder *MatchFinder);
+
+  void run(const ast_matchers::MatchFinder::MatchResult &result) override;
+
+protected:
+  void onEndOfTranslationUnit() override;
+
+private:
+  // Current source file being processed, filled by first symbol found.
+  std::string Filename;
+  // Findings for the current source file, flushed on onEndOfTranslationUnit.
+  SymbolInfo::SignalMap FileSymbols;
+  // Reporter for SymbolInfo.
+  SymbolReporter *const Reporter;
+  // A remapping header file collector allowing clients include a different
+  // header.
+  HeaderMapCollector *const Collector;
+};
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_MATCHER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbolsAction.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbolsAction.cpp
new file mode 100644
index 0000000..bc00547
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbolsAction.cpp
@@ -0,0 +1,37 @@
+//===-- FindAllSymbolsAction.cpp - find all symbols action --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FindAllSymbolsAction.h"
+#include "FindAllMacros.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/STLExtras.h"
+
+namespace clang {
+namespace find_all_symbols {
+
+FindAllSymbolsAction::FindAllSymbolsAction(
+    SymbolReporter *Reporter,
+    const HeaderMapCollector::RegexHeaderMap *RegexHeaderMap)
+    : Reporter(Reporter), Collector(RegexHeaderMap), Handler(&Collector),
+      Matcher(Reporter, &Collector) {
+  Matcher.registerMatchers(&MatchFinder);
+}
+
+std::unique_ptr<ASTConsumer>
+FindAllSymbolsAction::CreateASTConsumer(CompilerInstance &Compiler,
+                                        StringRef InFile) {
+  Compiler.getPreprocessor().addCommentHandler(&Handler);
+  Compiler.getPreprocessor().addPPCallbacks(llvm::make_unique<FindAllMacros>(
+      Reporter, &Compiler.getSourceManager(), &Collector));
+  return MatchFinder.newASTConsumer();
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbolsAction.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbolsAction.h
new file mode 100644
index 0000000..7be9fe2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbolsAction.h
@@ -0,0 +1,63 @@
+//===-- FindAllSymbolsAction.h - find all symbols action --------*- 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_FIND_ALL_SYMBOLS_FIND_ALL_SYMBOLS_ACTION_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_FIND_ALL_SYMBOLS_ACTION_H
+
+#include "FindAllSymbols.h"
+#include "HeaderMapCollector.h"
+#include "PragmaCommentHandler.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/StringRef.h"
+#include <memory>
+
+namespace clang {
+namespace find_all_symbols {
+
+class FindAllSymbolsAction : public clang::ASTFrontendAction {
+public:
+  explicit FindAllSymbolsAction(
+      SymbolReporter *Reporter,
+      const HeaderMapCollector::RegexHeaderMap *RegexHeaderMap = nullptr);
+
+  std::unique_ptr<clang::ASTConsumer>
+  CreateASTConsumer(clang::CompilerInstance &Compiler,
+                    StringRef InFile) override;
+
+private:
+  SymbolReporter *const Reporter;
+  clang::ast_matchers::MatchFinder MatchFinder;
+  HeaderMapCollector Collector;
+  PragmaCommentHandler Handler;
+  FindAllSymbols Matcher;
+};
+
+class FindAllSymbolsActionFactory : public tooling::FrontendActionFactory {
+public:
+  FindAllSymbolsActionFactory(
+      SymbolReporter *Reporter,
+      const HeaderMapCollector::RegexHeaderMap *RegexHeaderMap = nullptr)
+      : Reporter(Reporter), RegexHeaderMap(RegexHeaderMap) {}
+
+  clang::FrontendAction *create() override {
+    return new FindAllSymbolsAction(Reporter, RegexHeaderMap);
+  }
+
+private:
+  SymbolReporter *const Reporter;
+  const HeaderMapCollector::RegexHeaderMap *const RegexHeaderMap;
+};
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_FIND_ALL_SYMBOLS_ACTION_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/HeaderMapCollector.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/HeaderMapCollector.cpp
new file mode 100644
index 0000000..379df81
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/HeaderMapCollector.cpp
@@ -0,0 +1,45 @@
+//===-- HeaderMapCoolector.h - find all symbols------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "HeaderMapCollector.h"
+#include "llvm/Support/Regex.h"
+
+namespace clang {
+namespace find_all_symbols {
+
+HeaderMapCollector::HeaderMapCollector(
+    const RegexHeaderMap *RegexHeaderMappingTable) {
+  assert(RegexHeaderMappingTable);
+  this->RegexHeaderMappingTable.reserve(RegexHeaderMappingTable->size());
+  for (const auto &Entry : *RegexHeaderMappingTable) {
+    this->RegexHeaderMappingTable.emplace_back(llvm::Regex(Entry.first),
+                                               Entry.second);
+  }
+}
+
+llvm::StringRef
+HeaderMapCollector::getMappedHeader(llvm::StringRef Header) const {
+  auto Iter = HeaderMappingTable.find(Header);
+  if (Iter != HeaderMappingTable.end())
+    return Iter->second;
+  // If there is no complete header name mapping for this header, check the
+  // regex header mapping.
+  for (auto &Entry : RegexHeaderMappingTable) {
+#ifndef NDEBUG
+    std::string Dummy;
+    assert(Entry.first.isValid(Dummy) && "Regex should never be invalid!");
+#endif
+    if (Entry.first.match(Header))
+      return Entry.second;
+  }
+  return Header;
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/HeaderMapCollector.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/HeaderMapCollector.h
new file mode 100644
index 0000000..65edd75
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/HeaderMapCollector.h
@@ -0,0 +1,57 @@
+//===-- HeaderMapCoolector.h - find all symbols------------------*- 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_FIND_ALL_SYMBOLS_HEADER_MAP_COLLECTOR_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_HEADER_MAP_COLLECTOR_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Regex.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace find_all_symbols {
+
+/// \brief HeaderMappCollector collects all remapping header files. This maps
+/// complete header names or header name regex patterns to header names.
+class HeaderMapCollector {
+public:
+  typedef llvm::StringMap<std::string> HeaderMap;
+  typedef std::vector<std::pair<const char *, const char *>> RegexHeaderMap;
+
+  HeaderMapCollector() = default;
+  explicit HeaderMapCollector(const RegexHeaderMap *RegexHeaderMappingTable);
+
+  void addHeaderMapping(llvm::StringRef OrignalHeaderPath,
+                        llvm::StringRef MappingHeaderPath) {
+    HeaderMappingTable[OrignalHeaderPath] = MappingHeaderPath;
+  };
+
+  /// Check if there is a mapping from \p Header or a regex pattern that matches
+  /// it to another header name.
+  /// \param Header A header name.
+  /// \return \p Header itself if there is no mapping for it; otherwise, return
+  /// a mapped header name.
+  llvm::StringRef getMappedHeader(llvm::StringRef Header) const;
+
+private:
+  /// A string-to-string map saving the mapping relationship.
+  HeaderMap HeaderMappingTable;
+
+  // A map from header patterns to header names.
+  // The header names are not owned. This is only threadsafe because the regexes
+  // never fail.
+  mutable std::vector<std::pair<llvm::Regex, const char *>>
+      RegexHeaderMappingTable;
+};
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_HEADER_MAP_COLLECTOR_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/PathConfig.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/PathConfig.cpp
new file mode 100644
index 0000000..de799b9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/PathConfig.cpp
@@ -0,0 +1,42 @@
+//===-- PathConfig.cpp - Process paths of symbols ---------------*- C++ -*-===//
+//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PathConfig.h"
+#include "llvm/Support/Path.h"
+
+namespace clang {
+namespace find_all_symbols {
+
+std::string getIncludePath(const SourceManager &SM, SourceLocation Loc,
+                           const HeaderMapCollector *Collector) {
+  llvm::StringRef FilePath;
+  // Walk up the include stack to skip .inc files.
+  while (true) {
+    if (!Loc.isValid() || SM.isInMainFile(Loc))
+      return "";
+    FilePath = SM.getFilename(Loc);
+    if (FilePath.empty())
+      return "";
+    if (!FilePath.endswith(".inc"))
+      break;
+    FileID ID = SM.getFileID(Loc);
+    Loc = SM.getIncludeLoc(ID);
+  }
+
+  if (Collector)
+    FilePath = Collector->getMappedHeader(FilePath);
+  SmallString<256> CleanedFilePath = FilePath;
+  llvm::sys::path::remove_dots(CleanedFilePath, /*remove_dot_dot=*/false);
+
+  return CleanedFilePath.str();
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/PathConfig.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/PathConfig.h
new file mode 100644
index 0000000..50de548
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/PathConfig.h
@@ -0,0 +1,37 @@
+//===-- PathConfig.h - Process paths of symbols -----------------*- 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_FIND_ALL_SYMBOLS_PATH_CONFIG_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_PATH_CONFIG_H
+
+#include "HeaderMapCollector.h"
+#include "clang/Basic/SourceManager.h"
+#include <string>
+
+namespace clang {
+namespace find_all_symbols {
+
+/// \brief This calculates the include path for \p Loc.
+///
+/// \param SM SourceManager.
+/// \param Loc A SourceLocation.
+/// \param Collector An optional header mapping collector.
+///
+/// \return The file path (or mapped file path if Collector is provided) of the
+/// header that includes \p Loc. If \p Loc comes from .inc header file, \p Loc
+/// is set to the location from which the .inc header file is included. If \p
+/// Loc is invalid or comes from a main file, this returns an empty string.
+std::string getIncludePath(const SourceManager &SM, SourceLocation Loc,
+                           const HeaderMapCollector *Collector = nullptr);
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_PATH_CONFIG_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/PragmaCommentHandler.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/PragmaCommentHandler.cpp
new file mode 100644
index 0000000..0242d38
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/PragmaCommentHandler.cpp
@@ -0,0 +1,37 @@
+//===-- PragmaCommentHandler.cpp - find all symbols -----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PragmaCommentHandler.h"
+#include "FindAllSymbols.h"
+#include "HeaderMapCollector.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/Regex.h"
+
+namespace clang {
+namespace find_all_symbols {
+namespace {
+const char IWYUPragma[] = "// IWYU pragma: private, include ";
+} // namespace
+
+bool PragmaCommentHandler::HandleComment(Preprocessor &PP, SourceRange Range) {
+  StringRef Text =
+      Lexer::getSourceText(CharSourceRange::getCharRange(Range),
+                           PP.getSourceManager(), PP.getLangOpts());
+  size_t Pos = Text.find(IWYUPragma);
+  if (Pos == StringRef::npos)
+    return false;
+  StringRef RemappingFilePath = Text.substr(Pos + std::strlen(IWYUPragma));
+  Collector->addHeaderMapping(
+      PP.getSourceManager().getFilename(Range.getBegin()),
+      RemappingFilePath.trim("\"<>"));
+  return false;
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/PragmaCommentHandler.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/PragmaCommentHandler.h
new file mode 100644
index 0000000..9eb4972
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/PragmaCommentHandler.h
@@ -0,0 +1,41 @@
+//===-- PragmaCommentHandler.h - find all symbols----------------*- 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_FIND_ALL_SYMBOLS_PRAGMA_COMMENT_HANDLER_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_PRAGMA_COMMENT_HANDLER_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Preprocessor.h"
+#include <map>
+
+namespace clang {
+namespace find_all_symbols {
+
+class HeaderMapCollector;
+
+/// \brief PragmaCommentHandler parses pragma comment on include files to
+/// determine when we should include a different header from the header that
+/// directly defines a symbol.
+///
+/// Currently it only supports IWYU private pragma:
+/// https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/IWYUPragmas.md#iwyu-pragma-private
+class PragmaCommentHandler : public clang::CommentHandler {
+public:
+  PragmaCommentHandler(HeaderMapCollector *Collector) : Collector(Collector) {}
+
+  bool HandleComment(Preprocessor &PP, SourceRange Range) override;
+
+private:
+  HeaderMapCollector *const Collector;
+};
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_PRAGMA_COMMENT_HANDLER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
new file mode 100644
index 0000000..4a49479
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
@@ -0,0 +1,654 @@
+//===-- STLPostfixHeaderMap.h - hardcoded STL header map --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "STLPostfixHeaderMap.h"
+
+namespace clang {
+namespace find_all_symbols {
+
+const HeaderMapCollector::RegexHeaderMap *getSTLPostfixHeaderMap() {
+  static const HeaderMapCollector::RegexHeaderMap STLPostfixHeaderMap = {
+      {"include/__stddef_max_align_t.h$", "<cstddef>"},
+      {"include/__wmmintrin_aes.h$", "<wmmintrin.h>"},
+      {"include/__wmmintrin_pclmul.h$", "<wmmintrin.h>"},
+      {"include/adxintrin.h$", "<immintrin.h>"},
+      {"include/ammintrin.h$", "<ammintrin.h>"},
+      {"include/avx2intrin.h$", "<immintrin.h>"},
+      {"include/avx512bwintrin.h$", "<immintrin.h>"},
+      {"include/avx512cdintrin.h$", "<immintrin.h>"},
+      {"include/avx512dqintrin.h$", "<immintrin.h>"},
+      {"include/avx512erintrin.h$", "<immintrin.h>"},
+      {"include/avx512fintrin.h$", "<immintrin.h>"},
+      {"include/avx512ifmaintrin.h$", "<immintrin.h>"},
+      {"include/avx512ifmavlintrin.h$", "<immintrin.h>"},
+      {"include/avx512pfintrin.h$", "<immintrin.h>"},
+      {"include/avx512vbmiintrin.h$", "<immintrin.h>"},
+      {"include/avx512vbmivlintrin.h$", "<immintrin.h>"},
+      {"include/avx512vlbwintrin.h$", "<immintrin.h>"},
+      {"include/avx512vlcdintrin.h$", "<immintrin.h>"},
+      {"include/avx512vldqintrin.h$", "<immintrin.h>"},
+      {"include/avx512vlintrin.h$", "<immintrin.h>"},
+      {"include/avxintrin.h$", "<immintrin.h>"},
+      {"include/bmi2intrin.h$", "<x86intrin.h>"},
+      {"include/bmiintrin.h$", "<x86intrin.h>"},
+      {"include/emmintrin.h$", "<emmintrin.h>"},
+      {"include/f16cintrin.h$", "<emmintrin.h>"},
+      {"include/float.h$", "<cfloat>"},
+      {"include/fma4intrin.h$", "<x86intrin.h>"},
+      {"include/fmaintrin.h$", "<immintrin.h>"},
+      {"include/fxsrintrin.h$", "<immintrin.h>"},
+      {"include/ia32intrin.h$", "<x86intrin.h>"},
+      {"include/immintrin.h$", "<immintrin.h>"},
+      {"include/inttypes.h$", "<cinttypes>"},
+      {"include/limits.h$", "<climits>"},
+      {"include/lzcntintrin.h$", "<x86intrin.h>"},
+      {"include/mm3dnow.h$", "<mm3dnow.h>"},
+      {"include/mm_malloc.h$", "<mm_malloc.h>"},
+      {"include/mmintrin.h$", "<mmintrin>"},
+      {"include/mwaitxintrin.h$", "<x86intrin.h>"},
+      {"include/pkuintrin.h$", "<immintrin.h>"},
+      {"include/pmmintrin.h$", "<pmmintrin.h>"},
+      {"include/popcntintrin.h$", "<popcntintrin.h>"},
+      {"include/prfchwintrin.h$", "<x86intrin.h>"},
+      {"include/rdseedintrin.h$", "<x86intrin.h>"},
+      {"include/rtmintrin.h$", "<immintrin.h>"},
+      {"include/shaintrin.h$", "<immintrin.h>"},
+      {"include/smmintrin.h$", "<smmintrin.h>"},
+      {"include/stdalign.h$", "<cstdalign>"},
+      {"include/stdarg.h$", "<cstdarg>"},
+      {"include/stdbool.h$", "<cstdbool>"},
+      {"include/stddef.h$", "<cstddef>"},
+      {"include/stdint.h$", "<cstdint>"},
+      {"include/tbmintrin.h$", "<x86intrin.h>"},
+      {"include/tmmintrin.h$", "<tmmintrin.h>"},
+      {"include/wmmintrin.h$", "<wmmintrin.h>"},
+      {"include/x86intrin.h$", "<x86intrin.h>"},
+      {"include/xmmintrin.h$", "<xmmintrin.h>"},
+      {"include/xopintrin.h$", "<x86intrin.h>"},
+      {"include/xsavecintrin.h$", "<immintrin.h>"},
+      {"include/xsaveintrin.h$", "<immintrin.h>"},
+      {"include/xsaveoptintrin.h$", "<immintrin.h>"},
+      {"include/xsavesintrin.h$", "<immintrin.h>"},
+      {"include/xtestintrin.h$", "<immintrin.h>"},
+      {"include/_G_config.h$", "<cstdio>"},
+      {"include/assert.h$", "<cassert>"},
+      {"algorithm$", "<algorithm>"},
+      {"array$", "<array>"},
+      {"atomic$", "<atomic>"},
+      {"backward/auto_ptr.h$", "<memory>"},
+      {"backward/binders.h$", "<string>"},
+      {"bits/algorithmfwd.h$", "<algorithm>"},
+      {"bits/alloc_traits.h$", "<unordered_set>"},
+      {"bits/allocator.h$", "<string>"},
+      {"bits/atomic_base.h$", "<atomic>"},
+      {"bits/atomic_lockfree_defines.h$", "<exception>"},
+      {"bits/basic_ios.h$", "<ios>"},
+      {"bits/basic_ios.tcc$", "<ios>"},
+      {"bits/basic_string.h$", "<string>"},
+      {"bits/basic_string.tcc$", "<string>"},
+      {"bits/char_traits.h$", "<string>"},
+      {"bits/codecvt.h$", "<locale>"},
+      {"bits/concept_check.h$", "<numeric>"},
+      {"bits/cpp_type_traits.h$", "<cmath>"},
+      {"bits/cxxabi_forced.h$", "<cxxabi.h>"},
+      {"bits/deque.tcc$", "<deque>"},
+      {"bits/exception_defines.h$", "<exception>"},
+      {"bits/exception_ptr.h$", "<exception>"},
+      {"bits/forward_list.h$", "<forward_list>"},
+      {"bits/forward_list.tcc$", "<forward_list>"},
+      {"bits/fstream.tcc$", "<fstream>"},
+      {"bits/functexcept.h$", "<list>"},
+      {"bits/functional_hash.h$", "<string>"},
+      {"bits/gslice.h$", "<valarray>"},
+      {"bits/gslice_array.h$", "<valarray>"},
+      {"bits/hash_bytes.h$", "<typeinfo>"},
+      {"bits/hashtable.h$", "<unordered_set>"},
+      {"bits/hashtable_policy.h$", "<unordered_set>"},
+      {"bits/indirect_array.h$", "<valarray>"},
+      {"bits/ios_base.h$", "<ios>"},
+      {"bits/istream.tcc$", "<istream>"},
+      {"bits/list.tcc$", "<list>"},
+      {"bits/locale_classes.h$", "<locale>"},
+      {"bits/locale_classes.tcc$", "<locale>"},
+      {"bits/locale_facets.h$", "<locale>"},
+      {"bits/locale_facets.tcc$", "<locale>"},
+      {"bits/locale_facets_nonio.h$", "<locale>"},
+      {"bits/locale_facets_nonio.tcc$", "<locale>"},
+      {"bits/localefwd.h$", "<locale>"},
+      {"bits/mask_array.h$", "<valarray>"},
+      {"bits/memoryfwd.h$", "<memory>"},
+      {"bits/move.h$", "<utility>"},
+      {"bits/nested_exception.h$", "<exception>"},
+      {"bits/ostream.tcc$", "<ostream>"},
+      {"bits/ostream_insert.h$", "<ostream>"},
+      {"bits/postypes.h$", "<iosfwd>"},
+      {"bits/ptr_traits.h$", "<memory>"},
+      {"bits/random.h$", "<random>"},
+      {"bits/random.tcc$", "<random>"},
+      {"bits/range_access.h$", "<iterator>"},
+      {"bits/regex.h$", "<regex>"},
+      {"bits/regex_compiler.h$", "<regex>"},
+      {"bits/regex_constants.h$", "<regex>"},
+      {"bits/regex_cursor.h$", "<regex>"},
+      {"bits/regex_error.h$", "<regex>"},
+      {"bits/regex_grep_matcher.h$", "<regex>"},
+      {"bits/regex_grep_matcher.tcc$", "<regex>"},
+      {"bits/regex_nfa.h$", "<regex>"},
+      {"bits/shared_ptr.h$", "<memory>"},
+      {"bits/shared_ptr_base.h$", "<memory>"},
+      {"bits/slice_array.h$", "<valarray>"},
+      {"bits/sstream.tcc$", "<sstream>"},
+      {"bits/stl_algo.h$", "<algorithm>"},
+      {"bits/stl_algobase.h$", "<list>"},
+      {"bits/stl_bvector.h$", "<vector>"},
+      {"bits/stl_construct.h$", "<deque>"},
+      {"bits/stl_deque.h$", "<deque>"},
+      {"bits/stl_function.h$", "<string>"},
+      {"bits/stl_heap.h$", "<queue>"},
+      {"bits/stl_iterator.h$", "<iterator>"},
+      {"bits/stl_iterator_base_funcs.h$", "<iterator>"},
+      {"bits/stl_iterator_base_types.h$", "<numeric>"},
+      {"bits/stl_list.h$", "<list>"},
+      {"bits/stl_map.h$", "<map>"},
+      {"bits/stl_multimap.h$", "<map>"},
+      {"bits/stl_multiset.h$", "<set>"},
+      {"bits/stl_numeric.h$", "<numeric>"},
+      {"bits/stl_pair.h$", "<utility>"},
+      {"bits/stl_queue.h$", "<queue>"},
+      {"bits/stl_raw_storage_iter.h$", "<memory>"},
+      {"bits/stl_relops.h$", "<utility>"},
+      {"bits/stl_set.h$", "<set>"},
+      {"bits/stl_stack.h$", "<stack>"},
+      {"bits/stl_tempbuf.h$", "<memory>"},
+      {"bits/stl_tree.h$", "<map>"},
+      {"bits/stl_uninitialized.h$", "<deque>"},
+      {"bits/stl_vector.h$", "<vector>"},
+      {"bits/stream_iterator.h$", "<iterator>"},
+      {"bits/streambuf.tcc$", "<streambuf>"},
+      {"bits/streambuf_iterator.h$", "<iterator>"},
+      {"bits/stringfwd.h$", "<string>"},
+      {"bits/unique_ptr.h$", "<memory>"},
+      {"bits/unordered_map.h$", "<unordered_map>"},
+      {"bits/unordered_set.h$", "<unordered_set>"},
+      {"bits/uses_allocator.h$", "<tuple>"},
+      {"bits/valarray_after.h$", "<valarray>"},
+      {"bits/valarray_array.h$", "<valarray>"},
+      {"bits/valarray_array.tcc$", "<valarray>"},
+      {"bits/valarray_before.h$", "<valarray>"},
+      {"bits/vector.tcc$", "<vector>"},
+      {"bitset$", "<bitset>"},
+      {"ccomplex$", "<ccomplex>"},
+      {"cctype$", "<cctype>"},
+      {"cerrno$", "<cerrno>"},
+      {"cfenv$", "<cfenv>"},
+      {"cfloat$", "<cfloat>"},
+      {"chrono$", "<chrono>"},
+      {"cinttypes$", "<cinttypes>"},
+      {"climits$", "<climits>"},
+      {"clocale$", "<clocale>"},
+      {"cmath$", "<cmath>"},
+      {"complex$", "<complex>"},
+      {"complex.h$", "<complex.h>"},
+      {"condition_variable$", "<condition_variable>"},
+      {"csetjmp$", "<csetjmp>"},
+      {"csignal$", "<csignal>"},
+      {"cstdalign$", "<cstdalign>"},
+      {"cstdarg$", "<cstdarg>"},
+      {"cstdbool$", "<cstdbool>"},
+      {"cstdint$", "<cstdint>"},
+      {"cstdio$", "<cstdio>"},
+      {"cstdlib$", "<cstdlib>"},
+      {"cstring$", "<cstring>"},
+      {"ctgmath$", "<ctgmath>"},
+      {"ctime$", "<ctime>"},
+      {"cwchar$", "<cwchar>"},
+      {"cwctype$", "<cwctype>"},
+      {"cxxabi.h$", "<cxxabi.h>"},
+      {"debug/debug.h$", "<numeric>"},
+      {"debug/map.h$", "<map>"},
+      {"debug/multimap.h$", "<multimap>"},
+      {"debug/multiset.h$", "<multiset>"},
+      {"debug/set.h$", "<set>"},
+      {"deque$", "<deque>"},
+      {"exception$", "<exception>"},
+      {"ext/alloc_traits.h$", "<deque>"},
+      {"ext/atomicity.h$", "<memory>"},
+      {"ext/concurrence.h$", "<memory>"},
+      {"ext/new_allocator.h$", "<string>"},
+      {"ext/numeric_traits.h$", "<list>"},
+      {"ext/string_conversions.h$", "<string>"},
+      {"ext/type_traits.h$", "<cmath>"},
+      {"fenv.h$", "<fenv.h>"},
+      {"forward_list$", "<forward_list>"},
+      {"fstream$", "<fstream>"},
+      {"functional$", "<functional>"},
+      {"future$", "<future>"},
+      {"initializer_list$", "<initializer_list>"},
+      {"iomanip$", "<iomanip>"},
+      {"ios$", "<ios>"},
+      {"iosfwd$", "<iosfwd>"},
+      {"iostream$", "<iostream>"},
+      {"istream$", "<istream>"},
+      {"iterator$", "<iterator>"},
+      {"limits$", "<limits>"},
+      {"list$", "<list>"},
+      {"locale$", "<locale>"},
+      {"map$", "<map>"},
+      {"memory$", "<memory>"},
+      {"mutex$", "<mutex>"},
+      {"new$", "<new>"},
+      {"numeric$", "<numeric>"},
+      {"ostream$", "<ostream>"},
+      {"queue$", "<queue>"},
+      {"random$", "<random>"},
+      {"ratio$", "<ratio>"},
+      {"regex$", "<regex>"},
+      {"scoped_allocator$", "<scoped_allocator>"},
+      {"set$", "<set>"},
+      {"sstream$", "<sstream>"},
+      {"stack$", "<stack>"},
+      {"stdexcept$", "<stdexcept>"},
+      {"streambuf$", "<streambuf>"},
+      {"string$", "<string>"},
+      {"system_error$", "<system_error>"},
+      {"tgmath.h$", "<tgmath.h>"},
+      {"thread$", "<thread>"},
+      {"tuple$", "<tuple>"},
+      {"type_traits$", "<type_traits>"},
+      {"typeindex$", "<typeindex>"},
+      {"typeinfo$", "<typeinfo>"},
+      {"unordered_map$", "<unordered_map>"},
+      {"unordered_set$", "<unordered_set>"},
+      {"utility$", "<utility>"},
+      {"valarray$", "<valarray>"},
+      {"vector$", "<vector>"},
+      {"include/complex.h$", "<complex.h>"},
+      {"include/ctype.h$", "<cctype>"},
+      {"include/errno.h$", "<cerrno>"},
+      {"include/fenv.h$", "<fenv.h>"},
+      {"include/inttypes.h$", "<cinttypes>"},
+      {"include/libio.h$", "<cstdio>"},
+      {"include/limits.h$", "<climits>"},
+      {"include/locale.h$", "<clocale>"},
+      {"include/math.h$", "<cmath>"},
+      {"include/setjmp.h$", "<csetjmp>"},
+      {"include/signal.h$", "<csignal>"},
+      {"include/stdint.h$", "<cstdint>"},
+      {"include/stdio.h$", "<cstdio>"},
+      {"include/stdlib.h$", "<cstdlib>"},
+      {"include/string.h$", "<cstring>"},
+      {"include/time.h$", "<ctime>"},
+      {"include/wchar.h$", "<cwchar>"},
+      {"include/wctype.h$", "<cwctype>"},
+      {"bits/cmathcalls.h$", "<complex.h>"},
+      {"bits/errno.h$", "<cerrno>"},
+      {"bits/fenv.h$", "<fenv.h>"},
+      {"bits/huge_val.h$", "<cmath>"},
+      {"bits/huge_valf.h$", "<cmath>"},
+      {"bits/huge_vall.h$", "<cmath>"},
+      {"bits/inf.h$", "<cmath>"},
+      {"bits/local_lim.h$", "<climits>"},
+      {"bits/locale.h$", "<clocale>"},
+      {"bits/mathcalls.h$", "<math.h>"},
+      {"bits/mathdef.h$", "<cmath>"},
+      {"bits/nan.h$", "<cmath>"},
+      {"bits/posix1_lim.h$", "<climits>"},
+      {"bits/posix2_lim.h$", "<climits>"},
+      {"bits/setjmp.h$", "<csetjmp>"},
+      {"bits/sigaction.h$", "<csignal>"},
+      {"bits/sigcontext.h$", "<csignal>"},
+      {"bits/siginfo.h$", "<csignal>"},
+      {"bits/signum.h$", "<csignal>"},
+      {"bits/sigset.h$", "<csignal>"},
+      {"bits/sigstack.h$", "<csignal>"},
+      {"bits/stdio_lim.h$", "<cstdio>"},
+      {"bits/sys_errlist.h$", "<cstdio>"},
+      {"bits/time.h$", "<ctime>"},
+      {"bits/timex.h$", "<ctime>"},
+      {"bits/typesizes.h$", "<cstdio>"},
+      {"bits/wchar.h$", "<cwchar>"},
+      {"bits/wordsize.h$", "<csetjmp>"},
+      {"bits/xopen_lim.h$", "<climits>"},
+      {"include/xlocale.h$", "<cstring>"},
+      {"bits/atomic_word.h$", "<memory>"},
+      {"bits/basic_file.h$", "<fstream>"},
+      {"bits/c\\+\\+allocator.h$", "<string>"},
+      {"bits/c\\+\\+config.h$", "<iosfwd>"},
+      {"bits/c\\+\\+io.h$", "<ios>"},
+      {"bits/c\\+\\+locale.h$", "<locale>"},
+      {"bits/cpu_defines.h$", "<iosfwd>"},
+      {"bits/ctype_base.h$", "<locale>"},
+      {"bits/cxxabi_tweaks.h$", "<cxxabi.h>"},
+      {"bits/error_constants.h$", "<system_error>"},
+      {"bits/gthr-default.h$", "<memory>"},
+      {"bits/gthr.h$", "<memory>"},
+      {"bits/opt_random.h$", "<random>"},
+      {"bits/os_defines.h$", "<iosfwd>"},
+      // GNU C headers
+      {"include/aio.h$", "<aio.h>"},
+      {"include/aliases.h$", "<aliases.h>"},
+      {"include/alloca.h$", "<alloca.h>"},
+      {"include/ar.h$", "<ar.h>"},
+      {"include/argp.h$", "<argp.h>"},
+      {"include/argz.h$", "<argz.h>"},
+      {"include/arpa/nameser.h$", "<resolv.h>"},
+      {"include/arpa/nameser_compat.h$", "<resolv.h>"},
+      {"include/byteswap.h$", "<byteswap.h>"},
+      {"include/cpio.h$", "<cpio.h>"},
+      {"include/crypt.h$", "<crypt.h>"},
+      {"include/dirent.h$", "<dirent.h>"},
+      {"include/dlfcn.h$", "<dlfcn.h>"},
+      {"include/elf.h$", "<elf.h>"},
+      {"include/endian.h$", "<endian.h>"},
+      {"include/envz.h$", "<envz.h>"},
+      {"include/err.h$", "<err.h>"},
+      {"include/error.h$", "<error.h>"},
+      {"include/execinfo.h$", "<execinfo.h>"},
+      {"include/fcntl.h$", "<fcntl.h>"},
+      {"include/features.h$", "<features.h>"},
+      {"include/fenv.h$", "<fenv.h>"},
+      {"include/fmtmsg.h$", "<fmtmsg.h>"},
+      {"include/fnmatch.h$", "<fnmatch.h>"},
+      {"include/fstab.h$", "<fstab.h>"},
+      {"include/fts.h$", "<fts.h>"},
+      {"include/ftw.h$", "<ftw.h>"},
+      {"include/gconv.h$", "<gconv.h>"},
+      {"include/getopt.h$", "<getopt.h>"},
+      {"include/glob.h$", "<glob.h>"},
+      {"include/grp.h$", "<grp.h>"},
+      {"include/gshadow.h$", "<gshadow.h>"},
+      {"include/iconv.h$", "<iconv.h>"},
+      {"include/ifaddrs.h$", "<ifaddrs.h>"},
+      {"include/kdb.h$", "<kdb.h>"},
+      {"include/langinfo.h$", "<langinfo.h>"},
+      {"include/libgen.h$", "<libgen.h>"},
+      {"include/libintl.h$", "<libintl.h>"},
+      {"include/link.h$", "<link.h>"},
+      {"include/malloc.h$", "<malloc.h>"},
+      {"include/mcheck.h$", "<mcheck.h>"},
+      {"include/memory.h$", "<memory.h>"},
+      {"include/mntent.h$", "<mntent.h>"},
+      {"include/monetary.h$", "<monetary.h>"},
+      {"include/mqueue.h$", "<mqueue.h>"},
+      {"include/netdb.h$", "<netdb.h>"},
+      {"include/netinet/in.h$", "<netinet/in.h>"},
+      {"include/nl_types.h$", "<nl_types.h>"},
+      {"include/nss.h$", "<nss.h>"},
+      {"include/obstack.h$", "<obstack.h>"},
+      {"include/panel.h$", "<panel.h>"},
+      {"include/paths.h$", "<paths.h>"},
+      {"include/printf.h$", "<printf.h>"},
+      {"include/profile.h$", "<profile.h>"},
+      {"include/pthread.h$", "<pthread.h>"},
+      {"include/pty.h$", "<pty.h>"},
+      {"include/pwd.h$", "<pwd.h>"},
+      {"include/re_comp.h$", "<re_comp.h>"},
+      {"include/regex.h$", "<regex.h>"},
+      {"include/regexp.h$", "<regexp.h>"},
+      {"include/resolv.h$", "<resolv.h>"},
+      {"include/rpc/netdb.h$", "<netdb.h>"},
+      {"include/sched.h$", "<sched.h>"},
+      {"include/search.h$", "<search.h>"},
+      {"include/semaphore.h$", "<semaphore.h>"},
+      {"include/sgtty.h$", "<sgtty.h>"},
+      {"include/shadow.h$", "<shadow.h>"},
+      {"include/spawn.h$", "<spawn.h>"},
+      {"include/stab.h$", "<stab.h>"},
+      {"include/stdc-predef.h$", "<stdc-predef.h>"},
+      {"include/stdio_ext.h$", "<stdio_ext.h>"},
+      {"include/strings.h$", "<strings.h>"},
+      {"include/stropts.h$", "<stropts.h>"},
+      {"include/sudo_plugin.h$", "<sudo_plugin.h>"},
+      {"include/sysexits.h$", "<sysexits.h>"},
+      {"include/tar.h$", "<tar.h>"},
+      {"include/tcpd.h$", "<tcpd.h>"},
+      {"include/term.h$", "<term.h>"},
+      {"include/term_entry.h$", "<term_entry.h>"},
+      {"include/termcap.h$", "<termcap.h>"},
+      {"include/termios.h$", "<termios.h>"},
+      {"include/thread_db.h$", "<thread_db.h>"},
+      {"include/tic.h$", "<tic.h>"},
+      {"include/ttyent.h$", "<ttyent.h>"},
+      {"include/uchar.h$", "<uchar.h>"},
+      {"include/ucontext.h$", "<ucontext.h>"},
+      {"include/ulimit.h$", "<ulimit.h>"},
+      {"include/unctrl.h$", "<unctrl.h>"},
+      {"include/unistd.h$", "<unistd.h>"},
+      {"include/utime.h$", "<utime.h>"},
+      {"include/utmp.h$", "<utmp.h>"},
+      {"include/utmpx.h$", "<utmpx.h>"},
+      {"include/values.h$", "<values.h>"},
+      {"include/wordexp.h$", "<wordexp.h>"},
+      {"fpu_control.h$", "<fpu_control.h>"},
+      {"ieee754.h$", "<ieee754.h>"},
+      {"include/xlocale.h$", "<xlocale.h>"},
+      {"gnu/lib-names.h$", "<gnu/lib-names.h>"},
+      {"gnu/libc-version.h$", "<gnu/libc-version.h>"},
+      {"gnu/option-groups.h$", "<gnu/option-groups.h>"},
+      {"gnu/stubs-32.h$", "<gnu/stubs-32.h>"},
+      {"gnu/stubs-64.h$", "<gnu/stubs-64.h>"},
+      {"gnu/stubs-x32.h$", "<gnu/stubs-x32.h>"},
+      {"include/rpc/auth_des.h$", "<rpc/auth_des.h>"},
+      {"include/rpc/rpc_msg.h$", "<rpc/rpc_msg.h>"},
+      {"include/rpc/pmap_clnt.h$", "<rpc/pmap_clnt.h>"},
+      {"include/rpc/rpc.h$", "<rpc/rpc.h>"},
+      {"include/rpc/types.h$", "<rpc/types.h>"},
+      {"include/rpc/auth_unix.h$", "<rpc/auth_unix.h>"},
+      {"include/rpc/key_prot.h$", "<rpc/key_prot.h>"},
+      {"include/rpc/pmap_prot.h$", "<rpc/pmap_prot.h>"},
+      {"include/rpc/auth.h$", "<rpc/auth.h>"},
+      {"include/rpc/svc_auth.h$", "<rpc/svc_auth.h>"},
+      {"include/rpc/xdr.h$", "<rpc/xdr.h>"},
+      {"include/rpc/pmap_rmt.h$", "<rpc/pmap_rmt.h>"},
+      {"include/rpc/des_crypt.h$", "<rpc/des_crypt.h>"},
+      {"include/rpc/svc.h$", "<rpc/svc.h>"},
+      {"include/rpc/rpc_des.h$", "<rpc/rpc_des.h>"},
+      {"include/rpc/clnt.h$", "<rpc/clnt.h>"},
+      {"include/scsi/scsi.h$", "<scsi/scsi.h>"},
+      {"include/scsi/sg.h$", "<scsi/sg.h>"},
+      {"include/scsi/scsi_ioctl.h$", "<scsi/scsi_ioctl>"},
+      {"include/netrose/rose.h$", "<netrose/rose.h>"},
+      {"include/nfs/nfs.h$", "<nfs/nfs.h>"},
+      {"include/netatalk/at.h$", "<netatalk/at.h>"},
+      {"include/netinet/ether.h$", "<netinet/ether.h>"},
+      {"include/netinet/icmp6.h$", "<netinet/icmp6.h>"},
+      {"include/netinet/if_ether.h$", "<netinet/if_ether.h>"},
+      {"include/netinet/if_fddi.h$", "<netinet/if_fddi.h>"},
+      {"include/netinet/if_tr.h$", "<netinet/if_tr.h>"},
+      {"include/netinet/igmp.h$", "<netinet/igmp.h>"},
+      {"include/netinet/in.h$", "<netinet/in.h>"},
+      {"include/netinet/in_systm.h$", "<netinet/in_systm.h>"},
+      {"include/netinet/ip.h$", "<netinet/ip.h>"},
+      {"include/netinet/ip6.h$", "<netinet/ip6.h>"},
+      {"include/netinet/ip_icmp.h$", "<netinet/ip_icmp.h>"},
+      {"include/netinet/tcp.h$", "<netinet/tcp.h>"},
+      {"include/netinet/udp.h$", "<netinet/udp.h>"},
+      {"include/netrom/netrom.h$", "<netrom/netrom.h>"},
+      {"include/protocols/routed.h$", "<protocols/routed.h>"},
+      {"include/protocols/rwhod.h$", "<protocols/rwhod.h>"},
+      {"include/protocols/talkd.h$", "<protocols/talkd.h>"},
+      {"include/protocols/timed.h$", "<protocols/timed.h>"},
+      {"include/rpcsvc/klm_prot.x$", "<rpcsvc/klm_prot.x>"},
+      {"include/rpcsvc/rstat.h$", "<rpcsvc/rstat.h>"},
+      {"include/rpcsvc/spray.x$", "<rpcsvc/spray.x>"},
+      {"include/rpcsvc/nlm_prot.x$", "<rpcsvc/nlm_prot.x>"},
+      {"include/rpcsvc/nis_callback.x$", "<rpcsvc/nis_callback.x>"},
+      {"include/rpcsvc/yp.h$", "<rpcsvc/yp.h>"},
+      {"include/rpcsvc/yp.x$", "<rpcsvc/yp.x>"},
+      {"include/rpcsvc/nfs_prot.h$", "<rpcsvc/nfs_prot.h>"},
+      {"include/rpcsvc/rex.h$", "<rpcsvc/rex.h>"},
+      {"include/rpcsvc/yppasswd.h$", "<rpcsvc/yppasswd.h>"},
+      {"include/rpcsvc/rex.x$", "<rpcsvc/rex.x>"},
+      {"include/rpcsvc/nis_tags.h$", "<rpcsvc/nis_tags.h>"},
+      {"include/rpcsvc/nis_callback.h$", "<rpcsvc/nis_callback.h>"},
+      {"include/rpcsvc/nfs_prot.x$", "<rpcsvc/nfs_prot.x>"},
+      {"include/rpcsvc/bootparam_prot.x$", "<rpcsvc/bootparam_prot.x>"},
+      {"include/rpcsvc/rusers.x$", "<rpcsvc/rusers.x>"},
+      {"include/rpcsvc/rquota.x$", "<rpcsvc/rquota.x>"},
+      {"include/rpcsvc/nis.h$", "<rpcsvc/nis.h>"},
+      {"include/rpcsvc/nislib.h$", "<rpcsvc/nislib.h>"},
+      {"include/rpcsvc/ypupd.h$", "<rpcsvc/ypupd.h>"},
+      {"include/rpcsvc/bootparam.h$", "<rpcsvc/bootparam.h>"},
+      {"include/rpcsvc/spray.h$", "<rpcsvc/spray.h>"},
+      {"include/rpcsvc/key_prot.h$", "<rpcsvc/key_prot.h>"},
+      {"include/rpcsvc/klm_prot.h$", "<rpcsvc/klm_prot.h>"},
+      {"include/rpcsvc/sm_inter.h$", "<rpcsvc/sm_inter.h>"},
+      {"include/rpcsvc/nlm_prot.h$", "<rpcsvc/nlm_prot.h>"},
+      {"include/rpcsvc/yp_prot.h$", "<rpcsvc/yp_prot.h>"},
+      {"include/rpcsvc/ypclnt.h$", "<rpcsvc/ypclnt.h>"},
+      {"include/rpcsvc/rstat.x$", "<rpcsvc/rstat.x>"},
+      {"include/rpcsvc/rusers.h$", "<rpcsvc/rusers.h>"},
+      {"include/rpcsvc/key_prot.x$", "<rpcsvc/key_prot.x>"},
+      {"include/rpcsvc/sm_inter.x$", "<rpcsvc/sm_inter.x>"},
+      {"include/rpcsvc/rquota.h$", "<rpcsvc/rquota.h>"},
+      {"include/rpcsvc/nis.x$", "<rpcsvc/nis.x>"},
+      {"include/rpcsvc/bootparam_prot.h$", "<rpcsvc/bootparam_prot.h>"},
+      {"include/rpcsvc/mount.h$", "<rpcsvc/mount.h>"},
+      {"include/rpcsvc/mount.x$", "<rpcsvc/mount.x>"},
+      {"include/rpcsvc/nis_object.x$", "<rpcsvc/nis_object.x>"},
+      {"include/rpcsvc/yppasswd.x$", "<rpcsvc/yppasswd.x>"},
+      {"sys/acct.h$", "<sys/acct.h>"},
+      {"sys/auxv.h$", "<sys/auxv.h>"},
+      {"sys/cdefs.h$", "<sys/cdefs.h>"},
+      {"sys/debugreg.h$", "<sys/debugreg.h>"},
+      {"sys/dir.h$", "<sys/dir.h>"},
+      {"sys/elf.h$", "<sys/elf.h>"},
+      {"sys/epoll.h$", "<sys/epoll.h>"},
+      {"sys/eventfd.h$", "<sys/eventfd.h>"},
+      {"sys/fanotify.h$", "<sys/fanotify.h>"},
+      {"sys/file.h$", "<sys/file.h>"},
+      {"sys/fsuid.h$", "<sys/fsuid.h>"},
+      {"sys/gmon.h$", "<sys/gmon.h>"},
+      {"sys/gmon_out.h$", "<sys/gmon_out.h>"},
+      {"sys/inotify.h$", "<sys/inotify.h>"},
+      {"sys/io.h$", "<sys/io.h>"},
+      {"sys/ioctl.h$", "<sys/ioctl.h>"},
+      {"sys/ipc.h$", "<sys/ipc.h>"},
+      {"sys/kd.h$", "<sys/kd.h>"},
+      {"sys/kdaemon.h$", "<sys/kdaemon.h>"},
+      {"sys/klog.h$", "<sys/klog.h>"},
+      {"sys/mman.h$", "<sys/mman.h>"},
+      {"sys/mount.h$", "<sys/mount.h>"},
+      {"sys/msg.h$", "<sys/msg.h>"},
+      {"sys/mtio.h$", "<sys/mtio.h>"},
+      {"sys/param.h$", "<sys/param.h>"},
+      {"sys/pci.h$", "<sys/pci.h>"},
+      {"sys/perm.h$", "<sys/perm.h>"},
+      {"sys/personality.h$", "<sys/personality.h>"},
+      {"sys/poll.h$", "<sys/poll.h>"},
+      {"sys/prctl.h$", "<sys/prctl.h>"},
+      {"sys/procfs.h$", "<sys/procfs.h>"},
+      {"sys/profil.h$", "<sys/profil.h>"},
+      {"sys/ptrace.h$", "<sys/ptrace.h>"},
+      {"sys/queue.h$", "<sys/queue.h>"},
+      {"sys/quota.h$", "<sys/quota.h>"},
+      {"sys/raw.h$", "<sys/raw.h>"},
+      {"sys/reboot.h$", "<sys/reboot.h>"},
+      {"sys/reg.h$", "<sys/reg.h>"},
+      {"sys/resource.h$", "<sys/resource.h>"},
+      {"sys/select.h$", "<sys/select.h>"},
+      {"sys/sem.h$", "<sys/sem.h>"},
+      {"sys/sendfile.h$", "<sys/sendfile.h>"},
+      {"sys/shm.h$", "<sys/shm.h>"},
+      {"sys/signalfd.h$", "<sys/signalfd.h>"},
+      {"sys/socket.h$", "<sys/socket.h>"},
+      {"sys/stat.h$", "<sys/stat.h>"},
+      {"sys/statfs.h$", "<sys/statfs.h>"},
+      {"sys/statvfs.h$", "<sys/statvfs.h>"},
+      {"sys/swap.h$", "<sys/swap.h>"},
+      {"sys/syscall.h$", "<sys/syscall.h>"},
+      {"sys/sysctl.h$", "<sys/sysctl.h>"},
+      {"sys/sysinfo.h$", "<sys/sysinfo.h>"},
+      {"sys/syslog.h$", "<sys/syslog.h>"},
+      {"sys/sysmacros.h$", "<sys/sysmacros.h>"},
+      {"sys/termios.h$", "<sys/termios.h>"},
+      {"sys/time.h$", "<sys/select.h>"},
+      {"sys/timeb.h$", "<sys/timeb.h>"},
+      {"sys/timerfd.h$", "<sys/timerfd.h>"},
+      {"sys/times.h$", "<sys/times.h>"},
+      {"sys/timex.h$", "<sys/timex.h>"},
+      {"sys/ttychars.h$", "<sys/ttychars.h>"},
+      {"sys/ttydefaults.h$", "<sys/ttydefaults.h>"},
+      {"sys/types.h$", "<sys/types.h>"},
+      {"sys/ucontext.h$", "<sys/ucontext.h>"},
+      {"sys/uio.h$", "<sys/uio.h>"},
+      {"sys/un.h$", "<sys/un.h>"},
+      {"sys/user.h$", "<sys/user.h>"},
+      {"sys/ustat.h$", "<sys/ustat.h>"},
+      {"sys/utsname.h$", "<sys/utsname.h>"},
+      {"sys/vlimit.h$", "<sys/vlimit.h>"},
+      {"sys/vm86.h$", "<sys/vm86.h>"},
+      {"sys/vtimes.h$", "<sys/vtimes.h>"},
+      {"sys/wait.h$", "<sys/wait.h>"},
+      {"sys/xattr.h$", "<sys/xattr.h>"},
+      {"bits/epoll.h$", "<sys/epoll.h>"},
+      {"bits/eventfd.h$", "<sys/eventfd.h>"},
+      {"bits/inotify.h$", "<sys/inotify.h>"},
+      {"bits/ipc.h$", "<sys/ipc.h>"},
+      {"bits/ipctypes.h$", "<sys/ipc.h>"},
+      {"bits/mman-linux.h$", "<sys/mman.h>"},
+      {"bits/mman.h$", "<sys/mman.h>"},
+      {"bits/msq.h$", "<sys/msg.h>"},
+      {"bits/resource.h$", "<sys/resource.h>"},
+      {"bits/sem.h$", "<sys/sem.h>"},
+      {"bits/shm.h$", "<sys/shm.h>"},
+      {"bits/signalfd.h$", "<sys/signalfd.h>"},
+      {"bits/statfs.h$", "<sys/statfs.h>"},
+      {"bits/statvfs.h$", "<sys/statvfs.h>"},
+      {"bits/timerfd.h$", "<sys/timerfd.h>"},
+      {"bits/utsname.h$", "<sys/utsname.h>"},
+      {"bits/auxv.h$", "<sys/auxv.h>"},
+      {"bits/byteswap-16.h$", "<byteswap.h>"},
+      {"bits/byteswap.h$", "<byteswap.h>"},
+      {"bits/confname.h$", "<unistd.h>"},
+      {"bits/dirent.h$", "<dirent.h>"},
+      {"bits/dlfcn.h$", "<dlfcn.h>"},
+      {"bits/elfclass.h$", "<link.h>"},
+      {"bits/endian.h$", "<endian.h>"},
+      {"bits/environments.h$", "<unistd.h>"},
+      {"bits/fcntl-linux.h$", "<fcntl.h>"},
+      {"bits/fcntl.h$", "<fcntl.h>"},
+      {"bits/in.h$", "<netinet/in.h>"},
+      {"bits/ioctl-types.h$", "<sys/ioctl.h>"},
+      {"bits/ioctls.h$", "<sys/ioctl.h>"},
+      {"bits/link.h$", "<link.h>"},
+      {"bits/mqueue.h$", "<mqueue.h>"},
+      {"bits/netdb.h$", "<netdb.h>"},
+      {"bits/param.h$", "<sys/param.h>"},
+      {"bits/poll.h$", "<sys/poll.h>"},
+      {"bits/posix_opt.h$", "<bits/posix_opt.h>"},
+      {"bits/pthreadtypes.h$", "<pthread.h>"},
+      {"bits/sched.h$", "<sched.h>"},
+      {"bits/select.h$", "<sys/select.h>"},
+      {"bits/semaphore.h$", "<semaphore.h>"},
+      {"bits/sigthread.h$", "<pthread.h>"},
+      {"bits/sockaddr.h$", "<sys/socket.h>"},
+      {"bits/socket.h$", "<sys/socket.h>"},
+      {"bits/socket_type.h$", "<sys/socket.h>"},
+      {"bits/stab.def$", "<stab.h>"},
+      {"bits/stat.h$", "<sys/stat.h>"},
+      {"bits/stropts.h$", "<stropts.h>"},
+      {"bits/syscall.h$", "<sys/syscall.h>"},
+      {"bits/syslog-path.h$", "<sys/syslog.h>"},
+      {"bits/termios.h$", "<termios.h>"},
+      {"bits/types.h$", "<sys/types.h>"},
+      {"bits/typesizes.h$", "<sys/types.h>"},
+      {"bits/uio.h$", "<sys/uio.h>"},
+      {"bits/ustat.h$", "<sys/ustat.h>"},
+      {"bits/utmp.h$", "<utmp.h>"},
+      {"bits/utmpx.h$", "<utmpx.h>"},
+      {"bits/waitflags.h$", "<sys/wait.h>"},
+      {"bits/waitstatus.h$", "<sys/wait.h>"},
+      {"bits/xtitypes.h$", "<stropts.h>"},
+  };
+  return &STLPostfixHeaderMap;
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/STLPostfixHeaderMap.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/STLPostfixHeaderMap.h
new file mode 100644
index 0000000..162580d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/STLPostfixHeaderMap.h
@@ -0,0 +1,23 @@
+//===-- STLPostfixHeaderMap.h - hardcoded header map for STL ----*- 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_FIND_ALL_SYMBOLS_TOOL_STL_POSTFIX_HEADER_MAP_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_TOOL_STL_POSTFIX_HEADER_MAP_H
+
+#include "HeaderMapCollector.h"
+
+namespace clang {
+namespace find_all_symbols {
+
+const HeaderMapCollector::RegexHeaderMap *getSTLPostfixHeaderMap();
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_TOOL_STL_POSTFIX_HEADER_MAP_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/SymbolInfo.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/SymbolInfo.cpp
new file mode 100644
index 0000000..00bfbe5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/SymbolInfo.cpp
@@ -0,0 +1,137 @@
+//===-- SymbolInfo.cpp - Symbol Info ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolInfo.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+
+using llvm::yaml::MappingTraits;
+using llvm::yaml::IO;
+using llvm::yaml::Input;
+using ContextType = clang::find_all_symbols::SymbolInfo::ContextType;
+using clang::find_all_symbols::SymbolInfo;
+using clang::find_all_symbols::SymbolAndSignals;
+using SymbolKind = clang::find_all_symbols::SymbolInfo::SymbolKind;
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(SymbolAndSignals)
+LLVM_YAML_IS_SEQUENCE_VECTOR(SymbolInfo::Context)
+
+namespace llvm {
+namespace yaml {
+template <> struct MappingTraits<SymbolAndSignals> {
+  static void mapping(IO &io, SymbolAndSignals &Symbol) {
+    io.mapRequired("Name", Symbol.Symbol.Name);
+    io.mapRequired("Contexts", Symbol.Symbol.Contexts);
+    io.mapRequired("FilePath", Symbol.Symbol.FilePath);
+    io.mapRequired("Type", Symbol.Symbol.Type);
+    io.mapRequired("Seen", Symbol.Signals.Seen);
+    io.mapRequired("Used", Symbol.Signals.Used);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<ContextType> {
+  static void enumeration(IO &io, ContextType &value) {
+    io.enumCase(value, "Record", ContextType::Record);
+    io.enumCase(value, "Namespace", ContextType::Namespace);
+    io.enumCase(value, "EnumDecl", ContextType::EnumDecl);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<SymbolKind> {
+  static void enumeration(IO &io, SymbolKind &value) {
+    io.enumCase(value, "Variable", SymbolKind::Variable);
+    io.enumCase(value, "Function", SymbolKind::Function);
+    io.enumCase(value, "Class", SymbolKind::Class);
+    io.enumCase(value, "TypedefName", SymbolKind::TypedefName);
+    io.enumCase(value, "EnumDecl", SymbolKind::EnumDecl);
+    io.enumCase(value, "EnumConstantDecl", SymbolKind::EnumConstantDecl);
+    io.enumCase(value, "Macro", SymbolKind::Macro);
+    io.enumCase(value, "Unknown", SymbolKind::Unknown);
+  }
+};
+
+template <> struct MappingTraits<SymbolInfo::Context> {
+  static void mapping(IO &io, SymbolInfo::Context &Context) {
+    io.mapRequired("ContextType", Context.first);
+    io.mapRequired("ContextName", Context.second);
+  }
+};
+
+} // namespace yaml
+} // namespace llvm
+
+namespace clang {
+namespace find_all_symbols {
+
+SymbolInfo::SymbolInfo(llvm::StringRef Name, SymbolKind Type,
+                       llvm::StringRef FilePath,
+                       const std::vector<Context> &Contexts)
+    : Name(Name), Type(Type), FilePath(FilePath), Contexts(Contexts) {}
+
+bool SymbolInfo::operator==(const SymbolInfo &Symbol) const {
+  return std::tie(Name, Type, FilePath, Contexts) ==
+         std::tie(Symbol.Name, Symbol.Type, Symbol.FilePath, Symbol.Contexts);
+}
+
+bool SymbolInfo::operator<(const SymbolInfo &Symbol) const {
+  return std::tie(Name, Type, FilePath, Contexts) <
+         std::tie(Symbol.Name, Symbol.Type, Symbol.FilePath, Symbol.Contexts);
+}
+
+std::string SymbolInfo::getQualifiedName() const {
+  std::string QualifiedName = Name;
+  for (const auto &Context : Contexts) {
+    if (Context.first == ContextType::EnumDecl)
+      continue;
+    QualifiedName = Context.second + "::" + QualifiedName;
+  }
+  return QualifiedName;
+}
+
+SymbolInfo::Signals &SymbolInfo::Signals::operator+=(const Signals &RHS) {
+  Seen += RHS.Seen;
+  Used += RHS.Used;
+  return *this;
+}
+
+SymbolInfo::Signals SymbolInfo::Signals::operator+(const Signals &RHS) const {
+  Signals Result = *this;
+  Result += RHS;
+  return Result;
+}
+
+bool SymbolInfo::Signals::operator==(const Signals &RHS) const {
+  return std::tie(Seen, Used) == std::tie(RHS.Seen, RHS.Used);
+}
+
+bool SymbolAndSignals::operator==(const SymbolAndSignals& RHS) const {
+  return std::tie(Symbol, Signals) == std::tie(RHS.Symbol, RHS.Signals);
+}
+
+bool WriteSymbolInfosToStream(llvm::raw_ostream &OS,
+                              const SymbolInfo::SignalMap &Symbols) {
+  llvm::yaml::Output yout(OS);
+  for (const auto &Symbol : Symbols) {
+    SymbolAndSignals S{Symbol.first, Symbol.second};
+    yout << S;
+  }
+  return true;
+}
+
+std::vector<SymbolAndSignals> ReadSymbolInfosFromYAML(llvm::StringRef Yaml) {
+  std::vector<SymbolAndSignals> Symbols;
+  llvm::yaml::Input yin(Yaml);
+  yin >> Symbols;
+  return Symbols;
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/SymbolInfo.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/SymbolInfo.h
new file mode 100644
index 0000000..92d360d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/SymbolInfo.h
@@ -0,0 +1,143 @@
+//===-- SymbolInfo.h - Symbol Info ------------------------------*- 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_INCLUDE_FIXER_FIND_ALL_SYMBOLS_SYMBOLINFO_H
+#define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_ALL_SYMBOLS_SYMBOLINFO_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+#include <set>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace find_all_symbols {
+/// \brief Describes a named symbol from a header.
+/// Symbols with the same qualified name and type (e.g. function overloads)
+/// that appear in the same header are represented by a single SymbolInfo.
+///
+/// TODO: keep track of instances, e.g. overload locations and signatures.
+class SymbolInfo {
+public:
+  /// \brief The SymbolInfo Type.
+  enum class SymbolKind {
+    Function,
+    Class,
+    Variable,
+    TypedefName,
+    EnumDecl,
+    EnumConstantDecl,
+    Macro,
+    Unknown,
+  };
+
+  /// \brief The Context Type.
+  enum class ContextType {
+    Namespace, // Symbols declared in a namespace.
+    Record,    // Symbols declared in a class.
+    EnumDecl,  // Enum constants declared in a enum declaration.
+  };
+
+  /// \brief A pair of <ContextType, ContextName>.
+  typedef std::pair<ContextType, std::string> Context;
+
+  // \brief Signals are signals gathered by observing how a symbol is used.
+  // These are used to rank results.
+  struct Signals {
+    Signals() {}
+    Signals(unsigned Seen, unsigned Used) : Seen(Seen), Used(Used) {}
+
+    // Number of times this symbol was visible to a TU.
+    unsigned Seen = 0;
+
+    // Number of times this symbol was referenced a TU's main file.
+    unsigned Used = 0;
+
+    Signals &operator+=(const Signals &RHS);
+    Signals operator+(const Signals &RHS) const;
+    bool operator==(const Signals &RHS) const;
+  };
+
+  using SignalMap = std::map<SymbolInfo, Signals>;
+
+  // The default constructor is required by YAML traits in
+  // LLVM_YAML_IS_DOCUMENT_LIST_VECTOR.
+  SymbolInfo() : Type(SymbolKind::Unknown) {}
+
+  SymbolInfo(llvm::StringRef Name, SymbolKind Type, llvm::StringRef FilePath,
+             const std::vector<Context> &Contexts);
+
+  void SetFilePath(llvm::StringRef Path) { FilePath = Path; }
+
+  /// \brief Get symbol name.
+  llvm::StringRef getName() const { return Name; }
+
+  /// \brief Get the fully-qualified symbol name.
+  std::string getQualifiedName() const;
+
+  /// \brief Get symbol type.
+  SymbolKind getSymbolKind() const { return Type; }
+
+  /// \brief Get a relative file path where symbol comes from.
+  llvm::StringRef getFilePath() const { return FilePath; }
+
+  /// \brief Get symbol contexts.
+  const std::vector<SymbolInfo::Context> &getContexts() const {
+    return Contexts;
+  }
+
+  bool operator<(const SymbolInfo &Symbol) const;
+
+  bool operator==(const SymbolInfo &Symbol) const;
+
+private:
+  friend struct llvm::yaml::MappingTraits<struct SymbolAndSignals>;
+
+  /// \brief Identifier name.
+  std::string Name;
+
+  /// \brief Symbol type.
+  SymbolKind Type;
+
+  /// \brief The file path where the symbol comes from. It's a relative file
+  /// path based on the build directory.
+  std::string FilePath;
+
+  /// \brief Contains information about symbol contexts. Context information is
+  /// stored from the inner-most level to outer-most level.
+  ///
+  /// For example, if a symbol 'x' is declared as:
+  ///     namespace na { namespace nb { class A { int x; } } }
+  /// The contexts would be { {RECORD, "A"}, {NAMESPACE, "nb"}, {NAMESPACE,
+  /// "na"} }.
+  /// The name of an anonymous namespace is "".
+  ///
+  /// If the symbol is declared in `TranslationUnitDecl`, it has no context.
+  std::vector<Context> Contexts;
+};
+
+struct SymbolAndSignals {
+  SymbolInfo Symbol;
+  SymbolInfo::Signals Signals;
+  bool operator==(const SymbolAndSignals& RHS) const;
+};
+
+/// \brief Write SymbolInfos to a stream (YAML format).
+bool WriteSymbolInfosToStream(llvm::raw_ostream &OS,
+                              const SymbolInfo::SignalMap &Symbols);
+
+/// \brief Read SymbolInfos from a YAML document.
+std::vector<SymbolAndSignals> ReadSymbolInfosFromYAML(llvm::StringRef Yaml);
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_ALL_SYMBOLS_SYMBOLINFO_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/SymbolReporter.h b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/SymbolReporter.h
new file mode 100644
index 0000000..2398234
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/SymbolReporter.h
@@ -0,0 +1,30 @@
+//===--- SymbolReporter.h - Symbol Reporter ---------------------*- 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_FIND_ALL_SYMBOLS_SYMBOL_REPORTER_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_REPORTER_H
+
+#include "SymbolInfo.h"
+
+namespace clang {
+namespace find_all_symbols {
+
+/// \brief An interface for classes that collect symbols.
+class SymbolReporter {
+public:
+  virtual ~SymbolReporter() = default;
+
+  virtual void reportSymbols(llvm::StringRef FileName,
+                             const SymbolInfo::SignalMap &Symbols) = 0;
+};
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_REPORTER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/tool/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/tool/CMakeLists.txt
new file mode 100644
index 0000000..474dc51
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/tool/CMakeLists.txt
@@ -0,0 +1,23 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
+
+add_clang_executable(find-all-symbols
+  FindAllSymbolsMain.cpp
+  )
+
+target_link_libraries(find-all-symbols
+  PRIVATE
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFrontend
+  clangLex
+  clangTooling
+  findAllSymbols
+  )
+
+install(TARGETS find-all-symbols
+  RUNTIME DESTINATION bin)
+
+install(PROGRAMS run-find-all-symbols.py
+  DESTINATION share/clang
+  COMPONENT find-all-symbols)
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
new file mode 100644
index 0000000..e09a5aa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
@@ -0,0 +1,152 @@
+//===-- FindAllSymbolsMain.cpp - find all symbols tool ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FindAllSymbolsAction.h"
+#include "STLPostfixHeaderMap.h"
+#include "SymbolInfo.h"
+#include "SymbolReporter.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/ThreadPool.h"
+#include "llvm/Support/raw_ostream.h"
+#include <map>
+#include <mutex>
+#include <set>
+#include <string>
+#include <system_error>
+#include <vector>
+
+using namespace clang::tooling;
+using namespace llvm;
+using SymbolInfo = clang::find_all_symbols::SymbolInfo;
+
+// Apply a custom category to all command-line options so that they are the
+// only ones displayed.
+static cl::OptionCategory FindAllSymbolsCategory("find_all_symbols options");
+
+// CommonOptionsParser declares HelpMessage with a description of the common
+// command-line options related to the compilation database and input files.
+// It's nice to have this help message in all tools.
+static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
+
+// A help message for this specific tool can be added afterwards.
+static cl::extrahelp MoreHelp("\nMore help text...");
+
+static cl::opt<std::string> OutputDir("output-dir", cl::desc(R"(
+The output directory for saving the results.)"),
+                                      cl::init("."),
+                                      cl::cat(FindAllSymbolsCategory));
+
+static cl::opt<std::string> MergeDir("merge-dir", cl::desc(R"(
+The directory for merging symbols.)"),
+                                     cl::init(""),
+                                     cl::cat(FindAllSymbolsCategory));
+namespace clang {
+namespace find_all_symbols {
+
+class YamlReporter : public SymbolReporter {
+public:
+  void reportSymbols(StringRef FileName,
+                     const SymbolInfo::SignalMap &Symbols) override {
+    int FD;
+    SmallString<128> ResultPath;
+    llvm::sys::fs::createUniqueFile(
+        OutputDir + "/" + llvm::sys::path::filename(FileName) + "-%%%%%%.yaml",
+        FD, ResultPath);
+    llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true);
+    WriteSymbolInfosToStream(OS, Symbols);
+  }
+};
+
+bool Merge(llvm::StringRef MergeDir, llvm::StringRef OutputFile) {
+  std::error_code EC;
+  SymbolInfo::SignalMap Symbols;
+  std::mutex SymbolMutex;
+  auto AddSymbols = [&](ArrayRef<SymbolAndSignals> NewSymbols) {
+    // Synchronize set accesses.
+    std::unique_lock<std::mutex> LockGuard(SymbolMutex);
+    for (const auto &Symbol : NewSymbols) {
+      Symbols[Symbol.Symbol] += Symbol.Signals;
+    }
+  };
+
+  // Load all symbol files in MergeDir.
+  {
+    llvm::ThreadPool Pool;
+    for (llvm::sys::fs::directory_iterator Dir(MergeDir, EC), DirEnd;
+         Dir != DirEnd && !EC; Dir.increment(EC)) {
+      // Parse YAML files in parallel.
+      Pool.async(
+          [&AddSymbols](std::string Path) {
+            auto Buffer = llvm::MemoryBuffer::getFile(Path);
+            if (!Buffer) {
+              llvm::errs() << "Can't open " << Path << "\n";
+              return;
+            }
+            std::vector<SymbolAndSignals> Symbols =
+                ReadSymbolInfosFromYAML(Buffer.get()->getBuffer());
+            for (auto &Symbol : Symbols) {
+              // Only count one occurrence per file, to avoid spam.
+              Symbol.Signals.Seen = std::min(Symbol.Signals.Seen, 1u);
+              Symbol.Signals.Used = std::min(Symbol.Signals.Used, 1u);
+            }
+            // FIXME: Merge without creating such a heavy contention point.
+            AddSymbols(Symbols);
+          },
+          Dir->path());
+    }
+  }
+
+  llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_None);
+  if (EC) {
+    llvm::errs() << "Can't open '" << OutputFile << "': " << EC.message()
+                 << '\n';
+    return false;
+  }
+  WriteSymbolInfosToStream(OS, Symbols);
+  return true;
+}
+
+} // namespace clang
+} // namespace find_all_symbols
+
+int main(int argc, const char **argv) {
+  CommonOptionsParser OptionsParser(argc, argv, FindAllSymbolsCategory);
+  ClangTool Tool(OptionsParser.getCompilations(),
+                 OptionsParser.getSourcePathList());
+
+  std::vector<std::string> sources = OptionsParser.getSourcePathList();
+  if (sources.empty()) {
+    llvm::errs() << "Must specify at least one one source file.\n";
+    return 1;
+  }
+  if (!MergeDir.empty()) {
+    clang::find_all_symbols::Merge(MergeDir, sources[0]);
+    return 0;
+  }
+
+  clang::find_all_symbols::YamlReporter Reporter;
+
+  auto Factory =
+      llvm::make_unique<clang::find_all_symbols::FindAllSymbolsActionFactory>(
+          &Reporter, clang::find_all_symbols::getSTLPostfixHeaderMap());
+  return Tool.run(Factory.get());
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/tool/run-find-all-symbols.py b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/tool/run-find-all-symbols.py
new file mode 100755
index 0000000..461d959
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/find-all-symbols/tool/run-find-all-symbols.py
@@ -0,0 +1,124 @@
+#!/usr/bin/env python
+#
+#=- run-find-all-symbols.py - Parallel find-all-symbols runner -*- python  -*-=#
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+"""
+Parallel find-all-symbols runner
+================================
+
+Runs find-all-symbols over all files in a compilation database.
+
+Example invocations.
+- Run find-all-symbols on all files in the current working directory.
+    run-find-all-symbols.py <source-file>
+
+Compilation database setup:
+http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
+"""
+
+import argparse
+import json
+import multiprocessing
+import os
+import Queue
+import shutil
+import subprocess
+import sys
+import tempfile
+import threading
+
+
+def find_compilation_database(path):
+  """Adjusts the directory until a compilation database is found."""
+  result = './'
+  while not os.path.isfile(os.path.join(result, path)):
+    if os.path.realpath(result) == '/':
+      print 'Error: could not find compilation database.'
+      sys.exit(1)
+    result += '../'
+  return os.path.realpath(result)
+
+
+def MergeSymbols(directory, args):
+  """Merge all symbol files (yaml) in a given directaory into a single file."""
+  invocation = [args.binary, '-merge-dir='+directory, args.saving_path]
+  subprocess.call(invocation)
+  print 'Merge is finished. Saving results in ' + args.saving_path
+
+
+def run_find_all_symbols(args, tmpdir, build_path, queue):
+  """Takes filenames out of queue and runs find-all-symbols on them."""
+  while True:
+    name = queue.get()
+    invocation = [args.binary, name, '-output-dir='+tmpdir, '-p='+build_path]
+    sys.stdout.write(' '.join(invocation) + '\n')
+    subprocess.call(invocation)
+    queue.task_done()
+
+
+def main():
+  parser = argparse.ArgumentParser(description='Runs find-all-symbols over all'
+                                   'files in a compilation database.')
+  parser.add_argument('-binary', metavar='PATH',
+                      default='./bin/find-all-symbols',
+                      help='path to find-all-symbols binary')
+  parser.add_argument('-j', type=int, default=0,
+                      help='number of instances to be run in parallel.')
+  parser.add_argument('-p', dest='build_path',
+                      help='path used to read a compilation database.')
+  parser.add_argument('-saving-path', default='./find_all_symbols_db.yaml',
+                      help='result saving path')
+  args = parser.parse_args()
+
+  db_path = 'compile_commands.json'
+
+  if args.build_path is not None:
+    build_path = args.build_path
+  else:
+    build_path = find_compilation_database(db_path)
+
+  tmpdir = tempfile.mkdtemp()
+
+  # Load the database and extract all files.
+  database = json.load(open(os.path.join(build_path, db_path)))
+  files = [entry['file'] for entry in database]
+
+  max_task = args.j
+  if max_task == 0:
+    max_task = multiprocessing.cpu_count()
+
+  try:
+    # Spin up a bunch of tidy-launching threads.
+    queue = Queue.Queue(max_task)
+    for _ in range(max_task):
+      t = threading.Thread(target=run_find_all_symbols,
+                           args=(args, tmpdir, build_path, queue))
+      t.daemon = True
+      t.start()
+
+    # Fill the queue with files.
+    for name in files:
+      queue.put(name)
+
+    # Wait for all threads to be done.
+    queue.join()
+
+    MergeSymbols(tmpdir, args)
+
+
+  except KeyboardInterrupt:
+    # This is a sad hack. Unfortunately subprocess goes
+    # bonkers with ctrl-c and we start forking merrily.
+    print '\nCtrl-C detected, goodbye.'
+    os.kill(0, 9)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/plugin/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/include-fixer/plugin/CMakeLists.txt
new file mode 100644
index 0000000..df792ea
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/plugin/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_clang_library(clangIncludeFixerPlugin
+  IncludeFixerPlugin.cpp
+
+  LINK_LIBS
+  clangAST
+  clangBasic
+  clangFrontend
+  clangIncludeFixer
+  clangParse
+  clangSema
+  clangTooling
+  ${LLVM_PTHREAD_LIB}
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/plugin/IncludeFixerPlugin.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/plugin/IncludeFixerPlugin.cpp
new file mode 100644
index 0000000..0d6bdb7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/plugin/IncludeFixerPlugin.cpp
@@ -0,0 +1,100 @@
+//===- IncludeFixerPlugin.cpp - clang-include-fixer as a clang plugin -----===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../IncludeFixer.h"
+#include "../YamlSymbolIndex.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendPluginRegistry.h"
+#include "clang/Parse/ParseAST.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/Path.h"
+
+namespace clang {
+namespace include_fixer {
+
+/// The core include fixer plugin action. This just provides the AST consumer
+/// and command line flag parsing for using include fixer as a clang plugin.
+class ClangIncludeFixerPluginAction : public PluginASTAction {
+  /// ASTConsumer to keep the symbol index alive. We don't really need an
+  /// ASTConsumer for this plugin (everything is funneled on the side through
+  /// Sema) but we have to keep the symbol index alive until sema is done.
+  struct ASTConsumerManagerWrapper : public ASTConsumer {
+    ASTConsumerManagerWrapper(std::shared_ptr<SymbolIndexManager> SIM)
+        : SymbolIndexMgr(std::move(SIM)) {}
+    std::shared_ptr<SymbolIndexManager> SymbolIndexMgr;
+  };
+
+public:
+  explicit ClangIncludeFixerPluginAction()
+      : SymbolIndexMgr(std::make_shared<SymbolIndexManager>()),
+        SemaSource(new IncludeFixerSemaSource(*SymbolIndexMgr,
+                                              /*MinimizeIncludePaths=*/true,
+                                              /*GenerateDiagnostics=*/true)) {}
+
+  std::unique_ptr<clang::ASTConsumer>
+  CreateASTConsumer(clang::CompilerInstance &CI, StringRef InFile) override {
+    CI.setExternalSemaSource(SemaSource);
+    SemaSource->setFilePath(InFile);
+    SemaSource->setCompilerInstance(&CI);
+    return llvm::make_unique<ASTConsumerManagerWrapper>(SymbolIndexMgr);
+  }
+
+  void ExecuteAction() override {} // Do nothing.
+
+  bool ParseArgs(const CompilerInstance &CI,
+                 const std::vector<std::string> &Args) override {
+    StringRef DB = "yaml";
+    StringRef Input;
+
+    // Parse the extra command line args.
+    // FIXME: This is very limited at the moment.
+    for (StringRef Arg : Args) {
+      if (Arg.startswith("-db="))
+        DB = Arg.substr(strlen("-db="));
+      else if (Arg.startswith("-input="))
+        Input = Arg.substr(strlen("-input="));
+    }
+
+    std::string InputFile = CI.getFrontendOpts().Inputs[0].getFile();
+    auto CreateYamlIdx = [=]() -> std::unique_ptr<include_fixer::SymbolIndex> {
+      llvm::ErrorOr<std::unique_ptr<include_fixer::YamlSymbolIndex>> SymbolIdx(
+          nullptr);
+      if (DB == "yaml") {
+        if (!Input.empty()) {
+          SymbolIdx = include_fixer::YamlSymbolIndex::createFromFile(Input);
+        } else {
+          // If we don't have any input file, look in the directory of the first
+          // file and its parents.
+          SmallString<128> AbsolutePath(tooling::getAbsolutePath(InputFile));
+          StringRef Directory = llvm::sys::path::parent_path(AbsolutePath);
+          SymbolIdx = include_fixer::YamlSymbolIndex::createFromDirectory(
+              Directory, "find_all_symbols_db.yaml");
+        }
+      }
+      return std::move(*SymbolIdx);
+    };
+
+    SymbolIndexMgr->addSymbolIndex(std::move(CreateYamlIdx));
+    return true;
+  }
+
+private:
+  std::shared_ptr<SymbolIndexManager> SymbolIndexMgr;
+  IntrusiveRefCntPtr<IncludeFixerSemaSource> SemaSource;
+};
+} // namespace include_fixer
+} // namespace clang
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the include fixer plugin.
+volatile int ClangIncludeFixerPluginAnchorSource = 0;
+
+static clang::FrontendPluginRegistry::Add<
+    clang::include_fixer::ClangIncludeFixerPluginAction>
+    X("clang-include-fixer", "clang-include-fixer");
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/tool/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/include-fixer/tool/CMakeLists.txt
new file mode 100644
index 0000000..a641a36
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/tool/CMakeLists.txt
@@ -0,0 +1,27 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
+
+add_clang_tool(clang-include-fixer
+  ClangIncludeFixer.cpp
+  )
+
+target_link_libraries(clang-include-fixer
+  PRIVATE
+  clangBasic
+  clangFormat
+  clangFrontend
+  clangIncludeFixer
+  clangRewrite
+  clangTooling
+  clangToolingCore
+  findAllSymbols
+  )
+
+install(TARGETS clang-include-fixer
+  RUNTIME DESTINATION bin)
+
+install(PROGRAMS clang-include-fixer.el
+  DESTINATION share/clang
+  COMPONENT clang-include-fixer)
+install(PROGRAMS clang-include-fixer.py
+  DESTINATION share/clang
+  COMPONENT clang-include-fixer)
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/tool/ClangIncludeFixer.cpp b/src/third_party/llvm-project/clang-tools-extra/include-fixer/tool/ClangIncludeFixer.cpp
new file mode 100644
index 0000000..2f2e45e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/tool/ClangIncludeFixer.cpp
@@ -0,0 +1,471 @@
+//===-- ClangIncludeFixer.cpp - Standalone include fixer ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FuzzySymbolIndex.h"
+#include "InMemorySymbolIndex.h"
+#include "IncludeFixer.h"
+#include "IncludeFixerContext.h"
+#include "SymbolIndexManager.h"
+#include "YamlSymbolIndex.h"
+#include "clang/Format/Format.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/YAMLTraits.h"
+
+using namespace clang;
+using namespace llvm;
+using clang::include_fixer::IncludeFixerContext;
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(IncludeFixerContext)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(IncludeFixerContext::HeaderInfo)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(IncludeFixerContext::QuerySymbolInfo)
+
+namespace llvm {
+namespace yaml {
+
+template <> struct MappingTraits<tooling::Range> {
+  struct NormalizedRange {
+    NormalizedRange(const IO &) : Offset(0), Length(0) {}
+
+    NormalizedRange(const IO &, const tooling::Range &R)
+        : Offset(R.getOffset()), Length(R.getLength()) {}
+
+    tooling::Range denormalize(const IO &) {
+      return tooling::Range(Offset, Length);
+    }
+
+    unsigned Offset;
+    unsigned Length;
+  };
+  static void mapping(IO &IO, tooling::Range &Info) {
+    MappingNormalization<NormalizedRange, tooling::Range> Keys(IO, Info);
+    IO.mapRequired("Offset", Keys->Offset);
+    IO.mapRequired("Length", Keys->Length);
+  }
+};
+
+template <> struct MappingTraits<IncludeFixerContext::HeaderInfo> {
+  static void mapping(IO &io, IncludeFixerContext::HeaderInfo &Info) {
+    io.mapRequired("Header", Info.Header);
+    io.mapRequired("QualifiedName", Info.QualifiedName);
+  }
+};
+
+template <> struct MappingTraits<IncludeFixerContext::QuerySymbolInfo> {
+  static void mapping(IO &io, IncludeFixerContext::QuerySymbolInfo &Info) {
+    io.mapRequired("RawIdentifier", Info.RawIdentifier);
+    io.mapRequired("Range", Info.Range);
+  }
+};
+
+template <> struct MappingTraits<IncludeFixerContext> {
+  static void mapping(IO &IO, IncludeFixerContext &Context) {
+    IO.mapRequired("QuerySymbolInfos", Context.QuerySymbolInfos);
+    IO.mapRequired("HeaderInfos", Context.HeaderInfos);
+    IO.mapRequired("FilePath", Context.FilePath);
+  }
+};
+} // namespace yaml
+} // namespace llvm
+
+namespace {
+cl::OptionCategory IncludeFixerCategory("Tool options");
+
+enum DatabaseFormatTy {
+  fixed,     ///< Hard-coded mapping.
+  yaml,      ///< Yaml database created by find-all-symbols.
+  fuzzyYaml, ///< Yaml database with fuzzy-matched identifiers.
+};
+
+cl::opt<DatabaseFormatTy> DatabaseFormat(
+    "db", cl::desc("Specify input format"),
+    cl::values(clEnumVal(fixed, "Hard-coded mapping"),
+               clEnumVal(yaml, "Yaml database created by find-all-symbols"),
+               clEnumVal(fuzzyYaml, "Yaml database, with fuzzy-matched names")),
+    cl::init(yaml), cl::cat(IncludeFixerCategory));
+
+cl::opt<std::string> Input("input",
+                           cl::desc("String to initialize the database"),
+                           cl::cat(IncludeFixerCategory));
+
+cl::opt<std::string>
+    QuerySymbol("query-symbol",
+                 cl::desc("Query a given symbol (e.g. \"a::b::foo\") in\n"
+                          "database directly without parsing the file."),
+                 cl::cat(IncludeFixerCategory));
+
+cl::opt<bool>
+    MinimizeIncludePaths("minimize-paths",
+                         cl::desc("Whether to minimize added include paths"),
+                         cl::init(true), cl::cat(IncludeFixerCategory));
+
+cl::opt<bool> Quiet("q", cl::desc("Reduce terminal output"), cl::init(false),
+                    cl::cat(IncludeFixerCategory));
+
+cl::opt<bool>
+    STDINMode("stdin",
+              cl::desc("Override source file's content (in the overlaying\n"
+                       "virtual file system) with input from <stdin> and run\n"
+                       "the tool on the new content with the compilation\n"
+                       "options of the source file. This mode is currently\n"
+                       "used for editor integration."),
+              cl::init(false), cl::cat(IncludeFixerCategory));
+
+cl::opt<bool> OutputHeaders(
+    "output-headers",
+    cl::desc("Print the symbol being queried and all its relevant headers in\n"
+             "JSON format to stdout:\n"
+             "  {\n"
+             "    \"FilePath\": \"/path/to/foo.cc\",\n"
+             "    \"QuerySymbolInfos\": [\n"
+             "       {\"RawIdentifier\": \"foo\",\n"
+             "        \"Range\": {\"Offset\": 0, \"Length\": 3}}\n"
+             "    ],\n"
+             "    \"HeaderInfos\": [ {\"Header\": \"\\\"foo_a.h\\\"\",\n"
+             "                      \"QualifiedName\": \"a::foo\"} ]\n"
+             "  }"),
+    cl::init(false), cl::cat(IncludeFixerCategory));
+
+cl::opt<std::string> InsertHeader(
+    "insert-header",
+    cl::desc("Insert a specific header. This should run with STDIN mode.\n"
+             "The result is written to stdout. It is currently used for\n"
+             "editor integration. Support YAML/JSON format:\n"
+             "  -insert-header=\"{\n"
+             "     FilePath: \"/path/to/foo.cc\",\n"
+             "     QuerySymbolInfos: [\n"
+             "       {RawIdentifier: foo,\n"
+             "        Range: {Offset: 0, Length: 3}}\n"
+             "     ],\n"
+             "     HeaderInfos: [ {Headers: \"\\\"foo_a.h\\\"\",\n"
+             "                     QualifiedName: \"a::foo\"} ]}\""),
+    cl::init(""), cl::cat(IncludeFixerCategory));
+
+cl::opt<std::string>
+    Style("style",
+          cl::desc("Fallback style for reformatting after inserting new\n"
+                   "headers if there is no clang-format config file found."),
+          cl::init("llvm"), cl::cat(IncludeFixerCategory));
+
+std::unique_ptr<include_fixer::SymbolIndexManager>
+createSymbolIndexManager(StringRef FilePath) {
+  using find_all_symbols::SymbolInfo;
+
+  auto SymbolIndexMgr = llvm::make_unique<include_fixer::SymbolIndexManager>();
+  switch (DatabaseFormat) {
+  case fixed: {
+    // Parse input and fill the database with it.
+    // <symbol>=<header><, header...>
+    // Multiple symbols can be given, separated by semicolons.
+    std::map<std::string, std::vector<std::string>> SymbolsMap;
+    SmallVector<StringRef, 4> SemicolonSplits;
+    StringRef(Input).split(SemicolonSplits, ";");
+    std::vector<find_all_symbols::SymbolAndSignals> Symbols;
+    for (StringRef Pair : SemicolonSplits) {
+      auto Split = Pair.split('=');
+      std::vector<std::string> Headers;
+      SmallVector<StringRef, 4> CommaSplits;
+      Split.second.split(CommaSplits, ",");
+      for (size_t I = 0, E = CommaSplits.size(); I != E; ++I)
+        Symbols.push_back(
+            {SymbolInfo(Split.first.trim(), SymbolInfo::SymbolKind::Unknown,
+                        CommaSplits[I].trim(), {}),
+             // Use fake "seen" signal for tests, so first header wins.
+             SymbolInfo::Signals(/*Seen=*/static_cast<unsigned>(E - I),
+                                 /*Used=*/0)});
+    }
+    SymbolIndexMgr->addSymbolIndex([=]() {
+      return llvm::make_unique<include_fixer::InMemorySymbolIndex>(Symbols);
+    });
+    break;
+  }
+  case yaml: {
+    auto CreateYamlIdx = [=]() -> std::unique_ptr<include_fixer::SymbolIndex> {
+      llvm::ErrorOr<std::unique_ptr<include_fixer::YamlSymbolIndex>> DB(
+          nullptr);
+      if (!Input.empty()) {
+        DB = include_fixer::YamlSymbolIndex::createFromFile(Input);
+      } else {
+        // If we don't have any input file, look in the directory of the
+        // first
+        // file and its parents.
+        SmallString<128> AbsolutePath(tooling::getAbsolutePath(FilePath));
+        StringRef Directory = llvm::sys::path::parent_path(AbsolutePath);
+        DB = include_fixer::YamlSymbolIndex::createFromDirectory(
+            Directory, "find_all_symbols_db.yaml");
+      }
+
+      if (!DB) {
+        llvm::errs() << "Couldn't find YAML db: " << DB.getError().message()
+                     << '\n';
+        return nullptr;
+      }
+      return std::move(*DB);
+    };
+
+    SymbolIndexMgr->addSymbolIndex(std::move(CreateYamlIdx));
+    break;
+  }
+  case fuzzyYaml: {
+    // This mode is not very useful, because we don't correct the identifier.
+    // It's main purpose is to expose FuzzySymbolIndex to tests.
+    SymbolIndexMgr->addSymbolIndex(
+        []() -> std::unique_ptr<include_fixer::SymbolIndex> {
+          auto DB = include_fixer::FuzzySymbolIndex::createFromYAML(Input);
+          if (!DB) {
+            llvm::errs() << "Couldn't load fuzzy YAML db: "
+                         << llvm::toString(DB.takeError()) << '\n';
+            return nullptr;
+          }
+          return std::move(*DB);
+        });
+    break;
+  }
+  }
+  return SymbolIndexMgr;
+}
+
+void writeToJson(llvm::raw_ostream &OS, const IncludeFixerContext& Context) {
+  OS << "{\n"
+     << "  \"FilePath\": \""
+     << llvm::yaml::escape(Context.getFilePath()) << "\",\n"
+     << "  \"QuerySymbolInfos\": [\n";
+  for (const auto &Info : Context.getQuerySymbolInfos()) {
+    OS << "     {\"RawIdentifier\": \"" << Info.RawIdentifier << "\",\n";
+    OS << "      \"Range\":{";
+    OS << "\"Offset\":" << Info.Range.getOffset() << ",";
+    OS << "\"Length\":" << Info.Range.getLength() << "}}";
+    if (&Info != &Context.getQuerySymbolInfos().back())
+      OS << ",\n";
+  }
+  OS << "\n  ],\n";
+  OS << "  \"HeaderInfos\": [\n";
+  const auto &HeaderInfos = Context.getHeaderInfos();
+  for (const auto &Info : HeaderInfos) {
+    OS << "     {\"Header\": \"" << llvm::yaml::escape(Info.Header) << "\",\n"
+       << "      \"QualifiedName\": \"" << Info.QualifiedName << "\"}";
+    if (&Info != &HeaderInfos.back())
+      OS << ",\n";
+  }
+  OS << "\n";
+  OS << "  ]\n";
+  OS << "}\n";
+}
+
+int includeFixerMain(int argc, const char **argv) {
+  tooling::CommonOptionsParser options(argc, argv, IncludeFixerCategory);
+  tooling::ClangTool tool(options.getCompilations(),
+                          options.getSourcePathList());
+
+  llvm::StringRef SourceFilePath = options.getSourcePathList().front();
+  // In STDINMode, we override the file content with the <stdin> input.
+  // Since `tool.mapVirtualFile` takes `StringRef`, we define `Code` outside of
+  // the if-block so that `Code` is not released after the if-block.
+  std::unique_ptr<llvm::MemoryBuffer> Code;
+  if (STDINMode) {
+    assert(options.getSourcePathList().size() == 1 &&
+           "Expect exactly one file path in STDINMode.");
+    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> CodeOrErr =
+        MemoryBuffer::getSTDIN();
+    if (std::error_code EC = CodeOrErr.getError()) {
+      errs() << EC.message() << "\n";
+      return 1;
+    }
+    Code = std::move(CodeOrErr.get());
+    if (Code->getBufferSize() == 0)
+      return 0;  // Skip empty files.
+
+    tool.mapVirtualFile(SourceFilePath, Code->getBuffer());
+  }
+
+  if (!InsertHeader.empty()) {
+    if (!STDINMode) {
+      errs() << "Should be running in STDIN mode\n";
+      return 1;
+    }
+
+    llvm::yaml::Input yin(InsertHeader);
+    IncludeFixerContext Context;
+    yin >> Context;
+
+    const auto &HeaderInfos = Context.getHeaderInfos();
+    assert(!HeaderInfos.empty());
+    // We only accept one unique header.
+    // Check all elements in HeaderInfos have the same header.
+    bool IsUniqueHeader = std::equal(
+        HeaderInfos.begin()+1, HeaderInfos.end(), HeaderInfos.begin(),
+        [](const IncludeFixerContext::HeaderInfo &LHS,
+           const IncludeFixerContext::HeaderInfo &RHS) {
+          return LHS.Header == RHS.Header;
+        });
+    if (!IsUniqueHeader) {
+      errs() << "Expect exactly one unique header.\n";
+      return 1;
+    }
+
+    // If a header has multiple symbols, we won't add the missing namespace
+    // qualifiers because we don't know which one is exactly used.
+    //
+    // Check whether all elements in HeaderInfos have the same qualified name.
+    bool IsUniqueQualifiedName = std::equal(
+        HeaderInfos.begin() + 1, HeaderInfos.end(), HeaderInfos.begin(),
+        [](const IncludeFixerContext::HeaderInfo &LHS,
+           const IncludeFixerContext::HeaderInfo &RHS) {
+          return LHS.QualifiedName == RHS.QualifiedName;
+        });
+    auto InsertStyle = format::getStyle("file", Context.getFilePath(), Style);
+    if (!InsertStyle) {
+      llvm::errs() << llvm::toString(InsertStyle.takeError()) << "\n";
+      return 1;
+    }
+    auto Replacements = clang::include_fixer::createIncludeFixerReplacements(
+        Code->getBuffer(), Context, *InsertStyle,
+        /*AddQualifiers=*/IsUniqueQualifiedName);
+    if (!Replacements) {
+      errs() << "Failed to create replacements: "
+             << llvm::toString(Replacements.takeError()) << "\n";
+      return 1;
+    }
+
+    auto ChangedCode =
+        tooling::applyAllReplacements(Code->getBuffer(), *Replacements);
+    if (!ChangedCode) {
+      llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n";
+      return 1;
+    }
+    llvm::outs() << *ChangedCode;
+    return 0;
+  }
+
+  // Set up data source.
+  std::unique_ptr<include_fixer::SymbolIndexManager> SymbolIndexMgr =
+      createSymbolIndexManager(SourceFilePath);
+  if (!SymbolIndexMgr)
+    return 1;
+
+  // Query symbol mode.
+  if (!QuerySymbol.empty()) {
+    auto MatchedSymbols = SymbolIndexMgr->search(
+        QuerySymbol, /*IsNestedSearch=*/true, SourceFilePath);
+    for (auto &Symbol : MatchedSymbols) {
+      std::string HeaderPath = Symbol.getFilePath().str();
+      Symbol.SetFilePath(((HeaderPath[0] == '"' || HeaderPath[0] == '<')
+                              ? HeaderPath
+                              : "\"" + HeaderPath + "\""));
+    }
+
+    // We leave an empty symbol range as we don't know the range of the symbol
+    // being queried in this mode. include-fixer won't add namespace qualifiers
+    // if the symbol range is empty, which also fits this case.
+    IncludeFixerContext::QuerySymbolInfo Symbol;
+    Symbol.RawIdentifier = QuerySymbol;
+    auto Context =
+        IncludeFixerContext(SourceFilePath, {Symbol}, MatchedSymbols);
+    writeToJson(llvm::outs(), Context);
+    return 0;
+  }
+
+  // Now run our tool.
+  std::vector<include_fixer::IncludeFixerContext> Contexts;
+  include_fixer::IncludeFixerActionFactory Factory(*SymbolIndexMgr, Contexts,
+                                                   Style, MinimizeIncludePaths);
+
+  if (tool.run(&Factory) != 0) {
+    // We suppress all Clang diagnostics (because they would be wrong,
+    // include-fixer does custom recovery) but still want to give some feedback
+    // in case there was a compiler error we couldn't recover from. The most
+    // common case for this is a #include in the file that couldn't be found.
+    llvm::errs() << "Fatal compiler error occurred while parsing file!"
+                    " (incorrect include paths?)\n";
+    return 1;
+  }
+
+  assert(!Contexts.empty());
+
+  if (OutputHeaders) {
+    // FIXME: Print contexts of all processing files instead of the first one.
+    writeToJson(llvm::outs(), Contexts.front());
+    return 0;
+  }
+
+  std::vector<tooling::Replacements> FixerReplacements;
+  for (const auto &Context : Contexts) {
+    StringRef FilePath = Context.getFilePath();
+    auto InsertStyle = format::getStyle("file", FilePath, Style);
+    if (!InsertStyle) {
+      llvm::errs() << llvm::toString(InsertStyle.takeError()) << "\n";
+      return 1;
+    }
+    auto Buffer = llvm::MemoryBuffer::getFile(FilePath);
+    if (!Buffer) {
+      errs() << "Couldn't open file: " + FilePath.str() + ": "
+             << Buffer.getError().message() + "\n";
+      return 1;
+    }
+
+    auto Replacements = clang::include_fixer::createIncludeFixerReplacements(
+        Buffer.get()->getBuffer(), Context, *InsertStyle);
+    if (!Replacements) {
+      errs() << "Failed to create replacement: "
+             << llvm::toString(Replacements.takeError()) << "\n";
+      return 1;
+    }
+    FixerReplacements.push_back(*Replacements);
+  }
+
+  if (!Quiet) {
+    for (const auto &Context : Contexts) {
+      if (!Context.getHeaderInfos().empty()) {
+        llvm::errs() << "Added #include "
+                     << Context.getHeaderInfos().front().Header << " for "
+                     << Context.getFilePath() << "\n";
+      }
+    }
+  }
+
+  if (STDINMode) {
+    assert(FixerReplacements.size() == 1);
+    auto ChangedCode = tooling::applyAllReplacements(Code->getBuffer(),
+                                                     FixerReplacements.front());
+    if (!ChangedCode) {
+      llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n";
+      return 1;
+    }
+    llvm::outs() << *ChangedCode;
+    return 0;
+  }
+
+  // Set up a new source manager for applying the resulting replacements.
+  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions);
+  DiagnosticsEngine Diagnostics(new DiagnosticIDs, &*DiagOpts);
+  TextDiagnosticPrinter DiagnosticPrinter(outs(), &*DiagOpts);
+  SourceManager SM(Diagnostics, tool.getFiles());
+  Diagnostics.setClient(&DiagnosticPrinter, false);
+
+  // Write replacements to disk.
+  Rewriter Rewrites(SM, LangOptions());
+  for (const auto &Replacement : FixerReplacements) {
+    if (!tooling::applyAllReplacements(Replacement, Rewrites)) {
+      llvm::errs() << "Failed to apply replacements.\n";
+      return 1;
+    }
+  }
+  return Rewrites.overwriteChangedFiles();
+}
+
+} // namespace
+
+int main(int argc, const char **argv) {
+  return includeFixerMain(argc, argv);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/tool/clang-include-fixer-test.el b/src/third_party/llvm-project/clang-tools-extra/include-fixer/tool/clang-include-fixer-test.el
new file mode 100644
index 0000000..d66d530
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/tool/clang-include-fixer-test.el
@@ -0,0 +1,65 @@
+;;; clang-include-fixer-test.el --- unit tests for clang-include-fixer.el  -*- lexical-binding: t; -*-
+
+;;; Commentary:
+
+;; Unit tests for clang-include-fixer.el.
+
+;;; Code:
+
+(require 'clang-include-fixer)
+
+(require 'cc-mode)
+(require 'ert)
+
+(ert-deftest clang-include-fixer--insert-line ()
+  "Unit test for `clang-include-fixer--insert-line'."
+  (with-temp-buffer
+    (insert "aa\nab\nac\nad\n")
+    (let ((from (current-buffer)))
+      (with-temp-buffer
+        (insert "aa\nac\nad\n")
+        (let ((to (current-buffer)))
+          (should (clang-include-fixer--insert-line from to))
+          (should (equal (buffer-string) "aa\nab\nac\nad\n")))))
+    (should (equal (buffer-string) "aa\nab\nac\nad\n"))))
+
+(ert-deftest clang-include-fixer--insert-line-diff-on-empty-line ()
+  "Unit test for `clang-include-fixer--insert-line'."
+  (with-temp-buffer
+    (insert "aa\nab\n\nac\nad\n")
+    (let ((from (current-buffer)))
+      (with-temp-buffer
+        (insert "aa\n\nac\nad\n")
+        (let ((to (current-buffer)))
+          (should (clang-include-fixer--insert-line from to))
+          (should (equal (buffer-string) "aa\nab\n\nac\nad\n")))))
+    (should (equal (buffer-string) "aa\nab\n\nac\nad\n"))))
+
+(ert-deftest clang-include-fixer--symbol-at-point ()
+  "Unit test for `clang-include-fixer--symbol-at-point'."
+  (with-temp-buffer
+    (insert "a+bbb::cc")
+    (c++-mode)
+    (goto-char (point-min))
+    (should (equal (clang-include-fixer--symbol-at-point) "a"))
+    (forward-char)
+    ;; Emacs treats the character immediately following a symbol as part of the
+    ;; symbol.
+    (should (equal (clang-include-fixer--symbol-at-point) "a"))
+    (forward-char)
+    (should (equal (clang-include-fixer--symbol-at-point) "bbb::cc"))
+    (goto-char (point-max))
+    (should (equal (clang-include-fixer--symbol-at-point) "bbb::cc"))))
+
+(ert-deftest clang-include-fixer--highlight ()
+  (with-temp-buffer
+    (insert "util::Status foo;\n")
+    (setq buffer-file-coding-system 'utf-8-unix)
+    (should (equal nil (clang-include-fixer--highlight
+                        '((Range . ((Offset . 0) (Length . 0)))))))
+    (let ((overlay (clang-include-fixer--highlight
+                    '((Range . ((Offset . 1) (Length . 12)))))))
+      (should (equal 2 (overlay-start overlay)))
+      (should (equal 14 (overlay-end overlay))))))
+
+;;; clang-include-fixer-test.el ends here
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/tool/clang-include-fixer.el b/src/third_party/llvm-project/clang-tools-extra/include-fixer/tool/clang-include-fixer.el
new file mode 100644
index 0000000..c3a3bba
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/tool/clang-include-fixer.el
@@ -0,0 +1,450 @@
+;;; clang-include-fixer.el --- Emacs integration of the clang include fixer  -*- lexical-binding: t; -*-
+
+;; Keywords: tools, c
+;; Package-Requires: ((cl-lib "0.5") (json "1.2") (let-alist "1.0.4"))
+
+;;; Commentary:
+
+;; This package allows Emacs users to invoke the 'clang-include-fixer' within
+;; Emacs.  'clang-include-fixer' provides an automated way of adding #include
+;; directives for missing symbols in one translation unit, see
+;; <http://clang.llvm.org/extra/include-fixer.html>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'json)
+(require 'let-alist)
+
+(defgroup clang-include-fixer nil
+  "Clang-based include fixer."
+  :group 'tools)
+
+(defvar clang-include-fixer-add-include-hook nil
+  "A hook that will be called for every added include.
+The first argument is the filename of the include, the second argument is
+non-nil if the include is a system-header.")
+
+(defcustom clang-include-fixer-executable
+  "clang-include-fixer"
+  "Location of the clang-include-fixer executable.
+
+A string containing the name or the full path of the executable."
+  :group 'clang-include-fixer
+  :type '(file :must-match t)
+  :risky t)
+
+(defcustom clang-include-fixer-input-format
+  'yaml
+  "Input format for clang-include-fixer.
+This string is passed as -db argument to
+`clang-include-fixer-executable'."
+  :group 'clang-include-fixer
+  :type '(radio
+          (const :tag "Hard-coded mapping" :fixed)
+          (const :tag "YAML" yaml)
+          (symbol :tag "Other"))
+  :risky t)
+
+(defcustom clang-include-fixer-init-string
+  ""
+  "Database initialization string for clang-include-fixer.
+This string is passed as -input argument to
+`clang-include-fixer-executable'."
+  :group 'clang-include-fixer
+  :type 'string
+  :risky t)
+
+(defface clang-include-fixer-highlight '((t :background "green"))
+  "Used for highlighting the symbol for which a header file is being added.")
+
+;;;###autoload
+(defun clang-include-fixer ()
+  "Invoke the Include Fixer to insert missing C++ headers."
+  (interactive)
+  (message (concat "Calling the include fixer. "
+                   "This might take some seconds. Please wait."))
+  (clang-include-fixer--start #'clang-include-fixer--add-header
+                              "-output-headers"))
+
+;;;###autoload
+(defun clang-include-fixer-at-point ()
+  "Invoke the Clang include fixer for the symbol at point."
+  (interactive)
+  (let ((symbol (clang-include-fixer--symbol-at-point)))
+    (unless symbol
+      (user-error "No symbol at current location"))
+    (clang-include-fixer-from-symbol symbol)))
+
+;;;###autoload
+(defun clang-include-fixer-from-symbol (symbol)
+  "Invoke the Clang include fixer for the SYMBOL.
+When called interactively, prompts the user for a symbol."
+  (interactive
+   (list (read-string "Symbol: " (clang-include-fixer--symbol-at-point))))
+  (clang-include-fixer--start #'clang-include-fixer--add-header
+                              (format "-query-symbol=%s" symbol)))
+
+(defun clang-include-fixer--start (callback &rest args)
+  "Asynchronously start clang-include-fixer with parameters ARGS.
+The current file name is passed after ARGS as last argument.  If
+the call was successful the returned result is stored in a
+temporary buffer, and CALLBACK is called with the temporary
+buffer as only argument."
+  (unless buffer-file-name
+    (user-error "clang-include-fixer works only in buffers that visit a file"))
+  (let ((process (if (fboundp 'make-process)
+                     ;; Prefer using ‘make-process’ if available, because
+                     ;; ‘start-process’ doesn’t allow us to separate the
+                     ;; standard error from the output.
+                     (clang-include-fixer--make-process callback args)
+                   (clang-include-fixer--start-process callback args))))
+    (save-restriction
+      (widen)
+      (process-send-region process (point-min) (point-max)))
+    (process-send-eof process))
+  nil)
+
+(defun clang-include-fixer--make-process (callback args)
+  "Start a new clang-incude-fixer process using `make-process'.
+CALLBACK is called after the process finishes successfully; it is
+called with a single argument, the buffer where standard output
+has been inserted.  ARGS is a list of additional command line
+arguments.  Return the new process object."
+  (let ((stdin (current-buffer))
+        (stdout (generate-new-buffer "*clang-include-fixer output*"))
+        (stderr (generate-new-buffer "*clang-include-fixer errors*")))
+    (make-process :name "clang-include-fixer"
+                  :buffer stdout
+                  :command (clang-include-fixer--command args)
+                  :coding 'utf-8-unix
+                  :noquery t
+                  :connection-type 'pipe
+                  :sentinel (clang-include-fixer--sentinel stdin stdout stderr
+                                                           callback)
+                  :stderr stderr)))
+
+(defun clang-include-fixer--start-process (callback args)
+  "Start a new clang-incude-fixer process using `start-process'.
+CALLBACK is called after the process finishes successfully; it is
+called with a single argument, the buffer where standard output
+has been inserted.  ARGS is a list of additional command line
+arguments.  Return the new process object."
+  (let* ((stdin (current-buffer))
+         (stdout (generate-new-buffer "*clang-include-fixer output*"))
+         (process-connection-type nil)
+         (process (apply #'start-process "clang-include-fixer" stdout
+                         (clang-include-fixer--command args))))
+    (set-process-coding-system process 'utf-8-unix 'utf-8-unix)
+    (set-process-query-on-exit-flag process nil)
+    (set-process-sentinel process
+                          (clang-include-fixer--sentinel stdin stdout nil
+                                                         callback))
+    process))
+
+(defun clang-include-fixer--command (args)
+  "Return the clang-include-fixer command line.
+Returns a list; the first element is the binary to
+execute (`clang-include-fixer-executable'), and the remaining
+elements are the command line arguments.  Adds proper arguments
+for `clang-include-fixer-input-format' and
+`clang-include-fixer-init-string'.  Appends the current buffer's
+file name; prepends ARGS directly in front of it."
+  (cl-check-type args list)
+  `(,clang-include-fixer-executable
+    ,(format "-db=%s" clang-include-fixer-input-format)
+    ,(format "-input=%s" clang-include-fixer-init-string)
+    "-stdin"
+    ,@args
+    ,(buffer-file-name)))
+
+(defun clang-include-fixer--sentinel (stdin stdout stderr callback)
+  "Return a process sentinel for clang-include-fixer processes.
+STDIN, STDOUT, and STDERR are buffers for the standard streams;
+only STDERR may be nil.  CALLBACK is called in the case of
+success; it is called with a single argument, STDOUT.  On
+failure, a buffer containing the error output is displayed."
+  (cl-check-type stdin buffer-live)
+  (cl-check-type stdout buffer-live)
+  (cl-check-type stderr (or null buffer-live))
+  (cl-check-type callback function)
+  (lambda (process event)
+    (cl-check-type process process)
+    (cl-check-type event string)
+    (unwind-protect
+        (if (string-equal event "finished\n")
+            (progn
+              (when stderr (kill-buffer stderr))
+              (with-current-buffer stdin
+                (funcall callback stdout))
+              (kill-buffer stdout))
+          (when stderr (kill-buffer stdout))
+          (message "clang-include-fixer failed")
+          (with-current-buffer (or stderr stdout)
+            (insert "\nProcess " (process-name process)
+                    ?\s event))
+          (display-buffer (or stderr stdout))))
+    nil))
+
+(defun clang-include-fixer--replace-buffer (stdout)
+  "Replace current buffer by content of STDOUT."
+  (cl-check-type stdout buffer-live)
+  (barf-if-buffer-read-only)
+  (cond ((fboundp 'replace-buffer-contents) (replace-buffer-contents stdout))
+        ((clang-include-fixer--insert-line stdout (current-buffer)))
+        (t (erase-buffer) (insert-buffer-substring stdout)))
+  (message "Fix applied")
+  nil)
+
+(defun clang-include-fixer--insert-line (from to)
+  "Insert a single missing line from the buffer FROM into TO.
+FROM and TO must be buffers.  If the contents of FROM and TO are
+equal, do nothing and return non-nil.  If FROM contains a single
+line missing from TO, insert that line into TO so that the buffer
+contents are equal and return non-nil.  Otherwise, do nothing and
+return nil.  Buffer restrictions are ignored."
+  (cl-check-type from buffer-live)
+  (cl-check-type to buffer-live)
+  (with-current-buffer from
+    (save-excursion
+      (save-restriction
+        (widen)
+        (with-current-buffer to
+          (save-excursion
+            (save-restriction
+              (widen)
+              ;; Search for the first buffer difference.
+              (let ((chars (abs (compare-buffer-substrings to nil nil from nil nil))))
+                (if (zerop chars)
+                    ;; Buffer contents are equal, nothing to do.
+                    t
+                  (goto-char chars)
+                  ;; We might have ended up in the middle of a line if the
+                  ;; current line partially matches.  In this case we would
+                  ;; have to insert more than a line.  Move to the beginning of
+                  ;; the line to avoid this situation.
+                  (beginning-of-line)
+                  (with-current-buffer from
+                    (goto-char chars)
+                    (beginning-of-line)
+                    (let ((from-begin (point))
+                          (from-end (progn (forward-line) (point)))
+                          (to-point (with-current-buffer to (point))))
+                      ;; Search for another buffer difference after the line in
+                      ;; question.  If there is none, we can proceed.
+                      (when (zerop (compare-buffer-substrings from from-end nil
+                                                              to to-point nil))
+                        (with-current-buffer to
+                          (insert-buffer-substring from from-begin from-end))
+                        t))))))))))))
+
+(defun clang-include-fixer--add-header (stdout)
+  "Analyse the result of include-fixer stored in STDOUT.
+Add a missing header if there is any.  If there are multiple
+possible headers the user can select one of them to be included.
+Temporarily highlight the affected symbols.  Asynchronously call
+clang-include-fixer to insert the selected header."
+  (cl-check-type stdout buffer-live)
+  (let ((context (clang-include-fixer--parse-json stdout)))
+    (let-alist context
+      (cond
+       ((null .QuerySymbolInfos)
+        (message "The file is fine, no need to add a header."))
+       ((null .HeaderInfos)
+        (message "Couldn't find header for '%s'"
+                 (let-alist (car .QuerySymbolInfos) .RawIdentifier)))
+       (t
+        ;; Users may C-g in prompts, make sure the process sentinel
+        ;; behaves correctly.
+        (with-local-quit
+          ;; Replace the HeaderInfos list by a single header selected by
+          ;; the user.
+          (clang-include-fixer--select-header context)
+          ;; Call clang-include-fixer again to insert the selected header.
+          (clang-include-fixer--start
+           (let ((old-tick (buffer-chars-modified-tick)))
+             (lambda (stdout)
+               (when (/= old-tick (buffer-chars-modified-tick))
+                 ;; Replacing the buffer now would undo the user’s changes.
+                 (user-error (concat "The buffer has been changed "
+                                     "before the header could be inserted")))
+               (clang-include-fixer--replace-buffer stdout)
+               (let-alist context
+                 (let-alist (car .HeaderInfos)
+                   (with-local-quit
+                     (run-hook-with-args 'clang-include-fixer-add-include-hook
+                                         (substring .Header 1 -1)
+                                         (string= (substring .Header 0 1) "<")))))))
+           (format "-insert-header=%s"
+                   (clang-include-fixer--encode-json context))))))))
+  nil)
+
+(defun clang-include-fixer--select-header (context)
+  "Prompt the user for a header if necessary.
+CONTEXT must be a clang-include-fixer context object in
+association list format.  If it contains more than one HeaderInfo
+element, prompt the user to select one of the headers.  CONTEXT
+is modified to include only the selected element."
+  (cl-check-type context cons)
+  (let-alist context
+    (if (cdr .HeaderInfos)
+        (clang-include-fixer--prompt-for-header context)
+      (message "Only one include is missing: %s"
+               (let-alist (car .HeaderInfos) .Header))))
+  nil)
+
+(defvar clang-include-fixer--history nil
+  "History for `clang-include-fixer--prompt-for-header'.")
+
+(defun clang-include-fixer--prompt-for-header (context)
+  "Prompt the user for a single header.
+The choices are taken from the HeaderInfo elements in CONTEXT.
+They are replaced by the single element selected by the user."
+  (let-alist context
+    (let ((symbol (clang-include-fixer--symbol-name .QuerySymbolInfos))
+          ;; Add temporary highlighting so that the user knows which
+          ;; symbols the current session is about.
+          (overlays (remove nil
+                            (mapcar #'clang-include-fixer--highlight .QuerySymbolInfos))))
+      (unwind-protect
+          (save-excursion
+            ;; While prompting, go to the closest overlay so that the user sees
+            ;; some context.
+            (when overlays
+              (goto-char (clang-include-fixer--closest-overlay overlays)))
+            (cl-flet ((header (info) (let-alist info .Header)))
+              ;; The header-infos is already sorted by include-fixer.
+              (let* ((headers (mapcar #'header .HeaderInfos))
+                     (header (completing-read
+                              (clang-include-fixer--format-message
+                               "Select include for '%s': " symbol)
+                              headers nil :require-match nil
+                              'clang-include-fixer--history
+                              ;; Specify a default to prevent the behavior
+                              ;; described in
+                              ;; https://github.com/DarwinAwardWinner/ido-completing-read-plus#why-does-ret-sometimes-not-select-the-first-completion-on-the-list--why-is-there-an-empty-entry-at-the-beginning-of-the-completion-list--what-happened-to-old-style-default-selection.
+                              (car headers)))
+                     (info (cl-find header .HeaderInfos :key #'header :test #'string=)))
+                (unless info (user-error "No header selected"))
+                (setcar .HeaderInfos info)
+                (setcdr .HeaderInfos nil))))
+        (mapc #'delete-overlay overlays)))))
+
+(defun clang-include-fixer--symbol-name (symbol-infos)
+  "Return the unique symbol name in SYMBOL-INFOS.
+Raise a signal if the symbol name is not unique."
+  (let ((symbols (delete-dups (mapcar (lambda (info)
+                                        (let-alist info .RawIdentifier))
+                                      symbol-infos))))
+    (when (cdr symbols)
+      (error "Multiple symbols %s returned" symbols))
+    (car symbols)))
+
+(defun clang-include-fixer--highlight (symbol-info)
+  "Add an overlay to highlight SYMBOL-INFO, if it points to a non-empty range.
+Return the overlay object, or nil."
+  (let-alist symbol-info
+    (unless (zerop .Range.Length)
+      (let ((overlay (make-overlay
+                      (clang-include-fixer--filepos-to-bufferpos
+                       .Range.Offset 'approximate)
+                      (clang-include-fixer--filepos-to-bufferpos
+                       (+ .Range.Offset .Range.Length) 'approximate))))
+        (overlay-put overlay 'face 'clang-include-fixer-highlight)
+        overlay))))
+
+(defun clang-include-fixer--closest-overlay (overlays)
+  "Return the start of the overlay in OVERLAYS that is closest to point."
+  (cl-check-type overlays cons)
+  (let ((point (point))
+        acc)
+    (dolist (overlay overlays acc)
+      (let ((start (overlay-start overlay)))
+        (when (or (null acc) (< (abs (- point start)) (abs (- point acc))))
+          (setq acc start))))))
+
+(defun clang-include-fixer--parse-json (buffer)
+  "Parse a JSON response from clang-include-fixer in BUFFER.
+Return the JSON object as an association list."
+  (with-current-buffer buffer
+    (save-excursion
+      (goto-char (point-min))
+      (let ((json-object-type 'alist)
+            (json-array-type 'list)
+            (json-key-type 'symbol)
+            (json-false :json-false)
+            (json-null nil)
+            (json-pre-element-read-function nil)
+            (json-post-element-read-function nil))
+        (json-read)))))
+
+(defun clang-include-fixer--encode-json (object)
+  "Return the JSON representation of OBJECT as a string."
+  (let ((json-encoding-separator ",")
+        (json-encoding-default-indentation "  ")
+        (json-encoding-pretty-print nil)
+        (json-encoding-lisp-style-closings nil)
+        (json-encoding-object-sort-predicate nil))
+    (json-encode object)))
+
+(defun clang-include-fixer--symbol-at-point ()
+  "Return the qualified symbol at point.
+If there is no symbol at point, return nil."
+  ;; Let ‘bounds-of-thing-at-point’ to do the hard work and deal with edge
+  ;; cases.
+  (let ((bounds (bounds-of-thing-at-point 'symbol)))
+    (when bounds
+      (let ((beg (car bounds))
+            (end (cdr bounds)))
+        (save-excursion
+          ;; Extend the symbol range to the left.  Skip over namespace
+          ;; delimiters and parent namespace names.
+          (goto-char beg)
+          (while (and (clang-include-fixer--skip-double-colon-backward)
+                      (skip-syntax-backward "w_")))
+          ;; Skip over one more namespace delimiter, for absolute names.
+          (clang-include-fixer--skip-double-colon-backward)
+          (setq beg (point))
+          ;; Extend the symbol range to the right.  Skip over namespace
+          ;; delimiters and child namespace names.
+          (goto-char end)
+          (while (and (clang-include-fixer--skip-double-colon-forward)
+                      (skip-syntax-forward "w_")))
+          (setq end (point)))
+        (buffer-substring-no-properties beg end)))))
+
+(defun clang-include-fixer--skip-double-colon-forward ()
+  "Skip a double colon.
+When the next two characters are '::', skip them and return
+non-nil.  Otherwise return nil."
+  (let ((end (+ (point) 2)))
+    (when (and (<= end (point-max))
+               (string-equal (buffer-substring-no-properties (point) end) "::"))
+      (goto-char end)
+      t)))
+
+(defun clang-include-fixer--skip-double-colon-backward ()
+  "Skip a double colon.
+When the previous two characters are '::', skip them and return
+non-nil.  Otherwise return nil."
+  (let ((beg (- (point) 2)))
+    (when (and (>= beg (point-min))
+               (string-equal (buffer-substring-no-properties beg (point)) "::"))
+      (goto-char beg)
+      t)))
+
+;; ‘filepos-to-bufferpos’ is new in Emacs 25.1.  Provide a fallback for older
+;; versions.
+(defalias 'clang-include-fixer--filepos-to-bufferpos
+  (if (fboundp 'filepos-to-bufferpos)
+      'filepos-to-bufferpos
+    (lambda (byte &optional _quality _coding-system)
+      (byte-to-position (1+ byte)))))
+
+;; ‘format-message’ is new in Emacs 25.1.  Provide a fallback for older
+;; versions.
+(defalias 'clang-include-fixer--format-message
+  (if (fboundp 'format-message) 'format-message 'format))
+
+(provide 'clang-include-fixer)
+;;; clang-include-fixer.el ends here
diff --git a/src/third_party/llvm-project/clang-tools-extra/include-fixer/tool/clang-include-fixer.py b/src/third_party/llvm-project/clang-tools-extra/include-fixer/tool/clang-include-fixer.py
new file mode 100644
index 0000000..0e9306d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/include-fixer/tool/clang-include-fixer.py
@@ -0,0 +1,208 @@
+# This file is a minimal clang-include-fixer vim-integration. To install:
+# - Change 'binary' if clang-include-fixer is not on the path (see below).
+# - Add to your .vimrc:
+#
+#   noremap <leader>cf :pyf path/to/llvm/source/tools/clang/tools/extra/include-fixer/tool/clang-include-fixer.py<cr>
+#
+# This enables clang-include-fixer for NORMAL and VISUAL mode. Change "<leader>cf"
+# to another binding if you need clang-include-fixer on a different key.
+#
+# To set up clang-include-fixer, see http://clang.llvm.org/extra/include-fixer.html
+#
+# With this integration you can press the bound key and clang-include-fixer will
+# be run on the current buffer.
+#
+# It operates on the current, potentially unsaved buffer and does not create
+# or save any files. To revert a fix, just undo.
+
+import argparse
+import difflib
+import json
+import re
+import subprocess
+import vim
+
+# set g:clang_include_fixer_path to the path to clang-include-fixer if it is not
+# on the path.
+# Change this to the full path if clang-include-fixer is not on the path.
+binary = 'clang-include-fixer'
+if vim.eval('exists("g:clang_include_fixer_path")') == "1":
+  binary = vim.eval('g:clang_include_fixer_path')
+
+maximum_suggested_headers = 3
+if vim.eval('exists("g:clang_include_fixer_maximum_suggested_headers")') == "1":
+  maximum_suggested_headers = max(
+      1,
+      vim.eval('g:clang_include_fixer_maximum_suggested_headers'))
+
+increment_num = 5
+if vim.eval('exists("g:clang_include_fixer_increment_num")') == "1":
+  increment_num = max(
+      1,
+      vim.eval('g:clang_include_fixer_increment_num'))
+
+jump_to_include = False
+if vim.eval('exists("g:clang_include_fixer_jump_to_include")') == "1":
+  jump_to_include = vim.eval('g:clang_include_fixer_jump_to_include') != "0"
+
+query_mode = False
+if vim.eval('exists("g:clang_include_fixer_query_mode")') == "1":
+  query_mode = vim.eval('g:clang_include_fixer_query_mode') != "0"
+
+
+def GetUserSelection(message, headers, maximum_suggested_headers):
+  eval_message = message + '\n'
+  for idx, header in enumerate(headers[0:maximum_suggested_headers]):
+    eval_message += "({0}). {1}\n".format(idx + 1, header)
+  eval_message += "Enter (q) to quit;"
+  if maximum_suggested_headers < len(headers):
+    eval_message += " (m) to show {0} more candidates.".format(
+        min(increment_num, len(headers) - maximum_suggested_headers))
+
+  eval_message += "\nSelect (default 1): "
+  res = vim.eval("input('{0}')".format(eval_message))
+  if res == '':
+    # choose the top ranked header by default
+    idx = 1
+  elif res == 'q':
+    raise Exception('   Insertion cancelled...')
+  elif res == 'm':
+    return GetUserSelection(message,
+                            headers, maximum_suggested_headers + increment_num)
+  else:
+    try:
+      idx = int(res)
+      if idx <= 0 or idx > len(headers):
+        raise Exception()
+    except Exception:
+      # Show a new prompt on invalid option instead of aborting so that users
+      # don't need to wait for another include-fixer run.
+      print >> sys.stderr, "Invalid option:", res
+      return GetUserSelection(message, headers, maximum_suggested_headers)
+  return headers[idx - 1]
+
+
+def execute(command, text):
+  p = subprocess.Popen(command,
+                       stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+                       stdin=subprocess.PIPE)
+  return p.communicate(input=text)
+
+
+def InsertHeaderToVimBuffer(header, text):
+  command = [binary, "-stdin", "-insert-header=" + json.dumps(header),
+             vim.current.buffer.name]
+  stdout, stderr = execute(command, text)
+  if stderr:
+    raise Exception(stderr)
+  if stdout:
+    lines = stdout.splitlines()
+    sequence = difflib.SequenceMatcher(None, vim.current.buffer, lines)
+    line_num = None
+    for op in reversed(sequence.get_opcodes()):
+      if op[0] != 'equal':
+        vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]]
+      if op[0] == 'insert':
+        # line_num in vim is 1-based.
+        line_num = op[1] + 1
+
+    if jump_to_include and line_num:
+      vim.current.window.cursor = (line_num, 0)
+
+
+# The vim internal implementation (expand("cword"/"cWORD")) doesn't support
+# our use case very well, we re-implement our own one.
+def get_symbol_under_cursor():
+  line = vim.eval("line(\".\")")
+  # column number in vim is 1-based.
+  col = int(vim.eval("col(\".\")")) - 1
+  line_text = vim.eval("getline({0})".format(line))
+  if len(line_text) == 0: return ""
+  symbol_pos_begin = col
+  p = re.compile('[a-zA-Z0-9:_]')
+  while symbol_pos_begin >= 0 and p.match(line_text[symbol_pos_begin]):
+    symbol_pos_begin -= 1
+
+  symbol_pos_end = col
+  while symbol_pos_end < len(line_text) and p.match(line_text[symbol_pos_end]):
+    symbol_pos_end += 1
+  return line_text[symbol_pos_begin+1:symbol_pos_end]
+
+
+def main():
+  parser = argparse.ArgumentParser(
+      description='Vim integration for clang-include-fixer')
+  parser.add_argument('-db', default='yaml',
+                      help='clang-include-fixer input format.')
+  parser.add_argument('-input', default='',
+                      help='String to initialize the database.')
+  # Don't throw exception when parsing unknown arguements to make the script
+  # work in neovim.
+  # Neovim (at least v0.2.1) somehow mangles the sys.argv in a weird way: it
+  # will pass additional arguments (e.g. "-c script_host.py") to sys.argv,
+  # which makes the script fail.
+  args, _ = parser.parse_known_args()
+
+  # Get the current text.
+  buf = vim.current.buffer
+  text = '\n'.join(buf)
+
+  if query_mode:
+    symbol = get_symbol_under_cursor()
+    if len(symbol) == 0:
+      print "Skip querying empty symbol."
+      return
+    command = [binary, "-stdin", "-query-symbol="+get_symbol_under_cursor(),
+               "-db=" + args.db, "-input=" + args.input,
+               vim.current.buffer.name]
+  else:
+    # Run command to get all headers.
+    command = [binary, "-stdin", "-output-headers", "-db=" + args.db,
+               "-input=" + args.input, vim.current.buffer.name]
+  stdout, stderr = execute(command, text)
+  if stderr:
+    print >> sys.stderr, "Error while running clang-include-fixer: " + stderr
+    return
+
+  include_fixer_context = json.loads(stdout)
+  query_symbol_infos = include_fixer_context["QuerySymbolInfos"]
+  if not query_symbol_infos:
+    print "The file is fine, no need to add a header."
+    return
+  symbol = query_symbol_infos[0]["RawIdentifier"]
+  # The header_infos is already sorted by include-fixer.
+  header_infos = include_fixer_context["HeaderInfos"]
+  # Deduplicate headers while keeping the order, so that the same header would
+  # not be suggested twice.
+  unique_headers = []
+  seen = set()
+  for header_info in header_infos:
+    header = header_info["Header"]
+    if header not in seen:
+      seen.add(header)
+      unique_headers.append(header)
+
+  if not unique_headers:
+    print "Couldn't find a header for {0}.".format(symbol)
+    return
+
+  try:
+    selected = unique_headers[0]
+    inserted_header_infos = header_infos
+    if len(unique_headers) > 1:
+      selected = GetUserSelection(
+          "choose a header file for {0}.".format(symbol),
+          unique_headers, maximum_suggested_headers)
+      inserted_header_infos = [
+        header for header in header_infos if header["Header"] == selected]
+    include_fixer_context["HeaderInfos"] = inserted_header_infos
+
+    InsertHeaderToVimBuffer(include_fixer_context, text)
+    print "Added #include {0} for {1}.".format(selected, symbol)
+  except Exception as error:
+    print >> sys.stderr, error.message
+  return
+
+
+if __name__ == '__main__':
+  main()
diff --git a/src/third_party/llvm-project/clang-tools-extra/modularize/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/modularize/CMakeLists.txt
new file mode 100644
index 0000000..4481ce0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/modularize/CMakeLists.txt
@@ -0,0 +1,26 @@
+set(LLVM_LINK_COMPONENTS
+  Option
+  Support
+  )
+
+add_clang_tool(modularize
+  Modularize.cpp
+  ModuleAssistant.cpp
+  ModularizeUtilities.cpp
+  CoverageChecker.cpp
+  PreprocessorTracker.cpp
+  )
+
+target_link_libraries(modularize
+  PRIVATE
+  clangAST
+  clangBasic
+  clangDriver
+  clangFrontend
+  clangLex
+  clangTooling
+  )
+
+install(TARGETS modularize
+        RUNTIME DESTINATION bin
+        COMPONENT clang-extras)
diff --git a/src/third_party/llvm-project/clang-tools-extra/modularize/CoverageChecker.cpp b/src/third_party/llvm-project/clang-tools-extra/modularize/CoverageChecker.cpp
new file mode 100644
index 0000000..4e2a23c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/modularize/CoverageChecker.cpp
@@ -0,0 +1,423 @@
+//===--- extra/module-map-checker/CoverageChecker.cpp -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a class that validates a module map by checking that
+// all headers in the corresponding directories are accounted for.
+//
+// This class uses a previously loaded module map object.
+// Starting at the module map file directory, or just the include
+// paths, if specified, it will collect the names of all the files it
+// considers headers (no extension, .h, or .inc--if you need more, modify the
+// ModularizeUtilities::isHeader function).
+//  It then compares the headers against those referenced
+// in the module map, either explicitly named, or implicitly named via an
+// umbrella directory or umbrella file, as parsed by the ModuleMap object.
+// If headers are found which are not referenced or covered by an umbrella
+// directory or file, warning messages will be produced, and the doChecks
+// function will return an error code of 1.  Other errors result in an error
+// code of 2. If no problems are found, an error code of 0 is returned.
+//
+// Note that in the case of umbrella headers, this tool invokes the compiler
+// to preprocess the file, and uses a callback to collect the header files
+// included by the umbrella header or any of its nested includes.  If any
+// front end options are needed for these compiler invocations, these are
+// to be passed in via the CommandLine parameter.
+//
+// Warning message have the form:
+//
+//  warning: module.modulemap does not account for file: Level3A.h
+//
+// Note that for the case of the module map referencing a file that does
+// not exist, the module map parser in Clang will (at the time of this
+// writing) display an error message.
+//
+// Potential problems with this program:
+//
+// 1. Might need a better header matching mechanism, or extensions to the
+//    canonical file format used.
+//
+// 2. It might need to support additional header file extensions.
+//
+// Future directions:
+//
+// 1. Add an option to fix the problems found, writing a new module map.
+//    Include an extra option to add unaccounted-for headers as excluded.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ModularizeUtilities.h"
+#include "clang/AST/ASTConsumer.h"
+#include "CoverageChecker.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Driver/Options.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace Modularize;
+using namespace clang;
+using namespace clang::driver;
+using namespace clang::driver::options;
+using namespace clang::tooling;
+namespace cl = llvm::cl;
+namespace sys = llvm::sys;
+
+// Preprocessor callbacks.
+// We basically just collect include files.
+class CoverageCheckerCallbacks : public PPCallbacks {
+public:
+  CoverageCheckerCallbacks(CoverageChecker &Checker) : Checker(Checker) {}
+  ~CoverageCheckerCallbacks() override {}
+
+  // Include directive callback.
+  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+                          StringRef FileName, bool IsAngled,
+                          CharSourceRange FilenameRange, const FileEntry *File,
+                          StringRef SearchPath, StringRef RelativePath,
+                          const Module *Imported,
+                          SrcMgr::CharacteristicKind FileType) override {
+    Checker.collectUmbrellaHeaderHeader(File->getName());
+  }
+
+private:
+  CoverageChecker &Checker;
+};
+
+// Frontend action stuff:
+
+// Consumer is responsible for setting up the callbacks.
+class CoverageCheckerConsumer : public ASTConsumer {
+public:
+  CoverageCheckerConsumer(CoverageChecker &Checker, Preprocessor &PP) {
+    // PP takes ownership.
+    PP.addPPCallbacks(llvm::make_unique<CoverageCheckerCallbacks>(Checker));
+  }
+};
+
+class CoverageCheckerAction : public SyntaxOnlyAction {
+public:
+  CoverageCheckerAction(CoverageChecker &Checker) : Checker(Checker) {}
+
+protected:
+  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+    StringRef InFile) override {
+    return llvm::make_unique<CoverageCheckerConsumer>(Checker,
+      CI.getPreprocessor());
+  }
+
+private:
+  CoverageChecker &Checker;
+};
+
+class CoverageCheckerFrontendActionFactory : public FrontendActionFactory {
+public:
+  CoverageCheckerFrontendActionFactory(CoverageChecker &Checker)
+    : Checker(Checker) {}
+
+  CoverageCheckerAction *create() override {
+    return new CoverageCheckerAction(Checker);
+  }
+
+private:
+  CoverageChecker &Checker;
+};
+
+// CoverageChecker class implementation.
+
+// Constructor.
+CoverageChecker::CoverageChecker(StringRef ModuleMapPath,
+    std::vector<std::string> &IncludePaths,
+    ArrayRef<std::string> CommandLine,
+    clang::ModuleMap *ModuleMap)
+  : ModuleMapPath(ModuleMapPath), IncludePaths(IncludePaths),
+    CommandLine(CommandLine),
+    ModMap(ModuleMap) {}
+
+// Create instance of CoverageChecker, to simplify setting up
+// subordinate objects.
+std::unique_ptr<CoverageChecker> CoverageChecker::createCoverageChecker(
+    StringRef ModuleMapPath, std::vector<std::string> &IncludePaths,
+    ArrayRef<std::string> CommandLine, clang::ModuleMap *ModuleMap) {
+
+  return llvm::make_unique<CoverageChecker>(ModuleMapPath, IncludePaths,
+                                            CommandLine, ModuleMap);
+}
+
+// Do checks.
+// Starting from the directory of the module.modulemap file,
+// Find all header files, optionally looking only at files
+// covered by the include path options, and compare against
+// the headers referenced by the module.modulemap file.
+// Display warnings for unaccounted-for header files.
+// Returns error_code of 0 if there were no errors or warnings, 1 if there
+//   were warnings, 2 if any other problem, such as if a bad
+//   module map path argument was specified.
+std::error_code CoverageChecker::doChecks() {
+  std::error_code returnValue;
+
+  // Collect the headers referenced in the modules.
+  collectModuleHeaders();
+
+  // Collect the file system headers.
+  if (!collectFileSystemHeaders())
+    return std::error_code(2, std::generic_category());
+
+  // Do the checks.  These save the problematic file names.
+  findUnaccountedForHeaders();
+
+  // Check for warnings.
+  if (!UnaccountedForHeaders.empty())
+    returnValue = std::error_code(1, std::generic_category());
+
+  return returnValue;
+}
+
+// The following functions are called by doChecks.
+
+// Collect module headers.
+// Walks the modules and collects referenced headers into
+// ModuleMapHeadersSet.
+void CoverageChecker::collectModuleHeaders() {
+  for (ModuleMap::module_iterator I = ModMap->module_begin(),
+    E = ModMap->module_end();
+    I != E; ++I) {
+    collectModuleHeaders(*I->second);
+  }
+}
+
+// Collect referenced headers from one module.
+// Collects the headers referenced in the given module into
+// ModuleMapHeadersSet.
+// FIXME: Doesn't collect files from umbrella header.
+bool CoverageChecker::collectModuleHeaders(const Module &Mod) {
+
+  if (const FileEntry *UmbrellaHeader = Mod.getUmbrellaHeader().Entry) {
+    // Collect umbrella header.
+    ModuleMapHeadersSet.insert(ModularizeUtilities::getCanonicalPath(
+      UmbrellaHeader->getName()));
+    // Preprocess umbrella header and collect the headers it references.
+    if (!collectUmbrellaHeaderHeaders(UmbrellaHeader->getName()))
+      return false;
+  }
+  else if (const DirectoryEntry *UmbrellaDir = Mod.getUmbrellaDir().Entry) {
+    // Collect headers in umbrella directory.
+    if (!collectUmbrellaHeaders(UmbrellaDir->getName()))
+      return false;
+  }
+
+  for (auto &HeaderKind : Mod.Headers)
+    for (auto &Header : HeaderKind)
+      ModuleMapHeadersSet.insert(ModularizeUtilities::getCanonicalPath(
+        Header.Entry->getName()));
+
+  for (auto MI = Mod.submodule_begin(), MIEnd = Mod.submodule_end();
+       MI != MIEnd; ++MI)
+    collectModuleHeaders(**MI);
+
+  return true;
+}
+
+// Collect headers from an umbrella directory.
+bool CoverageChecker::collectUmbrellaHeaders(StringRef UmbrellaDirName) {
+  // Initialize directory name.
+  SmallString<256> Directory(ModuleMapDirectory);
+  if (UmbrellaDirName.size())
+    sys::path::append(Directory, UmbrellaDirName);
+  if (Directory.size() == 0)
+    Directory = ".";
+  // Walk the directory.
+  std::error_code EC;
+  for (sys::fs::directory_iterator I(Directory.str(), EC), E; I != E;
+    I.increment(EC)) {
+    if (EC)
+      return false;
+    std::string File(I->path());
+    llvm::ErrorOr<sys::fs::basic_file_status> Status = I->status();
+    if (!Status)
+      return false;
+    sys::fs::file_type Type = Status->type();
+    // If the file is a directory, ignore the name and recurse.
+    if (Type == sys::fs::file_type::directory_file) {
+      if (!collectUmbrellaHeaders(File))
+        return false;
+      continue;
+    }
+    // If the file does not have a common header extension, ignore it.
+    if (!ModularizeUtilities::isHeader(File))
+      continue;
+    // Save header name.
+    ModuleMapHeadersSet.insert(ModularizeUtilities::getCanonicalPath(File));
+  }
+  return true;
+}
+
+// Collect headers rferenced from an umbrella file.
+bool
+CoverageChecker::collectUmbrellaHeaderHeaders(StringRef UmbrellaHeaderName) {
+
+  SmallString<256> PathBuf(ModuleMapDirectory);
+
+  // If directory is empty, it's the current directory.
+  if (ModuleMapDirectory.length() == 0)
+    sys::fs::current_path(PathBuf);
+
+  // Create the compilation database.
+  std::unique_ptr<CompilationDatabase> Compilations;
+  Compilations.reset(new FixedCompilationDatabase(Twine(PathBuf), CommandLine));
+
+  std::vector<std::string> HeaderPath;
+  HeaderPath.push_back(UmbrellaHeaderName);
+
+  // Create the tool and run the compilation.
+  ClangTool Tool(*Compilations, HeaderPath);
+  int HadErrors = Tool.run(new CoverageCheckerFrontendActionFactory(*this));
+
+  // If we had errors, exit early.
+  return !HadErrors;
+}
+
+// Called from CoverageCheckerCallbacks to track a header included
+// from an umbrella header.
+void CoverageChecker::collectUmbrellaHeaderHeader(StringRef HeaderName) {
+
+  SmallString<256> PathBuf(ModuleMapDirectory);
+  // If directory is empty, it's the current directory.
+  if (ModuleMapDirectory.length() == 0)
+    sys::fs::current_path(PathBuf);
+  // HeaderName will have an absolute path, so if it's the module map
+  // directory, we remove it, also skipping trailing separator.
+  if (HeaderName.startswith(PathBuf))
+    HeaderName = HeaderName.substr(PathBuf.size() + 1);
+  // Save header name.
+  ModuleMapHeadersSet.insert(ModularizeUtilities::getCanonicalPath(HeaderName));
+}
+
+// Collect file system header files.
+// This function scans the file system for header files,
+// starting at the directory of the module.modulemap file,
+// optionally filtering out all but the files covered by
+// the include path options.
+// Returns true if no errors.
+bool CoverageChecker::collectFileSystemHeaders() {
+
+  // Get directory containing the module.modulemap file.
+  // Might be relative to current directory, absolute, or empty.
+  ModuleMapDirectory = ModularizeUtilities::getDirectoryFromPath(ModuleMapPath);
+
+  // If no include paths specified, we do the whole tree starting
+  // at the module.modulemap directory.
+  if (IncludePaths.size() == 0) {
+    if (!collectFileSystemHeaders(StringRef("")))
+      return false;
+  }
+  else {
+    // Otherwise we only look at the sub-trees specified by the
+    // include paths.
+    for (std::vector<std::string>::const_iterator I = IncludePaths.begin(),
+      E = IncludePaths.end();
+      I != E; ++I) {
+      if (!collectFileSystemHeaders(*I))
+        return false;
+    }
+  }
+
+  // Sort it, because different file systems might order the file differently.
+  std::sort(FileSystemHeaders.begin(), FileSystemHeaders.end());
+
+  return true;
+}
+
+// Collect file system header files from the given path.
+// This function scans the file system for header files,
+// starting at the given directory, which is assumed to be
+// relative to the directory of the module.modulemap file.
+// \returns True if no errors.
+bool CoverageChecker::collectFileSystemHeaders(StringRef IncludePath) {
+
+  // Initialize directory name.
+  SmallString<256> Directory(ModuleMapDirectory);
+  if (IncludePath.size())
+    sys::path::append(Directory, IncludePath);
+  if (Directory.size() == 0)
+    Directory = ".";
+  if (IncludePath.startswith("/") || IncludePath.startswith("\\") ||
+    ((IncludePath.size() >= 2) && (IncludePath[1] == ':'))) {
+    llvm::errs() << "error: Include path \"" << IncludePath
+      << "\" is not relative to the module map file.\n";
+    return false;
+  }
+
+  // Recursively walk the directory tree.
+  std::error_code EC;
+  int Count = 0;
+  for (sys::fs::recursive_directory_iterator I(Directory.str(), EC), E; I != E;
+    I.increment(EC)) {
+    if (EC)
+      return false;
+    //std::string file(I->path());
+    StringRef file(I->path());
+    llvm::ErrorOr<sys::fs::basic_file_status> Status = I->status();
+    if (!Status)
+      return false;
+    sys::fs::file_type type = Status->type();
+    // If the file is a directory, ignore the name (but still recurses).
+    if (type == sys::fs::file_type::directory_file)
+      continue;
+    // Assume directories or files starting with '.' are private and not to
+    // be considered.
+    if ((file.find("\\.") != StringRef::npos) ||
+        (file.find("/.") != StringRef::npos))
+      continue;
+    // If the file does not have a common header extension, ignore it.
+    if (!ModularizeUtilities::isHeader(file))
+      continue;
+    // Save header name.
+    FileSystemHeaders.push_back(ModularizeUtilities::getCanonicalPath(file));
+    Count++;
+  }
+  if (Count == 0) {
+    llvm::errs() << "warning: No headers found in include path: \""
+      << IncludePath << "\"\n";
+  }
+  return true;
+}
+
+// Find headers unaccounted-for in module map.
+// This function compares the list of collected header files
+// against those referenced in the module map.  Display
+// warnings for unaccounted-for header files.
+// Save unaccounted-for file list for possible.
+// fixing action.
+// FIXME: There probably needs to be some canonalization
+// of file names so that header path can be correctly
+// matched.  Also, a map could be used for the headers
+// referenced in the module, but
+void CoverageChecker::findUnaccountedForHeaders() {
+  // Walk over file system headers.
+  for (std::vector<std::string>::const_iterator I = FileSystemHeaders.begin(),
+    E = FileSystemHeaders.end();
+    I != E; ++I) {
+    // Look for header in module map.
+    if (ModuleMapHeadersSet.insert(*I).second) {
+      UnaccountedForHeaders.push_back(*I);
+      llvm::errs() << "warning: " << ModuleMapPath
+        << " does not account for file: " << *I << "\n";
+    }
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/modularize/CoverageChecker.h b/src/third_party/llvm-project/clang-tools-extra/modularize/CoverageChecker.h
new file mode 100644
index 0000000..f6c8367
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/modularize/CoverageChecker.h
@@ -0,0 +1,164 @@
+//===-- CoverageChecker.h - Module map coverage checker -*- C++ -*-------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Definitions for CoverageChecker.
+///
+//===--------------------------------------------------------------------===//
+
+#ifndef COVERAGECHECKER_H
+#define COVERAGECHECKER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/ModuleMap.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Host.h"
+#include <string>
+#include <vector>
+
+namespace Modularize {
+
+/// Module map checker class.
+/// This is the heart of the checker.
+/// The doChecks function does the main work.
+/// The data members store the options and internally collected data.
+class CoverageChecker {
+  // Checker arguments.
+
+  /// The module.modulemap file path. Can be relative or absolute.
+  llvm::StringRef ModuleMapPath;
+  /// The include paths to check for files.
+  /// (Note that other directories above these paths are ignored.
+  /// To expect all files to be accounted for from the module.modulemap
+  /// file directory on down, leave this empty.)
+  std::vector<std::string> IncludePaths;
+  /// The remaining arguments, to be passed to the front end.
+  llvm::ArrayRef<std::string> CommandLine;
+  /// The module map.
+  clang::ModuleMap *ModMap;
+
+  // Internal data.
+
+  /// Directory containing the module map.
+  /// Might be relative to the current directory, or absolute.
+  std::string ModuleMapDirectory;
+  /// Set of all the headers found in the module map.
+  llvm::StringSet<llvm::MallocAllocator> ModuleMapHeadersSet;
+  /// All the headers found in the file system starting at the
+  /// module map, or the union of those from the include paths.
+  std::vector<std::string> FileSystemHeaders;
+  /// Headers found in file system, but not in module map.
+  std::vector<std::string> UnaccountedForHeaders;
+
+public:
+  /// Constructor.
+  /// You can use the static createCoverageChecker to create an instance
+  /// of this object.
+  /// \param ModuleMapPath The module.modulemap file path.
+  ///   Can be relative or absolute.
+  /// \param IncludePaths The include paths to check for files.
+  ///   (Note that other directories above these paths are ignored.
+  ///   To expect all files to be accounted for from the module.modulemap
+  ///   file directory on down, leave this empty.)
+  /// \param CommandLine Compile command line arguments.
+  /// \param ModuleMap The module map to check.
+  CoverageChecker(llvm::StringRef ModuleMapPath,
+    std::vector<std::string> &IncludePaths,
+    llvm::ArrayRef<std::string> CommandLine,
+    clang::ModuleMap *ModuleMap);
+
+  /// Create instance of CoverageChecker.
+  /// \param ModuleMapPath The module.modulemap file path.
+  ///   Can be relative or absolute.
+  /// \param IncludePaths The include paths to check for files.
+  ///   (Note that other directories above these paths are ignored.
+  ///   To expect all files to be accounted for from the module.modulemap
+  ///   file directory on down, leave this empty.)
+  /// \param CommandLine Compile command line arguments.
+  /// \param ModuleMap The module map to check.
+  /// \returns Initialized CoverageChecker object.
+  static std::unique_ptr<CoverageChecker> createCoverageChecker(
+      llvm::StringRef ModuleMapPath, std::vector<std::string> &IncludePaths,
+      llvm::ArrayRef<std::string> CommandLine, clang::ModuleMap *ModuleMap);
+
+  /// Do checks.
+  /// Starting from the directory of the module.modulemap file,
+  /// Find all header files, optionally looking only at files
+  /// covered by the include path options, and compare against
+  /// the headers referenced by the module.modulemap file.
+  /// Display warnings for unaccounted-for header files.
+  /// \returns 0 if there were no errors or warnings, 1 if there
+  ///   were warnings, 2 if any other problem, such as a bad
+  ///   module map path argument was specified.
+  std::error_code doChecks();
+
+  // The following functions are called by doChecks.
+
+  /// Collect module headers.
+  /// Walks the modules and collects referenced headers into
+  /// ModuleMapHeadersSet.
+  void collectModuleHeaders();
+
+  /// Collect referenced headers from one module.
+  /// Collects the headers referenced in the given module into
+  /// ModuleMapHeadersSet.
+  /// \param Mod The module reference.
+  /// \return True if no errors.
+  bool collectModuleHeaders(const clang::Module &Mod);
+
+  /// Collect headers from an umbrella directory.
+  /// \param UmbrellaDirName The umbrella directory name.
+  /// \return True if no errors.
+  bool collectUmbrellaHeaders(llvm::StringRef UmbrellaDirName);
+
+  /// Collect headers rferenced from an umbrella file.
+  /// \param UmbrellaHeaderName The umbrella file path.
+  /// \return True if no errors.
+  bool collectUmbrellaHeaderHeaders(llvm::StringRef UmbrellaHeaderName);
+
+  /// Called from CoverageCheckerCallbacks to track a header included
+  /// from an umbrella header.
+  /// \param HeaderName The header file path.
+  void collectUmbrellaHeaderHeader(llvm::StringRef HeaderName);
+
+  /// Collect file system header files.
+  /// This function scans the file system for header files,
+  /// starting at the directory of the module.modulemap file,
+  /// optionally filtering out all but the files covered by
+  /// the include path options.
+  /// \returns True if no errors.
+  bool collectFileSystemHeaders();
+
+  /// Collect file system header files from the given path.
+  /// This function scans the file system for header files,
+  /// starting at the given directory, which is assumed to be
+  /// relative to the directory of the module.modulemap file.
+  /// \returns True if no errors.
+  bool collectFileSystemHeaders(llvm::StringRef IncludePath);
+
+  /// Find headers unaccounted-for in module map.
+  /// This function compares the list of collected header files
+  /// against those referenced in the module map.  Display
+  /// warnings for unaccounted-for header files.
+  /// Save unaccounted-for file list for possible.
+  /// fixing action.
+  void findUnaccountedForHeaders();
+};
+
+} // end namespace Modularize
+
+#endif // COVERAGECHECKER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/modularize/Modularize.cpp b/src/third_party/llvm-project/clang-tools-extra/modularize/Modularize.cpp
new file mode 100644
index 0000000..83f2340
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/modularize/Modularize.cpp
@@ -0,0 +1,998 @@
+//===- extra/modularize/Modularize.cpp - Check modularized headers --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Introduction
+//
+// This file implements a tool that checks whether a set of headers provides
+// the consistent definitions required to use modules.  It can also check an
+// existing module map for full coverage of the headers in a directory tree.
+//
+// For example, in examining headers, it detects whether the same entity
+// (say, a NULL macro or size_t typedef) is defined in multiple headers
+// or whether a header produces different definitions under
+// different circumstances. These conditions cause modules built from the
+// headers to behave poorly, and should be fixed before introducing a module
+// map.
+//
+// Modularize takes as input either one or more module maps (by default,
+// "module.modulemap") or one or more text files contatining lists of headers
+// to check.
+//
+// In the case of a module map, the module map must be well-formed in
+// terms of syntax.  Modularize will extract the header file names
+// from the map.  Only normal headers are checked, assuming headers
+// marked "private", "textual", or "exclude" are not to be checked
+// as a top-level include, assuming they either are included by
+// other headers which are checked, or they are not suitable for
+// modules.
+//
+// In the case of a file list, the list is a newline-separated list of headers
+// to check with respect to each other.
+// Lines beginning with '#' and empty lines are ignored.
+// Header file names followed by a colon and other space-separated
+// file names will include those extra files as dependencies.
+// The file names can be relative or full paths, but must be on the
+// same line.
+//
+// Modularize also accepts regular clang front-end arguments.
+//
+// Usage:   modularize [(modularize options)]
+//   [(include-files_list)|(module map)]+ [(front-end-options) ...]
+//
+// Options:
+//    -prefix=(optional header path prefix)
+//          Note that unless a "-prefix (header path)" option is specified,
+//          non-absolute file paths in the header list file will be relative
+//          to the header list file directory.  Use -prefix to specify a
+//          different directory.
+//    -module-map-path=(module map)
+//          Skip the checks, and instead act as a module.map generation
+//          assistant, generating a module map file based on the header list.
+//          An optional "-root-module=(rootName)" argument can specify a root
+//          module to be created in the generated module.map file.  Note that
+//          you will likely need to edit this file to suit the needs of your
+//          headers.
+//    -problem-files-list=(problem files list file name)
+//          For use only with module map assistant.  Input list of files that
+//          have problems with respect to modules.  These will still be
+//          included in the generated module map, but will be marked as
+//          "excluded" headers.
+//    -root-module=(root module name)
+//          Specifies a root module to be created in the generated module.map
+//          file.
+//    -block-check-header-list-only
+//          Only warn if #include directives are inside extern or namespace
+//          blocks if the included header is in the header list.
+//    -no-coverage-check
+//          Don't do the coverage check.
+//    -coverage-check-only
+//          Only do the coverage check.
+//    -display-file-lists
+//          Display lists of good files (no compile errors), problem files,
+//          and a combined list with problem files preceded by a '#'.
+//          This can be used to quickly determine which files have problems.
+//          The latter combined list might be useful in starting to modularize
+//          a set of headers.  You can start with a full list of headers,
+//          use -display-file-lists option, and then use the combined list as
+//          your intermediate list, uncommenting-out headers as you fix them.
+//
+// Note that by default, the modularize assumes .h files contain C++ source.
+// If your .h files in the file list contain another language, you should
+// append an appropriate -x option to your command line, i.e.:  -x c
+//
+// Modularization Issue Checks
+//
+// In the process of checking headers for modularization issues, modularize
+// will do normal parsing, reporting normal errors and warnings,
+// but will also report special error messages like the following:
+//
+//   error: '(symbol)' defined at multiple locations:
+//       (file):(row):(column)
+//       (file):(row):(column)
+//
+//   error: header '(file)' has different contents depending on how it was
+//     included
+//
+// The latter might be followed by messages like the following:
+//
+//   note: '(symbol)' in (file) at (row):(column) not always provided
+//
+// Checks will also be performed for macro expansions, defined(macro)
+// expressions, and preprocessor conditional directives that evaluate
+// inconsistently, and can produce error messages like the following:
+//
+//   (...)/SubHeader.h:11:5:
+//   #if SYMBOL == 1
+//       ^
+//   error: Macro instance 'SYMBOL' has different values in this header,
+//          depending on how it was included.
+//     'SYMBOL' expanded to: '1' with respect to these inclusion paths:
+//       (...)/Header1.h
+//         (...)/SubHeader.h
+//   (...)/SubHeader.h:3:9:
+//   #define SYMBOL 1
+//             ^
+//   Macro defined here.
+//     'SYMBOL' expanded to: '2' with respect to these inclusion paths:
+//       (...)/Header2.h
+//           (...)/SubHeader.h
+//   (...)/SubHeader.h:7:9:
+//   #define SYMBOL 2
+//             ^
+//   Macro defined here.
+//
+// Checks will also be performed for '#include' directives that are
+// nested inside 'extern "C/C++" {}' or 'namespace (name) {}' blocks,
+// and can produce error message like the following:
+//
+// IncludeInExtern.h:2:3
+//   #include "Empty.h"
+//   ^
+// error: Include directive within extern "C" {}.
+// IncludeInExtern.h:1:1
+// extern "C" {
+// ^
+// The "extern "C" {}" block is here.
+//
+// See PreprocessorTracker.cpp for additional details.
+//
+// Module Map Coverage Check
+//
+// The coverage check uses the Clang ModuleMap class to read and parse the
+// module map file.  Starting at the module map file directory, or just the
+// include paths, if specified, it will collect the names of all the files it
+// considers headers (no extension, .h, or .inc--if you need more, modify the
+// isHeader function).  It then compares the headers against those referenced
+// in the module map, either explicitly named, or implicitly named via an
+// umbrella directory or umbrella file, as parsed by the ModuleMap object.
+// If headers are found which are not referenced or covered by an umbrella
+// directory or file, warning messages will be produced, and this program
+// will return an error code of 1.  Other errors result in an error code of 2.
+// If no problems are found, an error code of 0 is returned.
+//
+// Note that in the case of umbrella headers, this tool invokes the compiler
+// to preprocess the file, and uses a callback to collect the header files
+// included by the umbrella header or any of its nested includes.  If any
+// front end options are needed for these compiler invocations, these
+// can be included on the command line after the module map file argument.
+//
+// Warning message have the form:
+//
+//  warning: module.modulemap does not account for file: Level3A.h
+//
+// Note that for the case of the module map referencing a file that does
+// not exist, the module map parser in Clang will (at the time of this
+// writing) display an error message.
+//
+// Module Map Assistant - Module Map Generation
+//
+// Modularize also has an option ("-module-map-path=module.modulemap") that will
+// skip the checks, and instead act as a module.modulemap generation assistant,
+// generating a module map file based on the header list.  An optional
+// "-root-module=(rootName)" argument can specify a root module to be
+// created in the generated module.modulemap file.  Note that you will likely
+// need to edit this file to suit the needs of your headers.
+//
+// An example command line for generating a module.modulemap file:
+//
+//   modularize -module-map-path=module.modulemap -root-module=myroot \
+//      headerlist.txt
+//
+// Note that if the headers in the header list have partial paths, sub-modules
+// will be created for the subdirectires involved, assuming that the
+// subdirectories contain headers to be grouped into a module, but still with
+// individual modules for the headers in the subdirectory.
+//
+// See the ModuleAssistant.cpp file comments for additional details about the
+// implementation of the assistant mode.
+//
+// Future directions:
+//
+// Basically, we want to add new checks for whatever we can check with respect
+// to checking headers for module'ability.
+//
+// Some ideas:
+//
+// 1. Omit duplicate "not always provided" messages
+//
+// 2. Add options to disable any of the checks, in case
+// there is some problem with them, or the messages get too verbose.
+//
+// 3. Try to figure out the preprocessor conditional directives that
+// contribute to problems and tie them to the inconsistent definitions.
+//
+// 4. There are some legitimate uses of preprocessor macros that
+// modularize will flag as errors, such as repeatedly #include'ing
+// a file and using interleaving defined/undefined macros
+// to change declarations in the included file.  Is there a way
+// to address this?  Maybe have modularize accept a list of macros
+// to ignore.  Otherwise you can just exclude the file, after checking
+// for legitimate errors.
+//
+// 5. What else?
+//
+// General clean-up and refactoring:
+//
+// 1. The Location class seems to be something that we might
+// want to design to be applicable to a wider range of tools, and stick it
+// somewhere into Tooling/ in mainline
+//
+//===----------------------------------------------------------------------===//
+
+#include "Modularize.h"
+#include "ModularizeUtilities.h"
+#include "PreprocessorTracker.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Driver/Options.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include <algorithm>
+#include <fstream>
+#include <iterator>
+#include <string>
+#include <vector>
+
+using namespace clang;
+using namespace clang::driver;
+using namespace clang::driver::options;
+using namespace clang::tooling;
+using namespace llvm;
+using namespace llvm::opt;
+using namespace Modularize;
+
+// Option to specify a file name for a list of header files to check.
+static cl::list<std::string>
+    ListFileNames(cl::Positional, cl::value_desc("list"),
+                  cl::desc("<list of one or more header list files>"),
+                  cl::CommaSeparated);
+
+// Collect all other arguments, which will be passed to the front end.
+static cl::list<std::string>
+    CC1Arguments(cl::ConsumeAfter,
+                 cl::desc("<arguments to be passed to front end>..."));
+
+// Option to specify a prefix to be prepended to the header names.
+static cl::opt<std::string> HeaderPrefix(
+    "prefix", cl::init(""),
+    cl::desc(
+        "Prepend header file paths with this prefix."
+        " If not specified,"
+        " the files are considered to be relative to the header list file."));
+
+// Option for assistant mode, telling modularize to output a module map
+// based on the headers list, and where to put it.
+static cl::opt<std::string> ModuleMapPath(
+    "module-map-path", cl::init(""),
+    cl::desc("Turn on module map output and specify output path or file name."
+             " If no path is specified and if prefix option is specified,"
+             " use prefix for file path."));
+
+// Option to specify list of problem files for assistant.
+// This will cause assistant to exclude these files.
+static cl::opt<std::string> ProblemFilesList(
+  "problem-files-list", cl::init(""),
+  cl::desc(
+  "List of files with compilation or modularization problems for"
+    " assistant mode.  This will be excluded."));
+
+// Option for assistant mode, telling modularize the name of the root module.
+static cl::opt<std::string>
+RootModule("root-module", cl::init(""),
+           cl::desc("Specify the name of the root module."));
+
+// Option for limiting the #include-inside-extern-or-namespace-block
+// check to only those headers explicitly listed in the header list.
+// This is a work-around for private includes that purposefully get
+// included inside blocks.
+static cl::opt<bool>
+BlockCheckHeaderListOnly("block-check-header-list-only", cl::init(false),
+cl::desc("Only warn if #include directives are inside extern or namespace"
+  " blocks if the included header is in the header list."));
+
+// Option for include paths for coverage check.
+static cl::list<std::string>
+IncludePaths("I", cl::desc("Include path for coverage check."),
+cl::ZeroOrMore, cl::value_desc("path"));
+
+// Option for disabling the coverage check.
+static cl::opt<bool>
+NoCoverageCheck("no-coverage-check", cl::init(false),
+cl::desc("Don't do the coverage check."));
+
+// Option for just doing the coverage check.
+static cl::opt<bool>
+CoverageCheckOnly("coverage-check-only", cl::init(false),
+cl::desc("Only do the coverage check."));
+
+// Option for displaying lists of good, bad, and mixed files.
+static cl::opt<bool>
+DisplayFileLists("display-file-lists", cl::init(false),
+cl::desc("Display lists of good files (no compile errors), problem files,"
+  " and a combined list with problem files preceded by a '#'."));
+
+// Save the program name for error messages.
+const char *Argv0;
+// Save the command line for comments.
+std::string CommandLine;
+
+// Helper function for finding the input file in an arguments list.
+static std::string findInputFile(const CommandLineArguments &CLArgs) {
+  std::unique_ptr<OptTable> Opts(createDriverOptTable());
+  const unsigned IncludedFlagsBitmask = options::CC1Option;
+  unsigned MissingArgIndex, MissingArgCount;
+  SmallVector<const char *, 256> Argv;
+  for (auto I = CLArgs.begin(), E = CLArgs.end(); I != E; ++I)
+    Argv.push_back(I->c_str());
+  InputArgList Args = Opts->ParseArgs(Argv, MissingArgIndex, MissingArgCount,
+                                      IncludedFlagsBitmask);
+  std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);
+  return ModularizeUtilities::getCanonicalPath(Inputs.back());
+}
+
+// This arguments adjuster inserts "-include (file)" arguments for header
+// dependencies.  It also inserts a "-w" option and a "-x c++",
+// if no other "-x" option is present.
+static ArgumentsAdjuster
+getModularizeArgumentsAdjuster(DependencyMap &Dependencies) {
+  return [&Dependencies](const CommandLineArguments &Args,
+                         StringRef /*unused*/) {
+    std::string InputFile = findInputFile(Args);
+    DependentsVector &FileDependents = Dependencies[InputFile];
+    CommandLineArguments NewArgs(Args);
+    if (int Count = FileDependents.size()) {
+      for (int Index = 0; Index < Count; ++Index) {
+        NewArgs.push_back("-include");
+        std::string File(std::string("\"") + FileDependents[Index] +
+                         std::string("\""));
+        NewArgs.push_back(FileDependents[Index]);
+      }
+    }
+    // Ignore warnings.  (Insert after "clang_tool" at beginning.)
+    NewArgs.insert(NewArgs.begin() + 1, "-w");
+    // Since we are compiling .h files, assume C++ unless given a -x option.
+    if (std::find(NewArgs.begin(), NewArgs.end(), "-x") == NewArgs.end()) {
+      NewArgs.insert(NewArgs.begin() + 2, "-x");
+      NewArgs.insert(NewArgs.begin() + 3, "c++");
+    }
+    return NewArgs;
+  };
+}
+
+// FIXME: The Location class seems to be something that we might
+// want to design to be applicable to a wider range of tools, and stick it
+// somewhere into Tooling/ in mainline
+struct Location {
+  const FileEntry *File;
+  unsigned Line, Column;
+
+  Location() : File(), Line(), Column() {}
+
+  Location(SourceManager &SM, SourceLocation Loc) : File(), Line(), Column() {
+    Loc = SM.getExpansionLoc(Loc);
+    if (Loc.isInvalid())
+      return;
+
+    std::pair<FileID, unsigned> Decomposed = SM.getDecomposedLoc(Loc);
+    File = SM.getFileEntryForID(Decomposed.first);
+    if (!File)
+      return;
+
+    Line = SM.getLineNumber(Decomposed.first, Decomposed.second);
+    Column = SM.getColumnNumber(Decomposed.first, Decomposed.second);
+  }
+
+  operator bool() const { return File != nullptr; }
+
+  friend bool operator==(const Location &X, const Location &Y) {
+    return X.File == Y.File && X.Line == Y.Line && X.Column == Y.Column;
+  }
+
+  friend bool operator!=(const Location &X, const Location &Y) {
+    return !(X == Y);
+  }
+
+  friend bool operator<(const Location &X, const Location &Y) {
+    if (X.File != Y.File)
+      return X.File < Y.File;
+    if (X.Line != Y.Line)
+      return X.Line < Y.Line;
+    return X.Column < Y.Column;
+  }
+  friend bool operator>(const Location &X, const Location &Y) { return Y < X; }
+  friend bool operator<=(const Location &X, const Location &Y) {
+    return !(Y < X);
+  }
+  friend bool operator>=(const Location &X, const Location &Y) {
+    return !(X < Y);
+  }
+};
+
+struct Entry {
+  enum EntryKind {
+    EK_Tag,
+    EK_Value,
+    EK_Macro,
+
+    EK_NumberOfKinds
+  } Kind;
+
+  Location Loc;
+
+  StringRef getKindName() { return getKindName(Kind); }
+  static StringRef getKindName(EntryKind kind);
+};
+
+// Return a string representing the given kind.
+StringRef Entry::getKindName(Entry::EntryKind kind) {
+  switch (kind) {
+  case EK_Tag:
+    return "tag";
+  case EK_Value:
+    return "value";
+  case EK_Macro:
+    return "macro";
+  case EK_NumberOfKinds:
+    break;
+  }
+  llvm_unreachable("invalid Entry kind");
+}
+
+struct HeaderEntry {
+  std::string Name;
+  Location Loc;
+
+  friend bool operator==(const HeaderEntry &X, const HeaderEntry &Y) {
+    return X.Loc == Y.Loc && X.Name == Y.Name;
+  }
+  friend bool operator!=(const HeaderEntry &X, const HeaderEntry &Y) {
+    return !(X == Y);
+  }
+  friend bool operator<(const HeaderEntry &X, const HeaderEntry &Y) {
+    return X.Loc < Y.Loc || (X.Loc == Y.Loc && X.Name < Y.Name);
+  }
+  friend bool operator>(const HeaderEntry &X, const HeaderEntry &Y) {
+    return Y < X;
+  }
+  friend bool operator<=(const HeaderEntry &X, const HeaderEntry &Y) {
+    return !(Y < X);
+  }
+  friend bool operator>=(const HeaderEntry &X, const HeaderEntry &Y) {
+    return !(X < Y);
+  }
+};
+
+typedef std::vector<HeaderEntry> HeaderContents;
+
+class EntityMap : public StringMap<SmallVector<Entry, 2> > {
+public:
+  DenseMap<const FileEntry *, HeaderContents> HeaderContentMismatches;
+
+  void add(const std::string &Name, enum Entry::EntryKind Kind, Location Loc) {
+    // Record this entity in its header.
+    HeaderEntry HE = { Name, Loc };
+    CurHeaderContents[Loc.File].push_back(HE);
+
+    // Check whether we've seen this entry before.
+    SmallVector<Entry, 2> &Entries = (*this)[Name];
+    for (unsigned I = 0, N = Entries.size(); I != N; ++I) {
+      if (Entries[I].Kind == Kind && Entries[I].Loc == Loc)
+        return;
+    }
+
+    // We have not seen this entry before; record it.
+    Entry E = { Kind, Loc };
+    Entries.push_back(E);
+  }
+
+  void mergeCurHeaderContents() {
+    for (DenseMap<const FileEntry *, HeaderContents>::iterator
+             H = CurHeaderContents.begin(),
+             HEnd = CurHeaderContents.end();
+         H != HEnd; ++H) {
+      // Sort contents.
+      std::sort(H->second.begin(), H->second.end());
+
+      // Check whether we've seen this header before.
+      DenseMap<const FileEntry *, HeaderContents>::iterator KnownH =
+          AllHeaderContents.find(H->first);
+      if (KnownH == AllHeaderContents.end()) {
+        // We haven't seen this header before; record its contents.
+        AllHeaderContents.insert(*H);
+        continue;
+      }
+
+      // If the header contents are the same, we're done.
+      if (H->second == KnownH->second)
+        continue;
+
+      // Determine what changed.
+      std::set_symmetric_difference(
+          H->second.begin(), H->second.end(), KnownH->second.begin(),
+          KnownH->second.end(),
+          std::back_inserter(HeaderContentMismatches[H->first]));
+    }
+
+    CurHeaderContents.clear();
+  }
+
+private:
+  DenseMap<const FileEntry *, HeaderContents> CurHeaderContents;
+  DenseMap<const FileEntry *, HeaderContents> AllHeaderContents;
+};
+
+class CollectEntitiesVisitor
+    : public RecursiveASTVisitor<CollectEntitiesVisitor> {
+public:
+  CollectEntitiesVisitor(SourceManager &SM, EntityMap &Entities,
+                         Preprocessor &PP, PreprocessorTracker &PPTracker,
+                         int &HadErrors)
+      : SM(SM), Entities(Entities), PP(PP), PPTracker(PPTracker),
+        HadErrors(HadErrors) {}
+
+  bool TraverseStmt(Stmt *S) { return true; }
+  bool TraverseType(QualType T) { return true; }
+  bool TraverseTypeLoc(TypeLoc TL) { return true; }
+  bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { return true; }
+  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+    return true;
+  }
+  bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo) {
+    return true;
+  }
+  bool TraverseTemplateName(TemplateName Template) { return true; }
+  bool TraverseTemplateArgument(const TemplateArgument &Arg) { return true; }
+  bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
+    return true;
+  }
+  bool TraverseTemplateArguments(const TemplateArgument *Args,
+                                 unsigned NumArgs) {
+    return true;
+  }
+  bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { return true; }
+  bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
+                             Expr *Init) {
+    return true;
+  }
+
+  // Check 'extern "*" {}' block for #include directives.
+  bool VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+    // Bail if not a block.
+    if (!D->hasBraces())
+      return true;
+    SourceRange BlockRange = D->getSourceRange();
+    const char *LinkageLabel;
+    switch (D->getLanguage()) {
+    case LinkageSpecDecl::lang_c:
+      LinkageLabel = "extern \"C\" {}";
+      break;
+    case LinkageSpecDecl::lang_cxx:
+      LinkageLabel = "extern \"C++\" {}";
+      break;
+    }
+    if (!PPTracker.checkForIncludesInBlock(PP, BlockRange, LinkageLabel,
+                                           errs()))
+      HadErrors = 1;
+    return true;
+  }
+
+  // Check 'namespace (name) {}' block for #include directives.
+  bool VisitNamespaceDecl(const NamespaceDecl *D) {
+    SourceRange BlockRange = D->getSourceRange();
+    std::string Label("namespace ");
+    Label += D->getName();
+    Label += " {}";
+    if (!PPTracker.checkForIncludesInBlock(PP, BlockRange, Label.c_str(),
+                                           errs()))
+      HadErrors = 1;
+    return true;
+  }
+
+  // Collect definition entities.
+  bool VisitNamedDecl(NamedDecl *ND) {
+    // We only care about file-context variables.
+    if (!ND->getDeclContext()->isFileContext())
+      return true;
+
+    // Skip declarations that tend to be properly multiply-declared.
+    if (isa<NamespaceDecl>(ND) || isa<UsingDirectiveDecl>(ND) ||
+        isa<NamespaceAliasDecl>(ND) ||
+        isa<ClassTemplateSpecializationDecl>(ND) || isa<UsingDecl>(ND) ||
+        isa<ClassTemplateDecl>(ND) || isa<TemplateTypeParmDecl>(ND) ||
+        isa<TypeAliasTemplateDecl>(ND) || isa<UsingShadowDecl>(ND) ||
+        isa<FunctionDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
+        (isa<TagDecl>(ND) &&
+         !cast<TagDecl>(ND)->isThisDeclarationADefinition()))
+      return true;
+
+    // Skip anonymous declarations.
+    if (!ND->getDeclName())
+      return true;
+
+    // Get the qualified name.
+    std::string Name;
+    llvm::raw_string_ostream OS(Name);
+    ND->printQualifiedName(OS);
+    OS.flush();
+    if (Name.empty())
+      return true;
+
+    Location Loc(SM, ND->getLocation());
+    if (!Loc)
+      return true;
+
+    Entities.add(Name, isa<TagDecl>(ND) ? Entry::EK_Tag : Entry::EK_Value, Loc);
+    return true;
+  }
+
+private:
+  SourceManager &SM;
+  EntityMap &Entities;
+  Preprocessor &PP;
+  PreprocessorTracker &PPTracker;
+  int &HadErrors;
+};
+
+class CollectEntitiesConsumer : public ASTConsumer {
+public:
+  CollectEntitiesConsumer(EntityMap &Entities,
+                          PreprocessorTracker &preprocessorTracker,
+                          Preprocessor &PP, StringRef InFile, int &HadErrors)
+      : Entities(Entities), PPTracker(preprocessorTracker), PP(PP),
+        HadErrors(HadErrors) {
+    PPTracker.handlePreprocessorEntry(PP, InFile);
+  }
+
+  ~CollectEntitiesConsumer() override { PPTracker.handlePreprocessorExit(); }
+
+  void HandleTranslationUnit(ASTContext &Ctx) override {
+    SourceManager &SM = Ctx.getSourceManager();
+
+    // Collect declared entities.
+    CollectEntitiesVisitor(SM, Entities, PP, PPTracker, HadErrors)
+        .TraverseDecl(Ctx.getTranslationUnitDecl());
+
+    // Collect macro definitions.
+    for (Preprocessor::macro_iterator M = PP.macro_begin(),
+                                      MEnd = PP.macro_end();
+         M != MEnd; ++M) {
+      Location Loc(SM, M->second.getLatest()->getLocation());
+      if (!Loc)
+        continue;
+
+      Entities.add(M->first->getName().str(), Entry::EK_Macro, Loc);
+    }
+
+    // Merge header contents.
+    Entities.mergeCurHeaderContents();
+  }
+
+private:
+  EntityMap &Entities;
+  PreprocessorTracker &PPTracker;
+  Preprocessor &PP;
+  int &HadErrors;
+};
+
+class CollectEntitiesAction : public SyntaxOnlyAction {
+public:
+  CollectEntitiesAction(EntityMap &Entities,
+                        PreprocessorTracker &preprocessorTracker,
+                        int &HadErrors)
+      : Entities(Entities), PPTracker(preprocessorTracker),
+        HadErrors(HadErrors) {}
+
+protected:
+  std::unique_ptr<clang::ASTConsumer>
+  CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override {
+    return llvm::make_unique<CollectEntitiesConsumer>(
+        Entities, PPTracker, CI.getPreprocessor(), InFile, HadErrors);
+  }
+
+private:
+  EntityMap &Entities;
+  PreprocessorTracker &PPTracker;
+  int &HadErrors;
+};
+
+class ModularizeFrontendActionFactory : public FrontendActionFactory {
+public:
+  ModularizeFrontendActionFactory(EntityMap &Entities,
+                                  PreprocessorTracker &preprocessorTracker,
+                                  int &HadErrors)
+      : Entities(Entities), PPTracker(preprocessorTracker),
+        HadErrors(HadErrors) {}
+
+  CollectEntitiesAction *create() override {
+    return new CollectEntitiesAction(Entities, PPTracker, HadErrors);
+  }
+
+private:
+  EntityMap &Entities;
+  PreprocessorTracker &PPTracker;
+  int &HadErrors;
+};
+
+class CompileCheckVisitor
+  : public RecursiveASTVisitor<CompileCheckVisitor> {
+public:
+  CompileCheckVisitor() {}
+
+  bool TraverseStmt(Stmt *S) { return true; }
+  bool TraverseType(QualType T) { return true; }
+  bool TraverseTypeLoc(TypeLoc TL) { return true; }
+  bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { return true; }
+  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+    return true;
+  }
+  bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo) {
+    return true;
+  }
+  bool TraverseTemplateName(TemplateName Template) { return true; }
+  bool TraverseTemplateArgument(const TemplateArgument &Arg) { return true; }
+  bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
+    return true;
+  }
+  bool TraverseTemplateArguments(const TemplateArgument *Args,
+    unsigned NumArgs) {
+    return true;
+  }
+  bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { return true; }
+  bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
+                             Expr *Init) {
+    return true;
+  }
+
+  // Check 'extern "*" {}' block for #include directives.
+  bool VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+    return true;
+  }
+
+  // Check 'namespace (name) {}' block for #include directives.
+  bool VisitNamespaceDecl(const NamespaceDecl *D) {
+    return true;
+  }
+
+  // Collect definition entities.
+  bool VisitNamedDecl(NamedDecl *ND) {
+    return true;
+  }
+};
+
+class CompileCheckConsumer : public ASTConsumer {
+public:
+  CompileCheckConsumer() {}
+
+  void HandleTranslationUnit(ASTContext &Ctx) override {
+    CompileCheckVisitor().TraverseDecl(Ctx.getTranslationUnitDecl());
+  }
+};
+
+class CompileCheckAction : public SyntaxOnlyAction {
+public:
+  CompileCheckAction() {}
+
+protected:
+  std::unique_ptr<clang::ASTConsumer>
+    CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override {
+    return llvm::make_unique<CompileCheckConsumer>();
+  }
+};
+
+class CompileCheckFrontendActionFactory : public FrontendActionFactory {
+public:
+  CompileCheckFrontendActionFactory() {}
+
+  CompileCheckAction *create() override {
+    return new CompileCheckAction();
+  }
+};
+
+int main(int Argc, const char **Argv) {
+
+  // Save program name for error messages.
+  Argv0 = Argv[0];
+
+  // Save program arguments for use in module.modulemap comment.
+  CommandLine = sys::path::stem(sys::path::filename(Argv0));
+  for (int ArgIndex = 1; ArgIndex < Argc; ArgIndex++) {
+    CommandLine.append(" ");
+    CommandLine.append(Argv[ArgIndex]);
+  }
+
+  // This causes options to be parsed.
+  cl::ParseCommandLineOptions(Argc, Argv, "modularize.\n");
+
+  // No go if we have no header list file.
+  if (ListFileNames.size() == 0) {
+    cl::PrintHelpMessage();
+    return 1;
+  }
+
+  std::unique_ptr<ModularizeUtilities> ModUtil;
+  int HadErrors = 0;
+
+  ModUtil.reset(
+    ModularizeUtilities::createModularizeUtilities(
+      ListFileNames, HeaderPrefix, ProblemFilesList));
+
+  // Get header file names and dependencies.
+  if (ModUtil->loadAllHeaderListsAndDependencies())
+    HadErrors = 1;
+
+  // If we are in assistant mode, output the module map and quit.
+  if (ModuleMapPath.length() != 0) {
+    if (!createModuleMap(ModuleMapPath, ModUtil->HeaderFileNames,
+                         ModUtil->ProblemFileNames,
+                         ModUtil->Dependencies, HeaderPrefix, RootModule))
+      return 1; // Failed.
+    return 0;   // Success - Skip checks in assistant mode.
+  }
+
+  // If we're doing module maps.
+  if (!NoCoverageCheck && ModUtil->HasModuleMap) {
+    // Do coverage check.
+    if (ModUtil->doCoverageCheck(IncludePaths, CommandLine))
+      HadErrors = 1;
+  }
+
+  // Bail early if only doing the coverage check.
+  if (CoverageCheckOnly)
+    return HadErrors;
+
+  // Create the compilation database.
+  SmallString<256> PathBuf;
+  sys::fs::current_path(PathBuf);
+  std::unique_ptr<CompilationDatabase> Compilations;
+  Compilations.reset(
+      new FixedCompilationDatabase(Twine(PathBuf), CC1Arguments));
+
+  // Create preprocessor tracker, to watch for macro and conditional problems.
+  std::unique_ptr<PreprocessorTracker> PPTracker(
+    PreprocessorTracker::create(ModUtil->HeaderFileNames,
+                                BlockCheckHeaderListOnly));
+
+  // Coolect entities here.
+  EntityMap Entities;
+
+  // Because we can't easily determine which files failed
+  // during the tool run, if we're collecting the file lists
+  // for display, we do a first compile pass on individual
+  // files to find which ones don't compile stand-alone.
+  if (DisplayFileLists) {
+    // First, make a pass to just get compile errors.
+    for (auto &CompileCheckFile : ModUtil->HeaderFileNames) {
+      llvm::SmallVector<std::string, 32> CompileCheckFileArray;
+      CompileCheckFileArray.push_back(CompileCheckFile);
+      ClangTool CompileCheckTool(*Compilations, CompileCheckFileArray);
+      CompileCheckTool.appendArgumentsAdjuster(
+        getModularizeArgumentsAdjuster(ModUtil->Dependencies));
+      int CompileCheckFileErrors = 0;
+      CompileCheckFrontendActionFactory CompileCheckFactory;
+      CompileCheckFileErrors |= CompileCheckTool.run(&CompileCheckFactory);
+      if (CompileCheckFileErrors != 0) {
+        ModUtil->addUniqueProblemFile(CompileCheckFile);   // Save problem file.
+        HadErrors |= 1;
+      }
+      else
+        ModUtil->addNoCompileErrorsFile(CompileCheckFile); // Save good file.
+    }
+  }
+
+  // Then we make another pass on the good files to do the rest of the work.
+  ClangTool Tool(*Compilations,
+    (DisplayFileLists ? ModUtil->GoodFileNames : ModUtil->HeaderFileNames));
+  Tool.appendArgumentsAdjuster(
+    getModularizeArgumentsAdjuster(ModUtil->Dependencies));
+  ModularizeFrontendActionFactory Factory(Entities, *PPTracker, HadErrors);
+  HadErrors |= Tool.run(&Factory);
+
+  // Create a place to save duplicate entity locations, separate bins per kind.
+  typedef SmallVector<Location, 8> LocationArray;
+  typedef SmallVector<LocationArray, Entry::EK_NumberOfKinds> EntryBinArray;
+  EntryBinArray EntryBins;
+  int KindIndex;
+  for (KindIndex = 0; KindIndex < Entry::EK_NumberOfKinds; ++KindIndex) {
+    LocationArray Array;
+    EntryBins.push_back(Array);
+  }
+
+  // Check for the same entity being defined in multiple places.
+  for (EntityMap::iterator E = Entities.begin(), EEnd = Entities.end();
+       E != EEnd; ++E) {
+    // If only one occurrence, exit early.
+    if (E->second.size() == 1)
+      continue;
+    // Clear entity locations.
+    for (EntryBinArray::iterator CI = EntryBins.begin(), CE = EntryBins.end();
+         CI != CE; ++CI) {
+      CI->clear();
+    }
+    // Walk the entities of a single name, collecting the locations,
+    // separated into separate bins.
+    for (unsigned I = 0, N = E->second.size(); I != N; ++I) {
+      EntryBins[E->second[I].Kind].push_back(E->second[I].Loc);
+    }
+    // Report any duplicate entity definition errors.
+    int KindIndex = 0;
+    for (EntryBinArray::iterator DI = EntryBins.begin(), DE = EntryBins.end();
+         DI != DE; ++DI, ++KindIndex) {
+      int ECount = DI->size();
+      // If only 1 occurrence of this entity, skip it, we only report duplicates.
+      if (ECount <= 1)
+        continue;
+      LocationArray::iterator FI = DI->begin();
+      StringRef kindName = Entry::getKindName((Entry::EntryKind)KindIndex);
+      errs() << "error: " << kindName << " '" << E->first()
+             << "' defined at multiple locations:\n";
+      for (LocationArray::iterator FE = DI->end(); FI != FE; ++FI) {
+        errs() << "    " << FI->File->getName() << ":" << FI->Line << ":"
+               << FI->Column << "\n";
+        ModUtil->addUniqueProblemFile(FI->File->getName());
+      }
+      HadErrors = 1;
+    }
+  }
+
+  // Complain about macro instance in header files that differ based on how
+  // they are included.
+  if (PPTracker->reportInconsistentMacros(errs()))
+    HadErrors = 1;
+
+  // Complain about preprocessor conditional directives in header files that
+  // differ based on how they are included.
+  if (PPTracker->reportInconsistentConditionals(errs()))
+    HadErrors = 1;
+
+  // Complain about any headers that have contents that differ based on how
+  // they are included.
+  // FIXME: Could we provide information about which preprocessor conditionals
+  // are involved?
+  for (DenseMap<const FileEntry *, HeaderContents>::iterator
+           H = Entities.HeaderContentMismatches.begin(),
+           HEnd = Entities.HeaderContentMismatches.end();
+       H != HEnd; ++H) {
+    if (H->second.empty()) {
+      errs() << "internal error: phantom header content mismatch\n";
+      continue;
+    }
+
+    HadErrors = 1;
+    ModUtil->addUniqueProblemFile(H->first->getName());
+    errs() << "error: header '" << H->first->getName()
+           << "' has different contents depending on how it was included.\n";
+    for (unsigned I = 0, N = H->second.size(); I != N; ++I) {
+      errs() << "note: '" << H->second[I].Name << "' in "
+             << H->second[I].Loc.File->getName() << " at "
+             << H->second[I].Loc.Line << ":" << H->second[I].Loc.Column
+             << " not always provided\n";
+    }
+  }
+
+  if (DisplayFileLists) {
+    ModUtil->displayProblemFiles();
+    ModUtil->displayGoodFiles();
+    ModUtil->displayCombinedFiles();
+  }
+
+  return HadErrors;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/modularize/Modularize.h b/src/third_party/llvm-project/clang-tools-extra/modularize/Modularize.h
new file mode 100644
index 0000000..a3f2ad3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/modularize/Modularize.h
@@ -0,0 +1,54 @@
+//===--- Modularize.h - Common definitions for Modularize -*- C++ -*-----===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Common definitions for Modularize.
+///
+//===--------------------------------------------------------------------===//
+
+#ifndef MODULARIZE_H
+#define MODULARIZE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+#include <vector>
+
+// Save the program name for error messages.
+extern const char *Argv0;
+// Save the command line for comments.
+extern std::string CommandLine;
+
+// Dependency types.
+typedef llvm::SmallVector<std::string, 4> DependentsVector;
+typedef llvm::StringMap<DependentsVector> DependencyMap;
+
+// Global function declarations.
+
+/// Create the module map file.
+/// \param ModuleMapPath The path to the module map file to be generated.
+/// \param HeaderFileNames The list of header files, absolute native paths.
+/// \param ProblemFileNames The list of problem header files.
+/// \param Dependencies Map of headers that depend on other headers.
+/// \param HeaderPrefix Tells the code where the headers are, if they
+///   aren's in the current directory, allowing the generator to strip
+///   the leading, non-relative beginning of the header paths.
+/// \brief RootModuleName If not empty, specifies that a root module
+///   should be created with this name.
+/// \returns True if successful.
+bool createModuleMap(llvm::StringRef ModuleMapPath,
+                     llvm::ArrayRef<std::string> HeaderFileNames,
+                     llvm::ArrayRef<std::string> ProblemFileNames,
+                     DependencyMap &Dependencies, llvm::StringRef HeaderPrefix,
+                     llvm::StringRef RootModuleName);
+
+#endif // MODULARIZE_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/modularize/ModularizeUtilities.cpp b/src/third_party/llvm-project/clang-tools-extra/modularize/ModularizeUtilities.cpp
new file mode 100644
index 0000000..85768d5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/modularize/ModularizeUtilities.cpp
@@ -0,0 +1,546 @@
+//===--- extra/modularize/ModularizeUtilities.cpp -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a class for loading and validating a module map or
+// header list by checking that all headers in the corresponding directories
+// are accounted for.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/SourceManager.h"
+#include "clang/Driver/Options.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "CoverageChecker.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include "ModularizeUtilities.h"
+
+using namespace clang;
+using namespace llvm;
+using namespace Modularize;
+
+namespace {
+// Subclass TargetOptions so we can construct it inline with
+// the minimal option, the triple.
+class ModuleMapTargetOptions : public clang::TargetOptions {
+public:
+  ModuleMapTargetOptions() { Triple = llvm::sys::getDefaultTargetTriple(); }
+};
+} // namespace
+
+// ModularizeUtilities class implementation.
+
+// Constructor.
+ModularizeUtilities::ModularizeUtilities(std::vector<std::string> &InputPaths,
+                                         llvm::StringRef Prefix,
+                                         llvm::StringRef ProblemFilesListPath)
+    : InputFilePaths(InputPaths), HeaderPrefix(Prefix),
+      ProblemFilesPath(ProblemFilesListPath), HasModuleMap(false),
+      MissingHeaderCount(0),
+      // Init clang stuff needed for loading the module map and preprocessing.
+      LangOpts(new LangOptions()), DiagIDs(new DiagnosticIDs()),
+      DiagnosticOpts(new DiagnosticOptions()),
+      DC(llvm::errs(), DiagnosticOpts.get()),
+      Diagnostics(
+          new DiagnosticsEngine(DiagIDs, DiagnosticOpts.get(), &DC, false)),
+      TargetOpts(new ModuleMapTargetOptions()),
+      Target(TargetInfo::CreateTargetInfo(*Diagnostics, TargetOpts)),
+      FileMgr(new FileManager(FileSystemOpts)),
+      SourceMgr(new SourceManager(*Diagnostics, *FileMgr, false)),
+      HeaderInfo(new HeaderSearch(std::make_shared<HeaderSearchOptions>(),
+                                  *SourceMgr, *Diagnostics, *LangOpts,
+                                  Target.get())) {}
+
+// Create instance of ModularizeUtilities, to simplify setting up
+// subordinate objects.
+ModularizeUtilities *ModularizeUtilities::createModularizeUtilities(
+    std::vector<std::string> &InputPaths, llvm::StringRef Prefix,
+    llvm::StringRef ProblemFilesListPath) {
+
+  return new ModularizeUtilities(InputPaths, Prefix, ProblemFilesListPath);
+}
+
+// Load all header lists and dependencies.
+std::error_code ModularizeUtilities::loadAllHeaderListsAndDependencies() {
+  // For each input file.
+  for (auto I = InputFilePaths.begin(), E = InputFilePaths.end(); I != E; ++I) {
+    llvm::StringRef InputPath = *I;
+    // If it's a module map.
+    if (InputPath.endswith(".modulemap")) {
+      // Load the module map.
+      if (std::error_code EC = loadModuleMap(InputPath))
+        return EC;
+    }
+    else {
+      // Else we assume it's a header list and load it.
+      if (std::error_code EC = loadSingleHeaderListsAndDependencies(InputPath)) {
+        errs() << "modularize: error: Unable to get header list '" << InputPath
+          << "': " << EC.message() << '\n';
+        return EC;
+      }
+    }
+  }
+  // If we have a problem files list.
+  if (ProblemFilesPath.size() != 0) {
+    // Load problem files list.
+    if (std::error_code EC = loadProblemHeaderList(ProblemFilesPath)) {
+      errs() << "modularize: error: Unable to get problem header list '" << ProblemFilesPath
+        << "': " << EC.message() << '\n';
+      return EC;
+    }
+  }
+  return std::error_code();
+}
+
+// Do coverage checks.
+// For each loaded module map, do header coverage check.
+// Starting from the directory of the module.map file,
+// Find all header files, optionally looking only at files
+// covered by the include path options, and compare against
+// the headers referenced by the module.map file.
+// Display warnings for unaccounted-for header files.
+// Returns 0 if there were no errors or warnings, 1 if there
+// were warnings, 2 if any other problem, such as a bad
+// module map path argument was specified.
+std::error_code ModularizeUtilities::doCoverageCheck(
+    std::vector<std::string> &IncludePaths,
+    llvm::ArrayRef<std::string> CommandLine) {
+  int ModuleMapCount = ModuleMaps.size();
+  int ModuleMapIndex;
+  std::error_code EC;
+  for (ModuleMapIndex = 0; ModuleMapIndex < ModuleMapCount; ++ModuleMapIndex) {
+    std::unique_ptr<clang::ModuleMap> &ModMap = ModuleMaps[ModuleMapIndex];
+    auto Checker = CoverageChecker::createCoverageChecker(
+        InputFilePaths[ModuleMapIndex], IncludePaths, CommandLine,
+        ModMap.get());
+    std::error_code LocalEC = Checker->doChecks();
+    if (LocalEC.value() > 0)
+      EC = LocalEC;
+  }
+  return EC;
+}
+
+// Load single header list and dependencies.
+std::error_code ModularizeUtilities::loadSingleHeaderListsAndDependencies(
+    llvm::StringRef InputPath) {
+
+  // By default, use the path component of the list file name.
+  SmallString<256> HeaderDirectory(InputPath);
+  llvm::sys::path::remove_filename(HeaderDirectory);
+  SmallString<256> CurrentDirectory;
+  llvm::sys::fs::current_path(CurrentDirectory);
+
+  // Get the prefix if we have one.
+  if (HeaderPrefix.size() != 0)
+    HeaderDirectory = HeaderPrefix;
+
+  // Read the header list file into a buffer.
+  ErrorOr<std::unique_ptr<MemoryBuffer>> listBuffer =
+    MemoryBuffer::getFile(InputPath);
+  if (std::error_code EC = listBuffer.getError())
+    return EC;
+
+  // Parse the header list into strings.
+  SmallVector<StringRef, 32> Strings;
+  listBuffer.get()->getBuffer().split(Strings, "\n", -1, false);
+
+  // Collect the header file names from the string list.
+  for (SmallVectorImpl<StringRef>::iterator I = Strings.begin(),
+    E = Strings.end();
+    I != E; ++I) {
+    StringRef Line = I->trim();
+    // Ignore comments and empty lines.
+    if (Line.empty() || (Line[0] == '#'))
+      continue;
+    std::pair<StringRef, StringRef> TargetAndDependents = Line.split(':');
+    SmallString<256> HeaderFileName;
+    // Prepend header file name prefix if it's not absolute.
+    if (llvm::sys::path::is_absolute(TargetAndDependents.first))
+      llvm::sys::path::native(TargetAndDependents.first, HeaderFileName);
+    else {
+      if (HeaderDirectory.size() != 0)
+        HeaderFileName = HeaderDirectory;
+      else
+        HeaderFileName = CurrentDirectory;
+      llvm::sys::path::append(HeaderFileName, TargetAndDependents.first);
+      llvm::sys::path::native(HeaderFileName);
+    }
+    // Handle optional dependencies.
+    DependentsVector Dependents;
+    SmallVector<StringRef, 4> DependentsList;
+    TargetAndDependents.second.split(DependentsList, " ", -1, false);
+    int Count = DependentsList.size();
+    for (int Index = 0; Index < Count; ++Index) {
+      SmallString<256> Dependent;
+      if (llvm::sys::path::is_absolute(DependentsList[Index]))
+        Dependent = DependentsList[Index];
+      else {
+        if (HeaderDirectory.size() != 0)
+          Dependent = HeaderDirectory;
+        else
+          Dependent = CurrentDirectory;
+        llvm::sys::path::append(Dependent, DependentsList[Index]);
+      }
+      llvm::sys::path::native(Dependent);
+      Dependents.push_back(getCanonicalPath(Dependent.str()));
+    }
+    // Get canonical form.
+    HeaderFileName = getCanonicalPath(HeaderFileName);
+    // Save the resulting header file path and dependencies.
+    HeaderFileNames.push_back(HeaderFileName.str());
+    Dependencies[HeaderFileName.str()] = Dependents;
+  }
+  return std::error_code();
+}
+
+// Load problem header list.
+std::error_code ModularizeUtilities::loadProblemHeaderList(
+  llvm::StringRef InputPath) {
+
+  // By default, use the path component of the list file name.
+  SmallString<256> HeaderDirectory(InputPath);
+  llvm::sys::path::remove_filename(HeaderDirectory);
+  SmallString<256> CurrentDirectory;
+  llvm::sys::fs::current_path(CurrentDirectory);
+
+  // Get the prefix if we have one.
+  if (HeaderPrefix.size() != 0)
+    HeaderDirectory = HeaderPrefix;
+
+  // Read the header list file into a buffer.
+  ErrorOr<std::unique_ptr<MemoryBuffer>> listBuffer =
+    MemoryBuffer::getFile(InputPath);
+  if (std::error_code EC = listBuffer.getError())
+    return EC;
+
+  // Parse the header list into strings.
+  SmallVector<StringRef, 32> Strings;
+  listBuffer.get()->getBuffer().split(Strings, "\n", -1, false);
+
+  // Collect the header file names from the string list.
+  for (SmallVectorImpl<StringRef>::iterator I = Strings.begin(),
+    E = Strings.end();
+    I != E; ++I) {
+    StringRef Line = I->trim();
+    // Ignore comments and empty lines.
+    if (Line.empty() || (Line[0] == '#'))
+      continue;
+    SmallString<256> HeaderFileName;
+    // Prepend header file name prefix if it's not absolute.
+    if (llvm::sys::path::is_absolute(Line))
+      llvm::sys::path::native(Line, HeaderFileName);
+    else {
+      if (HeaderDirectory.size() != 0)
+        HeaderFileName = HeaderDirectory;
+      else
+        HeaderFileName = CurrentDirectory;
+      llvm::sys::path::append(HeaderFileName, Line);
+      llvm::sys::path::native(HeaderFileName);
+    }
+    // Get canonical form.
+    HeaderFileName = getCanonicalPath(HeaderFileName);
+    // Save the resulting header file path.
+    ProblemFileNames.push_back(HeaderFileName.str());
+  }
+  return std::error_code();
+}
+
+// Load single module map and extract header file list.
+std::error_code ModularizeUtilities::loadModuleMap(
+    llvm::StringRef InputPath) {
+  // Get file entry for module.modulemap file.
+  const FileEntry *ModuleMapEntry =
+    SourceMgr->getFileManager().getFile(InputPath);
+
+  // return error if not found.
+  if (!ModuleMapEntry) {
+    llvm::errs() << "error: File \"" << InputPath << "\" not found.\n";
+    return std::error_code(1, std::generic_category());
+  }
+
+  // Because the module map parser uses a ForwardingDiagnosticConsumer,
+  // which doesn't forward the BeginSourceFile call, we do it explicitly here.
+  DC.BeginSourceFile(*LangOpts, nullptr);
+
+  // Figure out the home directory for the module map file.
+  const DirectoryEntry *Dir = ModuleMapEntry->getDir();
+  StringRef DirName(Dir->getName());
+  if (llvm::sys::path::filename(DirName) == "Modules") {
+    DirName = llvm::sys::path::parent_path(DirName);
+    if (DirName.endswith(".framework"))
+      Dir = FileMgr->getDirectory(DirName);
+    // FIXME: This assert can fail if there's a race between the above check
+    // and the removal of the directory.
+    assert(Dir && "parent must exist");
+  }
+
+  std::unique_ptr<ModuleMap> ModMap;
+  ModMap.reset(new ModuleMap(*SourceMgr, *Diagnostics, *LangOpts,
+    Target.get(), *HeaderInfo));
+
+  // Parse module.modulemap file into module map.
+  if (ModMap->parseModuleMapFile(ModuleMapEntry, false, Dir)) {
+    return std::error_code(1, std::generic_category());
+  }
+
+  // Do matching end call.
+  DC.EndSourceFile();
+
+  // Reset missing header count.
+  MissingHeaderCount = 0;
+
+  if (!collectModuleMapHeaders(ModMap.get()))
+    return std::error_code(1, std::generic_category());
+
+  // Save module map.
+  ModuleMaps.push_back(std::move(ModMap));
+
+  // Indicate we are using module maps.
+  HasModuleMap = true;
+
+  // Return code of 1 for missing headers.
+  if (MissingHeaderCount)
+    return std::error_code(1, std::generic_category());
+
+  return std::error_code();
+}
+
+// Collect module map headers.
+// Walks the modules and collects referenced headers into
+// HeaderFileNames.
+bool ModularizeUtilities::collectModuleMapHeaders(clang::ModuleMap *ModMap) {
+  for (ModuleMap::module_iterator I = ModMap->module_begin(),
+    E = ModMap->module_end();
+    I != E; ++I) {
+    if (!collectModuleHeaders(*I->second))
+      return false;
+  }
+  return true;
+}
+
+// Collect referenced headers from one module.
+// Collects the headers referenced in the given module into
+// HeaderFileNames.
+bool ModularizeUtilities::collectModuleHeaders(const clang::Module &Mod) {
+
+  // Ignore explicit modules because they often have dependencies
+  // we can't know.
+  if (Mod.IsExplicit)
+    return true;
+
+  // Treat headers in umbrella directory as dependencies.
+  DependentsVector UmbrellaDependents;
+
+  // Recursively do submodules.
+  for (auto MI = Mod.submodule_begin(), MIEnd = Mod.submodule_end();
+       MI != MIEnd; ++MI)
+    collectModuleHeaders(**MI);
+
+  if (const FileEntry *UmbrellaHeader = Mod.getUmbrellaHeader().Entry) {
+    std::string HeaderPath = getCanonicalPath(UmbrellaHeader->getName());
+    // Collect umbrella header.
+    HeaderFileNames.push_back(HeaderPath);
+
+    // FUTURE: When needed, umbrella header header collection goes here.
+  }
+  else if (const DirectoryEntry *UmbrellaDir = Mod.getUmbrellaDir().Entry) {
+    // If there normal headers, assume these are umbrellas and skip collection.
+    if (Mod.Headers->size() == 0) {
+      // Collect headers in umbrella directory.
+      if (!collectUmbrellaHeaders(UmbrellaDir->getName(), UmbrellaDependents))
+        return false;
+    }
+  }
+
+  // We ignore HK_Private, HK_Textual, HK_PrivateTextual, and HK_Excluded,
+  // assuming they are marked as such either because of unsuitability for
+  // modules or because they are meant to be included by another header,
+  // and thus should be ignored by modularize.
+
+  int NormalHeaderCount = Mod.Headers[clang::Module::HK_Normal].size();
+
+  for (int Index = 0; Index < NormalHeaderCount; ++Index) {
+    DependentsVector NormalDependents;
+    // Collect normal header.
+    const clang::Module::Header &Header(
+      Mod.Headers[clang::Module::HK_Normal][Index]);
+    std::string HeaderPath = getCanonicalPath(Header.Entry->getName());
+    HeaderFileNames.push_back(HeaderPath);
+  }
+
+  int MissingCountThisModule = Mod.MissingHeaders.size();
+
+  for (int Index = 0; Index < MissingCountThisModule; ++Index) {
+    std::string MissingFile = Mod.MissingHeaders[Index].FileName;
+    SourceLocation Loc = Mod.MissingHeaders[Index].FileNameLoc;
+    errs() << Loc.printToString(*SourceMgr)
+      << ": error : Header not found: " << MissingFile << "\n";
+  }
+
+  MissingHeaderCount += MissingCountThisModule;
+
+  return true;
+}
+
+// Collect headers from an umbrella directory.
+bool ModularizeUtilities::collectUmbrellaHeaders(StringRef UmbrellaDirName,
+  DependentsVector &Dependents) {
+  // Initialize directory name.
+  SmallString<256> Directory(UmbrellaDirName);
+  // Walk the directory.
+  std::error_code EC;
+  for (llvm::sys::fs::directory_iterator I(Directory.str(), EC), E; I != E;
+    I.increment(EC)) {
+    if (EC)
+      return false;
+    std::string File(I->path());
+    llvm::ErrorOr<llvm::sys::fs::basic_file_status> Status = I->status();
+    if (!Status)
+      return false;
+    llvm::sys::fs::file_type Type = Status->type();
+    // If the file is a directory, ignore the name and recurse.
+    if (Type == llvm::sys::fs::file_type::directory_file) {
+      if (!collectUmbrellaHeaders(File, Dependents))
+        return false;
+      continue;
+    }
+    // If the file does not have a common header extension, ignore it.
+    if (!isHeader(File))
+      continue;
+    // Save header name.
+    std::string HeaderPath = getCanonicalPath(File);
+    Dependents.push_back(HeaderPath);
+  }
+  return true;
+}
+
+// Replace .. embedded in path for purposes of having
+// a canonical path.
+static std::string replaceDotDot(StringRef Path) {
+  SmallString<128> Buffer;
+  llvm::sys::path::const_iterator B = llvm::sys::path::begin(Path),
+    E = llvm::sys::path::end(Path);
+  while (B != E) {
+    if (B->compare(".") == 0) {
+    }
+    else if (B->compare("..") == 0)
+      llvm::sys::path::remove_filename(Buffer);
+    else
+      llvm::sys::path::append(Buffer, *B);
+    ++B;
+  }
+  if (Path.endswith("/") || Path.endswith("\\"))
+    Buffer.append(1, Path.back());
+  return Buffer.c_str();
+}
+
+// Convert header path to canonical form.
+// The canonical form is basically just use forward slashes, and remove "./".
+// \param FilePath The file path, relative to the module map directory.
+// \returns The file path in canonical form.
+std::string ModularizeUtilities::getCanonicalPath(StringRef FilePath) {
+  std::string Tmp(replaceDotDot(FilePath));
+  std::replace(Tmp.begin(), Tmp.end(), '\\', '/');
+  StringRef Tmp2(Tmp);
+  if (Tmp2.startswith("./"))
+    Tmp = Tmp2.substr(2);
+  return Tmp;
+}
+
+// Check for header file extension.
+// If the file extension is .h, .inc, or missing, it's
+// assumed to be a header.
+// \param FileName The file name.  Must not be a directory.
+// \returns true if it has a header extension or no extension.
+bool ModularizeUtilities::isHeader(StringRef FileName) {
+  StringRef Extension = llvm::sys::path::extension(FileName);
+  if (Extension.size() == 0)
+    return true;
+  if (Extension.equals_lower(".h"))
+    return true;
+  if (Extension.equals_lower(".inc"))
+    return true;
+  return false;
+}
+
+// Get directory path component from file path.
+// \returns the component of the given path, which will be
+// relative if the given path is relative, absolute if the
+// given path is absolute, or "." if the path has no leading
+// path component.
+std::string ModularizeUtilities::getDirectoryFromPath(StringRef Path) {
+  SmallString<256> Directory(Path);
+  sys::path::remove_filename(Directory);
+  if (Directory.size() == 0)
+    return ".";
+  return Directory.str();
+}
+
+// Add unique problem file.
+// Also standardizes the path.
+void ModularizeUtilities::addUniqueProblemFile(std::string FilePath) {
+  FilePath = getCanonicalPath(FilePath);
+  // Don't add if already present.
+  for(auto &TestFilePath : ProblemFileNames) {
+    if (TestFilePath == FilePath)
+      return;
+  }
+  ProblemFileNames.push_back(FilePath);
+}
+
+// Add file with no compile errors.
+// Also standardizes the path.
+void ModularizeUtilities::addNoCompileErrorsFile(std::string FilePath) {
+  FilePath = getCanonicalPath(FilePath);
+  GoodFileNames.push_back(FilePath);
+}
+
+// List problem files.
+void ModularizeUtilities::displayProblemFiles() {
+  errs() << "\nThese are the files with possible errors:\n\n";
+  for (auto &ProblemFile : ProblemFileNames) {
+    errs() << ProblemFile << "\n";
+  }
+}
+
+// List files with no problems.
+void ModularizeUtilities::displayGoodFiles() {
+  errs() << "\nThese are the files with no detected errors:\n\n";
+  for (auto &GoodFile : HeaderFileNames) {
+    bool Good = true;
+    for (auto &ProblemFile : ProblemFileNames) {
+      if (ProblemFile == GoodFile) {
+        Good = false;
+        break;
+      }
+    }
+    if (Good)
+      errs() << GoodFile << "\n";
+  }
+}
+
+// List files with problem files commented out.
+void ModularizeUtilities::displayCombinedFiles() {
+  errs() <<
+    "\nThese are the combined files, with problem files preceded by #:\n\n";
+  for (auto &File : HeaderFileNames) {
+    bool Good = true;
+    for (auto &ProblemFile : ProblemFileNames) {
+      if (ProblemFile == File) {
+        Good = false;
+        break;
+      }
+    }
+    errs() << (Good ? "" : "#") << File << "\n";
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/modularize/ModularizeUtilities.h b/src/third_party/llvm-project/clang-tools-extra/modularize/ModularizeUtilities.h
new file mode 100644
index 0000000..4ad2b56
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/modularize/ModularizeUtilities.h
@@ -0,0 +1,225 @@
+//=====-- ModularizeUtilities.h - Utilities for modularize -*- C++ -*-======//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--------------------------------------------------------------------===//
+///
+/// \file
+/// \brief ModularizeUtilities class definition.
+///
+//===--------------------------------------------------------------------===//
+
+#ifndef MODULARIZEUTILITIES_H
+#define MODULARIZEUTILITIES_H
+
+#include "Modularize.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/ModuleMap.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringSet.h"
+#include <string>
+#include <vector>
+
+namespace Modularize {
+
+/// Modularize utilities class.
+/// Support functions and data for modularize.
+class ModularizeUtilities {
+public:
+  // Input arguments.
+
+  /// The input file paths.
+  std::vector<std::string> InputFilePaths;
+  /// The header prefix.
+  llvm::StringRef HeaderPrefix;
+  /// The path of problem files list file.
+  llvm::StringRef ProblemFilesPath;
+
+  // Output data.
+
+  /// List of top-level header files.
+  llvm::SmallVector<std::string, 32> HeaderFileNames;
+  /// Map of top-level header file dependencies.
+  DependencyMap Dependencies;
+  /// True if we have module maps.
+  bool HasModuleMap;
+  /// Missing header count.
+  int MissingHeaderCount;
+  /// List of header files with no problems during the first pass,
+  /// that is, no compile errors.
+  llvm::SmallVector<std::string, 32> GoodFileNames;
+  /// List of header files with problems.
+  llvm::SmallVector<std::string, 32> ProblemFileNames;
+
+  // Functions.
+
+  /// Constructor.
+  /// You can use the static createModularizeUtilities to create an instance
+  /// of this object.
+  /// \param InputPaths The input file paths.
+  /// \param Prefix The headear path prefix.
+  /// \param ProblemFilesListPath The problem header list path.
+  ModularizeUtilities(std::vector<std::string> &InputPaths,
+                      llvm::StringRef Prefix,
+                      llvm::StringRef ProblemFilesListPath);
+
+  /// Create instance of ModularizeUtilities.
+  /// \param InputPaths The input file paths.
+  /// \param Prefix The headear path prefix.
+  /// \param ProblemFilesListPath The problem header list path.
+  /// \returns Initialized ModularizeUtilities object.
+  static ModularizeUtilities *createModularizeUtilities(
+      std::vector<std::string> &InputPaths,
+      llvm::StringRef Prefix,
+      llvm::StringRef ProblemFilesListPath);
+
+  /// Load header list and dependencies.
+  /// \returns std::error_code.
+  std::error_code loadAllHeaderListsAndDependencies();
+
+  /// Do coverage checks.
+  /// For each loaded module map, do header coverage check.
+  /// Starting from the directory of the module.map file,
+  /// Find all header files, optionally looking only at files
+  /// covered by the include path options, and compare against
+  /// the headers referenced by the module.map file.
+  /// Display warnings for unaccounted-for header files.
+  /// \param IncludePaths The include paths to check for files.
+  ///   (Note that other directories above these paths are ignored.
+  ///   To expect all files to be accounted for from the module.modulemap
+  ///   file directory on down, leave this empty.)
+  /// \param CommandLine Compile command line arguments.
+  /// \returns 0 if there were no errors or warnings, 1 if there
+  ///   were warnings, 2 if any other problem, such as a bad
+  ///   module map path argument was specified.
+  std::error_code doCoverageCheck(std::vector<std::string> &IncludePaths,
+                                  llvm::ArrayRef<std::string> CommandLine);
+
+  /// Add unique problem file.
+  /// Also standardizes the path.
+  /// \param FilePath Problem file path.
+  void addUniqueProblemFile(std::string FilePath);
+
+  /// Add file with no compile errors.
+  /// Also standardizes the path.
+  /// \param FilePath Problem file path.
+  void addNoCompileErrorsFile(std::string FilePath);
+
+  /// List problem files.
+  void displayProblemFiles();
+
+  /// List files with no problems.
+  void displayGoodFiles();
+
+  /// List files with problem files commented out.
+  void displayCombinedFiles();
+
+  // Internal.
+
+protected:
+
+  /// Load single header list and dependencies.
+  /// \param InputPath The input file path.
+  /// \returns std::error_code.
+  std::error_code loadSingleHeaderListsAndDependencies(
+      llvm::StringRef InputPath);
+
+  /// Load problem header list.
+  /// \param InputPath The input file path.
+  /// \returns std::error_code.
+  std::error_code loadProblemHeaderList(
+    llvm::StringRef InputPath);
+
+  /// Load single module map and extract header file list.
+  /// \param InputPath The input file path.
+  /// \returns std::error_code.
+  std::error_code loadModuleMap(
+    llvm::StringRef InputPath);
+
+  /// Collect module Map headers.
+  /// Walks the modules and collects referenced headers into
+  /// HeaderFileNames.
+  /// \param ModMap A loaded module map object.
+  /// \return True if no errors.
+  bool collectModuleMapHeaders(clang::ModuleMap *ModMap);
+
+  /// Collect referenced headers from one module.
+  /// Collects the headers referenced in the given module into
+  /// HeaderFileNames.
+  /// \param Mod The module reference.
+  /// \return True if no errors.
+  bool collectModuleHeaders(const clang::Module &Mod);
+
+  /// Collect headers from an umbrella directory.
+  /// \param UmbrellaDirName The umbrella directory name.
+  /// \return True if no errors.
+  bool collectUmbrellaHeaders(llvm::StringRef UmbrellaDirName,
+    DependentsVector &Dependents);
+
+public:
+
+  // Utility functions.
+
+  /// Convert header path to canonical form.
+  /// The canonical form is basically just use forward slashes,
+  /// and remove "./".
+  /// \param FilePath The file path.
+  /// \returns The file path in canonical form.
+  static std::string getCanonicalPath(llvm::StringRef FilePath);
+
+  /// Check for header file extension.
+  /// If the file extension is .h, .inc, or missing, it's
+  /// assumed to be a header.
+  /// \param FileName The file name.  Must not be a directory.
+  /// \returns true if it has a header extension or no extension.
+  static bool isHeader(llvm::StringRef FileName);
+
+  /// Get directory path component from file path.
+  /// \returns the component of the given path, which will be
+  /// relative if the given path is relative, absolute if the
+  /// given path is absolute, or "." if the path has no leading
+  /// path component.
+  static std::string getDirectoryFromPath(llvm::StringRef Path);
+
+  // Internal data.
+
+  /// Options controlling the language variant.
+  std::shared_ptr<clang::LangOptions> LangOpts;
+  /// Diagnostic IDs.
+  const llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs;
+  /// Options controlling the diagnostic engine.
+  llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagnosticOpts;
+  /// Diagnostic consumer.
+  clang::TextDiagnosticPrinter DC;
+  /// Diagnostic engine.
+  llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> Diagnostics;
+  /// Options controlling the target.
+  std::shared_ptr<clang::TargetOptions> TargetOpts;
+  /// Target information.
+  llvm::IntrusiveRefCntPtr<clang::TargetInfo> Target;
+  /// Options controlling the file system manager.
+  clang::FileSystemOptions FileSystemOpts;
+  /// File system manager.
+  llvm::IntrusiveRefCntPtr<clang::FileManager> FileMgr;
+  /// Source manager.
+  llvm::IntrusiveRefCntPtr<clang::SourceManager> SourceMgr;
+  /// Header search manager.
+  std::unique_ptr<clang::HeaderSearch> HeaderInfo;
+  // The loaded module map objects.
+  std::vector<std::unique_ptr<clang::ModuleMap>> ModuleMaps;
+};
+
+} // end namespace Modularize
+
+#endif // MODULARIZEUTILITIES_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/modularize/ModuleAssistant.cpp b/src/third_party/llvm-project/clang-tools-extra/modularize/ModuleAssistant.cpp
new file mode 100644
index 0000000..7f1cb15
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/modularize/ModuleAssistant.cpp
@@ -0,0 +1,316 @@
+//===--- ModuleAssistant.cpp - Module map generation manager -*- C++ -*---===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// This file defines the module generation entry point function,
+// createModuleMap, a Module class for representing a module,
+// and various implementation functions for doing the underlying
+// work, described below.
+//
+// The "Module" class represents a module, with members for storing the module
+// name, associated header file names, and sub-modules, and an "output"
+// function that recursively writes the module definitions.
+//
+// The "createModuleMap" function implements the top-level logic of the
+// assistant mode.  It calls a loadModuleDescriptions function to walk
+// the header list passed to it and creates a tree of Module objects
+// representing the module hierarchy, represented by a "Module" object,
+// the "RootModule".  This root module may or may not represent an actual
+// module in the module map, depending on the "--root-module" option passed
+// to modularize.  It then calls a writeModuleMap function to set up the
+// module map file output and walk the module tree, outputting the module
+// map file using a stream obtained and managed by an
+// llvm::ToolOutputFile object.
+//
+//===---------------------------------------------------------------------===//
+
+#include "Modularize.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include <vector>
+
+// Local definitions:
+
+namespace {
+
+// Internal class definitions:
+
+// Represents a module.
+class Module {
+public:
+  Module(llvm::StringRef Name, bool Problem);
+  Module();
+  ~Module();
+  bool output(llvm::raw_fd_ostream &OS, int Indent);
+  Module *findSubModule(llvm::StringRef SubName);
+
+public:
+  std::string Name;
+  std::vector<std::string> HeaderFileNames;
+  std::vector<Module *> SubModules;
+  bool IsProblem;
+};
+
+} // end anonymous namespace.
+
+// Module functions:
+
+// Constructors.
+Module::Module(llvm::StringRef Name, bool Problem)
+  : Name(Name), IsProblem(Problem) {}
+Module::Module() : IsProblem(false) {}
+
+// Destructor.
+Module::~Module() {
+  // Free submodules.
+  while (!SubModules.empty()) {
+    Module *last = SubModules.back();
+    SubModules.pop_back();
+    delete last;
+  }
+}
+
+// Write a module hierarchy to the given output stream.
+bool Module::output(llvm::raw_fd_ostream &OS, int Indent) {
+  // If this is not the nameless root module, start a module definition.
+  if (Name.size() != 0) {
+    OS.indent(Indent);
+    OS << "module " << Name << " {\n";
+    Indent += 2;
+  }
+
+  // Output submodules.
+  for (auto I = SubModules.begin(), E = SubModules.end(); I != E; ++I) {
+    if (!(*I)->output(OS, Indent))
+      return false;
+  }
+
+  // Output header files.
+  for (auto I = HeaderFileNames.begin(), E = HeaderFileNames.end(); I != E;
+       ++I) {
+    OS.indent(Indent);
+    if (IsProblem || strstr((*I).c_str(), ".inl"))
+      OS << "exclude header \"" << *I << "\"\n";
+    else
+      OS << "header \"" << *I << "\"\n";
+  }
+
+  // If this module has header files, output export directive.
+  if (HeaderFileNames.size() != 0) {
+    OS.indent(Indent);
+    OS << "export *\n";
+  }
+
+  // If this is not the nameless root module, close the module definition.
+  if (Name.size() != 0) {
+    Indent -= 2;
+    OS.indent(Indent);
+    OS << "}\n";
+  }
+
+  return true;
+}
+
+// Lookup a sub-module.
+Module *Module::findSubModule(llvm::StringRef SubName) {
+  for (auto I = SubModules.begin(), E = SubModules.end(); I != E; ++I) {
+    if ((*I)->Name == SubName)
+      return *I;
+  }
+  return nullptr;
+}
+
+// Implementation functions:
+
+// Reserved keywords in module.modulemap syntax.
+// Keep in sync with keywords in module map parser in Lex/ModuleMap.cpp,
+// such as in ModuleMapParser::consumeToken().
+static const char *const ReservedNames[] = {
+  "config_macros", "export",   "module", "conflict", "framework",
+  "requires",      "exclude",  "header", "private",  "explicit",
+  "link",          "umbrella", "extern", "use",      nullptr // Flag end.
+};
+
+// Convert module name to a non-keyword.
+// Prepends a '_' to the name if and only if the name is a keyword.
+static std::string
+ensureNoCollisionWithReservedName(llvm::StringRef MightBeReservedName) {
+  std::string SafeName = MightBeReservedName;
+  for (int Index = 0; ReservedNames[Index] != nullptr; ++Index) {
+    if (MightBeReservedName == ReservedNames[Index]) {
+      SafeName.insert(0, "_");
+      break;
+    }
+  }
+  return SafeName;
+}
+
+// Convert module name to a non-keyword.
+// Prepends a '_' to the name if and only if the name is a keyword.
+static std::string
+ensureVaidModuleName(llvm::StringRef MightBeInvalidName) {
+  std::string SafeName = MightBeInvalidName;
+  std::replace(SafeName.begin(), SafeName.end(), '-', '_');
+  std::replace(SafeName.begin(), SafeName.end(), '.', '_');
+  if (isdigit(SafeName[0]))
+    SafeName = "_" + SafeName;
+  return SafeName;
+}
+
+// Add one module, given a header file path.
+static bool addModuleDescription(Module *RootModule,
+                                 llvm::StringRef HeaderFilePath,
+                                 llvm::StringRef HeaderPrefix,
+                                 DependencyMap &Dependencies,
+                                 bool IsProblemFile) {
+  Module *CurrentModule = RootModule;
+  DependentsVector &FileDependents = Dependencies[HeaderFilePath];
+  std::string FilePath;
+  // Strip prefix.
+  // HeaderFilePath should be compared to natively-canonicalized Prefix.
+  llvm::SmallString<256> NativePath, NativePrefix;
+  llvm::sys::path::native(HeaderFilePath, NativePath);
+  llvm::sys::path::native(HeaderPrefix, NativePrefix);
+  if (NativePath.startswith(NativePrefix))
+    FilePath = NativePath.substr(NativePrefix.size() + 1);
+  else
+    FilePath = HeaderFilePath;
+  int Count = FileDependents.size();
+  // Headers that go into modules must not depend on other files being
+  // included first.  If there are any dependents, warn user and omit.
+  if (Count != 0) {
+    llvm::errs() << "warning: " << FilePath
+                 << " depends on other headers being included first,"
+                    " meaning the module.modulemap won't compile."
+                    "  This header will be omitted from the module map.\n";
+    return true;
+  }
+  // Make canonical.
+  std::replace(FilePath.begin(), FilePath.end(), '\\', '/');
+  // Insert module into tree, using subdirectories as submodules.
+  for (llvm::sys::path::const_iterator I = llvm::sys::path::begin(FilePath),
+                                       E = llvm::sys::path::end(FilePath);
+       I != E; ++I) {
+    if ((*I)[0] == '.')
+      continue;
+    std::string Stem = llvm::sys::path::stem(*I);
+    Stem = ensureNoCollisionWithReservedName(Stem);
+    Stem = ensureVaidModuleName(Stem);
+    Module *SubModule = CurrentModule->findSubModule(Stem);
+    if (!SubModule) {
+      SubModule = new Module(Stem, IsProblemFile);
+      CurrentModule->SubModules.push_back(SubModule);
+    }
+    CurrentModule = SubModule;
+  }
+  // Add header file name to headers.
+  CurrentModule->HeaderFileNames.push_back(FilePath);
+  return true;
+}
+
+// Create the internal module tree representation.
+static Module *loadModuleDescriptions(
+    llvm::StringRef RootModuleName, llvm::ArrayRef<std::string> HeaderFileNames,
+    llvm::ArrayRef<std::string> ProblemFileNames,
+    DependencyMap &Dependencies, llvm::StringRef HeaderPrefix) {
+
+  // Create root module.
+  auto *RootModule = new Module(RootModuleName, false);
+
+  llvm::SmallString<256> CurrentDirectory;
+  llvm::sys::fs::current_path(CurrentDirectory);
+
+  // If no header prefix, use current directory.
+  if (HeaderPrefix.size() == 0)
+    HeaderPrefix = CurrentDirectory;
+
+  // Walk the header file names and output the module map.
+  for (llvm::ArrayRef<std::string>::iterator I = HeaderFileNames.begin(),
+                                             E = HeaderFileNames.end();
+       I != E; ++I) {
+    std::string Header(*I);
+    bool IsProblemFile = false;
+    for (auto &ProblemFile : ProblemFileNames) {
+      if (ProblemFile == Header) {
+        IsProblemFile = true;
+        break;
+      }
+    }
+    // Add as a module.
+    if (!addModuleDescription(RootModule, Header, HeaderPrefix, Dependencies, IsProblemFile))
+      return nullptr;
+  }
+
+  return RootModule;
+}
+
+// Kick off the writing of the module map.
+static bool writeModuleMap(llvm::StringRef ModuleMapPath,
+                           llvm::StringRef HeaderPrefix, Module *RootModule) {
+  llvm::SmallString<256> HeaderDirectory(ModuleMapPath);
+  llvm::sys::path::remove_filename(HeaderDirectory);
+  llvm::SmallString<256> FilePath;
+
+  // Get the module map file path to be used.
+  if ((HeaderDirectory.size() == 0) && (HeaderPrefix.size() != 0)) {
+    FilePath = HeaderPrefix;
+    // Prepend header file name prefix if it's not absolute.
+    llvm::sys::path::append(FilePath, ModuleMapPath);
+    llvm::sys::path::native(FilePath);
+  } else {
+    FilePath = ModuleMapPath;
+    llvm::sys::path::native(FilePath);
+  }
+
+  // Set up module map output file.
+  std::error_code EC;
+  llvm::ToolOutputFile Out(FilePath, EC, llvm::sys::fs::F_Text);
+  if (EC) {
+    llvm::errs() << Argv0 << ": error opening " << FilePath << ":"
+                 << EC.message() << "\n";
+    return false;
+  }
+
+  // Get output stream from tool output buffer/manager.
+  llvm::raw_fd_ostream &OS = Out.os();
+
+  // Output file comment.
+  OS << "// " << ModuleMapPath << "\n";
+  OS << "// Generated by: " << CommandLine << "\n\n";
+
+  // Write module hierarchy from internal representation.
+  if (!RootModule->output(OS, 0))
+    return false;
+
+  // Tell ToolOutputFile that we want to keep the file.
+  Out.keep();
+
+  return true;
+}
+
+// Global functions:
+
+// Module map generation entry point.
+bool createModuleMap(llvm::StringRef ModuleMapPath,
+                     llvm::ArrayRef<std::string> HeaderFileNames,
+                     llvm::ArrayRef<std::string> ProblemFileNames,
+                     DependencyMap &Dependencies, llvm::StringRef HeaderPrefix,
+                     llvm::StringRef RootModuleName) {
+  // Load internal representation of modules.
+  std::unique_ptr<Module> RootModule(
+    loadModuleDescriptions(
+      RootModuleName, HeaderFileNames, ProblemFileNames, Dependencies,
+      HeaderPrefix));
+  if (!RootModule.get())
+    return false;
+
+  // Write module map file.
+  return writeModuleMap(ModuleMapPath, HeaderPrefix, RootModule.get());
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/modularize/PreprocessorTracker.cpp b/src/third_party/llvm-project/clang-tools-extra/modularize/PreprocessorTracker.cpp
new file mode 100644
index 0000000..6cb34c7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/modularize/PreprocessorTracker.cpp
@@ -0,0 +1,1394 @@
+//===--- PreprocessorTracker.cpp - Preprocessor tracking -*- C++ -*------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--------------------------------------------------------------------===//
+//
+// The Basic Idea (Macro and Conditional Checking)
+//
+// Basically we install a PPCallbacks-derived object to track preprocessor
+// activity, namely when a header file is entered/exited, when a macro
+// is expanded, when "defined" is used, and when #if, #elif, #ifdef,
+// and #ifndef are used.  We save the state of macro and "defined"
+// expressions in a map, keyed on a name/file/line/column quadruple.
+// The map entries store the different states (values) that a macro expansion,
+// "defined" expression, or condition expression has in the course of
+// processing for the one location in the one header containing it,
+// plus a list of the nested include stacks for the states.  When a macro
+// or "defined" expression evaluates to the same value, which is the
+// desired case, only one state is stored.  Similarly, for conditional
+// directives, we save the condition expression states in a separate map.
+//
+// This information is collected as modularize compiles all the headers
+// given to it to process.  After all the compilations are performed,
+// a check is performed for any entries in the maps that contain more
+// than one different state, and for these an output message is generated.
+//
+// For example:
+//
+//   (...)/SubHeader.h:11:5:
+//   #if SYMBOL == 1
+//       ^
+//   error: Macro instance 'SYMBOL' has different values in this header,
+//          depending on how it was included.
+//     'SYMBOL' expanded to: '1' with respect to these inclusion paths:
+//       (...)/Header1.h
+//         (...)/SubHeader.h
+//   (...)/SubHeader.h:3:9:
+//   #define SYMBOL 1
+//             ^
+//   Macro defined here.
+//     'SYMBOL' expanded to: '2' with respect to these inclusion paths:
+//       (...)/Header2.h
+//           (...)/SubHeader.h
+//   (...)/SubHeader.h:7:9:
+//   #define SYMBOL 2
+//             ^
+//   Macro defined here.
+//
+// The Basic Idea ('Extern "C/C++" {}' Or 'namespace {}') With Nested
+// '#include' Checking)
+//
+// To check for '#include' directives nested inside 'Extern "C/C++" {}'
+// or 'namespace {}' blocks, we keep track of the '#include' directives
+// while running the preprocessor, and later during a walk of the AST
+// we call a function to check for any '#include' directies inside
+// an 'Extern "C/C++" {}' or 'namespace {}' block, given its source
+// range.
+//
+// Design and Implementation Details (Macro and Conditional Checking)
+//
+// A PreprocessorTrackerImpl class implements the PreprocessorTracker
+// interface. It uses a PreprocessorCallbacks class derived from PPCallbacks
+// to track preprocessor activity, namely entering/exiting a header, macro
+// expansions, use of "defined" expressions, and #if, #elif, #ifdef, and
+// #ifndef conditional directives. PreprocessorTrackerImpl stores a map
+// of MacroExpansionTracker objects keyed on a name/file/line/column
+// value represented by a light-weight PPItemKey value object. This
+// is the key top-level data structure tracking the values of macro
+// expansion instances.  Similarly, it stores a map of ConditionalTracker
+// objects with the same kind of key, for tracking preprocessor conditional
+// directives.
+//
+// The MacroExpansionTracker object represents one macro reference or use
+// of a "defined" expression in a header file. It stores a handle to a
+// string representing the unexpanded macro instance, a handle to a string
+// representing the unpreprocessed source line containing the unexpanded
+// macro instance, and a vector of one or more MacroExpansionInstance
+// objects.
+//
+// The MacroExpansionInstance object represents one or more expansions
+// of a macro reference, for the case where the macro expands to the same
+// value. MacroExpansionInstance stores a handle to a string representing
+// the expanded macro value, a PPItemKey representing the file/line/column
+// where the macro was defined, a handle to a string representing the source
+// line containing the macro definition, and a vector of InclusionPathHandle
+// values that represents the hierarchies of include files for each case
+// where the particular header containing the macro reference was referenced
+// or included.
+
+// In the normal case where a macro instance always expands to the same
+// value, the MacroExpansionTracker object will only contain one
+// MacroExpansionInstance representing all the macro expansion instances.
+// If a case was encountered where a macro instance expands to a value
+// that is different from that seen before, or the macro was defined in
+// a different place, a new MacroExpansionInstance object representing
+// that case will be added to the vector in MacroExpansionTracker. If a
+// macro instance expands to a value already seen before, the
+// InclusionPathHandle representing that case's include file hierarchy
+// will be added to the existing MacroExpansionInstance object.
+
+// For checking conditional directives, the ConditionalTracker class
+// functions similarly to MacroExpansionTracker, but tracks an #if,
+// #elif, #ifdef, or #ifndef directive in a header file.  It stores
+// a vector of one or two ConditionalExpansionInstance objects,
+// representing the cases where the conditional expression evaluates
+// to true or false.  This latter object stores the evaluated value
+// of the condition expression (a bool) and a vector of
+// InclusionPathHandles.
+//
+// To reduce the instances of string and object copying, the
+// PreprocessorTrackerImpl class uses a StringPool to save all stored
+// strings, and defines a StringHandle type to abstract the references
+// to the strings.
+//
+// PreprocessorTrackerImpl also maintains a list representing the unique
+// headers, which is just a vector of StringHandle's for the header file
+// paths. A HeaderHandle abstracts a reference to a header, and is simply
+// the index of the stored header file path.
+//
+// A HeaderInclusionPath class abstracts a unique hierarchy of header file
+// inclusions. It simply stores a vector of HeaderHandles ordered from the
+// top-most header (the one from the header list passed to modularize) down
+// to the header containing the macro reference. PreprocessorTrackerImpl
+// stores a vector of these objects. An InclusionPathHandle typedef
+// abstracts a reference to one of the HeaderInclusionPath objects, and is
+// simply the index of the stored HeaderInclusionPath object. The
+// MacroExpansionInstance object stores a vector of these handles so that
+// the reporting function can display the include hierarchies for the macro
+// expansion instances represented by that object, to help the user
+// understand how the header was included. (A future enhancement might
+// be to associate a line number for the #include directives, but I
+// think not doing so is good enough for the present.)
+//
+// A key reason for using these opaque handles was to try to keep all the
+// internal objects light-weight value objects, in order to reduce string
+// and object copying overhead, and to abstract this implementation detail.
+//
+// The key data structures are built up while modularize runs the headers
+// through the compilation. A PreprocessorTracker instance is created and
+// passed down to the AST action and consumer objects in modularize. For
+// each new compilation instance, the consumer calls the
+// PreprocessorTracker's handleNewPreprocessorEntry function, which sets
+// up a PreprocessorCallbacks object for the preprocessor. At the end of
+// the compilation instance, the PreprocessorTracker's
+// handleNewPreprocessorExit function handles cleaning up with respect
+// to the preprocessing instance.
+//
+// The PreprocessorCallbacks object uses an overidden FileChanged callback
+// to determine when a header is entered and exited (including exiting the
+// header during #include directives). It calls PreprocessorTracker's
+// handleHeaderEntry and handleHeaderExit functions upon entering and
+// exiting a header. These functions manage a stack of header handles
+// representing by a vector, pushing and popping header handles as headers
+// are entered and exited. When a HeaderInclusionPath object is created,
+// it simply copies this stack.
+//
+// The PreprocessorCallbacks object uses an overridden MacroExpands callback
+// to track when a macro expansion is performed. It calls a couple of helper
+// functions to get the unexpanded and expanded macro values as strings, but
+// then calls PreprocessorTrackerImpl's addMacroExpansionInstance function to
+// do the rest of the work. The getMacroExpandedString function uses the
+// preprocessor's getSpelling to convert tokens to strings using the
+// information passed to the MacroExpands callback, and simply concatenates
+// them. It makes recursive calls to itself to handle nested macro
+// definitions, and also handles function-style macros.
+//
+// PreprocessorTrackerImpl's addMacroExpansionInstance function looks for
+// an existing MacroExpansionTracker entry in its map of MacroExampleTracker
+// objects. If none exists, it adds one with one MacroExpansionInstance and
+// returns. If a MacroExpansionTracker object already exists, it looks for
+// an existing MacroExpansionInstance object stored in the
+// MacroExpansionTracker object, one that matches the macro expanded value
+// and the macro definition location. If a matching MacroExpansionInstance
+// object is found, it just adds the current HeaderInclusionPath object to
+// it. If not found, it creates and stores a new MacroExpantionInstance
+// object. The addMacroExpansionInstance function calls a couple of helper
+// functions to get the pre-formatted location and source line strings for
+// the macro reference and the macro definition stored as string handles.
+// These helper functions use the current source manager from the
+// preprocessor. This is done in advance at this point in time because the
+// source manager doesn't exist at the time of the reporting.
+//
+// For conditional check, the PreprocessorCallbacks class overrides the
+// PPCallbacks handlers for #if, #elif, #ifdef, and #ifndef.  These handlers
+// call the addConditionalExpansionInstance method of
+// PreprocessorTrackerImpl.  The process is similar to that of macros, but
+// with some different data and error messages.  A lookup is performed for
+// the conditional, and if a ConditionalTracker object doesn't yet exist for
+// the conditional, a new one is added, including adding a
+// ConditionalExpansionInstance object to it to represent the condition
+// expression state.  If a ConditionalTracker for the conditional does
+// exist, a lookup is made for a ConditionalExpansionInstance object
+// matching the condition expression state.  If one exists, a
+// HeaderInclusionPath is added to it.  Otherwise a new
+// ConditionalExpansionInstance  entry is made.  If a ConditionalTracker
+// has two ConditionalExpansionInstance objects, it means there was a
+// conflict, meaning the conditional expression evaluated differently in
+// one or more cases.
+//
+// After modularize has performed all the compilations, it enters a phase
+// of error reporting. This new feature adds to this reporting phase calls
+// to the PreprocessorTracker's reportInconsistentMacros and
+// reportInconsistentConditionals functions. These functions walk the maps
+// of MacroExpansionTracker's and ConditionalTracker's respectively. If
+// any of these objects have more than one MacroExpansionInstance or
+// ConditionalExpansionInstance objects, it formats and outputs an error
+// message like the example shown previously, using the stored data.
+//
+// A potential issue is that there is some overlap between the #if/#elif
+// conditional and macro reporting.  I could disable the #if and #elif,
+// leaving just the #ifdef and #ifndef, since these don't overlap.  Or,
+// to make clearer the separate reporting phases, I could add an output
+// message marking the phases.
+//
+// Design and Implementation Details ('Extern "C/C++" {}' Or
+// 'namespace {}') With Nested '#include' Checking)
+//
+// We override the InclusionDirective in PPCallbacks to record information
+// about each '#include' directive encountered during preprocessing.
+// We co-opt the PPItemKey class to store the information about each
+// '#include' directive, including the source file name containing the
+// directive, the name of the file being included, and the source line
+// and column of the directive.  We store these object in a vector,
+// after first check to see if an entry already exists.
+//
+// Later, while the AST is being walked for other checks, we provide
+// visit handlers for 'extern "C/C++" {}' and 'namespace (name) {}'
+// blocks, checking to see if any '#include' directives occurred
+// within the blocks, reporting errors if any found.
+//
+// Future Directions
+//
+// We probably should add options to disable any of the checks, in case
+// there is some problem with them, or the messages get too verbose.
+//
+// With the map of all the macro and conditional expansion instances,
+// it might be possible to add to the existing modularize error messages
+// (the second part referring to definitions being different), attempting
+// to tie them to the last macro conflict encountered with respect to the
+// order of the code encountered.
+//
+//===--------------------------------------------------------------------===//
+
+#include "clang/Lex/LexDiagnostic.h"
+#include "PreprocessorTracker.h"
+#include "clang/Lex/MacroArgs.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/Support/StringPool.h"
+#include "llvm/Support/raw_ostream.h"
+#include "ModularizeUtilities.h"
+
+namespace Modularize {
+
+// Some handle types
+typedef llvm::PooledStringPtr StringHandle;
+
+typedef int HeaderHandle;
+const HeaderHandle HeaderHandleInvalid = -1;
+
+typedef int InclusionPathHandle;
+const InclusionPathHandle InclusionPathHandleInvalid = -1;
+
+// Some utility functions.
+
+// Get a "file:line:column" source location string.
+static std::string getSourceLocationString(clang::Preprocessor &PP,
+                                           clang::SourceLocation Loc) {
+  if (Loc.isInvalid())
+    return std::string("(none)");
+  else
+    return Loc.printToString(PP.getSourceManager());
+}
+
+// Get just the file name from a source location.
+static std::string getSourceLocationFile(clang::Preprocessor &PP,
+                                         clang::SourceLocation Loc) {
+  std::string Source(getSourceLocationString(PP, Loc));
+  size_t Offset = Source.find(':', 2);
+  if (Offset == std::string::npos)
+    return Source;
+  return Source.substr(0, Offset);
+}
+
+// Get just the line and column from a source location.
+static void getSourceLocationLineAndColumn(clang::Preprocessor &PP,
+                                           clang::SourceLocation Loc, int &Line,
+                                           int &Column) {
+  clang::PresumedLoc PLoc = PP.getSourceManager().getPresumedLoc(Loc);
+  if (PLoc.isInvalid()) {
+    Line = 0;
+    Column = 0;
+    return;
+  }
+  Line = PLoc.getLine();
+  Column = PLoc.getColumn();
+}
+
+// Retrieve source snippet from file image.
+static std::string getSourceString(clang::Preprocessor &PP,
+                                   clang::SourceRange Range) {
+  clang::SourceLocation BeginLoc = Range.getBegin();
+  clang::SourceLocation EndLoc = Range.getEnd();
+  const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc);
+  const char *EndPtr = PP.getSourceManager().getCharacterData(EndLoc);
+  size_t Length = EndPtr - BeginPtr;
+  return llvm::StringRef(BeginPtr, Length).trim().str();
+}
+
+// Retrieve source line from file image given a location.
+static std::string getSourceLine(clang::Preprocessor &PP,
+                                 clang::SourceLocation Loc) {
+  const llvm::MemoryBuffer *MemBuffer =
+      PP.getSourceManager().getBuffer(PP.getSourceManager().getFileID(Loc));
+  const char *Buffer = MemBuffer->getBufferStart();
+  const char *BufferEnd = MemBuffer->getBufferEnd();
+  const char *BeginPtr = PP.getSourceManager().getCharacterData(Loc);
+  const char *EndPtr = BeginPtr;
+  while (BeginPtr > Buffer) {
+    if (*BeginPtr == '\n') {
+      BeginPtr++;
+      break;
+    }
+    BeginPtr--;
+  }
+  while (EndPtr < BufferEnd) {
+    if (*EndPtr == '\n') {
+      break;
+    }
+    EndPtr++;
+  }
+  size_t Length = EndPtr - BeginPtr;
+  return llvm::StringRef(BeginPtr, Length).str();
+}
+
+// Retrieve source line from file image given a file ID and line number.
+static std::string getSourceLine(clang::Preprocessor &PP, clang::FileID FileID,
+                                 int Line) {
+  const llvm::MemoryBuffer *MemBuffer = PP.getSourceManager().getBuffer(FileID);
+  const char *Buffer = MemBuffer->getBufferStart();
+  const char *BufferEnd = MemBuffer->getBufferEnd();
+  const char *BeginPtr = Buffer;
+  const char *EndPtr = BufferEnd;
+  int LineCounter = 1;
+  if (Line == 1)
+    BeginPtr = Buffer;
+  else {
+    while (Buffer < BufferEnd) {
+      if (*Buffer == '\n') {
+        if (++LineCounter == Line) {
+          BeginPtr = Buffer++ + 1;
+          break;
+        }
+      }
+      Buffer++;
+    }
+  }
+  while (Buffer < BufferEnd) {
+    if (*Buffer == '\n') {
+      EndPtr = Buffer;
+      break;
+    }
+    Buffer++;
+  }
+  size_t Length = EndPtr - BeginPtr;
+  return llvm::StringRef(BeginPtr, Length).str();
+}
+
+// Get the string for the Unexpanded macro instance.
+// The soureRange is expected to end at the last token
+// for the macro instance, which in the case of a function-style
+// macro will be a ')', but for an object-style macro, it
+// will be the macro name itself.
+static std::string getMacroUnexpandedString(clang::SourceRange Range,
+                                            clang::Preprocessor &PP,
+                                            llvm::StringRef MacroName,
+                                            const clang::MacroInfo *MI) {
+  clang::SourceLocation BeginLoc(Range.getBegin());
+  const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc);
+  size_t Length;
+  std::string Unexpanded;
+  if (MI->isFunctionLike()) {
+    clang::SourceLocation EndLoc(Range.getEnd());
+    const char *EndPtr = PP.getSourceManager().getCharacterData(EndLoc) + 1;
+    Length = (EndPtr - BeginPtr) + 1; // +1 is ')' width.
+  } else
+    Length = MacroName.size();
+  return llvm::StringRef(BeginPtr, Length).trim().str();
+}
+
+// Get the expansion for a macro instance, given the information
+// provided by PPCallbacks.
+// FIXME: This doesn't support function-style macro instances
+// passed as arguments to another function-style macro. However,
+// since it still expands the inner arguments, it still
+// allows modularize to effectively work with respect to macro
+// consistency checking, although it displays the incorrect
+// expansion in error messages.
+static std::string getMacroExpandedString(clang::Preprocessor &PP,
+                                          llvm::StringRef MacroName,
+                                          const clang::MacroInfo *MI,
+                                          const clang::MacroArgs *Args) {
+  std::string Expanded;
+  // Walk over the macro Tokens.
+  for (const auto &T : MI->tokens()) {
+    clang::IdentifierInfo *II = T.getIdentifierInfo();
+    int ArgNo = (II && Args ? MI->getParameterNum(II) : -1);
+    if (ArgNo == -1) {
+      // This isn't an argument, just add it.
+      if (II == nullptr)
+        Expanded += PP.getSpelling(T); // Not an identifier.
+      else {
+        // Token is for an identifier.
+        std::string Name = II->getName().str();
+        // Check for nexted macro references.
+        clang::MacroInfo *MacroInfo = PP.getMacroInfo(II);
+        if (MacroInfo && (Name != MacroName))
+          Expanded += getMacroExpandedString(PP, Name, MacroInfo, nullptr);
+        else
+          Expanded += Name;
+      }
+      continue;
+    }
+    // We get here if it's a function-style macro with arguments.
+    const clang::Token *ResultArgToks;
+    const clang::Token *ArgTok = Args->getUnexpArgument(ArgNo);
+    if (Args->ArgNeedsPreexpansion(ArgTok, PP))
+      ResultArgToks = &(const_cast<clang::MacroArgs *>(Args))
+          ->getPreExpArgument(ArgNo, PP)[0];
+    else
+      ResultArgToks = ArgTok; // Use non-preexpanded Tokens.
+    // If the arg token didn't expand into anything, ignore it.
+    if (ResultArgToks->is(clang::tok::eof))
+      continue;
+    unsigned NumToks = clang::MacroArgs::getArgLength(ResultArgToks);
+    // Append the resulting argument expansions.
+    for (unsigned ArgumentIndex = 0; ArgumentIndex < NumToks; ++ArgumentIndex) {
+      const clang::Token &AT = ResultArgToks[ArgumentIndex];
+      clang::IdentifierInfo *II = AT.getIdentifierInfo();
+      if (II == nullptr)
+        Expanded += PP.getSpelling(AT); // Not an identifier.
+      else {
+        // It's an identifier.  Check for further expansion.
+        std::string Name = II->getName().str();
+        clang::MacroInfo *MacroInfo = PP.getMacroInfo(II);
+        if (MacroInfo)
+          Expanded += getMacroExpandedString(PP, Name, MacroInfo, nullptr);
+        else
+          Expanded += Name;
+      }
+    }
+  }
+  return Expanded;
+}
+
+namespace {
+
+// ConditionValueKind strings.
+const char *
+ConditionValueKindStrings[] = {
+  "(not evaluated)", "false", "true"
+};
+
+bool operator<(const StringHandle &H1, const StringHandle &H2) {
+  const char *S1 = (H1 ? *H1 : "");
+  const char *S2 = (H2 ? *H2 : "");
+  int Diff = strcmp(S1, S2);
+  return Diff < 0;
+}
+bool operator>(const StringHandle &H1, const StringHandle &H2) {
+  const char *S1 = (H1 ? *H1 : "");
+  const char *S2 = (H2 ? *H2 : "");
+  int Diff = strcmp(S1, S2);
+  return Diff > 0;
+}
+
+// Preprocessor item key.
+//
+// This class represents a location in a source file, for use
+// as a key representing a unique name/file/line/column quadruplet,
+// which in this case is used to identify a macro expansion instance,
+// but could be used for other things as well.
+// The file is a header file handle, the line is a line number,
+// and the column is a column number.
+class PPItemKey {
+public:
+  PPItemKey(clang::Preprocessor &PP, StringHandle Name, HeaderHandle File,
+            clang::SourceLocation Loc)
+      : Name(Name), File(File) {
+    getSourceLocationLineAndColumn(PP, Loc, Line, Column);
+  }
+  PPItemKey(StringHandle Name, HeaderHandle File, int Line, int Column)
+      : Name(Name), File(File), Line(Line), Column(Column) {}
+  PPItemKey(const PPItemKey &Other)
+      : Name(Other.Name), File(Other.File), Line(Other.Line),
+        Column(Other.Column) {}
+  PPItemKey() : File(HeaderHandleInvalid), Line(0), Column(0) {}
+  bool operator==(const PPItemKey &Other) const {
+    if (Name != Other.Name)
+      return false;
+    if (File != Other.File)
+      return false;
+    if (Line != Other.Line)
+      return false;
+    return Column == Other.Column;
+  }
+  bool operator<(const PPItemKey &Other) const {
+    if (Name < Other.Name)
+      return true;
+    else if (Name > Other.Name)
+      return false;
+    if (File < Other.File)
+      return true;
+    else if (File > Other.File)
+      return false;
+    if (Line < Other.Line)
+      return true;
+    else if (Line > Other.Line)
+      return false;
+    return Column < Other.Column;
+  }
+  StringHandle Name;
+  HeaderHandle File;
+  int Line;
+  int Column;
+};
+
+// Header inclusion path.
+class HeaderInclusionPath {
+public:
+  HeaderInclusionPath(std::vector<HeaderHandle> HeaderInclusionPath)
+      : Path(HeaderInclusionPath) {}
+  HeaderInclusionPath(const HeaderInclusionPath &Other) : Path(Other.Path) {}
+  HeaderInclusionPath() {}
+  std::vector<HeaderHandle> Path;
+};
+
+// Macro expansion instance.
+//
+// This class represents an instance of a macro expansion with a
+// unique value.  It also stores the unique header inclusion paths
+// for use in telling the user the nested include path to the header.
+class MacroExpansionInstance {
+public:
+  MacroExpansionInstance(StringHandle MacroExpanded,
+                         PPItemKey &DefinitionLocation,
+                         StringHandle DefinitionSourceLine,
+                         InclusionPathHandle H)
+      : MacroExpanded(MacroExpanded), DefinitionLocation(DefinitionLocation),
+        DefinitionSourceLine(DefinitionSourceLine) {
+    InclusionPathHandles.push_back(H);
+  }
+  MacroExpansionInstance() {}
+
+  // Check for the presence of a header inclusion path handle entry.
+  // Return false if not found.
+  bool haveInclusionPathHandle(InclusionPathHandle H) {
+    for (auto I = InclusionPathHandles.begin(), E = InclusionPathHandles.end();
+         I != E; ++I) {
+      if (*I == H)
+        return true;
+    }
+    return InclusionPathHandleInvalid;
+  }
+  // Add a new header inclusion path entry, if not already present.
+  void addInclusionPathHandle(InclusionPathHandle H) {
+    if (!haveInclusionPathHandle(H))
+      InclusionPathHandles.push_back(H);
+  }
+
+  // A string representing the macro instance after preprocessing.
+  StringHandle MacroExpanded;
+  // A file/line/column triplet representing the macro definition location.
+  PPItemKey DefinitionLocation;
+  // A place to save the macro definition line string.
+  StringHandle DefinitionSourceLine;
+  // The header inclusion path handles for all the instances.
+  std::vector<InclusionPathHandle> InclusionPathHandles;
+};
+
+// Macro expansion instance tracker.
+//
+// This class represents one macro expansion, keyed by a PPItemKey.
+// It stores a string representing the macro reference in the source,
+// and a list of ConditionalExpansionInstances objects representing
+// the unique values the condition expands to in instances of the header.
+class MacroExpansionTracker {
+public:
+  MacroExpansionTracker(StringHandle MacroUnexpanded,
+                        StringHandle MacroExpanded,
+                        StringHandle InstanceSourceLine,
+                        PPItemKey &DefinitionLocation,
+                        StringHandle DefinitionSourceLine,
+                        InclusionPathHandle InclusionPathHandle)
+      : MacroUnexpanded(MacroUnexpanded),
+        InstanceSourceLine(InstanceSourceLine) {
+    addMacroExpansionInstance(MacroExpanded, DefinitionLocation,
+                              DefinitionSourceLine, InclusionPathHandle);
+  }
+  MacroExpansionTracker() {}
+
+  // Find a matching macro expansion instance.
+  MacroExpansionInstance *
+  findMacroExpansionInstance(StringHandle MacroExpanded,
+                             PPItemKey &DefinitionLocation) {
+    for (auto I = MacroExpansionInstances.begin(),
+              E = MacroExpansionInstances.end();
+         I != E; ++I) {
+      if ((I->MacroExpanded == MacroExpanded) &&
+          (I->DefinitionLocation == DefinitionLocation)) {
+        return &*I; // Found.
+      }
+    }
+    return nullptr; // Not found.
+  }
+
+  // Add a macro expansion instance.
+  void addMacroExpansionInstance(StringHandle MacroExpanded,
+                                 PPItemKey &DefinitionLocation,
+                                 StringHandle DefinitionSourceLine,
+                                 InclusionPathHandle InclusionPathHandle) {
+    MacroExpansionInstances.push_back(
+        MacroExpansionInstance(MacroExpanded, DefinitionLocation,
+                               DefinitionSourceLine, InclusionPathHandle));
+  }
+
+  // Return true if there is a mismatch.
+  bool hasMismatch() { return MacroExpansionInstances.size() > 1; }
+
+  // A string representing the macro instance without expansion.
+  StringHandle MacroUnexpanded;
+  // A place to save the macro instance source line string.
+  StringHandle InstanceSourceLine;
+  // The macro expansion instances.
+  // If all instances of the macro expansion expand to the same value,
+  // This vector will only have one instance.
+  std::vector<MacroExpansionInstance> MacroExpansionInstances;
+};
+
+// Conditional expansion instance.
+//
+// This class represents an instance of a condition exoression result
+// with a unique value.  It also stores the unique header inclusion paths
+// for use in telling the user the nested include path to the header.
+class ConditionalExpansionInstance {
+public:
+  ConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue, InclusionPathHandle H)
+      : ConditionValue(ConditionValue) {
+    InclusionPathHandles.push_back(H);
+  }
+  ConditionalExpansionInstance() {}
+
+  // Check for the presence of a header inclusion path handle entry.
+  // Return false if not found.
+  bool haveInclusionPathHandle(InclusionPathHandle H) {
+    for (auto I = InclusionPathHandles.begin(), E = InclusionPathHandles.end();
+         I != E; ++I) {
+      if (*I == H)
+        return true;
+    }
+    return InclusionPathHandleInvalid;
+  }
+  // Add a new header inclusion path entry, if not already present.
+  void addInclusionPathHandle(InclusionPathHandle H) {
+    if (!haveInclusionPathHandle(H))
+      InclusionPathHandles.push_back(H);
+  }
+
+  // A flag representing the evaluated condition value.
+  clang::PPCallbacks::ConditionValueKind ConditionValue;
+  // The header inclusion path handles for all the instances.
+  std::vector<InclusionPathHandle> InclusionPathHandles;
+};
+
+// Conditional directive instance tracker.
+//
+// This class represents one conditional directive, keyed by a PPItemKey.
+// It stores a string representing the macro reference in the source,
+// and a list of ConditionExpansionInstance objects representing
+// the unique value the condition expression expands to in instances of
+// the header.
+class ConditionalTracker {
+public:
+  ConditionalTracker(clang::tok::PPKeywordKind DirectiveKind,
+                     clang::PPCallbacks::ConditionValueKind ConditionValue,
+                     StringHandle ConditionUnexpanded,
+                     InclusionPathHandle InclusionPathHandle)
+      : DirectiveKind(DirectiveKind), ConditionUnexpanded(ConditionUnexpanded) {
+    addConditionalExpansionInstance(ConditionValue, InclusionPathHandle);
+  }
+  ConditionalTracker() {}
+
+  // Find a matching condition expansion instance.
+  ConditionalExpansionInstance *
+  findConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue) {
+    for (auto I = ConditionalExpansionInstances.begin(),
+              E = ConditionalExpansionInstances.end();
+         I != E; ++I) {
+      if (I->ConditionValue == ConditionValue) {
+        return &*I; // Found.
+      }
+    }
+    return nullptr; // Not found.
+  }
+
+  // Add a conditional expansion instance.
+  void
+  addConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue,
+                                  InclusionPathHandle InclusionPathHandle) {
+    ConditionalExpansionInstances.push_back(
+        ConditionalExpansionInstance(ConditionValue, InclusionPathHandle));
+  }
+
+  // Return true if there is a mismatch.
+  bool hasMismatch() { return ConditionalExpansionInstances.size() > 1; }
+
+  // The kind of directive.
+  clang::tok::PPKeywordKind DirectiveKind;
+  // A string representing the macro instance without expansion.
+  StringHandle ConditionUnexpanded;
+  // The condition expansion instances.
+  // If all instances of the conditional expression expand to the same value,
+  // This vector will only have one instance.
+  std::vector<ConditionalExpansionInstance> ConditionalExpansionInstances;
+};
+
+class PreprocessorTrackerImpl;
+
+// Preprocessor callbacks for modularize.
+//
+// This class derives from the Clang PPCallbacks class to track preprocessor
+// actions, such as changing files and handling preprocessor directives and
+// macro expansions.  It has to figure out when a new header file is entered
+// and left, as the provided handler is not particularly clear about it.
+class PreprocessorCallbacks : public clang::PPCallbacks {
+public:
+  PreprocessorCallbacks(PreprocessorTrackerImpl &ppTracker,
+                        clang::Preprocessor &PP, llvm::StringRef rootHeaderFile)
+      : PPTracker(ppTracker), PP(PP), RootHeaderFile(rootHeaderFile) {}
+  ~PreprocessorCallbacks() override {}
+
+  // Overridden handlers.
+  void InclusionDirective(clang::SourceLocation HashLoc,
+                          const clang::Token &IncludeTok,
+                          llvm::StringRef FileName, bool IsAngled,
+                          clang::CharSourceRange FilenameRange,
+                          const clang::FileEntry *File,
+                          llvm::StringRef SearchPath,
+                          llvm::StringRef RelativePath,
+                          const clang::Module *Imported,
+                          clang::SrcMgr::CharacteristicKind FileType) override;
+  void FileChanged(clang::SourceLocation Loc,
+                   clang::PPCallbacks::FileChangeReason Reason,
+                   clang::SrcMgr::CharacteristicKind FileType,
+                   clang::FileID PrevFID = clang::FileID()) override;
+  void MacroExpands(const clang::Token &MacroNameTok,
+                    const clang::MacroDefinition &MD, clang::SourceRange Range,
+                    const clang::MacroArgs *Args) override;
+  void Defined(const clang::Token &MacroNameTok,
+               const clang::MacroDefinition &MD,
+               clang::SourceRange Range) override;
+  void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
+          clang::PPCallbacks::ConditionValueKind ConditionResult) override;
+  void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
+            clang::PPCallbacks::ConditionValueKind ConditionResult,
+            clang::SourceLocation IfLoc) override;
+  void Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
+             const clang::MacroDefinition &MD) override;
+  void Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
+              const clang::MacroDefinition &MD) override;
+
+private:
+  PreprocessorTrackerImpl &PPTracker;
+  clang::Preprocessor &PP;
+  std::string RootHeaderFile;
+};
+
+// Preprocessor macro expansion item map types.
+typedef std::map<PPItemKey, MacroExpansionTracker> MacroExpansionMap;
+typedef std::map<PPItemKey, MacroExpansionTracker>::iterator
+MacroExpansionMapIter;
+
+// Preprocessor conditional expansion item map types.
+typedef std::map<PPItemKey, ConditionalTracker> ConditionalExpansionMap;
+typedef std::map<PPItemKey, ConditionalTracker>::iterator
+ConditionalExpansionMapIter;
+
+// Preprocessor tracker for modularize.
+//
+// This class stores information about all the headers processed in the
+// course of running modularize.
+class PreprocessorTrackerImpl : public PreprocessorTracker {
+public:
+  PreprocessorTrackerImpl(llvm::SmallVector<std::string, 32> &Headers,
+        bool DoBlockCheckHeaderListOnly)
+      : BlockCheckHeaderListOnly(DoBlockCheckHeaderListOnly),
+        CurrentInclusionPathHandle(InclusionPathHandleInvalid),
+        InNestedHeader(false) {
+    // Use canonical header path representation.
+    for (llvm::ArrayRef<std::string>::iterator I = Headers.begin(),
+      E = Headers.end();
+      I != E; ++I) {
+      HeaderList.push_back(getCanonicalPath(*I));
+    }
+  }
+
+  ~PreprocessorTrackerImpl() override {}
+
+  // Handle entering a preprocessing session.
+  void handlePreprocessorEntry(clang::Preprocessor &PP,
+                               llvm::StringRef rootHeaderFile) override {
+    HeadersInThisCompile.clear();
+    assert((HeaderStack.size() == 0) && "Header stack should be empty.");
+    pushHeaderHandle(addHeader(rootHeaderFile));
+    PP.addPPCallbacks(llvm::make_unique<PreprocessorCallbacks>(*this, PP,
+                                                               rootHeaderFile));
+  }
+  // Handle exiting a preprocessing session.
+  void handlePreprocessorExit() override { HeaderStack.clear(); }
+
+  // Handle include directive.
+  // This function is called every time an include directive is seen by the
+  // preprocessor, for the purpose of later checking for 'extern "" {}' or
+  // "namespace {}" blocks containing #include directives.
+  void handleIncludeDirective(llvm::StringRef DirectivePath, int DirectiveLine,
+                              int DirectiveColumn,
+                              llvm::StringRef TargetPath) override {
+    // If it's not a header in the header list, ignore it with respect to
+    // the check.
+    if (BlockCheckHeaderListOnly && !isHeaderListHeader(TargetPath))
+      return;
+    HeaderHandle CurrentHeaderHandle = findHeaderHandle(DirectivePath);
+    StringHandle IncludeHeaderHandle = addString(TargetPath);
+    for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(),
+                                                E = IncludeDirectives.end();
+         I != E; ++I) {
+      // If we already have an entry for this directive, return now.
+      if ((I->File == CurrentHeaderHandle) && (I->Line == DirectiveLine))
+        return;
+    }
+    PPItemKey IncludeDirectiveItem(IncludeHeaderHandle, CurrentHeaderHandle,
+                                   DirectiveLine, DirectiveColumn);
+    IncludeDirectives.push_back(IncludeDirectiveItem);
+  }
+
+  // Check for include directives within the given source line range.
+  // Report errors if any found.  Returns true if no include directives
+  // found in block.
+  bool checkForIncludesInBlock(clang::Preprocessor &PP,
+                               clang::SourceRange BlockSourceRange,
+                               const char *BlockIdentifierMessage,
+                               llvm::raw_ostream &OS) override {
+    clang::SourceLocation BlockStartLoc = BlockSourceRange.getBegin();
+    clang::SourceLocation BlockEndLoc = BlockSourceRange.getEnd();
+    // Use block location to get FileID of both the include directive
+    // and block statement.
+    clang::FileID FileID = PP.getSourceManager().getFileID(BlockStartLoc);
+    std::string SourcePath = getSourceLocationFile(PP, BlockStartLoc);
+    SourcePath = ModularizeUtilities::getCanonicalPath(SourcePath);
+    HeaderHandle SourceHandle = findHeaderHandle(SourcePath);
+    if (SourceHandle == -1)
+      return true;
+    int BlockStartLine, BlockStartColumn, BlockEndLine, BlockEndColumn;
+    bool returnValue = true;
+    getSourceLocationLineAndColumn(PP, BlockStartLoc, BlockStartLine,
+                                   BlockStartColumn);
+    getSourceLocationLineAndColumn(PP, BlockEndLoc, BlockEndLine,
+                                   BlockEndColumn);
+    for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(),
+                                                E = IncludeDirectives.end();
+         I != E; ++I) {
+      // If we find an entry within the block, report an error.
+      if ((I->File == SourceHandle) && (I->Line >= BlockStartLine) &&
+          (I->Line < BlockEndLine)) {
+        returnValue = false;
+        OS << SourcePath << ":" << I->Line << ":" << I->Column << ":\n";
+        OS << getSourceLine(PP, FileID, I->Line) << "\n";
+        if (I->Column > 0)
+          OS << std::string(I->Column - 1, ' ') << "^\n";
+        OS << "error: Include directive within " << BlockIdentifierMessage
+           << ".\n";
+        OS << SourcePath << ":" << BlockStartLine << ":" << BlockStartColumn
+           << ":\n";
+        OS << getSourceLine(PP, BlockStartLoc) << "\n";
+        if (BlockStartColumn > 0)
+          OS << std::string(BlockStartColumn - 1, ' ') << "^\n";
+        OS << "The \"" << BlockIdentifierMessage << "\" block is here.\n";
+      }
+    }
+    return returnValue;
+  }
+
+  // Handle entering a header source file.
+  void handleHeaderEntry(clang::Preprocessor &PP, llvm::StringRef HeaderPath) {
+    // Ignore <built-in> and <command-line> to reduce message clutter.
+    if (HeaderPath.startswith("<"))
+      return;
+    HeaderHandle H = addHeader(HeaderPath);
+    if (H != getCurrentHeaderHandle())
+      pushHeaderHandle(H);
+    // Check for nested header.
+    if (!InNestedHeader)
+      InNestedHeader = !HeadersInThisCompile.insert(H).second;
+  }
+
+  // Handle exiting a header source file.
+  void handleHeaderExit(llvm::StringRef HeaderPath) {
+    // Ignore <built-in> and <command-line> to reduce message clutter.
+    if (HeaderPath.startswith("<"))
+      return;
+    HeaderHandle H = findHeaderHandle(HeaderPath);
+    HeaderHandle TH;
+    if (isHeaderHandleInStack(H)) {
+      do {
+        TH = getCurrentHeaderHandle();
+        popHeaderHandle();
+      } while ((TH != H) && (HeaderStack.size() != 0));
+    }
+    InNestedHeader = false;
+  }
+
+  // Lookup/add string.
+  StringHandle addString(llvm::StringRef Str) { return Strings.intern(Str); }
+
+  // Convert to a canonical path.
+  std::string getCanonicalPath(llvm::StringRef path) const {
+    std::string CanonicalPath(path);
+    std::replace(CanonicalPath.begin(), CanonicalPath.end(), '\\', '/');
+    return CanonicalPath;
+  }
+
+  // Return true if the given header is in the header list.
+  bool isHeaderListHeader(llvm::StringRef HeaderPath) const {
+    std::string CanonicalPath = getCanonicalPath(HeaderPath);
+    for (llvm::ArrayRef<std::string>::iterator I = HeaderList.begin(),
+        E = HeaderList.end();
+        I != E; ++I) {
+      if (*I == CanonicalPath)
+        return true;
+    }
+    return false;
+  }
+
+  // Get the handle of a header file entry.
+  // Return HeaderHandleInvalid if not found.
+  HeaderHandle findHeaderHandle(llvm::StringRef HeaderPath) const {
+    std::string CanonicalPath = getCanonicalPath(HeaderPath);
+    HeaderHandle H = 0;
+    for (auto I = HeaderPaths.begin(), E = HeaderPaths.end(); I != E;
+         ++I, ++H) {
+      if (**I == CanonicalPath)
+        return H;
+    }
+    return HeaderHandleInvalid;
+  }
+
+  // Add a new header file entry, or return existing handle.
+  // Return the header handle.
+  HeaderHandle addHeader(llvm::StringRef HeaderPath) {
+    std::string CanonicalPath = getCanonicalPath(HeaderPath);
+    HeaderHandle H = findHeaderHandle(CanonicalPath);
+    if (H == HeaderHandleInvalid) {
+      H = HeaderPaths.size();
+      HeaderPaths.push_back(addString(CanonicalPath));
+    }
+    return H;
+  }
+
+  // Return a header file path string given its handle.
+  StringHandle getHeaderFilePath(HeaderHandle H) const {
+    if ((H >= 0) && (H < (HeaderHandle)HeaderPaths.size()))
+      return HeaderPaths[H];
+    return StringHandle();
+  }
+
+  // Returns a handle to the inclusion path.
+  InclusionPathHandle pushHeaderHandle(HeaderHandle H) {
+    HeaderStack.push_back(H);
+    return CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack);
+  }
+  // Pops the last header handle from the stack;
+  void popHeaderHandle() {
+    // assert((HeaderStack.size() != 0) && "Header stack already empty.");
+    if (HeaderStack.size() != 0) {
+      HeaderStack.pop_back();
+      CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack);
+    }
+  }
+  // Get the top handle on the header stack.
+  HeaderHandle getCurrentHeaderHandle() const {
+    if (HeaderStack.size() != 0)
+      return HeaderStack.back();
+    return HeaderHandleInvalid;
+  }
+
+  // Check for presence of header handle in the header stack.
+  bool isHeaderHandleInStack(HeaderHandle H) const {
+    for (auto I = HeaderStack.begin(), E = HeaderStack.end(); I != E; ++I) {
+      if (*I == H)
+        return true;
+    }
+    return false;
+  }
+
+  // Get the handle of a header inclusion path entry.
+  // Return InclusionPathHandleInvalid if not found.
+  InclusionPathHandle
+  findInclusionPathHandle(const std::vector<HeaderHandle> &Path) const {
+    InclusionPathHandle H = 0;
+    for (auto I = InclusionPaths.begin(), E = InclusionPaths.end(); I != E;
+         ++I, ++H) {
+      if (I->Path == Path)
+        return H;
+    }
+    return HeaderHandleInvalid;
+  }
+  // Add a new header inclusion path entry, or return existing handle.
+  // Return the header inclusion path entry handle.
+  InclusionPathHandle
+  addInclusionPathHandle(const std::vector<HeaderHandle> &Path) {
+    InclusionPathHandle H = findInclusionPathHandle(Path);
+    if (H == HeaderHandleInvalid) {
+      H = InclusionPaths.size();
+      InclusionPaths.push_back(HeaderInclusionPath(Path));
+    }
+    return H;
+  }
+  // Return the current inclusion path handle.
+  InclusionPathHandle getCurrentInclusionPathHandle() const {
+    return CurrentInclusionPathHandle;
+  }
+
+  // Return an inclusion path given its handle.
+  const std::vector<HeaderHandle> &
+  getInclusionPath(InclusionPathHandle H) const {
+    if ((H >= 0) && (H <= (InclusionPathHandle)InclusionPaths.size()))
+      return InclusionPaths[H].Path;
+    static std::vector<HeaderHandle> Empty;
+    return Empty;
+  }
+
+  // Add a macro expansion instance.
+  void addMacroExpansionInstance(clang::Preprocessor &PP, HeaderHandle H,
+                                 clang::SourceLocation InstanceLoc,
+                                 clang::SourceLocation DefinitionLoc,
+                                 clang::IdentifierInfo *II,
+                                 llvm::StringRef MacroUnexpanded,
+                                 llvm::StringRef MacroExpanded,
+                                 InclusionPathHandle InclusionPathHandle) {
+    if (InNestedHeader)
+      return;
+    StringHandle MacroName = addString(II->getName());
+    PPItemKey InstanceKey(PP, MacroName, H, InstanceLoc);
+    PPItemKey DefinitionKey(PP, MacroName, H, DefinitionLoc);
+    auto I = MacroExpansions.find(InstanceKey);
+    // If existing instance of expansion not found, add one.
+    if (I == MacroExpansions.end()) {
+      std::string InstanceSourceLine =
+          getSourceLocationString(PP, InstanceLoc) + ":\n" +
+          getSourceLine(PP, InstanceLoc) + "\n";
+      std::string DefinitionSourceLine =
+          getSourceLocationString(PP, DefinitionLoc) + ":\n" +
+          getSourceLine(PP, DefinitionLoc) + "\n";
+      MacroExpansions[InstanceKey] = MacroExpansionTracker(
+          addString(MacroUnexpanded), addString(MacroExpanded),
+          addString(InstanceSourceLine), DefinitionKey,
+          addString(DefinitionSourceLine), InclusionPathHandle);
+    } else {
+      // We've seen the macro before.  Get its tracker.
+      MacroExpansionTracker &CondTracker = I->second;
+      // Look up an existing instance value for the macro.
+      MacroExpansionInstance *MacroInfo =
+          CondTracker.findMacroExpansionInstance(addString(MacroExpanded),
+                                                 DefinitionKey);
+      // If found, just add the inclusion path to the instance.
+      if (MacroInfo)
+        MacroInfo->addInclusionPathHandle(InclusionPathHandle);
+      else {
+        // Otherwise add a new instance with the unique value.
+        std::string DefinitionSourceLine =
+            getSourceLocationString(PP, DefinitionLoc) + ":\n" +
+            getSourceLine(PP, DefinitionLoc) + "\n";
+        CondTracker.addMacroExpansionInstance(
+            addString(MacroExpanded), DefinitionKey,
+            addString(DefinitionSourceLine), InclusionPathHandle);
+      }
+    }
+  }
+
+  // Add a conditional expansion instance.
+  void
+  addConditionalExpansionInstance(clang::Preprocessor &PP, HeaderHandle H,
+                                  clang::SourceLocation InstanceLoc,
+                                  clang::tok::PPKeywordKind DirectiveKind,
+                                  clang::PPCallbacks::ConditionValueKind ConditionValue,
+                                  llvm::StringRef ConditionUnexpanded,
+                                  InclusionPathHandle InclusionPathHandle) {
+    // Ignore header guards, assuming the header guard is the only conditional.
+    if (InNestedHeader)
+      return;
+    StringHandle ConditionUnexpandedHandle(addString(ConditionUnexpanded));
+    PPItemKey InstanceKey(PP, ConditionUnexpandedHandle, H, InstanceLoc);
+    auto I = ConditionalExpansions.find(InstanceKey);
+    // If existing instance of condition not found, add one.
+    if (I == ConditionalExpansions.end()) {
+      std::string InstanceSourceLine =
+          getSourceLocationString(PP, InstanceLoc) + ":\n" +
+          getSourceLine(PP, InstanceLoc) + "\n";
+      ConditionalExpansions[InstanceKey] =
+          ConditionalTracker(DirectiveKind, ConditionValue,
+                             ConditionUnexpandedHandle, InclusionPathHandle);
+    } else {
+      // We've seen the conditional before.  Get its tracker.
+      ConditionalTracker &CondTracker = I->second;
+      // Look up an existing instance value for the condition.
+      ConditionalExpansionInstance *MacroInfo =
+          CondTracker.findConditionalExpansionInstance(ConditionValue);
+      // If found, just add the inclusion path to the instance.
+      if (MacroInfo)
+        MacroInfo->addInclusionPathHandle(InclusionPathHandle);
+      else {
+        // Otherwise add a new instance with the unique value.
+        CondTracker.addConditionalExpansionInstance(ConditionValue,
+                                                    InclusionPathHandle);
+      }
+    }
+  }
+
+  // Report on inconsistent macro instances.
+  // Returns true if any mismatches.
+  bool reportInconsistentMacros(llvm::raw_ostream &OS) override {
+    bool ReturnValue = false;
+    // Walk all the macro expansion trackers in the map.
+    for (auto I = MacroExpansions.begin(), E = MacroExpansions.end(); I != E;
+         ++I) {
+      const PPItemKey &ItemKey = I->first;
+      MacroExpansionTracker &MacroExpTracker = I->second;
+      // If no mismatch (only one instance value) continue.
+      if (!MacroExpTracker.hasMismatch())
+        continue;
+      // Tell caller we found one or more errors.
+      ReturnValue = true;
+      // Start the error message.
+      OS << *MacroExpTracker.InstanceSourceLine;
+      if (ItemKey.Column > 0)
+        OS << std::string(ItemKey.Column - 1, ' ') << "^\n";
+      OS << "error: Macro instance '" << *MacroExpTracker.MacroUnexpanded
+         << "' has different values in this header, depending on how it was "
+            "included.\n";
+      // Walk all the instances.
+      for (auto IMT = MacroExpTracker.MacroExpansionInstances.begin(),
+                EMT = MacroExpTracker.MacroExpansionInstances.end();
+           IMT != EMT; ++IMT) {
+        MacroExpansionInstance &MacroInfo = *IMT;
+        OS << "  '" << *MacroExpTracker.MacroUnexpanded << "' expanded to: '"
+           << *MacroInfo.MacroExpanded
+           << "' with respect to these inclusion paths:\n";
+        // Walk all the inclusion path hierarchies.
+        for (auto IIP = MacroInfo.InclusionPathHandles.begin(),
+                  EIP = MacroInfo.InclusionPathHandles.end();
+             IIP != EIP; ++IIP) {
+          const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
+          auto Count = (int)ip.size();
+          for (int Index = 0; Index < Count; ++Index) {
+            HeaderHandle H = ip[Index];
+            OS << std::string((Index * 2) + 4, ' ') << *getHeaderFilePath(H)
+               << "\n";
+          }
+        }
+        // For a macro that wasn't defined, we flag it by using the
+        // instance location.
+        // If there is a definition...
+        if (MacroInfo.DefinitionLocation.Line != ItemKey.Line) {
+          OS << *MacroInfo.DefinitionSourceLine;
+          if (MacroInfo.DefinitionLocation.Column > 0)
+            OS << std::string(MacroInfo.DefinitionLocation.Column - 1, ' ')
+               << "^\n";
+          OS << "Macro defined here.\n";
+        } else
+          OS << "(no macro definition)"
+             << "\n";
+      }
+    }
+    return ReturnValue;
+  }
+
+  // Report on inconsistent conditional instances.
+  // Returns true if any mismatches.
+  bool reportInconsistentConditionals(llvm::raw_ostream &OS) override {
+    bool ReturnValue = false;
+    // Walk all the conditional trackers in the map.
+    for (auto I = ConditionalExpansions.begin(),
+              E = ConditionalExpansions.end();
+         I != E; ++I) {
+      const PPItemKey &ItemKey = I->first;
+      ConditionalTracker &CondTracker = I->second;
+      if (!CondTracker.hasMismatch())
+        continue;
+      // Tell caller we found one or more errors.
+      ReturnValue = true;
+      // Start the error message.
+      OS << *HeaderPaths[ItemKey.File] << ":" << ItemKey.Line << ":"
+         << ItemKey.Column << "\n";
+      OS << "#" << getDirectiveSpelling(CondTracker.DirectiveKind) << " "
+         << *CondTracker.ConditionUnexpanded << "\n";
+      OS << "^\n";
+      OS << "error: Conditional expression instance '"
+         << *CondTracker.ConditionUnexpanded
+         << "' has different values in this header, depending on how it was "
+            "included.\n";
+      // Walk all the instances.
+      for (auto IMT = CondTracker.ConditionalExpansionInstances.begin(),
+                EMT = CondTracker.ConditionalExpansionInstances.end();
+           IMT != EMT; ++IMT) {
+        ConditionalExpansionInstance &MacroInfo = *IMT;
+        OS << "  '" << *CondTracker.ConditionUnexpanded << "' expanded to: '"
+           << ConditionValueKindStrings[MacroInfo.ConditionValue]
+           << "' with respect to these inclusion paths:\n";
+        // Walk all the inclusion path hierarchies.
+        for (auto IIP = MacroInfo.InclusionPathHandles.begin(),
+                  EIP = MacroInfo.InclusionPathHandles.end();
+             IIP != EIP; ++IIP) {
+          const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
+          auto Count = (int)ip.size();
+          for (int Index = 0; Index < Count; ++Index) {
+            HeaderHandle H = ip[Index];
+            OS << std::string((Index * 2) + 4, ' ') << *getHeaderFilePath(H)
+               << "\n";
+          }
+        }
+      }
+    }
+    return ReturnValue;
+  }
+
+  // Get directive spelling.
+  static const char *getDirectiveSpelling(clang::tok::PPKeywordKind kind) {
+    switch (kind) {
+    case clang::tok::pp_if:
+      return "if";
+    case clang::tok::pp_elif:
+      return "elif";
+    case clang::tok::pp_ifdef:
+      return "ifdef";
+    case clang::tok::pp_ifndef:
+      return "ifndef";
+    default:
+      return "(unknown)";
+    }
+  }
+
+private:
+  llvm::SmallVector<std::string, 32> HeaderList;
+  // Only do extern, namespace check for headers in HeaderList.
+  bool BlockCheckHeaderListOnly;
+  llvm::StringPool Strings;
+  std::vector<StringHandle> HeaderPaths;
+  std::vector<HeaderHandle> HeaderStack;
+  std::vector<HeaderInclusionPath> InclusionPaths;
+  InclusionPathHandle CurrentInclusionPathHandle;
+  llvm::SmallSet<HeaderHandle, 32> HeadersInThisCompile;
+  std::vector<PPItemKey> IncludeDirectives;
+  MacroExpansionMap MacroExpansions;
+  ConditionalExpansionMap ConditionalExpansions;
+  bool InNestedHeader;
+};
+
+} // namespace
+
+// PreprocessorTracker functions.
+
+// PreprocessorTracker desctructor.
+PreprocessorTracker::~PreprocessorTracker() {}
+
+// Create instance of PreprocessorTracker.
+PreprocessorTracker *PreprocessorTracker::create(
+    llvm::SmallVector<std::string, 32> &Headers,
+    bool DoBlockCheckHeaderListOnly) {
+  return new PreprocessorTrackerImpl(Headers, DoBlockCheckHeaderListOnly);
+}
+
+// Preprocessor callbacks for modularize.
+
+// Handle include directive.
+void PreprocessorCallbacks::InclusionDirective(
+    clang::SourceLocation HashLoc, const clang::Token &IncludeTok,
+    llvm::StringRef FileName, bool IsAngled,
+    clang::CharSourceRange FilenameRange, const clang::FileEntry *File,
+    llvm::StringRef SearchPath, llvm::StringRef RelativePath,
+    const clang::Module *Imported, clang::SrcMgr::CharacteristicKind FileType) {
+  int DirectiveLine, DirectiveColumn;
+  std::string HeaderPath = getSourceLocationFile(PP, HashLoc);
+  getSourceLocationLineAndColumn(PP, HashLoc, DirectiveLine, DirectiveColumn);
+  PPTracker.handleIncludeDirective(HeaderPath, DirectiveLine, DirectiveColumn,
+                                   FileName);
+}
+
+// Handle file entry/exit.
+void PreprocessorCallbacks::FileChanged(
+    clang::SourceLocation Loc, clang::PPCallbacks::FileChangeReason Reason,
+    clang::SrcMgr::CharacteristicKind FileType, clang::FileID PrevFID) {
+  switch (Reason) {
+  case EnterFile:
+    PPTracker.handleHeaderEntry(PP, getSourceLocationFile(PP, Loc));
+    break;
+  case ExitFile: {
+    const clang::FileEntry *F =
+        PP.getSourceManager().getFileEntryForID(PrevFID);
+    if (F)
+      PPTracker.handleHeaderExit(F->getName());
+  } break;
+  case SystemHeaderPragma:
+  case RenameFile:
+    break;
+  }
+}
+
+// Handle macro expansion.
+void PreprocessorCallbacks::MacroExpands(const clang::Token &MacroNameTok,
+                                         const clang::MacroDefinition &MD,
+                                         clang::SourceRange Range,
+                                         const clang::MacroArgs *Args) {
+  clang::SourceLocation Loc = Range.getBegin();
+  // Ignore macro argument expansions.
+  if (!Loc.isFileID())
+    return;
+  clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
+  const clang::MacroInfo *MI = MD.getMacroInfo();
+  std::string MacroName = II->getName().str();
+  std::string Unexpanded(getMacroUnexpandedString(Range, PP, MacroName, MI));
+  std::string Expanded(getMacroExpandedString(PP, MacroName, MI, Args));
+  PPTracker.addMacroExpansionInstance(
+      PP, PPTracker.getCurrentHeaderHandle(), Loc, MI->getDefinitionLoc(), II,
+      Unexpanded, Expanded, PPTracker.getCurrentInclusionPathHandle());
+}
+
+void PreprocessorCallbacks::Defined(const clang::Token &MacroNameTok,
+                                    const clang::MacroDefinition &MD,
+                                    clang::SourceRange Range) {
+  clang::SourceLocation Loc(Range.getBegin());
+  clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
+  const clang::MacroInfo *MI = MD.getMacroInfo();
+  std::string MacroName = II->getName().str();
+  std::string Unexpanded(getSourceString(PP, Range));
+  PPTracker.addMacroExpansionInstance(
+      PP, PPTracker.getCurrentHeaderHandle(), Loc,
+      (MI ? MI->getDefinitionLoc() : Loc), II, Unexpanded,
+      (MI ? "true" : "false"), PPTracker.getCurrentInclusionPathHandle());
+}
+
+void PreprocessorCallbacks::If(clang::SourceLocation Loc,
+                               clang::SourceRange ConditionRange,
+                               clang::PPCallbacks::ConditionValueKind ConditionResult) {
+  std::string Unexpanded(getSourceString(PP, ConditionRange));
+  PPTracker.addConditionalExpansionInstance(
+      PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_if,
+      ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle());
+}
+
+void PreprocessorCallbacks::Elif(clang::SourceLocation Loc,
+                                 clang::SourceRange ConditionRange,
+                                 clang::PPCallbacks::ConditionValueKind ConditionResult,
+                                 clang::SourceLocation IfLoc) {
+  std::string Unexpanded(getSourceString(PP, ConditionRange));
+  PPTracker.addConditionalExpansionInstance(
+      PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_elif,
+      ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle());
+}
+
+void PreprocessorCallbacks::Ifdef(clang::SourceLocation Loc,
+                                  const clang::Token &MacroNameTok,
+                                  const clang::MacroDefinition &MD) {
+  clang::PPCallbacks::ConditionValueKind IsDefined =
+    (MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
+  PPTracker.addConditionalExpansionInstance(
+      PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifdef,
+      IsDefined, PP.getSpelling(MacroNameTok),
+      PPTracker.getCurrentInclusionPathHandle());
+}
+
+void PreprocessorCallbacks::Ifndef(clang::SourceLocation Loc,
+                                   const clang::Token &MacroNameTok,
+                                   const clang::MacroDefinition &MD) {
+  clang::PPCallbacks::ConditionValueKind IsNotDefined =
+    (!MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
+  PPTracker.addConditionalExpansionInstance(
+      PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifndef,
+      IsNotDefined, PP.getSpelling(MacroNameTok),
+      PPTracker.getCurrentInclusionPathHandle());
+}
+} // end namespace Modularize
diff --git a/src/third_party/llvm-project/clang-tools-extra/modularize/PreprocessorTracker.h b/src/third_party/llvm-project/clang-tools-extra/modularize/PreprocessorTracker.h
new file mode 100644
index 0000000..a283d9f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/modularize/PreprocessorTracker.h
@@ -0,0 +1,87 @@
+//===- PreprocessorTracker.h - Tracks preprocessor activities -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Macro expansions and preprocessor conditional consistency checker.
+///
+//===--------------------------------------------------------------------===//
+
+#ifndef MODULARIZE_PREPROCESSOR_TRACKER_H
+#define MODULARIZE_PREPROCESSOR_TRACKER_H
+
+#include "clang/Lex/Preprocessor.h"
+
+namespace Modularize {
+
+/// \brief Preprocessor tracker for modularize.
+///
+/// The PreprocessorTracker class defines an API for
+/// checking macro expansions and preprocessor conditional expressions
+/// in a header file for consistency among one or more compilations of
+/// the header in a #include scenario.  This is for helping a user
+/// find which macro expansions or conditionals might be problematic with
+/// respect to using the headers in the modules scenario, because they
+/// evaluate to different values depending on how or where a header
+/// is included.
+///
+/// The handlePreprocessorEntry function implementation will register
+/// a PPCallbacks object in the given Preprocessor object.  The calls to
+/// the callbacks will collect information about the macro expansions
+/// and preprocessor conditionals encountered, for later analysis and
+/// reporting of inconsistencies between runs performed by calls to
+/// the reportInconsistentMacros and reportInconsistentConditionals
+/// functions respectively.  The handlePreprocessorExit informs the
+/// implementation that a preprocessing session is complete, allowing
+/// it to do any needed compilation completion activities in the checker.
+class PreprocessorTracker {
+public:
+  virtual ~PreprocessorTracker();
+
+  // Handle entering a preprocessing session.
+  // (Called after a Preprocessor object is created, but before preprocessing.)
+  virtual void handlePreprocessorEntry(clang::Preprocessor &PP,
+                                       llvm::StringRef RootHeaderFile) = 0;
+  // Handle exiting a preprocessing session.
+  // (Called after preprocessing is complete, but before the Preprocessor
+  // object is destroyed.)
+  virtual void handlePreprocessorExit() = 0;
+
+  // Handle include directive.
+  // This function is called every time an include directive is seen by the
+  // preprocessor, for the purpose of later checking for 'extern "" {}' or
+  // "namespace {}" blocks containing #include directives.
+  virtual void handleIncludeDirective(llvm::StringRef DirectivePath,
+                                      int DirectiveLine, int DirectiveColumn,
+                                      llvm::StringRef TargetPath) = 0;
+
+  // Check for include directives within the given source line range.
+  // Report errors if any found.  Returns true if no include directives
+  // found in block.
+  virtual bool checkForIncludesInBlock(clang::Preprocessor &PP,
+                                       clang::SourceRange BlockSourceRange,
+                                       const char *BlockIdentifierMessage,
+                                       llvm::raw_ostream &OS) = 0;
+
+  // Report on inconsistent macro instances.
+  // Returns true if any mismatches.
+  virtual bool reportInconsistentMacros(llvm::raw_ostream &OS) = 0;
+
+  // Report on inconsistent conditional directive instances.
+  // Returns true if any mismatches.
+  virtual bool reportInconsistentConditionals(llvm::raw_ostream &OS) = 0;
+
+  // Create instance of PreprocessorTracker.
+  static PreprocessorTracker *create(
+    llvm::SmallVector<std::string, 32> &Headers,
+    bool DoBlockCheckHeaderListOnly);
+};
+
+} // end namespace Modularize
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/pp-trace/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/pp-trace/CMakeLists.txt
new file mode 100644
index 0000000..fbbe865
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/pp-trace/CMakeLists.txt
@@ -0,0 +1,17 @@
+set(LLVM_LINK_COMPONENTS
+  Support
+  )
+
+add_clang_executable(pp-trace
+  PPTrace.cpp
+  PPCallbacksTracker.cpp
+  )
+
+target_link_libraries(pp-trace
+  PRIVATE
+  clangAST
+  clangBasic
+  clangFrontend
+  clangLex
+  clangTooling
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/pp-trace/PPCallbacksTracker.cpp b/src/third_party/llvm-project/clang-tools-extra/pp-trace/PPCallbacksTracker.cpp
new file mode 100644
index 0000000..2530dc2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/pp-trace/PPCallbacksTracker.cpp
@@ -0,0 +1,654 @@
+//===--- PPCallbacksTracker.cpp - Preprocessor tracker -*--*---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Implementations for preprocessor tracking.
+///
+/// See the header for details.
+///
+//===----------------------------------------------------------------------===//
+
+#include "PPCallbacksTracker.h"
+#include "clang/Lex/MacroArgs.h"
+#include "llvm/Support/raw_ostream.h"
+
+// Utility functions.
+
+// Get a "file:line:column" source location string.
+static std::string getSourceLocationString(clang::Preprocessor &PP,
+                                           clang::SourceLocation Loc) {
+  if (Loc.isInvalid())
+    return std::string("(none)");
+
+  if (Loc.isFileID()) {
+    clang::PresumedLoc PLoc = PP.getSourceManager().getPresumedLoc(Loc);
+
+    if (PLoc.isInvalid()) {
+      return std::string("(invalid)");
+    }
+
+    std::string Str;
+    llvm::raw_string_ostream SS(Str);
+
+    // The macro expansion and spelling pos is identical for file locs.
+    SS << "\"" << PLoc.getFilename() << ':' << PLoc.getLine() << ':'
+       << PLoc.getColumn() << "\"";
+
+    std::string Result = SS.str();
+
+    // YAML treats backslash as escape, so use forward slashes.
+    std::replace(Result.begin(), Result.end(), '\\', '/');
+
+    return Result;
+  }
+
+  return std::string("(nonfile)");
+}
+
+// Enum string tables.
+
+// FileChangeReason strings.
+static const char *const FileChangeReasonStrings[] = {
+  "EnterFile", "ExitFile", "SystemHeaderPragma", "RenameFile"
+};
+
+// CharacteristicKind strings.
+static const char *const CharacteristicKindStrings[] = { "C_User", "C_System",
+                                                         "C_ExternCSystem" };
+
+// MacroDirective::Kind strings.
+static const char *const MacroDirectiveKindStrings[] = {
+  "MD_Define","MD_Undefine", "MD_Visibility"
+};
+
+// PragmaIntroducerKind strings.
+static const char *const PragmaIntroducerKindStrings[] = { "PIK_HashPragma",
+                                                           "PIK__Pragma",
+                                                           "PIK___pragma" };
+
+// PragmaMessageKind strings.
+static const char *const PragmaMessageKindStrings[] = {
+  "PMK_Message", "PMK_Warning", "PMK_Error"
+};
+
+// ConditionValueKind strings.
+static const char *const ConditionValueKindStrings[] = {
+  "CVK_NotEvaluated", "CVK_False", "CVK_True"
+};
+
+// Mapping strings.
+static const char *const MappingStrings[] = { "0",          "MAP_IGNORE",
+                                              "MAP_REMARK", "MAP_WARNING",
+                                              "MAP_ERROR",  "MAP_FATAL" };
+
+// PPCallbacksTracker functions.
+
+PPCallbacksTracker::PPCallbacksTracker(llvm::SmallSet<std::string, 4> &Ignore,
+                                       std::vector<CallbackCall> &CallbackCalls,
+                                       clang::Preprocessor &PP)
+    : CallbackCalls(CallbackCalls), Ignore(Ignore), PP(PP) {}
+
+PPCallbacksTracker::~PPCallbacksTracker() {}
+
+// Callback functions.
+
+// Callback invoked whenever a source file is entered or exited.
+void PPCallbacksTracker::FileChanged(
+    clang::SourceLocation Loc, clang::PPCallbacks::FileChangeReason Reason,
+    clang::SrcMgr::CharacteristicKind FileType, clang::FileID PrevFID) {
+  beginCallback("FileChanged");
+  appendArgument("Loc", Loc);
+  appendArgument("Reason", Reason, FileChangeReasonStrings);
+  appendArgument("FileType", FileType, CharacteristicKindStrings);
+  appendArgument("PrevFID", PrevFID);
+}
+
+// Callback invoked whenever a source file is skipped as the result
+// of header guard optimization.
+void
+PPCallbacksTracker::FileSkipped(const clang::FileEntry &SkippedFile,
+                                const clang::Token &FilenameTok,
+                                clang::SrcMgr::CharacteristicKind FileType) {
+  beginCallback("FileSkipped");
+  appendArgument("ParentFile", &SkippedFile);
+  appendArgument("FilenameTok", FilenameTok);
+  appendArgument("FileType", FileType, CharacteristicKindStrings);
+}
+
+// Callback invoked whenever an inclusion directive results in a
+// file-not-found error.
+bool
+PPCallbacksTracker::FileNotFound(llvm::StringRef FileName,
+                                 llvm::SmallVectorImpl<char> &RecoveryPath) {
+  beginCallback("FileNotFound");
+  appendFilePathArgument("FileName", FileName);
+  return false;
+}
+
+// Callback invoked whenever an inclusion directive of
+// any kind (#include, #import, etc.) has been processed, regardless
+// of whether the inclusion will actually result in an inclusion.
+void PPCallbacksTracker::InclusionDirective(
+    clang::SourceLocation HashLoc, const clang::Token &IncludeTok,
+    llvm::StringRef FileName, bool IsAngled,
+    clang::CharSourceRange FilenameRange, const clang::FileEntry *File,
+    llvm::StringRef SearchPath, llvm::StringRef RelativePath,
+    const clang::Module *Imported, clang::SrcMgr::CharacteristicKind FileType) {
+  beginCallback("InclusionDirective");
+  appendArgument("IncludeTok", IncludeTok);
+  appendFilePathArgument("FileName", FileName);
+  appendArgument("IsAngled", IsAngled);
+  appendArgument("FilenameRange", FilenameRange);
+  appendArgument("File", File);
+  appendFilePathArgument("SearchPath", SearchPath);
+  appendFilePathArgument("RelativePath", RelativePath);
+  appendArgument("Imported", Imported);
+}
+
+// Callback invoked whenever there was an explicit module-import
+// syntax.
+void PPCallbacksTracker::moduleImport(clang::SourceLocation ImportLoc,
+                                      clang::ModuleIdPath Path,
+                                      const clang::Module *Imported) {
+  beginCallback("moduleImport");
+  appendArgument("ImportLoc", ImportLoc);
+  appendArgument("Path", Path);
+  appendArgument("Imported", Imported);
+}
+
+// Callback invoked when the end of the main file is reached.
+// No subsequent callbacks will be made.
+void PPCallbacksTracker::EndOfMainFile() { beginCallback("EndOfMainFile"); }
+
+// Callback invoked when a #ident or #sccs directive is read.
+void PPCallbacksTracker::Ident(clang::SourceLocation Loc, llvm::StringRef Str) {
+  beginCallback("Ident");
+  appendArgument("Loc", Loc);
+  appendArgument("Str", Str);
+}
+
+// Callback invoked when start reading any pragma directive.
+void
+PPCallbacksTracker::PragmaDirective(clang::SourceLocation Loc,
+                                    clang::PragmaIntroducerKind Introducer) {
+  beginCallback("PragmaDirective");
+  appendArgument("Loc", Loc);
+  appendArgument("Introducer", Introducer, PragmaIntroducerKindStrings);
+}
+
+// Callback invoked when a #pragma comment directive is read.
+void PPCallbacksTracker::PragmaComment(clang::SourceLocation Loc,
+                                       const clang::IdentifierInfo *Kind,
+                                       llvm::StringRef Str) {
+  beginCallback("PragmaComment");
+  appendArgument("Loc", Loc);
+  appendArgument("Kind", Kind);
+  appendArgument("Str", Str);
+}
+
+// Callback invoked when a #pragma detect_mismatch directive is
+// read.
+void PPCallbacksTracker::PragmaDetectMismatch(clang::SourceLocation Loc,
+                                              llvm::StringRef Name,
+                                              llvm::StringRef Value) {
+  beginCallback("PragmaDetectMismatch");
+  appendArgument("Loc", Loc);
+  appendArgument("Name", Name);
+  appendArgument("Value", Value);
+}
+
+// Callback invoked when a #pragma clang __debug directive is read.
+void PPCallbacksTracker::PragmaDebug(clang::SourceLocation Loc,
+                                     llvm::StringRef DebugType) {
+  beginCallback("PragmaDebug");
+  appendArgument("Loc", Loc);
+  appendArgument("DebugType", DebugType);
+}
+
+// Callback invoked when a #pragma message directive is read.
+void PPCallbacksTracker::PragmaMessage(
+    clang::SourceLocation Loc, llvm::StringRef Namespace,
+    clang::PPCallbacks::PragmaMessageKind Kind, llvm::StringRef Str) {
+  beginCallback("PragmaMessage");
+  appendArgument("Loc", Loc);
+  appendArgument("Namespace", Namespace);
+  appendArgument("Kind", Kind, PragmaMessageKindStrings);
+  appendArgument("Str", Str);
+}
+
+// Callback invoked when a #pragma gcc dianostic push directive
+// is read.
+void PPCallbacksTracker::PragmaDiagnosticPush(clang::SourceLocation Loc,
+                                              llvm::StringRef Namespace) {
+  beginCallback("PragmaDiagnosticPush");
+  appendArgument("Loc", Loc);
+  appendArgument("Namespace", Namespace);
+}
+
+// Callback invoked when a #pragma gcc dianostic pop directive
+// is read.
+void PPCallbacksTracker::PragmaDiagnosticPop(clang::SourceLocation Loc,
+                                             llvm::StringRef Namespace) {
+  beginCallback("PragmaDiagnosticPop");
+  appendArgument("Loc", Loc);
+  appendArgument("Namespace", Namespace);
+}
+
+// Callback invoked when a #pragma gcc dianostic directive is read.
+void PPCallbacksTracker::PragmaDiagnostic(clang::SourceLocation Loc,
+                                          llvm::StringRef Namespace,
+                                          clang::diag::Severity Mapping,
+                                          llvm::StringRef Str) {
+  beginCallback("PragmaDiagnostic");
+  appendArgument("Loc", Loc);
+  appendArgument("Namespace", Namespace);
+  appendArgument("Mapping", (unsigned)Mapping, MappingStrings);
+  appendArgument("Str", Str);
+}
+
+// Called when an OpenCL extension is either disabled or
+// enabled with a pragma.
+void PPCallbacksTracker::PragmaOpenCLExtension(
+    clang::SourceLocation NameLoc, const clang::IdentifierInfo *Name,
+    clang::SourceLocation StateLoc, unsigned State) {
+  beginCallback("PragmaOpenCLExtension");
+  appendArgument("NameLoc", NameLoc);
+  appendArgument("Name", Name);
+  appendArgument("StateLoc", StateLoc);
+  appendArgument("State", (int)State);
+}
+
+// Callback invoked when a #pragma warning directive is read.
+void PPCallbacksTracker::PragmaWarning(clang::SourceLocation Loc,
+                                       llvm::StringRef WarningSpec,
+                                       llvm::ArrayRef<int> Ids) {
+  beginCallback("PragmaWarning");
+  appendArgument("Loc", Loc);
+  appendArgument("WarningSpec", WarningSpec);
+
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << "[";
+  for (int i = 0, e = Ids.size(); i != e; ++i) {
+    if (i)
+      SS << ", ";
+    SS << Ids[i];
+  }
+  SS << "]";
+  appendArgument("Ids", SS.str());
+}
+
+// Callback invoked when a #pragma warning(push) directive is read.
+void PPCallbacksTracker::PragmaWarningPush(clang::SourceLocation Loc,
+                                           int Level) {
+  beginCallback("PragmaWarningPush");
+  appendArgument("Loc", Loc);
+  appendArgument("Level", Level);
+}
+
+// Callback invoked when a #pragma warning(pop) directive is read.
+void PPCallbacksTracker::PragmaWarningPop(clang::SourceLocation Loc) {
+  beginCallback("PragmaWarningPop");
+  appendArgument("Loc", Loc);
+}
+
+// Called by Preprocessor::HandleMacroExpandedIdentifier when a
+// macro invocation is found.
+void
+PPCallbacksTracker::MacroExpands(const clang::Token &MacroNameTok,
+                                 const clang::MacroDefinition &MacroDefinition,
+                                 clang::SourceRange Range,
+                                 const clang::MacroArgs *Args) {
+  beginCallback("MacroExpands");
+  appendArgument("MacroNameTok", MacroNameTok);
+  appendArgument("MacroDefinition", MacroDefinition);
+  appendArgument("Range", Range);
+  appendArgument("Args", Args);
+}
+
+// Hook called whenever a macro definition is seen.
+void
+PPCallbacksTracker::MacroDefined(const clang::Token &MacroNameTok,
+                                 const clang::MacroDirective *MacroDirective) {
+  beginCallback("MacroDefined");
+  appendArgument("MacroNameTok", MacroNameTok);
+  appendArgument("MacroDirective", MacroDirective);
+}
+
+// Hook called whenever a macro #undef is seen.
+void PPCallbacksTracker::MacroUndefined(
+    const clang::Token &MacroNameTok,
+    const clang::MacroDefinition &MacroDefinition,
+    const clang::MacroDirective *Undef) {
+  beginCallback("MacroUndefined");
+  appendArgument("MacroNameTok", MacroNameTok);
+  appendArgument("MacroDefinition", MacroDefinition);
+}
+
+// Hook called whenever the 'defined' operator is seen.
+void PPCallbacksTracker::Defined(const clang::Token &MacroNameTok,
+                                 const clang::MacroDefinition &MacroDefinition,
+                                 clang::SourceRange Range) {
+  beginCallback("Defined");
+  appendArgument("MacroNameTok", MacroNameTok);
+  appendArgument("MacroDefinition", MacroDefinition);
+  appendArgument("Range", Range);
+}
+
+// Hook called when a source range is skipped.
+void PPCallbacksTracker::SourceRangeSkipped(clang::SourceRange Range,
+                                            clang::SourceLocation EndifLoc) {
+  beginCallback("SourceRangeSkipped");
+  appendArgument("Range", clang::SourceRange(Range.getBegin(), EndifLoc));
+}
+
+// Hook called whenever an #if is seen.
+void PPCallbacksTracker::If(clang::SourceLocation Loc,
+                            clang::SourceRange ConditionRange,
+                            ConditionValueKind ConditionValue) {
+  beginCallback("If");
+  appendArgument("Loc", Loc);
+  appendArgument("ConditionRange", ConditionRange);
+  appendArgument("ConditionValue", ConditionValue, ConditionValueKindStrings);
+}
+
+// Hook called whenever an #elif is seen.
+void PPCallbacksTracker::Elif(clang::SourceLocation Loc,
+                              clang::SourceRange ConditionRange,
+                              ConditionValueKind ConditionValue,
+                              clang::SourceLocation IfLoc) {
+  beginCallback("Elif");
+  appendArgument("Loc", Loc);
+  appendArgument("ConditionRange", ConditionRange);
+  appendArgument("ConditionValue", ConditionValue, ConditionValueKindStrings);
+  appendArgument("IfLoc", IfLoc);
+}
+
+// Hook called whenever an #ifdef is seen.
+void PPCallbacksTracker::Ifdef(clang::SourceLocation Loc,
+                               const clang::Token &MacroNameTok,
+                               const clang::MacroDefinition &MacroDefinition) {
+  beginCallback("Ifdef");
+  appendArgument("Loc", Loc);
+  appendArgument("MacroNameTok", MacroNameTok);
+  appendArgument("MacroDefinition", MacroDefinition);
+}
+
+// Hook called whenever an #ifndef is seen.
+void PPCallbacksTracker::Ifndef(clang::SourceLocation Loc,
+                                const clang::Token &MacroNameTok,
+                                const clang::MacroDefinition &MacroDefinition) {
+  beginCallback("Ifndef");
+  appendArgument("Loc", Loc);
+  appendArgument("MacroNameTok", MacroNameTok);
+  appendArgument("MacroDefinition", MacroDefinition);
+}
+
+// Hook called whenever an #else is seen.
+void PPCallbacksTracker::Else(clang::SourceLocation Loc,
+                              clang::SourceLocation IfLoc) {
+  beginCallback("Else");
+  appendArgument("Loc", Loc);
+  appendArgument("IfLoc", IfLoc);
+}
+
+// Hook called whenever an #endif is seen.
+void PPCallbacksTracker::Endif(clang::SourceLocation Loc,
+                               clang::SourceLocation IfLoc) {
+  beginCallback("Endif");
+  appendArgument("Loc", Loc);
+  appendArgument("IfLoc", IfLoc);
+}
+
+// Helper functions.
+
+// Start a new callback.
+void PPCallbacksTracker::beginCallback(const char *Name) {
+  DisableTrace = Ignore.count(std::string(Name));
+  if (DisableTrace)
+    return;
+  CallbackCalls.push_back(CallbackCall(Name));
+}
+
+// Append a bool argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name, bool Value) {
+  appendArgument(Name, (Value ? "true" : "false"));
+}
+
+// Append an int argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name, int Value) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << Value;
+  appendArgument(Name, SS.str());
+}
+
+// Append a string argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name, const char *Value) {
+  if (DisableTrace)
+    return;
+  CallbackCalls.back().Arguments.push_back(Argument(Name, Value));
+}
+
+// Append a string object argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name,
+                                        llvm::StringRef Value) {
+  appendArgument(Name, Value.str());
+}
+
+// Append a string object argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name,
+                                        const std::string &Value) {
+  appendArgument(Name, Value.c_str());
+}
+
+// Append a token argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name,
+                                        const clang::Token &Value) {
+  appendArgument(Name, PP.getSpelling(Value));
+}
+
+// Append an enum argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name, int Value,
+                                        const char *const Strings[]) {
+  appendArgument(Name, Strings[Value]);
+}
+
+// Append a FileID argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name, clang::FileID Value) {
+  if (Value.isInvalid()) {
+    appendArgument(Name, "(invalid)");
+    return;
+  }
+  const clang::FileEntry *FileEntry =
+      PP.getSourceManager().getFileEntryForID(Value);
+  if (!FileEntry) {
+    appendArgument(Name, "(getFileEntryForID failed)");
+    return;
+  }
+  appendFilePathArgument(Name, FileEntry->getName());
+}
+
+// Append a FileEntry argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name,
+                                        const clang::FileEntry *Value) {
+  if (!Value) {
+    appendArgument(Name, "(null)");
+    return;
+  }
+  appendFilePathArgument(Name, Value->getName());
+}
+
+// Append a SourceLocation argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name,
+                                        clang::SourceLocation Value) {
+  if (Value.isInvalid()) {
+    appendArgument(Name, "(invalid)");
+    return;
+  }
+  appendArgument(Name, getSourceLocationString(PP, Value).c_str());
+}
+
+// Append a SourceRange argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name,
+                                        clang::SourceRange Value) {
+  if (DisableTrace)
+    return;
+  if (Value.isInvalid()) {
+    appendArgument(Name, "(invalid)");
+    return;
+  }
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << "[" << getSourceLocationString(PP, Value.getBegin()) << ", "
+     << getSourceLocationString(PP, Value.getEnd()) << "]";
+  appendArgument(Name, SS.str());
+}
+
+// Append a CharSourceRange argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name,
+                                        clang::CharSourceRange Value) {
+  if (Value.isInvalid()) {
+    appendArgument(Name, "(invalid)");
+    return;
+  }
+  appendArgument(Name, getSourceString(Value).str().c_str());
+}
+
+// Append a SourceLocation argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name,
+                                        clang::ModuleIdPath Value) {
+  if (DisableTrace)
+    return;
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << "[";
+  for (int I = 0, E = Value.size(); I != E; ++I) {
+    if (I)
+      SS << ", ";
+    SS << "{"
+       << "Name: " << Value[I].first->getName() << ", "
+       << "Loc: " << getSourceLocationString(PP, Value[I].second) << "}";
+  }
+  SS << "]";
+  appendArgument(Name, SS.str());
+}
+
+// Append an IdentifierInfo argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name,
+                                        const clang::IdentifierInfo *Value) {
+  if (!Value) {
+    appendArgument(Name, "(null)");
+    return;
+  }
+  appendArgument(Name, Value->getName().str().c_str());
+}
+
+// Append a MacroDirective argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name,
+                                        const clang::MacroDirective *Value) {
+  if (!Value) {
+    appendArgument(Name, "(null)");
+    return;
+  }
+  appendArgument(Name, MacroDirectiveKindStrings[Value->getKind()]);
+}
+
+// Append a MacroDefinition argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name,
+                                        const clang::MacroDefinition &Value) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << "[";
+  bool Any = false;
+  if (Value.getLocalDirective()) {
+    SS << "(local)";
+    Any = true;
+  }
+  for (auto *MM : Value.getModuleMacros()) {
+    if (Any) SS << ", ";
+    SS << MM->getOwningModule()->getFullModuleName();
+  }
+  SS << "]";
+  appendArgument(Name, SS.str());
+}
+
+// Append a MacroArgs argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name,
+                                        const clang::MacroArgs *Value) {
+  if (!Value) {
+    appendArgument(Name, "(null)");
+    return;
+  }
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << "[";
+
+  // Each argument is is a series of contiguous Tokens, terminated by a eof.
+  // Go through each argument printing tokens until we reach eof.
+  for (unsigned I = 0; I < Value->getNumMacroArguments(); ++I) {
+    const clang::Token *Current = Value->getUnexpArgument(I);
+    if (I)
+      SS << ", ";
+    bool First = true;
+    while (Current->isNot(clang::tok::eof)) {
+      if (!First)
+        SS << " ";
+      // We need to be careful here because the arguments might not be legal in
+      // YAML, so we use the token name for anything but identifiers and
+      // numeric literals.
+      if (Current->isAnyIdentifier() ||
+          Current->is(clang::tok::numeric_constant)) {
+        SS << PP.getSpelling(*Current);
+      } else {
+        SS << "<" << Current->getName() << ">";
+      }
+      ++Current;
+      First = false;
+    }
+  }
+  SS << "]";
+  appendArgument(Name, SS.str());
+}
+
+// Append a Module argument to the top trace item.
+void PPCallbacksTracker::appendArgument(const char *Name,
+                                        const clang::Module *Value) {
+  if (!Value) {
+    appendArgument(Name, "(null)");
+    return;
+  }
+  appendArgument(Name, Value->Name.c_str());
+}
+
+// Append a double-quoted argument to the top trace item.
+void PPCallbacksTracker::appendQuotedArgument(const char *Name,
+                                              const std::string &Value) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << "\"" << Value << "\"";
+  appendArgument(Name, SS.str());
+}
+
+// Append a double-quoted file path argument to the top trace item.
+void PPCallbacksTracker::appendFilePathArgument(const char *Name,
+                                                llvm::StringRef Value) {
+  std::string Path(Value);
+  // YAML treats backslash as escape, so use forward slashes.
+  std::replace(Path.begin(), Path.end(), '\\', '/');
+  appendQuotedArgument(Name, Path);
+}
+
+// Get the raw source string of the range.
+llvm::StringRef
+PPCallbacksTracker::getSourceString(clang::CharSourceRange Range) {
+  const char *B = PP.getSourceManager().getCharacterData(Range.getBegin());
+  const char *E = PP.getSourceManager().getCharacterData(Range.getEnd());
+  return llvm::StringRef(B, E - B);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/pp-trace/PPCallbacksTracker.h b/src/third_party/llvm-project/clang-tools-extra/pp-trace/PPCallbacksTracker.h
new file mode 100644
index 0000000..b46210e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/pp-trace/PPCallbacksTracker.h
@@ -0,0 +1,249 @@
+//===--- PPCallbacksTracker.h - Preprocessor tracking -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Classes and definitions for preprocessor tracking.
+///
+/// The core definition is the PPCallbacksTracker class, derived from Clang's
+/// PPCallbacks class from the Lex library, which overrides all the callbacks
+/// and collects information about each callback call, saving it in a
+/// data structure built up of CallbackCall and Argument objects, which
+/// record the preprocessor callback name and arguments in high-level string
+/// form for later inspection.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef PPTRACE_PPCALLBACKSTRACKER_H
+#define PPTRACE_PPCALLBACKSTRACKER_H
+
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+#include <vector>
+
+/// \brief This class represents one callback function argument by name
+///   and value.
+class Argument {
+public:
+  Argument(llvm::StringRef Name, llvm::StringRef Value)
+      : Name(Name), Value(Value) {}
+  Argument() = default;
+
+  std::string Name;
+  std::string Value;
+};
+
+/// \brief This class represents one callback call by name and an array
+///   of arguments.
+class CallbackCall {
+public:
+  CallbackCall(llvm::StringRef Name) : Name(Name) {}
+  CallbackCall() = default;
+
+  std::string Name;
+  std::vector<Argument> Arguments;
+};
+
+/// \brief This class overrides the PPCallbacks class for tracking preprocessor
+///   activity by means of its callback functions.
+///
+/// This object is given a vector for storing the trace information, built up
+/// of CallbackCall and subordinate Argument objects for representing the
+/// callback calls and their arguments.  It's a reference so the vector can
+/// exist beyond the lifetime of this object, because it's deleted by the
+/// preprocessor automatically in its destructor.
+///
+/// This class supports a mechanism for inhibiting trace output for
+/// specific callbacks by name, for the purpose of eliminating output for
+/// callbacks of no interest that might clutter the output.
+///
+/// Following the constructor and destructor function declarations, the
+/// overidden callback functions are defined.  The remaining functions are
+/// helpers for recording the trace data, to reduce the coupling between it
+/// and the recorded data structure.
+class PPCallbacksTracker : public clang::PPCallbacks {
+public:
+  /// \brief Note that all of the arguments are references, and owned
+  /// by the caller.
+  /// \param Ignore - Set of names of callbacks to ignore.
+  /// \param CallbackCalls - Trace buffer.
+  /// \param PP - The preprocessor.  Needed for getting some argument strings.
+  PPCallbacksTracker(llvm::SmallSet<std::string, 4> &Ignore,
+                     std::vector<CallbackCall> &CallbackCalls,
+                     clang::Preprocessor &PP);
+
+  ~PPCallbacksTracker() override;
+
+  // Overidden callback functions.
+
+  void FileChanged(clang::SourceLocation Loc,
+                   clang::PPCallbacks::FileChangeReason Reason,
+                   clang::SrcMgr::CharacteristicKind FileType,
+                   clang::FileID PrevFID = clang::FileID()) override;
+  void FileSkipped(const clang::FileEntry &SkippedFile,
+                   const clang::Token &FilenameTok,
+                   clang::SrcMgr::CharacteristicKind FileType) override;
+  bool FileNotFound(llvm::StringRef FileName,
+                    llvm::SmallVectorImpl<char> &RecoveryPath) override;
+  void InclusionDirective(clang::SourceLocation HashLoc,
+                          const clang::Token &IncludeTok,
+                          llvm::StringRef FileName, bool IsAngled,
+                          clang::CharSourceRange FilenameRange,
+                          const clang::FileEntry *File,
+                          llvm::StringRef SearchPath,
+                          llvm::StringRef RelativePath,
+                          const clang::Module *Imported,
+                          clang::SrcMgr::CharacteristicKind FileType) override;
+  void moduleImport(clang::SourceLocation ImportLoc, clang::ModuleIdPath Path,
+                    const clang::Module *Imported) override;
+  void EndOfMainFile() override;
+  void Ident(clang::SourceLocation Loc, llvm::StringRef str) override;
+  void PragmaDirective(clang::SourceLocation Loc,
+                       clang::PragmaIntroducerKind Introducer) override;
+  void PragmaComment(clang::SourceLocation Loc,
+                     const clang::IdentifierInfo *Kind,
+                     llvm::StringRef Str) override;
+  void PragmaDetectMismatch(clang::SourceLocation Loc, llvm::StringRef Name,
+                            llvm::StringRef Value) override;
+  void PragmaDebug(clang::SourceLocation Loc,
+                   llvm::StringRef DebugType) override;
+  void PragmaMessage(clang::SourceLocation Loc, llvm::StringRef Namespace,
+                     clang::PPCallbacks::PragmaMessageKind Kind,
+                     llvm::StringRef Str) override;
+  void PragmaDiagnosticPush(clang::SourceLocation Loc,
+                            llvm::StringRef Namespace) override;
+  void PragmaDiagnosticPop(clang::SourceLocation Loc,
+                           llvm::StringRef Namespace) override;
+  void PragmaDiagnostic(clang::SourceLocation Loc, llvm::StringRef Namespace,
+                        clang::diag::Severity mapping,
+                        llvm::StringRef Str) override;
+  void PragmaOpenCLExtension(clang::SourceLocation NameLoc,
+                             const clang::IdentifierInfo *Name,
+                             clang::SourceLocation StateLoc,
+                             unsigned State) override;
+  void PragmaWarning(clang::SourceLocation Loc, llvm::StringRef WarningSpec,
+                     llvm::ArrayRef<int> Ids) override;
+  void PragmaWarningPush(clang::SourceLocation Loc, int Level) override;
+  void PragmaWarningPop(clang::SourceLocation Loc) override;
+  void MacroExpands(const clang::Token &MacroNameTok,
+                    const clang::MacroDefinition &MD, clang::SourceRange Range,
+                    const clang::MacroArgs *Args) override;
+  void MacroDefined(const clang::Token &MacroNameTok,
+                    const clang::MacroDirective *MD) override;
+  void MacroUndefined(const clang::Token &MacroNameTok,
+                      const clang::MacroDefinition &MD,
+                      const clang::MacroDirective *Undef) override;
+  void Defined(const clang::Token &MacroNameTok,
+               const clang::MacroDefinition &MD,
+               clang::SourceRange Range) override;
+  void SourceRangeSkipped(clang::SourceRange Range,
+                          clang::SourceLocation EndifLoc) override;
+  void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
+          ConditionValueKind ConditionValue) override;
+  void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
+            ConditionValueKind ConditionValue, clang::SourceLocation IfLoc) override;
+  void Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
+             const clang::MacroDefinition &MD) override;
+  void Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
+              const clang::MacroDefinition &MD) override;
+  void Else(clang::SourceLocation Loc,
+            clang::SourceLocation IfLoc) override;
+  void Endif(clang::SourceLocation Loc,
+             clang::SourceLocation IfLoc) override;
+
+  // Helper functions.
+
+  /// \brief Start a new callback.
+  void beginCallback(const char *Name);
+
+  /// \brief Append a string to the top trace item.
+  void append(const char *Str);
+
+  /// \brief Append a bool argument to the top trace item.
+  void appendArgument(const char *Name, bool Value);
+
+  /// \brief Append an int argument to the top trace item.
+  void appendArgument(const char *Name, int Value);
+
+  /// \brief Append a string argument to the top trace item.
+  void appendArgument(const char *Name, const char *Value);
+
+  /// \brief Append a string reference object argument to the top trace item.
+  void appendArgument(const char *Name, llvm::StringRef Value);
+
+  /// \brief Append a string object argument to the top trace item.
+  void appendArgument(const char *Name, const std::string &Value);
+
+  /// \brief Append a token argument to the top trace item.
+  void appendArgument(const char *Name, const clang::Token &Value);
+
+  /// \brief Append an enum argument to the top trace item.
+  void appendArgument(const char *Name, int Value, const char *const Strings[]);
+
+  /// \brief Append a FileID argument to the top trace item.
+  void appendArgument(const char *Name, clang::FileID Value);
+
+  /// \brief Append a FileEntry argument to the top trace item.
+  void appendArgument(const char *Name, const clang::FileEntry *Value);
+
+  /// \brief Append a SourceLocation argument to the top trace item.
+  void appendArgument(const char *Name, clang::SourceLocation Value);
+
+  /// \brief Append a SourceRange argument to the top trace item.
+  void appendArgument(const char *Name, clang::SourceRange Value);
+
+  /// \brief Append a CharSourceRange argument to the top trace item.
+  void appendArgument(const char *Name, clang::CharSourceRange Value);
+
+  /// \brief Append a ModuleIdPath argument to the top trace item.
+  void appendArgument(const char *Name, clang::ModuleIdPath Value);
+
+  /// \brief Append an IdentifierInfo argument to the top trace item.
+  void appendArgument(const char *Name, const clang::IdentifierInfo *Value);
+
+  /// \brief Append a MacroDirective argument to the top trace item.
+  void appendArgument(const char *Name, const clang::MacroDirective *Value);
+
+  /// \brief Append a MacroDefinition argument to the top trace item.
+  void appendArgument(const char *Name, const clang::MacroDefinition &Value);
+
+  /// \brief Append a MacroArgs argument to the top trace item.
+  void appendArgument(const char *Name, const clang::MacroArgs *Value);
+
+  /// \brief Append a Module argument to the top trace item.
+  void appendArgument(const char *Name, const clang::Module *Value);
+
+  /// \brief Append a double-quoted argument to the top trace item.
+  void appendQuotedArgument(const char *Name, const std::string &Value);
+
+  /// \brief Append a double-quoted file path argument to the top trace item.
+  void appendFilePathArgument(const char *Name, llvm::StringRef Value);
+
+  /// \brief Get the raw source string of the range.
+  llvm::StringRef getSourceString(clang::CharSourceRange Range);
+
+  /// \brief Callback trace information.
+  /// We use a reference so the trace will be preserved for the caller
+  /// after this object is destructed.
+  std::vector<CallbackCall> &CallbackCalls;
+
+  /// \brief Names of callbacks to ignore.
+  llvm::SmallSet<std::string, 4> &Ignore;
+
+  /// \brief Inhibit trace while this is set.
+  bool DisableTrace;
+
+  clang::Preprocessor &PP;
+};
+
+#endif // PPTRACE_PPCALLBACKSTRACKER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/pp-trace/PPTrace.cpp b/src/third_party/llvm-project/clang-tools-extra/pp-trace/PPTrace.cpp
new file mode 100644
index 0000000..d49bc20
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/pp-trace/PPTrace.cpp
@@ -0,0 +1,233 @@
+//===--- tools/pp-trace/PPTrace.cpp - Clang preprocessor tracer -----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements pp-trace, a tool for displaying a textual trace
+// of the Clang preprocessor activity.  It's based on a derivation of the
+// PPCallbacks class, that once registerd with Clang, receives callback calls
+// to its virtual members, and outputs the information passed to the callbacks
+// in a high-level YAML format.
+//
+// The pp-trace tool also serves as the basis for a test of the PPCallbacks
+// mechanism.
+//
+// The pp-trace tool supports the following general command line format:
+//
+//    pp-trace [pp-trace options] (source file) [compiler options]
+//
+// Basically you put the pp-trace options first, then the source file or files,
+// and then any options you want to pass to the compiler.
+//
+// These are the pp-trace options:
+//
+//    -ignore (callback list)     Don't display output for a comma-separated
+//                                list of callbacks, i.e.:
+//                                  -ignore "FileChanged,InclusionDirective"
+//
+//    -output (file)              Output trace to the given file in a YAML
+//                                format, e.g.:
+//
+//                                  ---
+//                                  - Callback: Name
+//                                    Argument1: Value1
+//                                    Argument2: Value2
+//                                  (etc.)
+//                                  ...
+//
+// Future Directions:
+//
+// 1. Add option opposite to "-ignore" that specifys a comma-separated option
+// list of callbacs.  Perhaps "-only" or "-exclusive".
+//
+//===----------------------------------------------------------------------===//
+
+#include "PPCallbacksTracker.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Driver/Options.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include <algorithm>
+#include <fstream>
+#include <iterator>
+#include <string>
+#include <vector>
+
+using namespace clang;
+using namespace clang::driver;
+using namespace clang::driver::options;
+using namespace clang::tooling;
+using namespace llvm;
+using namespace llvm::opt;
+
+// Options:
+
+// Collect the source files.
+static cl::list<std::string> SourcePaths(cl::Positional,
+                                         cl::desc("<source0> [... <sourceN>]"),
+                                         cl::OneOrMore);
+
+// Option to specify a list or one or more callback names to ignore.
+static cl::opt<std::string> IgnoreCallbacks(
+    "ignore", cl::init(""),
+    cl::desc("Ignore callbacks, i.e. \"Callback1, Callback2...\"."));
+
+// Option to specify the trace output file name.
+static cl::opt<std::string> OutputFileName(
+    "output", cl::init(""),
+    cl::desc("Output trace to the given file name or '-' for stdout."));
+
+// Collect all other arguments, which will be passed to the front end.
+static cl::list<std::string>
+    CC1Arguments(cl::ConsumeAfter,
+                 cl::desc("<arguments to be passed to front end>..."));
+
+// Frontend action stuff:
+
+namespace {
+// Consumer is responsible for setting up the callbacks.
+class PPTraceConsumer : public ASTConsumer {
+public:
+  PPTraceConsumer(SmallSet<std::string, 4> &Ignore,
+                  std::vector<CallbackCall> &CallbackCalls, Preprocessor &PP) {
+    // PP takes ownership.
+    PP.addPPCallbacks(llvm::make_unique<PPCallbacksTracker>(Ignore,
+                                                            CallbackCalls, PP));
+  }
+};
+
+class PPTraceAction : public SyntaxOnlyAction {
+public:
+  PPTraceAction(SmallSet<std::string, 4> &Ignore,
+                std::vector<CallbackCall> &CallbackCalls)
+      : Ignore(Ignore), CallbackCalls(CallbackCalls) {}
+
+protected:
+  std::unique_ptr<clang::ASTConsumer>
+  CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override {
+    return llvm::make_unique<PPTraceConsumer>(Ignore, CallbackCalls,
+                                              CI.getPreprocessor());
+  }
+
+private:
+  SmallSet<std::string, 4> &Ignore;
+  std::vector<CallbackCall> &CallbackCalls;
+};
+
+class PPTraceFrontendActionFactory : public FrontendActionFactory {
+public:
+  PPTraceFrontendActionFactory(SmallSet<std::string, 4> &Ignore,
+                               std::vector<CallbackCall> &CallbackCalls)
+      : Ignore(Ignore), CallbackCalls(CallbackCalls) {}
+
+  PPTraceAction *create() override {
+    return new PPTraceAction(Ignore, CallbackCalls);
+  }
+
+private:
+  SmallSet<std::string, 4> &Ignore;
+  std::vector<CallbackCall> &CallbackCalls;
+};
+} // namespace
+
+// Output the trace given its data structure and a stream.
+static int outputPPTrace(std::vector<CallbackCall> &CallbackCalls,
+                         llvm::raw_ostream &OS) {
+  // Mark start of document.
+  OS << "---\n";
+
+  for (std::vector<CallbackCall>::const_iterator I = CallbackCalls.begin(),
+                                                 E = CallbackCalls.end();
+       I != E; ++I) {
+    const CallbackCall &Callback = *I;
+    OS << "- Callback: " << Callback.Name << "\n";
+
+    for (auto AI = Callback.Arguments.begin(), AE = Callback.Arguments.end();
+         AI != AE; ++AI) {
+      const Argument &Arg = *AI;
+      OS << "  " << Arg.Name << ": " << Arg.Value << "\n";
+    }
+  }
+
+  // Mark end of document.
+  OS << "...\n";
+
+  return 0;
+}
+
+// Program entry point.
+int main(int Argc, const char **Argv) {
+
+  // Parse command line.
+  cl::ParseCommandLineOptions(Argc, Argv, "pp-trace.\n");
+
+  // Parse the IgnoreCallbacks list into strings.
+  SmallVector<StringRef, 32> IgnoreCallbacksStrings;
+  StringRef(IgnoreCallbacks).split(IgnoreCallbacksStrings, ",",
+                                   /*MaxSplit=*/ -1, /*KeepEmpty=*/false);
+  SmallSet<std::string, 4> Ignore;
+  for (SmallVector<StringRef, 32>::iterator I = IgnoreCallbacksStrings.begin(),
+                                            E = IgnoreCallbacksStrings.end();
+       I != E; ++I)
+    Ignore.insert(*I);
+
+  // Create the compilation database.
+  SmallString<256> PathBuf;
+  sys::fs::current_path(PathBuf);
+  std::unique_ptr<CompilationDatabase> Compilations;
+  Compilations.reset(
+      new FixedCompilationDatabase(Twine(PathBuf), CC1Arguments));
+
+  // Store the callback trace information here.
+  std::vector<CallbackCall> CallbackCalls;
+
+  // Create the tool and run the compilation.
+  ClangTool Tool(*Compilations, SourcePaths);
+  PPTraceFrontendActionFactory Factory(Ignore, CallbackCalls);
+  int HadErrors = Tool.run(&Factory);
+
+  // If we had errors, exit early.
+  if (HadErrors)
+    return HadErrors;
+
+  // Do the output.
+  if (!OutputFileName.size()) {
+    HadErrors = outputPPTrace(CallbackCalls, llvm::outs());
+  } else {
+    // Set up output file.
+    std::error_code EC;
+    llvm::ToolOutputFile Out(OutputFileName, EC, llvm::sys::fs::F_Text);
+    if (EC) {
+      llvm::errs() << "pp-trace: error creating " << OutputFileName << ":"
+                   << EC.message() << "\n";
+      return 1;
+    }
+
+    HadErrors = outputPPTrace(CallbackCalls, Out.os());
+
+    // Tell ToolOutputFile that we want to keep the file.
+    if (HadErrors == 0)
+      Out.keep();
+  }
+
+  return HadErrors;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/.clang-format b/src/third_party/llvm-project/clang-tools-extra/test/.clang-format
new file mode 100644
index 0000000..4799b66
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/.clang-format
@@ -0,0 +1,2 @@
+BasedOnStyle: LLVM
+ColumnLimit: 0
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/test/CMakeLists.txt
new file mode 100644
index 0000000..fafe6c0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/CMakeLists.txt
@@ -0,0 +1,91 @@
+# Test runner infrastructure for Clang-based tools. This configures the Clang
+# test trees for use by Lit, and delegates to LLVM's lit test handlers.
+#
+# Note that currently we don't support stand-alone builds of Clang, you must
+# be building Clang from within a combined LLVM+Clang checkout..
+
+set(CLANG_TOOLS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
+set(CLANG_TOOLS_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/..")
+
+if (CMAKE_CFG_INTDIR STREQUAL ".")
+  set(LLVM_BUILD_MODE ".")
+else ()
+  set(LLVM_BUILD_MODE "%(build_mode)s")
+endif ()
+
+string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} CLANG_TOOLS_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR})
+
+llvm_canonicalize_cmake_booleans(
+  CLANG_ENABLE_STATIC_ANALYZER)
+
+configure_lit_site_cfg(
+  ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+  ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+  )
+
+configure_lit_site_cfg(
+  ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in
+  ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg
+  )
+
+option(CLANG_TOOLS_TEST_USE_VG "Run Clang tools' tests under Valgrind" OFF)
+if(CLANG_TOOLS_TEST_USE_VG)
+  set(CLANG_TOOLS_TEST_EXTRA_ARGS ${CLANG_TEST_EXTRA_ARGS} "--vg")
+endif()
+
+set(CLANG_TOOLS_TEST_DEPS
+  # For the clang-apply-replacements test that uses clang-rename.
+  clang-rename
+
+  # For the clang-doc tests that emit bitcode files.
+  llvm-bcanalyzer
+
+  # Individual tools we test.
+  clang-apply-replacements
+  clang-change-namespace
+  clangd
+  clang-doc
+  clang-include-fixer
+  clang-move
+  clang-query
+  clang-reorder-fields
+  find-all-symbols
+  modularize
+  pp-trace
+
+  # These individual tools have no tests, add them here to make them compile
+  # together with check-clang-tools, so that we won't break them in the future.
+  global-symbol-builder
+
+  # Unit tests
+  ExtraToolsUnitTests
+  )
+
+if(CLANG_ENABLE_STATIC_ANALYZER)
+  list(APPEND CLANG_TOOLS_TEST_DEPS
+    # For the clang-tidy libclang integration test.
+    c-index-test
+    # clang-tidy tests require it.
+    clang-headers
+
+    clang-tidy
+    )
+endif()
+
+set(llvm_utils
+  FileCheck count not
+  )
+
+foreach(t ${llvm_utils})
+  if(TARGET ${t})
+    list(APPEND CLANG_TOOLS_TEST_DEPS ${t})
+  endif()
+endforeach()
+
+add_lit_testsuite(check-clang-tools "Running the Clang extra tools' regression tests"
+  ${CMAKE_CURRENT_BINARY_DIR}
+  DEPENDS ${CLANG_TOOLS_TEST_DEPS}
+  ARGS ${CLANG_TOOLS_TEST_EXTRA_ARGS}
+  )
+
+set_target_properties(check-clang-tools PROPERTIES FOLDER "Clang extra tools' tests")
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/Unit/lit.cfg b/src/third_party/llvm-project/clang-tools-extra/test/Unit/lit.cfg
new file mode 100644
index 0000000..b40e1ca
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/Unit/lit.cfg
@@ -0,0 +1,37 @@
+# -*- Python -*-
+
+import platform
+
+import lit.formats
+
+config.name = "Extra Tools Unit Tests"
+config.suffixes = [] # Seems not to matter for google tests?
+
+# Test Source and Exec root dirs both point to the same directory where google
+# test binaries are built.
+
+config.test_source_root = config.extra_tools_obj_dir
+config.test_exec_root = config.test_source_root
+
+# All GoogleTests are named to have 'Tests' as their suffix. The '.' option is
+# a special value for GoogleTest indicating that it should look through the
+# entire testsuite recursively for tests (alternatively, one could provide a
+# ;-separated list of subdirectories).
+config.test_format = lit.formats.GoogleTest('.', 'Tests')
+
+if platform.system() == 'Darwin':
+    shlibpath_var = 'DYLD_LIBRARY_PATH'
+elif platform.system() == 'Windows':
+    shlibpath_var = 'PATH'
+else:
+    shlibpath_var = 'LD_LIBRARY_PATH'
+
+# Point the dynamic loader at dynamic libraries in 'lib'.
+shlibpath = os.path.pathsep.join((config.shlibdir, config.llvm_libs_dir,
+                                 config.environment.get(shlibpath_var,'')))
+
+# Win32 seeks DLLs along %PATH%.
+if sys.platform in ['win32', 'cygwin'] and os.path.isdir(config.shlibdir):
+    shlibpath = os.path.pathsep.join((config.shlibdir, shlibpath))
+
+config.environment[shlibpath_var] = shlibpath
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/Unit/lit.site.cfg.in b/src/third_party/llvm-project/clang-tools-extra/test/Unit/lit.site.cfg.in
new file mode 100644
index 0000000..69a5cd5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/Unit/lit.site.cfg.in
@@ -0,0 +1,9 @@
+@LIT_SITE_CFG_IN_HEADER@
+
+config.extra_tools_obj_dir = "@CLANG_TOOLS_BINARY_DIR@/unittests"
+config.extra_tools_src_dir = "@CLANG_TOOLS_SOURCE_DIR@/unittests"
+config.llvm_libs_dir = "@LLVM_LIBS_DIR@"
+config.shlibdir = "@SHLIBDIR@"
+config.target_triple = "@TARGET_TRIPLE@"
+
+lit_config.load_config(config, "@CLANG_TOOLS_SOURCE_DIR@/test/Unit/lit.cfg")
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/change-namespace/Inputs/fake-std.h b/src/third_party/llvm-project/clang-tools-extra/test/change-namespace/Inputs/fake-std.h
new file mode 100644
index 0000000..24d3f97
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/change-namespace/Inputs/fake-std.h
@@ -0,0 +1,5 @@
+namespace std {
+  class STD {};
+}
+
+using namespace std;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/change-namespace/lambda-function.cpp b/src/third_party/llvm-project/clang-tools-extra/test/change-namespace/lambda-function.cpp
new file mode 100644
index 0000000..452983e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/change-namespace/lambda-function.cpp
@@ -0,0 +1,37 @@
+// RUN: clang-change-namespace -old_namespace "na::nb" -new_namespace "x::y" --file_pattern ".*" %s -- -std=c++11 | sed 's,// CHECK.*,,' | FileCheck %s
+
+template <class T>
+class function;
+template <class R, class... ArgTypes>
+class function<R(ArgTypes...)> {
+public:
+  template <typename Functor>
+  function(Functor f) {}
+  R operator()(ArgTypes...) const {}
+};
+
+namespace x {
+// CHECK: namespace x {
+class X {};
+}
+
+namespace na {
+namespace nb {
+// CHECK: namespace x {
+// CHECK-NEXT: namespace y {
+void f(function<void(int)> func, int param) { func(param); }
+void g() { f([](int x) {}, 1); }
+
+// x::X in function type parameter list will have translation unit context, so
+// we simply replace it with fully-qualified name.
+using TX = function<x::X(x::X)>;
+// CHECK: using TX = function<X(x::X)>;
+
+class A {};
+using TA = function<A(A)>;
+// CHECK: using TA = function<A(A)>;
+
+// CHECK: } // namespace y
+// CHECK-NEXT: } // namespace x
+}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/change-namespace/macro.cpp b/src/third_party/llvm-project/clang-tools-extra/test/change-namespace/macro.cpp
new file mode 100644
index 0000000..ba47de6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/change-namespace/macro.cpp
@@ -0,0 +1,29 @@
+// RUN: cp %S/macro.cpp %T/macro.cpp
+// RUN: echo "#define USING using na::nc::X" > %T/macro.h
+//
+// RUN: clang-change-namespace -old_namespace "na::nb" -new_namespace "x::y" --file_pattern "macro.cpp" --i %T/macro.cpp --
+// RUN: FileCheck -input-file=%T/macro.cpp -check-prefix=CHECK-CC %s
+// RUN: FileCheck -input-file=%T/macro.h -check-prefix=CHECK-HEADER %s
+//
+// RUN: cp %S/macro.cpp %T/macro.cpp
+// RUN: echo "#define USING using na::nc::X" > %T/macro.h
+// RUN: clang-change-namespace -old_namespace "na::nb" -new_namespace "x::y" --file_pattern ".*" --i %T/macro.cpp --
+// RUN: FileCheck -input-file=%T/macro.cpp -check-prefix=CHECK-CC %s
+// RUN: FileCheck -input-file=%T/macro.h -check-prefix=CHECK-CHANGED-HEADER %s
+#include "macro.h"
+namespace na { namespace nc { class X{}; } }
+
+namespace na {
+namespace nb {
+USING;
+}
+}
+// CHECK-CC: namespace x {
+// CHECK-CC: namespace y {
+// CHECK-CC: USING;
+// CHECK-CC: } // namespace y
+// CHECK-CC: } // namespace x
+
+// CHECK-HEADER: #define USING using na::nc::X
+
+// CHECK-CHANGED-HEADER: #define USING using ::na::nc::X
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/change-namespace/simple-move.cpp b/src/third_party/llvm-project/clang-tools-extra/test/change-namespace/simple-move.cpp
new file mode 100644
index 0000000..ea3c3d3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/change-namespace/simple-move.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-change-namespace -old_namespace "na::nb" -new_namespace "x::y" --file_pattern ".*" %s -- | sed 's,// CHECK.*,,' | FileCheck %s
+// CHECK: namespace x {
+// CHECK-NEXT: namespace y {
+namespace na {
+namespace nb {
+class A {};
+// CHECK: } // namespace y
+// CHECK-NEXT: } // namespace x
+}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/change-namespace/white-list.cpp b/src/third_party/llvm-project/clang-tools-extra/test/change-namespace/white-list.cpp
new file mode 100644
index 0000000..48e3a78
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/change-namespace/white-list.cpp
@@ -0,0 +1,19 @@
+// RUN: echo "^std::.*$" > %T/white-list.txt
+// RUN: clang-change-namespace -old_namespace "na::nb" -new_namespace "x::y" --file_pattern ".*" --whitelist_file %T/white-list.txt %s -- | sed 's,// CHECK.*,,' | FileCheck %s
+
+#include "Inputs/fake-std.h"
+
+// CHECK: namespace x {
+// CHECK-NEXT: namespace y {
+namespace na {
+namespace nb {
+void f() {
+  std::STD x1;
+  STD x2;
+// CHECK: {{^}}  std::STD x1;{{$}}
+// CHECK-NEXT: {{^}}  STD x2;{{$}}
+}
+// CHECK: } // namespace y
+// CHECK-NEXT: } // namespace x
+}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/ClangRenameClassReplacements.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/ClangRenameClassReplacements.cpp
new file mode 100644
index 0000000..2b478bb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/ClangRenameClassReplacements.cpp
@@ -0,0 +1,11 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/fixes
+// RUN: cat %s > %t.cpp
+// RUN: clang-rename -offset=254 -new-name=Bar -export-fixes=%t/fixes/clang-rename.yaml %t.cpp --
+// RUN: clang-apply-replacements %t
+// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
+
+class Foo {}; // CHECK: class Bar {};
+
+// Use grep -FUbo 'Foo' <file> to get the correct offset of Cla when changing
+// this file.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/basic/basic.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/basic/basic.h
new file mode 100644
index 0000000..4850968
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/basic/basic.h
@@ -0,0 +1,32 @@
+#ifndef BASIC_H
+#define BASIC_H
+
+
+class Parent {
+public:
+  virtual void func() {}
+};
+
+class Derived : public Parent {
+public:
+  virtual void func() {}
+  // CHECK: virtual void func() override {}
+};
+
+extern void ext(int (&)[5], const Parent &);
+
+void func(int t) {
+  int ints[5];
+  for (unsigned i = 0; i < 5; ++i) {
+    int &e = ints[i];
+    e = t;
+    // CHECK: for (auto & elem : ints) {
+    // CHECK-NEXT: elem = t;
+  }
+
+  Derived d;
+
+  ext(ints, d);
+}
+
+#endif // BASIC_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/basic/file1.yaml b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/basic/file1.yaml
new file mode 100644
index 0000000..3a5375e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/basic/file1.yaml
@@ -0,0 +1,25 @@
+---
+MainSourceFile:     source1.cpp
+Diagnostics:
+  - DiagnosticName: test-basic
+    Message: Fix
+    FilePath: $(path)/basic.h
+    FileOffset: 242
+    Replacements:
+      - FilePath:        $(path)/basic.h
+        Offset:          242
+        Length:          26
+        ReplacementText: 'auto & elem : ints'
+      - FilePath:        $(path)/basic.h
+        Offset:          276
+        Length:          22
+        ReplacementText: ''
+      - FilePath:        $(path)/basic.h
+        Offset:          298
+        Length:          1
+        ReplacementText: elem
+      - FilePath:        $(path)/../basic/basic.h
+        Offset:          148
+        Length:          0
+        ReplacementText: 'override '
+...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/basic/file2.yaml b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/basic/file2.yaml
new file mode 100644
index 0000000..8f6f65a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/basic/file2.yaml
@@ -0,0 +1,13 @@
+---
+MainSourceFile:     source2.cpp
+Diagnostics:
+  - DiagnosticName: test-basic
+    Message: Fix
+    FilePath: $(path)/basic.h
+    FileOffset: 148
+    Replacements:
+      - FilePath:        $(path)/../basic/basic.h
+        Offset:          298
+        Length:          1
+        ReplacementText: elem
+...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/conflict/common.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/conflict/common.h
new file mode 100644
index 0000000..630a39a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/conflict/common.h
@@ -0,0 +1,17 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+extern void ext(int (&)[5]);
+
+void func(int t) {
+  int ints[5];
+  for (unsigned i = 0; i < 5; ++i) {
+    ints[i] = t;
+  }
+
+  int *i = 0;
+
+  ext(ints);
+}
+
+#endif // COMMON_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/conflict/expected.txt b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/conflict/expected.txt
new file mode 100644
index 0000000..b66f577
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/conflict/expected.txt
@@ -0,0 +1,12 @@
+The new replacement overlaps with an existing replacement.
+New replacement: $(path)/common.h: 106:+26:"int & elem : ints"
+Existing replacement: $(path)/common.h: 106:+26:"auto & i : ints"
+The new replacement overlaps with an existing replacement.
+New replacement: $(path)/common.h: 140:+7:"i"
+Existing replacement: $(path)/common.h: 140:+7:"elem"
+The new replacement overlaps with an existing replacement.
+New replacement: $(path)/common.h: 169:+0:"(int*)"
+Existing replacement: $(path)/common.h: 160:+12:""
+The new replacement overlaps with an existing replacement.
+New replacement: $(path)/common.h: 169:+1:"nullptr"
+Existing replacement: $(path)/common.h: 160:+12:""
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/conflict/file1.yaml b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/conflict/file1.yaml
new file mode 100644
index 0000000..8505273
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/conflict/file1.yaml
@@ -0,0 +1,21 @@
+---
+MainSourceFile: source1.cpp
+Diagnostics:
+  - DiagnosticName: test-conflict
+    Message: Fix
+    FilePath: $(path)/common.h
+    FileOffset: 106
+    Replacements:
+      - FilePath:        $(path)/common.h
+        Offset:          106
+        Length:          26
+        ReplacementText: 'auto & i : ints'
+      - FilePath:        $(path)/common.h
+        Offset:          140
+        Length:          7
+        ReplacementText: i
+      - FilePath:        $(path)/common.h
+        Offset:          160
+        Length:          12
+        ReplacementText: ''
+...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/conflict/file2.yaml b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/conflict/file2.yaml
new file mode 100644
index 0000000..32b35ac
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/conflict/file2.yaml
@@ -0,0 +1,21 @@
+---
+MainSourceFile: source2.cpp
+Diagnostics:
+  - DiagnosticName:  test-conflict
+    Message: Fix
+    FilePath: $(path)/common.h
+    FileOffset: 106
+    Replacements:
+      - FilePath:        $(path)/common.h
+        Offset:          106
+        Length:          26
+        ReplacementText: 'int & elem : ints'
+      - FilePath:        $(path)/common.h
+        Offset:          140
+        Length:          7
+        ReplacementText: elem
+      - FilePath:        $(path)/common.h
+        Offset:          169
+        Length:          1
+        ReplacementText: nullptr
+...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/conflict/file3.yaml b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/conflict/file3.yaml
new file mode 100644
index 0000000..88543e0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/conflict/file3.yaml
@@ -0,0 +1,13 @@
+---
+MainSourceFile: source1.cpp
+Diagnostics:
+  - DiagnosticName:  test-conflict
+    Message: Fix
+    FilePath: $(path)/common.h
+    FileOffset: 169
+    Replacements:
+      - FilePath:        $(path)/common.h
+        Offset:          169
+        Length:          0
+        ReplacementText: "(int*)"
+...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/crlf/crlf.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/crlf/crlf.cpp
new file mode 100644
index 0000000..26f7996
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/crlf/crlf.cpp
@@ -0,0 +1,6 @@
+

+// This file intentionally uses a CRLF newlines!

+

+void foo() {

+  int *x = 0;

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/crlf/crlf.cpp.expected b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/crlf/crlf.cpp.expected
new file mode 100644
index 0000000..ad8e907
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/crlf/crlf.cpp.expected
@@ -0,0 +1,6 @@
+

+// This file intentionally uses a CRLF newlines!

+

+void foo() {

+  int *x = nullptr;

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/crlf/file1.yaml b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/crlf/file1.yaml
new file mode 100644
index 0000000..06b058e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/crlf/file1.yaml
@@ -0,0 +1,13 @@
+---
+MainSourceFile:      source1.cpp
+Diagnostics:
+  - DiagnosticName:  test-crlf
+    Message: Fix
+    FilePath: $(path)/crlf.cpp
+    FileOffset: 79
+    Replacements:
+      - FilePath:        $(path)/crlf.cpp
+        Offset:          79
+        Length:          1
+        ReplacementText: nullptr
+...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/format/no.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/format/no.cpp
new file mode 100644
index 0000000..5bc9081
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/format/no.cpp
@@ -0,0 +1,6 @@
+class C {};
+
+void f() { // This comment necessary to prevent formatting as void f() { ... }
+  C *a = new C();
+  // CHECK: {{^\ \ auto\ a\ \=\ new\ C\(\);}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/format/no.yaml b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/format/no.yaml
new file mode 100644
index 0000000..3118cc6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/format/no.yaml
@@ -0,0 +1,13 @@
+---
+MainSourceFile:  no.cpp
+Diagnostics:
+  - DiagnosticName:  test-no
+    Message: Fix
+    FilePath: $(path)/no.cpp
+    FileOffset: 94
+    Replacements:
+      - FilePath:        $(path)/no.cpp
+        Offset:          94
+        Length:          3
+        ReplacementText: 'auto '
+...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/format/yes.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/format/yes.cpp
new file mode 100644
index 0000000..8f600c3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/format/yes.cpp
@@ -0,0 +1,22 @@
+class MyType012345678901234567890123456789 {};
+
+void g(int, int*, int, int*, int, int*, int);
+
+void f() {
+  MyType012345678901234567890123456789 *a =
+      new MyType012345678901234567890123456789();
+  // CHECK: {{^\ \ auto\ a\ \=\ new\ MyType012345678901234567890123456789\(\);}}
+
+  int iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii;
+  int jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj;
+  int kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk;
+  int mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm;
+  g(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii, 0, jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj,
+    0, kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk, 0, mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm);
+  // CHECK: g(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii, nullptr,
+  // CHECK-NEXT: jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj, nullptr,
+  // CHECK-NEXT: kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk, nullptr,
+  // CHECK-NEXT: mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm);
+
+  delete a;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/format/yes.yaml b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/format/yes.yaml
new file mode 100644
index 0000000..6ded4db
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/format/yes.yaml
@@ -0,0 +1,27 @@
+# These replacements are out of order on purpose to test that they get sorted
+# so that formatting happens correctly.
+---
+MainSourceFile:  yes.cpp
+Diagnostics:
+  - DiagnosticName:  test-yes
+    Message: Fix
+    FilePath: $(path)/yes.cpp
+    FileOffset: 494
+    Replacements:
+      - FilePath:        $(path)/yes.cpp
+        Offset:          494
+        Length:          1
+        ReplacementText: nullptr
+      - FilePath:        $(path)/yes.cpp
+        Offset:          410
+        Length:          1
+        ReplacementText: nullptr
+      - FilePath:        $(path)/yes.cpp
+        Offset:          454
+        Length:          1
+        ReplacementText: nullptr
+      - FilePath:        $(path)/yes.cpp
+        Offset:          108
+        Length:          38
+        ReplacementText: 'auto '
+...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/identical/file1.yaml b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/identical/file1.yaml
new file mode 100644
index 0000000..1ef5651
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/identical/file1.yaml
@@ -0,0 +1,18 @@
+---
+MainSourceFile:     identical.cpp
+Diagnostics:
+  - DiagnosticName: test-identical-insertion
+    Message: Fix
+    FilePath: $(path)/identical.cpp
+    FileOffset: 12
+    Replacements:
+      - FilePath:        $(path)/identical.cpp
+        Offset:          12
+        Length:          0
+        ReplacementText: '0'
+      - FilePath:        $(path)/identical.cpp
+        Offset:          12
+        Length:          0
+        ReplacementText: '0'
+...
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/identical/identical.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/identical/identical.cpp
new file mode 100644
index 0000000..bdaab4f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/identical/identical.cpp
@@ -0,0 +1,2 @@
+class MyType {};
+// CHECK: class MyType00 {};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/invalid-files/invalid-files.yaml b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/invalid-files/invalid-files.yaml
new file mode 100644
index 0000000..f84964d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/invalid-files/invalid-files.yaml
@@ -0,0 +1,12 @@
+---
+MainSourceFile:  ''
+Replacements:
+  - FilePath:        idontexist.h
+    Offset:          2669
+    Length:          0
+    ReplacementText: ' override'
+  - FilePath:        idontexist.h
+    Offset:          2669
+    Length:          0
+    ReplacementText: ' override'
+...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/order-dependent/expected.txt b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/order-dependent/expected.txt
new file mode 100644
index 0000000..cf38b34
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/order-dependent/expected.txt
@@ -0,0 +1,3 @@
+The new insertion has the same insert location as an existing replacement.
+New replacement: $(path)/order-dependent.cpp: 12:+0:"1"
+Existing replacement: $(path)/order-dependent.cpp: 12:+0:"0"
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/order-dependent/file1.yaml b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/order-dependent/file1.yaml
new file mode 100644
index 0000000..a823438
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/order-dependent/file1.yaml
@@ -0,0 +1,13 @@
+---
+MainSourceFile:     order-dependent.cpp
+Diagnostics:
+  - DiagnosticName: test-order-dependent-insertion
+    Message: Fix
+    FilePath: $(path)/order-dependent.cpp
+    FileOffset: 12
+    Replacements:
+      - FilePath:        $(path)/order-dependent.cpp
+        Offset:          12
+        Length:          0
+        ReplacementText: '0'
+...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/order-dependent/file2.yaml b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/order-dependent/file2.yaml
new file mode 100644
index 0000000..634d3ca
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/order-dependent/file2.yaml
@@ -0,0 +1,13 @@
+---
+MainSourceFile:     order-dependent.cpp
+Diagnostics:
+  - DiagnosticName: test-order-dependent-insertion
+    Message: Fix
+    FilePath: $(path)/order-dependent.cpp
+    FileOffset: 12
+    Replacements:
+      - FilePath:        $(path)/order-dependent.cpp
+        Offset:          12
+        Length:          0
+        ReplacementText: '1'
+...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/order-dependent/order-dependent.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/order-dependent/order-dependent.cpp
new file mode 100644
index 0000000..5b98860
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/Inputs/order-dependent/order-dependent.cpp
@@ -0,0 +1 @@
+class MyType {};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/basic.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/basic.cpp
new file mode 100644
index 0000000..4f19a96
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/basic.cpp
@@ -0,0 +1,17 @@
+// RUN: mkdir -p %T/Inputs/basic
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/basic/basic.h > %T/Inputs/basic/basic.h
+// RUN: sed "s#\$(path)#%/T/Inputs/basic#" %S/Inputs/basic/file1.yaml > %T/Inputs/basic/file1.yaml
+// RUN: sed "s#\$(path)#%/T/Inputs/basic#" %S/Inputs/basic/file2.yaml > %T/Inputs/basic/file2.yaml
+// RUN: clang-apply-replacements %T/Inputs/basic
+// RUN: FileCheck -input-file=%T/Inputs/basic/basic.h %S/Inputs/basic/basic.h
+//
+// Check that the yaml files are *not* deleted after running clang-apply-replacements without remove-change-desc-files.
+// RUN: ls -1 %T/Inputs/basic | FileCheck %s --check-prefix=YAML
+//
+// Check that the yaml files *are* deleted after running clang-apply-replacements with remove-change-desc-files.
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/basic/basic.h > %T/Inputs/basic/basic.h
+// RUN: clang-apply-replacements -remove-change-desc-files %T/Inputs/basic
+// RUN: ls -1 %T/Inputs/basic | FileCheck %s --check-prefix=NO_YAML
+//
+// YAML: {{^file.\.yaml$}}
+// NO_YAML-NOT: {{^file.\.yaml$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/conflict.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/conflict.cpp
new file mode 100644
index 0000000..c1f2342
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/conflict.cpp
@@ -0,0 +1,17 @@
+// RUN: mkdir -p %T/Inputs/conflict
+// RUN: sed "s#\$(path)#%/S/Inputs/conflict#" %S/Inputs/conflict/file1.yaml > %T/Inputs/conflict/file1.yaml
+// RUN: sed "s#\$(path)#%/S/Inputs/conflict#" %S/Inputs/conflict/file2.yaml > %T/Inputs/conflict/file2.yaml
+// RUN: sed "s#\$(path)#%/S/Inputs/conflict#" %S/Inputs/conflict/file3.yaml > %T/Inputs/conflict/file3.yaml
+// RUN: sed "s#\$(path)#%/S/Inputs/conflict#" %S/Inputs/conflict/expected.txt > %T/Inputs/conflict/expected.txt
+// RUN: not clang-apply-replacements %T/Inputs/conflict > %T/Inputs/conflict/output.txt 2>&1
+// RUN: diff -b %T/Inputs/conflict/output.txt %T/Inputs/conflict/expected.txt
+//
+// Check that the yaml files are *not* deleted after running clang-apply-replacements without remove-change-desc-files even when there is a failure.
+// RUN: ls -1 %T/Inputs/conflict | FileCheck %s --check-prefix=YAML
+//
+// Check that the yaml files *are* deleted after running clang-apply-replacements with remove-change-desc-files even when there is a failure.
+// RUN: not clang-apply-replacements %T/Inputs/conflict -remove-change-desc-files > %T/Inputs/conflict/output.txt 2>&1
+// RUN: ls -1 %T/Inputs/conflict | FileCheck %s --check-prefix=NO_YAML
+//
+// YAML: {{^file.\.yaml$}}
+// NO_YAML-NOT: {{^file.\.yaml$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/crlf.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/crlf.cpp
new file mode 100644
index 0000000..15ba5b5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/crlf.cpp
@@ -0,0 +1,5 @@
+// RUN: mkdir -p %T/Inputs/crlf
+// RUN: cat %S/Inputs/crlf/crlf.cpp > %T/Inputs/crlf/crlf.cpp
+// RUN: sed "s#\$(path)#%/T/Inputs/crlf#" %S/Inputs/crlf/file1.yaml > %T/Inputs/crlf/file1.yaml
+// RUN: clang-apply-replacements %T/Inputs/crlf
+// RUN: diff %T/Inputs/crlf/crlf.cpp %S/Inputs/crlf/crlf.cpp.expected
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/format.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/format.cpp
new file mode 100644
index 0000000..7de320d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/format.cpp
@@ -0,0 +1,15 @@
+// RUN: mkdir -p %T/Inputs/format
+//
+// yes.cpp requires formatting after replacements are applied. no.cpp does not.
+// The presence of no.cpp ensures that files that don't need formatting still
+// have their new state written to disk after applying replacements.
+//
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/format/yes.cpp > %T/Inputs/format/yes.cpp
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/format/no.cpp > %T/Inputs/format/no.cpp
+// RUN: sed "s#\$(path)#%/T/Inputs/format#" %S/Inputs/format/yes.yaml > %T/Inputs/format/yes.yaml
+// RUN: sed "s#\$(path)#%/T/Inputs/format#" %S/Inputs/format/no.yaml > %T/Inputs/format/no.yaml
+// RUN: clang-apply-replacements -format %T/Inputs/format
+// RUN: FileCheck --strict-whitespace -input-file=%T/Inputs/format/yes.cpp %S/Inputs/format/yes.cpp
+// RUN: FileCheck --strict-whitespace -input-file=%T/Inputs/format/no.cpp %S/Inputs/format/no.cpp
+//
+// RUN not clang-apply-replacements -format=blah %T/Inputs/format
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/identical.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/identical.cpp
new file mode 100644
index 0000000..b513f3e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/identical.cpp
@@ -0,0 +1,5 @@
+// RUN: mkdir -p %T/Inputs/identical
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/identical/identical.cpp > %T/Inputs/identical/identical.cpp
+// RUN: sed "s#\$(path)#%/T/Inputs/identical#" %S/Inputs/identical/file1.yaml > %T/Inputs/identical/file1.yaml
+// RUN: clang-apply-replacements %T/Inputs/identical
+// RUN: FileCheck -input-file=%T/Inputs/identical/identical.cpp %S/Inputs/identical/identical.cpp
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/invalid-files.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/invalid-files.cpp
new file mode 100644
index 0000000..b0eb9ef
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/invalid-files.cpp
@@ -0,0 +1,6 @@
+// RUN: mkdir -p %T/invalid-files
+// RUN: cp %S/Inputs/invalid-files/invalid-files.yaml %T/invalid-files/invalid-files.yaml
+// RUN: clang-apply-replacements %T/invalid-files
+//
+// Check that the yaml files are *not* deleted after running clang-apply-replacements without remove-change-desc-files.
+// RUN: ls %T/invalid-files/invalid-files.yaml
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/order-dependent.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/order-dependent.cpp
new file mode 100644
index 0000000..769f4f7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-apply-replacements/order-dependent.cpp
@@ -0,0 +1,7 @@
+// RUN: mkdir -p %T/Inputs/order-dependent
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/order-dependent/order-dependent.cpp > %T/Inputs/order-dependent/order-dependent.cpp
+// RUN: sed "s#\$(path)#%/T/Inputs/order-dependent#" %S/Inputs/order-dependent/file1.yaml > %T/Inputs/order-dependent/file1.yaml
+// RUN: sed "s#\$(path)#%/T/Inputs/order-dependent#" %S/Inputs/order-dependent/file2.yaml > %T/Inputs/order-dependent/file2.yaml
+// RUN: sed "s#\$(path)#%/T/Inputs/order-dependent#" %S/Inputs/order-dependent/expected.txt > %T/Inputs/order-dependent/expected.txt
+// RUN: not clang-apply-replacements %T/Inputs/order-dependent > %T/Inputs/order-dependent/output.txt 2>&1
+// RUN: diff -b %T/Inputs/order-dependent/output.txt %T/Inputs/order-dependent/expected.txt
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/bc-comment.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/bc-comment.cpp
new file mode 100644
index 0000000..fa3ea7f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/bc-comment.cpp
@@ -0,0 +1,202 @@
+// THIS IS A GENERATED TEST. DO NOT EDIT.
+// To regenerate, see clang-doc/gen_test.py docstring.
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+
+/// \brief Brief description.
+///
+/// Extended description that
+/// continues onto the next line.
+/// 
+/// <ul class="test">
+///   <li> Testing.
+/// </ul>
+///
+/// \verbatim
+/// The description continues.
+/// \endverbatim
+/// --
+/// \param [out] I is a parameter.
+/// \param J is a parameter.
+/// \return void
+void F(int I, int J);
+
+/// Bonus comment on definition
+void F(int I, int J) {}
+
+// RUN: clang-doc --dump-intermediate --doxygen -p %t %t/test.cpp -output=%t/docs
+
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/7574630614A535710E5A6ABCFFF98BCA2D06A4CA.bc | FileCheck %s --check-prefix CHECK-0
+// CHECK-0: <BLOCKINFO_BLOCK/>
+// CHECK-0-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-0-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-0-NEXT: </VersionBlock>
+// CHECK-0-NEXT: <FunctionBlock NumWords=429 BlockCodeSize=4>
+// CHECK-0-NEXT:   <USR abbrevid=4 op0=20 op1=117 op2=116 op3=99 op4=6 op5=20 op6=165 op7=53 op8=113 op9=14 op10=90 op11=106 op12=188 op13=255 op14=249 op15=139 op16=202 op17=45 op18=6 op19=164 op20=202/>
+// CHECK-0-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'F'
+// CHECK-0-NEXT:   <CommentBlock NumWords=354 BlockCodeSize=4>
+// CHECK-0-NEXT:     <Kind abbrevid=4 op0=11/> blob data = 'FullComment'
+// CHECK-0-NEXT:     <CommentBlock NumWords=13 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment'
+// CHECK-0-NEXT:       <CommentBlock NumWords=5 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:     </CommentBlock>
+// CHECK-0-NEXT:     <CommentBlock NumWords=31 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Kind abbrevid=4 op0=19/> blob data = 'BlockCommandComment'
+// CHECK-0-NEXT:       <Name abbrevid=6 op0=5/> blob data = 'brief'
+// CHECK-0-NEXT:       <CommentBlock NumWords=19 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment'
+// CHECK-0-NEXT:         <CommentBlock NumWords=11 BlockCodeSize=4>
+// CHECK-0-NEXT:           <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:           <Text abbrevid=5 op0=19/> blob data = ' Brief description.'
+// CHECK-0-NEXT:         </CommentBlock>
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:     </CommentBlock>
+// CHECK-0-NEXT:     <CommentBlock NumWords=37 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment'
+// CHECK-0-NEXT:       <CommentBlock NumWords=13 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:         <Text abbrevid=5 op0=26/> blob data = ' Extended description that'
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:       <CommentBlock NumWords=14 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:         <Text abbrevid=5 op0=30/> blob data = ' continues onto the next line.'
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:     </CommentBlock>
+// CHECK-0-NEXT:     <CommentBlock NumWords=76 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment'
+// CHECK-0-NEXT:       <CommentBlock NumWords=5 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:       <CommentBlock NumWords=14 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=19/> blob data = 'HTMLStartTagComment'
+// CHECK-0-NEXT:         <Name abbrevid=6 op0=2/> blob data = 'ul'
+// CHECK-0-NEXT:         <AttrKey abbrevid=12 op0=5/> blob data = 'class'
+// CHECK-0-NEXT:         <AttrVal abbrevid=13 op0=4/> blob data = '{{.*}}'
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:       <CommentBlock NumWords=5 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:       <CommentBlock NumWords=9 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=19/> blob data = 'HTMLStartTagComment'
+// CHECK-0-NEXT:         <Name abbrevid=6 op0=2/> blob data = 'li'
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:       <CommentBlock NumWords=9 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:         <Text abbrevid=5 op0=9/> blob data = ' Testing.'
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:       <CommentBlock NumWords=5 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:       <CommentBlock NumWords=9 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=17/> blob data = 'HTMLEndTagComment'
+// CHECK-0-NEXT:         <Name abbrevid=6 op0=2/> blob data = 'ul'
+// CHECK-0-NEXT:         <SelfClosing abbrevid=10 op0=1/>
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:     </CommentBlock>
+// CHECK-0-NEXT:     <CommentBlock NumWords=13 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment'
+// CHECK-0-NEXT:       <CommentBlock NumWords=5 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:     </CommentBlock>
+// CHECK-0-NEXT:     <CommentBlock NumWords=32 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Kind abbrevid=4 op0=20/> blob data = 'VerbatimBlockComment'
+// CHECK-0-NEXT:       <Name abbrevid=6 op0=8/> blob data = 'verbatim'
+// CHECK-0-NEXT:       <CloseName abbrevid=9 op0=11/> blob data = 'endverbatim'
+// CHECK-0-NEXT:       <CommentBlock NumWords=16 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=24/> blob data = 'VerbatimBlockLineComment'
+// CHECK-0-NEXT:         <Text abbrevid=5 op0=27/> blob data = ' The description continues.'
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:     </CommentBlock>
+// CHECK-0-NEXT:     <CommentBlock NumWords=22 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment'
+// CHECK-0-NEXT:       <CommentBlock NumWords=7 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:         <Text abbrevid=5 op0=3/> blob data = ' --'
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:       <CommentBlock NumWords=5 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:     </CommentBlock>
+// CHECK-0-NEXT:     <CommentBlock NumWords=39 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Kind abbrevid=4 op0=19/> blob data = 'ParamCommandComment'
+// CHECK-0-NEXT:       <Direction abbrevid=7 op0=5/> blob data = '[out]'
+// CHECK-0-NEXT:       <ParamName abbrevid=8 op0=1/> blob data = 'I'
+// CHECK-0-NEXT:       <Explicit abbrevid=11 op0=1/>
+// CHECK-0-NEXT:       <CommentBlock NumWords=25 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment'
+// CHECK-0-NEXT:         <CommentBlock NumWords=10 BlockCodeSize=4>
+// CHECK-0-NEXT:           <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:           <Text abbrevid=5 op0=16/> blob data = ' is a parameter.'
+// CHECK-0-NEXT:         </CommentBlock>
+// CHECK-0-NEXT:         <CommentBlock NumWords=5 BlockCodeSize=4>
+// CHECK-0-NEXT:           <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:         </CommentBlock>
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:     </CommentBlock>
+// CHECK-0-NEXT:     <CommentBlock NumWords=38 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Kind abbrevid=4 op0=19/> blob data = 'ParamCommandComment'
+// CHECK-0-NEXT:       <Direction abbrevid=7 op0=4/> blob data = '[in]'
+// CHECK-0-NEXT:       <ParamName abbrevid=8 op0=1/> blob data = 'J'
+// CHECK-0-NEXT:       <CommentBlock NumWords=25 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment'
+// CHECK-0-NEXT:         <CommentBlock NumWords=10 BlockCodeSize=4>
+// CHECK-0-NEXT:           <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:           <Text abbrevid=5 op0=16/> blob data = ' is a parameter.'
+// CHECK-0-NEXT:         </CommentBlock>
+// CHECK-0-NEXT:         <CommentBlock NumWords=5 BlockCodeSize=4>
+// CHECK-0-NEXT:           <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:         </CommentBlock>
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:     </CommentBlock>
+// CHECK-0-NEXT:     <CommentBlock NumWords=28 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Kind abbrevid=4 op0=19/> blob data = 'BlockCommandComment'
+// CHECK-0-NEXT:       <Name abbrevid=6 op0=6/> blob data = 'return'
+// CHECK-0-NEXT:       <CommentBlock NumWords=16 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment'
+// CHECK-0-NEXT:         <CommentBlock NumWords=8 BlockCodeSize=4>
+// CHECK-0-NEXT:           <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:           <Text abbrevid=5 op0=5/> blob data = ' void'
+// CHECK-0-NEXT:         </CommentBlock>
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:     </CommentBlock>
+// CHECK-0-NEXT:   </CommentBlock>
+// CHECK-0-NEXT:   <CommentBlock NumWords=28 BlockCodeSize=4>
+// CHECK-0-NEXT:     <Kind abbrevid=4 op0=11/> blob data = 'FullComment'
+// CHECK-0-NEXT:     <CommentBlock NumWords=21 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment'
+// CHECK-0-NEXT:       <CommentBlock NumWords=13 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:         <Text abbrevid=5 op0=28/> blob data = ' Bonus comment on definition'
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:     </CommentBlock>
+// CHECK-0-NEXT:   </CommentBlock>
+// CHECK-0-NEXT:   <DefLocation abbrevid=6 op0=28 op1=4/> blob data = '{{.*}}'
+// CHECK-0-NEXT:   <Location abbrevid=7 op0=25 op1=4/> blob data = '{{.*}}'
+// CHECK-0-NEXT:   <TypeBlock NumWords=6 BlockCodeSize=4>
+// CHECK-0-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Name abbrevid=5 op0=4/> blob data = 'void'
+// CHECK-0-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-0-NEXT:     </ReferenceBlock>
+// CHECK-0-NEXT:   </TypeBlock>
+// CHECK-0-NEXT:   <FieldTypeBlock NumWords=8 BlockCodeSize=4>
+// CHECK-0-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Name abbrevid=5 op0=3/> blob data = 'int'
+// CHECK-0-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-0-NEXT:     </ReferenceBlock>
+// CHECK-0-NEXT:     <Name abbrevid=4 op0=1/> blob data = 'I'
+// CHECK-0-NEXT:   </FieldTypeBlock>
+// CHECK-0-NEXT:   <FieldTypeBlock NumWords=8 BlockCodeSize=4>
+// CHECK-0-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Name abbrevid=5 op0=3/> blob data = 'int'
+// CHECK-0-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-0-NEXT:     </ReferenceBlock>
+// CHECK-0-NEXT:     <Name abbrevid=4 op0=1/> blob data = 'J'
+// CHECK-0-NEXT:   </FieldTypeBlock>
+// CHECK-0-NEXT: </FunctionBlock>
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/bc-namespace.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/bc-namespace.cpp
new file mode 100644
index 0000000..b1c0363
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/bc-namespace.cpp
@@ -0,0 +1,139 @@
+// THIS IS A GENERATED TEST. DO NOT EDIT.
+// To regenerate, see clang-doc/gen_test.py docstring.
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+
+namespace A {
+  
+void f();
+
+}  // namespace A
+
+namespace A {
+
+void f(){};
+
+namespace B {
+
+enum E { X };
+
+E func(int i) { return X; }
+
+}  // namespace B
+}  // namespace A
+
+// RUN: clang-doc --dump-intermediate --doxygen -p %t %t/test.cpp -output=%t/docs
+
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/E9ABF7E7E2425B626723D41E76E4BC7E7A5BD775.bc | FileCheck %s --check-prefix CHECK-0
+// CHECK-0: <BLOCKINFO_BLOCK/>
+// CHECK-0-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-0-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-0-NEXT: </VersionBlock>
+// CHECK-0-NEXT: <EnumBlock NumWords=38 BlockCodeSize=4>
+// CHECK-0-NEXT:   <USR abbrevid=4 op0=20 op1=233 op2=171 op3=247 op4=231 op5=226 op6=66 op7=91 op8=98 op9=103 op10=35 op11=212 op12=30 op13=118 op14=228 op15=188 op16=126 op17=122 op18=91 op19=215 op20=117/>
+// CHECK-0-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-0-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-0-NEXT:     <USR abbrevid=4 op0=20 op1=226 op2=26 op3=247 op4=158 op5=42 op6=157 op7=2 op8=85 op9=75 op10=160 op11=144 op12=209 op13=13 op14=243 op15=159 op16=226 op17=115 op18=245 op19=205 op20=181/>
+// CHECK-0-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'B'
+// CHECK-0-NEXT:     <RefType abbrevid=6 op0=1/>
+// CHECK-0-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-0-NEXT:   </ReferenceBlock>
+// CHECK-0-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-0-NEXT:     <USR abbrevid=4 op0=20 op1=141 op2=4 op3=46 op4=255 op5=201 op6=139 op7=55 op8=52 op9=80 op10=188 op11=107 op12=91 op13=144 op14=163 op15=48 op16=194 op17=90 op18=21 op19=14 op20=156/>
+// CHECK-0-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'A'
+// CHECK-0-NEXT:     <RefType abbrevid=6 op0=1/>
+// CHECK-0-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-0-NEXT:   </ReferenceBlock>
+// CHECK-0-NEXT:   <DefLocation abbrevid=6 op0=21 op1=4/> blob data = '{{.*}}'
+// CHECK-0-NEXT:   <Member abbrevid=8 op0=1/> blob data = 'X'
+// CHECK-0-NEXT: </EnumBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/39D3C95A5F7CE2BA4937BD7B01BAE09EBC2AD8AC.bc | FileCheck %s --check-prefix CHECK-1
+// CHECK-1: <BLOCKINFO_BLOCK/>
+// CHECK-1-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-1-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-1-NEXT: </VersionBlock>
+// CHECK-1-NEXT: <FunctionBlock NumWords=35 BlockCodeSize=4>
+// CHECK-1-NEXT:   <USR abbrevid=4 op0=20 op1=57 op2=211 op3=201 op4=90 op5=95 op6=124 op7=226 op8=186 op9=73 op10=55 op11=189 op12=123 op13=1 op14=186 op15=224 op16=158 op17=188 op18=42 op19=216 op20=172/>
+// CHECK-1-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'f'
+// CHECK-1-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-1-NEXT:     <USR abbrevid=4 op0=20 op1=141 op2=4 op3=46 op4=255 op5=201 op6=139 op7=55 op8=52 op9=80 op10=188 op11=107 op12=91 op13=144 op14=163 op15=48 op16=194 op17=90 op18=21 op19=14 op20=156/>
+// CHECK-1-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'A'
+// CHECK-1-NEXT:     <RefType abbrevid=6 op0=1/>
+// CHECK-1-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-1-NEXT:   </ReferenceBlock>
+// CHECK-1-NEXT:   <DefLocation abbrevid=6 op0=17 op1=4/> blob data = '{{.*}}'
+// CHECK-1-NEXT:   <Location abbrevid=7 op0=11 op1=4/> blob data = '{{.*}}'
+// CHECK-1-NEXT:   <TypeBlock NumWords=6 BlockCodeSize=4>
+// CHECK-1-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-1-NEXT:       <Name abbrevid=5 op0=4/> blob data = 'void'
+// CHECK-1-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-1-NEXT:     </ReferenceBlock>
+// CHECK-1-NEXT:   </TypeBlock>
+// CHECK-1-NEXT: </FunctionBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/9A82CB33ED0FDF81EE383D31CD0957D153C5E840.bc | FileCheck %s --check-prefix CHECK-2
+// CHECK-2: <BLOCKINFO_BLOCK/>
+// CHECK-2-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-2-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-2-NEXT: </VersionBlock>
+// CHECK-2-NEXT: <FunctionBlock NumWords=56 BlockCodeSize=4>
+// CHECK-2-NEXT:   <USR abbrevid=4 op0=20 op1=154 op2=130 op3=203 op4=51 op5=237 op6=15 op7=223 op8=129 op9=238 op10=56 op11=61 op12=49 op13=205 op14=9 op15=87 op16=209 op17=83 op18=197 op19=232 op20=64/>
+// CHECK-2-NEXT:   <Name abbrevid=5 op0=4/> blob data = 'func'
+// CHECK-2-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-2-NEXT:     <USR abbrevid=4 op0=20 op1=226 op2=26 op3=247 op4=158 op5=42 op6=157 op7=2 op8=85 op9=75 op10=160 op11=144 op12=209 op13=13 op14=243 op15=159 op16=226 op17=115 op18=245 op19=205 op20=181/>
+// CHECK-2-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'B'
+// CHECK-2-NEXT:     <RefType abbrevid=6 op0=1/>
+// CHECK-2-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-2-NEXT:   </ReferenceBlock>
+// CHECK-2-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-2-NEXT:     <USR abbrevid=4 op0=20 op1=141 op2=4 op3=46 op4=255 op5=201 op6=139 op7=55 op8=52 op9=80 op10=188 op11=107 op12=91 op13=144 op14=163 op15=48 op16=194 op17=90 op18=21 op19=14 op20=156/>
+// CHECK-2-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'A'
+// CHECK-2-NEXT:     <RefType abbrevid=6 op0=1/>
+// CHECK-2-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-2-NEXT:   </ReferenceBlock>
+// CHECK-2-NEXT:   <DefLocation abbrevid=6 op0=23 op1=4/> blob data = '{{.*}}'
+// CHECK-2-NEXT:   <TypeBlock NumWords=8 BlockCodeSize=4>
+// CHECK-2-NEXT:     <ReferenceBlock NumWords=5 BlockCodeSize=4>
+// CHECK-2-NEXT:       <Name abbrevid=5 op0=12/> blob data = 'enum A::B::E'
+// CHECK-2-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-2-NEXT:     </ReferenceBlock>
+// CHECK-2-NEXT:   </TypeBlock>
+// CHECK-2-NEXT:   <FieldTypeBlock NumWords=8 BlockCodeSize=4>
+// CHECK-2-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-2-NEXT:       <Name abbrevid=5 op0=3/> blob data = 'int'
+// CHECK-2-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-2-NEXT:     </ReferenceBlock>
+// CHECK-2-NEXT:     <Name abbrevid=4 op0=1/> blob data = 'i'
+// CHECK-2-NEXT:   </FieldTypeBlock>
+// CHECK-2-NEXT: </FunctionBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/8D042EFFC98B373450BC6B5B90A330C25A150E9C.bc | FileCheck %s --check-prefix CHECK-3
+// CHECK-3: <BLOCKINFO_BLOCK/>
+// CHECK-3-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-3-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-3-NEXT: </VersionBlock>
+// CHECK-3-NEXT: <NamespaceBlock NumWords=9 BlockCodeSize=4>
+// CHECK-3-NEXT:   <USR abbrevid=4 op0=20 op1=141 op2=4 op3=46 op4=255 op5=201 op6=139 op7=55 op8=52 op9=80 op10=188 op11=107 op12=91 op13=144 op14=163 op15=48 op16=194 op17=90 op18=21 op19=14 op20=156/>
+// CHECK-3-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'A'
+// CHECK-3-NEXT: </NamespaceBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/E21AF79E2A9D02554BA090D10DF39FE273F5CDB5.bc | FileCheck %s --check-prefix CHECK-4
+// CHECK-4: <BLOCKINFO_BLOCK/>
+// CHECK-4-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-4-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-4-NEXT: </VersionBlock>
+// CHECK-4-NEXT: <NamespaceBlock NumWords=21 BlockCodeSize=4>
+// CHECK-4-NEXT:   <USR abbrevid=4 op0=20 op1=226 op2=26 op3=247 op4=158 op5=42 op6=157 op7=2 op8=85 op9=75 op10=160 op11=144 op12=209 op13=13 op14=243 op15=159 op16=226 op17=115 op18=245 op19=205 op20=181/>
+// CHECK-4-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'B'
+// CHECK-4-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-4-NEXT:     <USR abbrevid=4 op0=20 op1=141 op2=4 op3=46 op4=255 op5=201 op6=139 op7=55 op8=52 op9=80 op10=188 op11=107 op12=91 op13=144 op14=163 op15=48 op16=194 op17=90 op18=21 op19=14 op20=156/>
+// CHECK-4-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'A'
+// CHECK-4-NEXT:     <RefType abbrevid=6 op0=1/>
+// CHECK-4-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-4-NEXT:   </ReferenceBlock>
+// CHECK-4-NEXT: </NamespaceBlock>
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/bc-record.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/bc-record.cpp
new file mode 100644
index 0000000..7a09118
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/bc-record.cpp
@@ -0,0 +1,321 @@
+// THIS IS A GENERATED TEST. DO NOT EDIT.
+// To regenerate, see clang-doc/gen_test.py docstring.
+//
+// This test requires Linux due to system-dependent USR for the inner class.
+// REQUIRES: system-linux
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+
+void H() {
+  class I {};
+}
+
+union A { int X; int Y; };
+
+enum B { X, Y };
+
+enum class Bc { A, B };
+
+struct C { int i; };
+
+class D {};
+
+class E {
+public:
+  E() {}
+  ~E() {}
+
+protected:
+  void ProtectedMethod();
+};
+
+void E::ProtectedMethod() {}
+
+class F : virtual private D, public E {};
+
+class X {
+  class Y {};
+};
+
+// RUN: clang-doc --dump-intermediate --doxygen -p %t %t/test.cpp -output=%t/docs
+
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/289584A8E0FF4178A794622A547AA622503967A1.bc | FileCheck %s --check-prefix CHECK-0
+// CHECK-0: <BLOCKINFO_BLOCK/>
+// CHECK-0-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-0-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-0-NEXT: </VersionBlock>
+// CHECK-0-NEXT: <RecordBlock NumWords=12 BlockCodeSize=4>
+// CHECK-0-NEXT:   <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-0-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-0-NEXT:   <DefLocation abbrevid=6 op0=25 op1=4/> blob data = '{{.*}}'
+// CHECK-0-NEXT:   <TagType abbrevid=8 op0=3/>
+// CHECK-0-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/3FB542274573CAEAD54CEBFFCAEE3D77FB9713D8.bc | FileCheck %s --check-prefix CHECK-1
+// CHECK-1: <BLOCKINFO_BLOCK/>
+// CHECK-1-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-1-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-1-NEXT: </VersionBlock>
+// CHECK-1-NEXT: <RecordBlock NumWords=24 BlockCodeSize=4>
+// CHECK-1-NEXT:   <USR abbrevid=4 op0=20 op1=63 op2=181 op3=66 op4=39 op5=69 op6=115 op7=202 op8=234 op9=213 op10=76 op11=235 op12=255 op13=202 op14=238 op15=61 op16=119 op17=251 op18=151 op19=19 op20=216/>
+// CHECK-1-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'I'
+// CHECK-1-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-1-NEXT:     <USR abbrevid=4 op0=20 op1=182 op2=172 op3=76 op4=92 op5=159 op6=46 op7=163 op8=242 op9=179 op10=236 op11=225 op12=163 op13=61 op14=52 op15=159 op16=78 op17=229 op18=2 op19=178 op20=78/>
+// CHECK-1-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'H'
+// CHECK-1-NEXT:     <RefType abbrevid=6 op0=3/>
+// CHECK-1-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-1-NEXT:   </ReferenceBlock>
+// CHECK-1-NEXT:   <DefLocation abbrevid=6 op0=12 op1=4/> blob data = '{{.*}}'
+// CHECK-1-NEXT:   <TagType abbrevid=8 op0=3/>
+// CHECK-1-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/5093D428CDC62096A67547BA52566E4FB9404EEE.bc | FileCheck %s --check-prefix CHECK-2
+// CHECK-2: <BLOCKINFO_BLOCK/>
+// CHECK-2-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-2-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-2-NEXT: </VersionBlock>
+// CHECK-2-NEXT: <FunctionBlock NumWords=50 BlockCodeSize=4>
+// CHECK-2-NEXT:   <USR abbrevid=4 op0=20 op1=80 op2=147 op3=212 op4=40 op5=205 op6=198 op7=32 op8=150 op9=166 op10=117 op11=71 op12=186 op13=82 op14=86 op15=110 op16=79 op17=185 op18=64 op19=78 op20=238/>
+// CHECK-2-NEXT:   <Name abbrevid=5 op0=15/> blob data = 'ProtectedMethod'
+// CHECK-2-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-2-NEXT:     <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-2-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-2-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-2-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-2-NEXT:   </ReferenceBlock>
+// CHECK-2-NEXT:   <IsMethod abbrevid=9 op0=1/>
+// CHECK-2-NEXT:   <DefLocation abbrevid=6 op0=34 op1=4/> blob data = '{{.*}}'
+// CHECK-2-NEXT:   <Location abbrevid=7 op0=31 op1=4/> blob data = '{{.*}}'
+// CHECK-2-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-2-NEXT:     <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-2-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-2-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-2-NEXT:     <Field abbrevid=7 op0=2/>
+// CHECK-2-NEXT:   </ReferenceBlock>
+// CHECK-2-NEXT:   <TypeBlock NumWords=6 BlockCodeSize=4>
+// CHECK-2-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-2-NEXT:       <Name abbrevid=5 op0=4/> blob data = 'void'
+// CHECK-2-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-2-NEXT:     </ReferenceBlock>
+// CHECK-2-NEXT:   </TypeBlock>
+// CHECK-2-NEXT: </FunctionBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/CA7C7935730B5EACD25F080E9C83FA087CCDC75E.bc | FileCheck %s --check-prefix CHECK-3
+// CHECK-3: <BLOCKINFO_BLOCK/>
+// CHECK-3-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-3-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-3-NEXT: </VersionBlock>
+// CHECK-3-NEXT: <RecordBlock NumWords=12 BlockCodeSize=4>
+// CHECK-3-NEXT:   <USR abbrevid=4 op0=20 op1=202 op2=124 op3=121 op4=53 op5=115 op6=11 op7=94 op8=172 op9=210 op10=95 op11=8 op12=14 op13=156 op14=131 op15=250 op16=8 op17=124 op18=205 op19=199 op20=94/>
+// CHECK-3-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'X'
+// CHECK-3-NEXT:   <DefLocation abbrevid=6 op0=38 op1=4/> blob data = '{{.*}}'
+// CHECK-3-NEXT:   <TagType abbrevid=8 op0=3/>
+// CHECK-3-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/B6AC4C5C9F2EA3F2B3ECE1A33D349F4EE502B24E.bc | FileCheck %s --check-prefix CHECK-4
+// CHECK-4: <BLOCKINFO_BLOCK/>
+// CHECK-4-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-4-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-4-NEXT: </VersionBlock>
+// CHECK-4-NEXT: <FunctionBlock NumWords=20 BlockCodeSize=4>
+// CHECK-4-NEXT:   <USR abbrevid=4 op0=20 op1=182 op2=172 op3=76 op4=92 op5=159 op6=46 op7=163 op8=242 op9=179 op10=236 op11=225 op12=163 op13=61 op14=52 op15=159 op16=78 op17=229 op18=2 op19=178 op20=78/>
+// CHECK-4-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'H'
+// CHECK-4-NEXT:   <DefLocation abbrevid=6 op0=11 op1=4/> blob data = '{{.*}}'
+// CHECK-4-NEXT:   <TypeBlock NumWords=6 BlockCodeSize=4>
+// CHECK-4-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-4-NEXT:       <Name abbrevid=5 op0=4/> blob data = 'void'
+// CHECK-4-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-4-NEXT:     </ReferenceBlock>
+// CHECK-4-NEXT:   </TypeBlock>
+// CHECK-4-NEXT: </FunctionBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/06B5F6A19BA9F6A832E127C9968282B94619B210.bc | FileCheck %s --check-prefix CHECK-5
+// CHECK-5: <BLOCKINFO_BLOCK/>
+// CHECK-5-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-5-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-5-NEXT: </VersionBlock>
+// CHECK-5-NEXT: <RecordBlock NumWords=22 BlockCodeSize=4>
+// CHECK-5-NEXT:   <USR abbrevid=4 op0=20 op1=6 op2=181 op3=246 op4=161 op5=155 op6=169 op7=246 op8=168 op9=50 op10=225 op11=39 op12=201 op13=150 op14=130 op15=130 op16=185 op17=70 op18=25 op19=178 op20=16/>
+// CHECK-5-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'C'
+// CHECK-5-NEXT:   <DefLocation abbrevid=6 op0=21 op1=4/> blob data = '{{.*}}'
+// CHECK-5-NEXT:   <MemberTypeBlock NumWords=8 BlockCodeSize=4>
+// CHECK-5-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-5-NEXT:       <Name abbrevid=5 op0=3/> blob data = 'int'
+// CHECK-5-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-5-NEXT:     </ReferenceBlock>
+// CHECK-5-NEXT:     <Name abbrevid=4 op0=1/> blob data = 'i'
+// CHECK-5-NEXT:     <Access abbrevid=5 op0=3/>
+// CHECK-5-NEXT:   </MemberTypeBlock>
+// CHECK-5-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/BD2BDEBD423F80BACCEA75DE6D6622D355FC2D17.bc | FileCheck %s --check-prefix CHECK-6
+// CHECK-6: <BLOCKINFO_BLOCK/>
+// CHECK-6-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-6-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-6-NEXT: </VersionBlock>
+// CHECK-6-NEXT: <FunctionBlock NumWords=44 BlockCodeSize=4>
+// CHECK-6-NEXT:   <USR abbrevid=4 op0=20 op1=189 op2=43 op3=222 op4=189 op5=66 op6=63 op7=128 op8=186 op9=204 op10=234 op11=117 op12=222 op13=109 op14=102 op15=34 op16=211 op17=85 op18=252 op19=45 op20=23/>
+// CHECK-6-NEXT:   <Name abbrevid=5 op0=2/> blob data = '~E'
+// CHECK-6-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-6-NEXT:     <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-6-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-6-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-6-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-6-NEXT:   </ReferenceBlock>
+// CHECK-6-NEXT:   <IsMethod abbrevid=9 op0=1/>
+// CHECK-6-NEXT:   <DefLocation abbrevid=6 op0=28 op1=4/> blob data = '{{.*}}'
+// CHECK-6-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-6-NEXT:     <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-6-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-6-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-6-NEXT:     <Field abbrevid=7 op0=2/>
+// CHECK-6-NEXT:   </ReferenceBlock>
+// CHECK-6-NEXT:   <TypeBlock NumWords=6 BlockCodeSize=4>
+// CHECK-6-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-6-NEXT:       <Name abbrevid=5 op0=4/> blob data = 'void'
+// CHECK-6-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-6-NEXT:     </ReferenceBlock>
+// CHECK-6-NEXT:   </TypeBlock>
+// CHECK-6-NEXT: </FunctionBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/DEB4AC1CD9253CD9EF7FBE6BCAC506D77984ABD4.bc | FileCheck %s --check-prefix CHECK-7
+// CHECK-7: <BLOCKINFO_BLOCK/>
+// CHECK-7-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-7-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-7-NEXT: </VersionBlock>
+// CHECK-7-NEXT: <FunctionBlock NumWords=44 BlockCodeSize=4>
+// CHECK-7-NEXT:   <USR abbrevid=4 op0=20 op1=222 op2=180 op3=172 op4=28 op5=217 op6=37 op7=60 op8=217 op9=239 op10=127 op11=190 op12=107 op13=202 op14=197 op15=6 op16=215 op17=121 op18=132 op19=171 op20=212/>
+// CHECK-7-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-7-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-7-NEXT:     <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-7-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-7-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-7-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-7-NEXT:   </ReferenceBlock>
+// CHECK-7-NEXT:   <IsMethod abbrevid=9 op0=1/>
+// CHECK-7-NEXT:   <DefLocation abbrevid=6 op0=27 op1=4/> blob data = '{{.*}}'
+// CHECK-7-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-7-NEXT:     <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-7-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-7-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-7-NEXT:     <Field abbrevid=7 op0=2/>
+// CHECK-7-NEXT:   </ReferenceBlock>
+// CHECK-7-NEXT:   <TypeBlock NumWords=6 BlockCodeSize=4>
+// CHECK-7-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-7-NEXT:       <Name abbrevid=5 op0=4/> blob data = 'void'
+// CHECK-7-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-7-NEXT:     </ReferenceBlock>
+// CHECK-7-NEXT:   </TypeBlock>
+// CHECK-7-NEXT: </FunctionBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/641AB4A3D36399954ACDE29C7A8833032BF40472.bc | FileCheck %s --check-prefix CHECK-8
+// CHECK-8: <BLOCKINFO_BLOCK/>
+// CHECK-8-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-8-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-8-NEXT: </VersionBlock>
+// CHECK-8-NEXT: <RecordBlock NumWords=24 BlockCodeSize=4>
+// CHECK-8-NEXT:   <USR abbrevid=4 op0=20 op1=100 op2=26 op3=180 op4=163 op5=211 op6=99 op7=153 op8=149 op9=74 op10=205 op11=226 op12=156 op13=122 op14=136 op15=51 op16=3 op17=43 op18=244 op19=4 op20=114/>
+// CHECK-8-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'Y'
+// CHECK-8-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-8-NEXT:     <USR abbrevid=4 op0=20 op1=202 op2=124 op3=121 op4=53 op5=115 op6=11 op7=94 op8=172 op9=210 op10=95 op11=8 op12=14 op13=156 op14=131 op15=250 op16=8 op17=124 op18=205 op19=199 op20=94/>
+// CHECK-8-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'X'
+// CHECK-8-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-8-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-8-NEXT:   </ReferenceBlock>
+// CHECK-8-NEXT:   <DefLocation abbrevid=6 op0=39 op1=4/> blob data = '{{.*}}'
+// CHECK-8-NEXT:   <TagType abbrevid=8 op0=3/>
+// CHECK-8-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/FC07BD34D5E77782C263FA944447929EA8753740.bc | FileCheck %s --check-prefix CHECK-9
+// CHECK-9: <BLOCKINFO_BLOCK/>
+// CHECK-9-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-9-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-9-NEXT: </VersionBlock>
+// CHECK-9-NEXT: <EnumBlock NumWords=16 BlockCodeSize=4>
+// CHECK-9-NEXT:   <USR abbrevid=4 op0=20 op1=252 op2=7 op3=189 op4=52 op5=213 op6=231 op7=119 op8=130 op9=194 op10=99 op11=250 op12=148 op13=68 op14=71 op15=146 op16=158 op17=168 op18=117 op19=55 op20=64/>
+// CHECK-9-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'B'
+// CHECK-9-NEXT:   <DefLocation abbrevid=6 op0=17 op1=4/> blob data = '{{.*}}'
+// CHECK-9-NEXT:   <Member abbrevid=8 op0=1/> blob data = 'X'
+// CHECK-9-NEXT:   <Member abbrevid=8 op0=1/> blob data = 'Y'
+// CHECK-9-NEXT: </EnumBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/0921737541208B8FA9BB42B60F78AC1D779AA054.bc | FileCheck %s --check-prefix CHECK-10
+// CHECK-10: <BLOCKINFO_BLOCK/>
+// CHECK-10-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-10-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-10-NEXT: </VersionBlock>
+// CHECK-10-NEXT: <RecordBlock NumWords=12 BlockCodeSize=4>
+// CHECK-10-NEXT:   <USR abbrevid=4 op0=20 op1=9 op2=33 op3=115 op4=117 op5=65 op6=32 op7=139 op8=143 op9=169 op10=187 op11=66 op12=182 op13=15 op14=120 op15=172 op16=29 op17=119 op18=154 op19=160 op20=84/>
+// CHECK-10-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'D'
+// CHECK-10-NEXT:   <DefLocation abbrevid=6 op0=23 op1=4/> blob data = '{{.*}}'
+// CHECK-10-NEXT:   <TagType abbrevid=8 op0=3/>
+// CHECK-10-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/E3B54702FABFF4037025BA194FC27C47006330B5.bc | FileCheck %s --check-prefix CHECK-11
+// CHECK-11: <BLOCKINFO_BLOCK/>
+// CHECK-11-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-11-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-11-NEXT: </VersionBlock>
+// CHECK-11-NEXT: <RecordBlock NumWords=37 BlockCodeSize=4>
+// CHECK-11-NEXT:   <USR abbrevid=4 op0=20 op1=227 op2=181 op3=71 op4=2 op5=250 op6=191 op7=244 op8=3 op9=112 op10=37 op11=186 op12=25 op13=79 op14=194 op15=124 op16=71 op17=0 op18=99 op19=48 op20=181/>
+// CHECK-11-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'F'
+// CHECK-11-NEXT:   <DefLocation abbrevid=6 op0=36 op1=4/> blob data = '{{.*}}'
+// CHECK-11-NEXT:   <TagType abbrevid=8 op0=3/>
+// CHECK-11-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-11-NEXT:     <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-11-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-11-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-11-NEXT:     <Field abbrevid=7 op0=2/>
+// CHECK-11-NEXT:   </ReferenceBlock>
+// CHECK-11-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-11-NEXT:     <USR abbrevid=4 op0=20 op1=9 op2=33 op3=115 op4=117 op5=65 op6=32 op7=139 op8=143 op9=169 op10=187 op11=66 op12=182 op13=15 op14=120 op15=172 op16=29 op17=119 op18=154 op19=160 op20=84/>
+// CHECK-11-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'D'
+// CHECK-11-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-11-NEXT:     <Field abbrevid=7 op0=3/>
+// CHECK-11-NEXT:   </ReferenceBlock>
+// CHECK-11-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/ACE81AFA6627B4CEF2B456FB6E1252925674AF7E.bc | FileCheck %s --check-prefix CHECK-12
+// CHECK-12: <BLOCKINFO_BLOCK/>
+// CHECK-12-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-12-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-12-NEXT: </VersionBlock>
+// CHECK-12-NEXT: <RecordBlock NumWords=33 BlockCodeSize=4>
+// CHECK-12-NEXT:   <USR abbrevid=4 op0=20 op1=172 op2=232 op3=26 op4=250 op5=102 op6=39 op7=180 op8=206 op9=242 op10=180 op11=86 op12=251 op13=110 op14=18 op15=82 op16=146 op17=86 op18=116 op19=175 op20=126/>
+// CHECK-12-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'A'
+// CHECK-12-NEXT:   <DefLocation abbrevid=6 op0=15 op1=4/> blob data = '{{.*}}'
+// CHECK-12-NEXT:   <TagType abbrevid=8 op0=2/>
+// CHECK-12-NEXT:   <MemberTypeBlock NumWords=8 BlockCodeSize=4>
+// CHECK-12-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-12-NEXT:       <Name abbrevid=5 op0=3/> blob data = 'int'
+// CHECK-12-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-12-NEXT:     </ReferenceBlock>
+// CHECK-12-NEXT:     <Name abbrevid=4 op0=1/> blob data = 'X'
+// CHECK-12-NEXT:     <Access abbrevid=5 op0=3/>
+// CHECK-12-NEXT:   </MemberTypeBlock>
+// CHECK-12-NEXT:   <MemberTypeBlock NumWords=8 BlockCodeSize=4>
+// CHECK-12-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-12-NEXT:       <Name abbrevid=5 op0=3/> blob data = 'int'
+// CHECK-12-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-12-NEXT:     </ReferenceBlock>
+// CHECK-12-NEXT:     <Name abbrevid=4 op0=1/> blob data = 'Y'
+// CHECK-12-NEXT:     <Access abbrevid=5 op0=3/>
+// CHECK-12-NEXT:   </MemberTypeBlock>
+// CHECK-12-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/1E3438A08BA22025C0B46289FF0686F92C8924C5.bc | FileCheck %s --check-prefix CHECK-13
+// CHECK-13: <BLOCKINFO_BLOCK/>
+// CHECK-13-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-13-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-13-NEXT: </VersionBlock>
+// CHECK-13-NEXT: <EnumBlock NumWords=16 BlockCodeSize=4>
+// CHECK-13-NEXT:   <USR abbrevid=4 op0=20 op1=30 op2=52 op3=56 op4=160 op5=139 op6=162 op7=32 op8=37 op9=192 op10=180 op11=98 op12=137 op13=255 op14=6 op15=134 op16=249 op17=44 op18=137 op19=36 op20=197/>
+// CHECK-13-NEXT:   <Name abbrevid=5 op0=2/> blob data = 'Bc'
+// CHECK-13-NEXT:   <DefLocation abbrevid=6 op0=19 op1=4/> blob data = '{{.*}}'
+// CHECK-13-NEXT:   <Scoped abbrevid=9 op0=1/>
+// CHECK-13-NEXT:   <Member abbrevid=8 op0=1/> blob data = 'A'
+// CHECK-13-NEXT:   <Member abbrevid=8 op0=1/> blob data = 'B'
+// CHECK-13-NEXT: </EnumBlock>
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/mapper-comment.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/mapper-comment.cpp
new file mode 100644
index 0000000..da691b1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/mapper-comment.cpp
@@ -0,0 +1,72 @@
+// THIS IS A GENERATED TEST. DO NOT EDIT.
+// To regenerate, see clang-doc/gen_test.py docstring.
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+
+/// \brief Brief description.
+///
+/// Extended description that
+/// continues onto the next line.
+/// 
+/// <ul class="test">
+///   <li> Testing.
+/// </ul>
+///
+/// \verbatim
+/// The description continues.
+/// \endverbatim
+/// --
+/// \param [out] I is a parameter.
+/// \param J is a parameter.
+/// \return void
+void F(int I, int J);
+
+/// Bonus comment on definition
+void F(int I, int J) {}
+
+// RUN: clang-doc --dump-mapper --doxygen -p %t %t/test.cpp -output=%t/docs
+
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/7574630614A535710E5A6ABCFFF98BCA2D06A4CA.bc | FileCheck %s --check-prefix CHECK-0
+// CHECK-0: <BLOCKINFO_BLOCK/>
+// CHECK-0-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-0-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-0-NEXT: </VersionBlock>
+// CHECK-0-NEXT: <FunctionBlock NumWords=70 BlockCodeSize=4>
+// CHECK-0-NEXT:   <USR abbrevid=4 op0=20 op1=117 op2=116 op3=99 op4=6 op5=20 op6=165 op7=53 op8=113 op9=14 op10=90 op11=106 op12=188 op13=255 op14=249 op15=139 op16=202 op17=45 op18=6 op19=164 op20=202/>
+// CHECK-0-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'F'
+// CHECK-0-NEXT:   <CommentBlock NumWords=28 BlockCodeSize=4>
+// CHECK-0-NEXT:     <Kind abbrevid=4 op0=11/> blob data = 'FullComment'
+// CHECK-0-NEXT:     <CommentBlock NumWords=21 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment'
+// CHECK-0-NEXT:       <CommentBlock NumWords=13 BlockCodeSize=4>
+// CHECK-0-NEXT:         <Kind abbrevid=4 op0=11/> blob data = 'TextComment'
+// CHECK-0-NEXT:         <Text abbrevid=5 op0=28/> blob data = ' Bonus comment on definition'
+// CHECK-0-NEXT:       </CommentBlock>
+// CHECK-0-NEXT:     </CommentBlock>
+// CHECK-0-NEXT:   </CommentBlock>
+// CHECK-0-NEXT:   <DefLocation abbrevid=6 op0=28 op1=4/> blob data = '{{.*}}'
+// CHECK-0-NEXT:   <TypeBlock NumWords=6 BlockCodeSize=4>
+// CHECK-0-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Name abbrevid=5 op0=4/> blob data = 'void'
+// CHECK-0-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-0-NEXT:     </ReferenceBlock>
+// CHECK-0-NEXT:   </TypeBlock>
+// CHECK-0-NEXT:   <FieldTypeBlock NumWords=8 BlockCodeSize=4>
+// CHECK-0-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Name abbrevid=5 op0=3/> blob data = 'int'
+// CHECK-0-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-0-NEXT:     </ReferenceBlock>
+// CHECK-0-NEXT:     <Name abbrevid=4 op0=1/> blob data = 'I'
+// CHECK-0-NEXT:   </FieldTypeBlock>
+// CHECK-0-NEXT:   <FieldTypeBlock NumWords=8 BlockCodeSize=4>
+// CHECK-0-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-0-NEXT:       <Name abbrevid=5 op0=3/> blob data = 'int'
+// CHECK-0-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-0-NEXT:     </ReferenceBlock>
+// CHECK-0-NEXT:     <Name abbrevid=4 op0=1/> blob data = 'J'
+// CHECK-0-NEXT:   </FieldTypeBlock>
+// CHECK-0-NEXT: </FunctionBlock>
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/mapper-namespace.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/mapper-namespace.cpp
new file mode 100644
index 0000000..aeda908
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/mapper-namespace.cpp
@@ -0,0 +1,138 @@
+// THIS IS A GENERATED TEST. DO NOT EDIT.
+// To regenerate, see clang-doc/gen_test.py docstring.
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+
+namespace A {
+  
+void f();
+
+}  // namespace A
+
+namespace A {
+
+void f(){};
+
+namespace B {
+
+enum E { X };
+
+E func(int i) { return X; }
+
+}  // namespace B
+}  // namespace A
+
+// RUN: clang-doc --dump-mapper --doxygen -p %t %t/test.cpp -output=%t/docs
+
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/E9ABF7E7E2425B626723D41E76E4BC7E7A5BD775.bc | FileCheck %s --check-prefix CHECK-0
+// CHECK-0: <BLOCKINFO_BLOCK/>
+// CHECK-0-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-0-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-0-NEXT: </VersionBlock>
+// CHECK-0-NEXT: <EnumBlock NumWords=38 BlockCodeSize=4>
+// CHECK-0-NEXT:   <USR abbrevid=4 op0=20 op1=233 op2=171 op3=247 op4=231 op5=226 op6=66 op7=91 op8=98 op9=103 op10=35 op11=212 op12=30 op13=118 op14=228 op15=188 op16=126 op17=122 op18=91 op19=215 op20=117/>
+// CHECK-0-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-0-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-0-NEXT:     <USR abbrevid=4 op0=20 op1=226 op2=26 op3=247 op4=158 op5=42 op6=157 op7=2 op8=85 op9=75 op10=160 op11=144 op12=209 op13=13 op14=243 op15=159 op16=226 op17=115 op18=245 op19=205 op20=181/>
+// CHECK-0-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'B'
+// CHECK-0-NEXT:     <RefType abbrevid=6 op0=1/>
+// CHECK-0-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-0-NEXT:   </ReferenceBlock>
+// CHECK-0-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-0-NEXT:     <USR abbrevid=4 op0=20 op1=141 op2=4 op3=46 op4=255 op5=201 op6=139 op7=55 op8=52 op9=80 op10=188 op11=107 op12=91 op13=144 op14=163 op15=48 op16=194 op17=90 op18=21 op19=14 op20=156/>
+// CHECK-0-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'A'
+// CHECK-0-NEXT:     <RefType abbrevid=6 op0=1/>
+// CHECK-0-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-0-NEXT:   </ReferenceBlock>
+// CHECK-0-NEXT:   <DefLocation abbrevid=6 op0=21 op1=4/> blob data = '{{.*}}'
+// CHECK-0-NEXT:   <Member abbrevid=8 op0=1/> blob data = 'X'
+// CHECK-0-NEXT: </EnumBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/39D3C95A5F7CE2BA4937BD7B01BAE09EBC2AD8AC.bc | FileCheck %s --check-prefix CHECK-1
+// CHECK-1: <BLOCKINFO_BLOCK/>
+// CHECK-1-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-1-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-1-NEXT: </VersionBlock>
+// CHECK-1-NEXT: <FunctionBlock NumWords=32 BlockCodeSize=4>
+// CHECK-1-NEXT:   <USR abbrevid=4 op0=20 op1=57 op2=211 op3=201 op4=90 op5=95 op6=124 op7=226 op8=186 op9=73 op10=55 op11=189 op12=123 op13=1 op14=186 op15=224 op16=158 op17=188 op18=42 op19=216 op20=172/>
+// CHECK-1-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'f'
+// CHECK-1-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-1-NEXT:     <USR abbrevid=4 op0=20 op1=141 op2=4 op3=46 op4=255 op5=201 op6=139 op7=55 op8=52 op9=80 op10=188 op11=107 op12=91 op13=144 op14=163 op15=48 op16=194 op17=90 op18=21 op19=14 op20=156/>
+// CHECK-1-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'A'
+// CHECK-1-NEXT:     <RefType abbrevid=6 op0=1/>
+// CHECK-1-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-1-NEXT:   </ReferenceBlock>
+// CHECK-1-NEXT:   <DefLocation abbrevid=6 op0=17 op1=4/> blob data = '{{.*}}'
+// CHECK-1-NEXT:   <TypeBlock NumWords=6 BlockCodeSize=4>
+// CHECK-1-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-1-NEXT:       <Name abbrevid=5 op0=4/> blob data = 'void'
+// CHECK-1-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-1-NEXT:     </ReferenceBlock>
+// CHECK-1-NEXT:   </TypeBlock>
+// CHECK-1-NEXT: </FunctionBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/9A82CB33ED0FDF81EE383D31CD0957D153C5E840.bc | FileCheck %s --check-prefix CHECK-2
+// CHECK-2: <BLOCKINFO_BLOCK/>
+// CHECK-2-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-2-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-2-NEXT: </VersionBlock>
+// CHECK-2-NEXT: <FunctionBlock NumWords=56 BlockCodeSize=4>
+// CHECK-2-NEXT:   <USR abbrevid=4 op0=20 op1=154 op2=130 op3=203 op4=51 op5=237 op6=15 op7=223 op8=129 op9=238 op10=56 op11=61 op12=49 op13=205 op14=9 op15=87 op16=209 op17=83 op18=197 op19=232 op20=64/>
+// CHECK-2-NEXT:   <Name abbrevid=5 op0=4/> blob data = 'func'
+// CHECK-2-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-2-NEXT:     <USR abbrevid=4 op0=20 op1=226 op2=26 op3=247 op4=158 op5=42 op6=157 op7=2 op8=85 op9=75 op10=160 op11=144 op12=209 op13=13 op14=243 op15=159 op16=226 op17=115 op18=245 op19=205 op20=181/>
+// CHECK-2-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'B'
+// CHECK-2-NEXT:     <RefType abbrevid=6 op0=1/>
+// CHECK-2-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-2-NEXT:   </ReferenceBlock>
+// CHECK-2-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-2-NEXT:     <USR abbrevid=4 op0=20 op1=141 op2=4 op3=46 op4=255 op5=201 op6=139 op7=55 op8=52 op9=80 op10=188 op11=107 op12=91 op13=144 op14=163 op15=48 op16=194 op17=90 op18=21 op19=14 op20=156/>
+// CHECK-2-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'A'
+// CHECK-2-NEXT:     <RefType abbrevid=6 op0=1/>
+// CHECK-2-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-2-NEXT:   </ReferenceBlock>
+// CHECK-2-NEXT:   <DefLocation abbrevid=6 op0=23 op1=4/> blob data = '{{.*}}'
+// CHECK-2-NEXT:   <TypeBlock NumWords=8 BlockCodeSize=4>
+// CHECK-2-NEXT:     <ReferenceBlock NumWords=5 BlockCodeSize=4>
+// CHECK-2-NEXT:       <Name abbrevid=5 op0=12/> blob data = 'enum A::B::E'
+// CHECK-2-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-2-NEXT:     </ReferenceBlock>
+// CHECK-2-NEXT:   </TypeBlock>
+// CHECK-2-NEXT:   <FieldTypeBlock NumWords=8 BlockCodeSize=4>
+// CHECK-2-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-2-NEXT:       <Name abbrevid=5 op0=3/> blob data = 'int'
+// CHECK-2-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-2-NEXT:     </ReferenceBlock>
+// CHECK-2-NEXT:     <Name abbrevid=4 op0=1/> blob data = 'i'
+// CHECK-2-NEXT:   </FieldTypeBlock>
+// CHECK-2-NEXT: </FunctionBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/8D042EFFC98B373450BC6B5B90A330C25A150E9C.bc | FileCheck %s --check-prefix CHECK-3
+// CHECK-3: <BLOCKINFO_BLOCK/>
+// CHECK-3-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-3-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-3-NEXT: </VersionBlock>
+// CHECK-3-NEXT: <NamespaceBlock NumWords=9 BlockCodeSize=4>
+// CHECK-3-NEXT:   <USR abbrevid=4 op0=20 op1=141 op2=4 op3=46 op4=255 op5=201 op6=139 op7=55 op8=52 op9=80 op10=188 op11=107 op12=91 op13=144 op14=163 op15=48 op16=194 op17=90 op18=21 op19=14 op20=156/>
+// CHECK-3-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'A'
+// CHECK-3-NEXT: </NamespaceBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/E21AF79E2A9D02554BA090D10DF39FE273F5CDB5.bc | FileCheck %s --check-prefix CHECK-4
+// CHECK-4: <BLOCKINFO_BLOCK/>
+// CHECK-4-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-4-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-4-NEXT: </VersionBlock>
+// CHECK-4-NEXT: <NamespaceBlock NumWords=21 BlockCodeSize=4>
+// CHECK-4-NEXT:   <USR abbrevid=4 op0=20 op1=226 op2=26 op3=247 op4=158 op5=42 op6=157 op7=2 op8=85 op9=75 op10=160 op11=144 op12=209 op13=13 op14=243 op15=159 op16=226 op17=115 op18=245 op19=205 op20=181/>
+// CHECK-4-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'B'
+// CHECK-4-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-4-NEXT:     <USR abbrevid=4 op0=20 op1=141 op2=4 op3=46 op4=255 op5=201 op6=139 op7=55 op8=52 op9=80 op10=188 op11=107 op12=91 op13=144 op14=163 op15=48 op16=194 op17=90 op18=21 op19=14 op20=156/>
+// CHECK-4-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'A'
+// CHECK-4-NEXT:     <RefType abbrevid=6 op0=1/>
+// CHECK-4-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-4-NEXT:   </ReferenceBlock>
+// CHECK-4-NEXT: </NamespaceBlock>
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/mapper-record.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/mapper-record.cpp
new file mode 100644
index 0000000..82a5e2f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/mapper-record.cpp
@@ -0,0 +1,317 @@
+// THIS IS A GENERATED TEST. DO NOT EDIT.
+// To regenerate, see clang-doc/gen_test.py docstring.
+//
+// This test requires Linux due to system-dependent USR for the inner class.
+// REQUIRES: system-linux
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+
+void H() {
+  class I {};
+}
+
+union A { int X; int Y; };
+
+enum B { X, Y };
+
+enum class Bc { A, B };
+
+struct C { int i; };
+
+class D {};
+
+class E {
+public:
+  E() {}
+  ~E() {}
+
+protected:
+  void ProtectedMethod();
+};
+
+void E::ProtectedMethod() {}
+
+class F : virtual private D, public E {};
+
+class X {
+  class Y {};
+};
+
+// RUN: clang-doc --dump-mapper --doxygen -p %t %t/test.cpp -output=%t/docs
+
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/289584A8E0FF4178A794622A547AA622503967A1.bc | FileCheck %s --check-prefix CHECK-0
+// CHECK-0: <BLOCKINFO_BLOCK/>
+// CHECK-0-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-0-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-0-NEXT: </VersionBlock>
+// CHECK-0-NEXT: <RecordBlock NumWords=12 BlockCodeSize=4>
+// CHECK-0-NEXT:   <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-0-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-0-NEXT:   <DefLocation abbrevid=6 op0=25 op1=4/> blob data = '{{.*}}'
+// CHECK-0-NEXT:   <TagType abbrevid=8 op0=3/>
+// CHECK-0-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/3FB542274573CAEAD54CEBFFCAEE3D77FB9713D8.bc | FileCheck %s --check-prefix CHECK-1
+// CHECK-1: <BLOCKINFO_BLOCK/>
+// CHECK-1-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-1-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-1-NEXT: </VersionBlock>
+// CHECK-1-NEXT: <RecordBlock NumWords=24 BlockCodeSize=4>
+// CHECK-1-NEXT:   <USR abbrevid=4 op0=20 op1=63 op2=181 op3=66 op4=39 op5=69 op6=115 op7=202 op8=234 op9=213 op10=76 op11=235 op12=255 op13=202 op14=238 op15=61 op16=119 op17=251 op18=151 op19=19 op20=216/>
+// CHECK-1-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'I'
+// CHECK-1-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-1-NEXT:     <USR abbrevid=4 op0=20 op1=182 op2=172 op3=76 op4=92 op5=159 op6=46 op7=163 op8=242 op9=179 op10=236 op11=225 op12=163 op13=61 op14=52 op15=159 op16=78 op17=229 op18=2 op19=178 op20=78/>
+// CHECK-1-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'H'
+// CHECK-1-NEXT:     <RefType abbrevid=6 op0=3/>
+// CHECK-1-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-1-NEXT:   </ReferenceBlock>
+// CHECK-1-NEXT:   <DefLocation abbrevid=6 op0=12 op1=4/> blob data = '{{.*}}'
+// CHECK-1-NEXT:   <TagType abbrevid=8 op0=3/>
+// CHECK-1-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/5093D428CDC62096A67547BA52566E4FB9404EEE.bc | FileCheck %s --check-prefix CHECK-2
+// CHECK-2: <BLOCKINFO_BLOCK/>
+// CHECK-2-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-2-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-2-NEXT: </VersionBlock>
+// CHECK-2-NEXT: <FunctionBlock NumWords=47 BlockCodeSize=4>
+// CHECK-2-NEXT:   <USR abbrevid=4 op0=20 op1=80 op2=147 op3=212 op4=40 op5=205 op6=198 op7=32 op8=150 op9=166 op10=117 op11=71 op12=186 op13=82 op14=86 op15=110 op16=79 op17=185 op18=64 op19=78 op20=238/>
+// CHECK-2-NEXT:   <Name abbrevid=5 op0=15/> blob data = 'ProtectedMethod'
+// CHECK-2-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-2-NEXT:     <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-2-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-2-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-2-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-2-NEXT:   </ReferenceBlock>
+// CHECK-2-NEXT:   <IsMethod abbrevid=9 op0=1/>
+// CHECK-2-NEXT:   <DefLocation abbrevid=6 op0=34 op1=4/> blob data = '{{.*}}'
+// CHECK-2-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-2-NEXT:     <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-2-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-2-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-2-NEXT:     <Field abbrevid=7 op0=2/>
+// CHECK-2-NEXT:   </ReferenceBlock>
+// CHECK-2-NEXT:   <TypeBlock NumWords=6 BlockCodeSize=4>
+// CHECK-2-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-2-NEXT:       <Name abbrevid=5 op0=4/> blob data = 'void'
+// CHECK-2-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-2-NEXT:     </ReferenceBlock>
+// CHECK-2-NEXT:   </TypeBlock>
+// CHECK-2-NEXT: </FunctionBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/CA7C7935730B5EACD25F080E9C83FA087CCDC75E.bc | FileCheck %s --check-prefix CHECK-3
+// CHECK-3: <BLOCKINFO_BLOCK/>
+// CHECK-3-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-3-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-3-NEXT: </VersionBlock>
+// CHECK-3-NEXT: <RecordBlock NumWords=12 BlockCodeSize=4>
+// CHECK-3-NEXT:   <USR abbrevid=4 op0=20 op1=202 op2=124 op3=121 op4=53 op5=115 op6=11 op7=94 op8=172 op9=210 op10=95 op11=8 op12=14 op13=156 op14=131 op15=250 op16=8 op17=124 op18=205 op19=199 op20=94/>
+// CHECK-3-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'X'
+// CHECK-3-NEXT:   <DefLocation abbrevid=6 op0=38 op1=4/> blob data = '{{.*}}'
+// CHECK-3-NEXT:   <TagType abbrevid=8 op0=3/>
+// CHECK-3-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/B6AC4C5C9F2EA3F2B3ECE1A33D349F4EE502B24E.bc | FileCheck %s --check-prefix CHECK-4
+// CHECK-4: <BLOCKINFO_BLOCK/>
+// CHECK-4-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-4-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-4-NEXT: </VersionBlock>
+// CHECK-4-NEXT: <FunctionBlock NumWords=20 BlockCodeSize=4>
+// CHECK-4-NEXT:   <USR abbrevid=4 op0=20 op1=182 op2=172 op3=76 op4=92 op5=159 op6=46 op7=163 op8=242 op9=179 op10=236 op11=225 op12=163 op13=61 op14=52 op15=159 op16=78 op17=229 op18=2 op19=178 op20=78/>
+// CHECK-4-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'H'
+// CHECK-4-NEXT:   <DefLocation abbrevid=6 op0=11 op1=4/> blob data = '{{.*}}'
+// CHECK-4-NEXT:   <TypeBlock NumWords=6 BlockCodeSize=4>
+// CHECK-4-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-4-NEXT:       <Name abbrevid=5 op0=4/> blob data = 'void'
+// CHECK-4-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-4-NEXT:     </ReferenceBlock>
+// CHECK-4-NEXT:   </TypeBlock>
+// CHECK-4-NEXT: </FunctionBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/06B5F6A19BA9F6A832E127C9968282B94619B210.bc | FileCheck %s --check-prefix CHECK-5
+// CHECK-5: <BLOCKINFO_BLOCK/>
+// CHECK-5-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-5-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-5-NEXT: </VersionBlock>
+// CHECK-5-NEXT: <RecordBlock NumWords=22 BlockCodeSize=4>
+// CHECK-5-NEXT:   <USR abbrevid=4 op0=20 op1=6 op2=181 op3=246 op4=161 op5=155 op6=169 op7=246 op8=168 op9=50 op10=225 op11=39 op12=201 op13=150 op14=130 op15=130 op16=185 op17=70 op18=25 op19=178 op20=16/>
+// CHECK-5-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'C'
+// CHECK-5-NEXT:   <DefLocation abbrevid=6 op0=21 op1=4/> blob data = '{{.*}}'
+// CHECK-5-NEXT:   <MemberTypeBlock NumWords=8 BlockCodeSize=4>
+// CHECK-5-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-5-NEXT:       <Name abbrevid=5 op0=3/> blob data = 'int'
+// CHECK-5-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-5-NEXT:     </ReferenceBlock>
+// CHECK-5-NEXT:     <Name abbrevid=4 op0=1/> blob data = 'i'
+// CHECK-5-NEXT:   </MemberTypeBlock>
+// CHECK-5-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/BD2BDEBD423F80BACCEA75DE6D6622D355FC2D17.bc | FileCheck %s --check-prefix CHECK-6
+// CHECK-6: <BLOCKINFO_BLOCK/>
+// CHECK-6-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-6-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-6-NEXT: </VersionBlock>
+// CHECK-6-NEXT: <FunctionBlock NumWords=44 BlockCodeSize=4>
+// CHECK-6-NEXT:   <USR abbrevid=4 op0=20 op1=189 op2=43 op3=222 op4=189 op5=66 op6=63 op7=128 op8=186 op9=204 op10=234 op11=117 op12=222 op13=109 op14=102 op15=34 op16=211 op17=85 op18=252 op19=45 op20=23/>
+// CHECK-6-NEXT:   <Name abbrevid=5 op0=2/> blob data = '~E'
+// CHECK-6-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-6-NEXT:     <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-6-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-6-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-6-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-6-NEXT:   </ReferenceBlock>
+// CHECK-6-NEXT:   <IsMethod abbrevid=9 op0=1/>
+// CHECK-6-NEXT:   <DefLocation abbrevid=6 op0=28 op1=4/> blob data = '{{.*}}'
+// CHECK-6-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-6-NEXT:     <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-6-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-6-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-6-NEXT:     <Field abbrevid=7 op0=2/>
+// CHECK-6-NEXT:   </ReferenceBlock>
+// CHECK-6-NEXT:   <TypeBlock NumWords=6 BlockCodeSize=4>
+// CHECK-6-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-6-NEXT:       <Name abbrevid=5 op0=4/> blob data = 'void'
+// CHECK-6-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-6-NEXT:     </ReferenceBlock>
+// CHECK-6-NEXT:   </TypeBlock>
+// CHECK-6-NEXT: </FunctionBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/DEB4AC1CD9253CD9EF7FBE6BCAC506D77984ABD4.bc | FileCheck %s --check-prefix CHECK-7
+// CHECK-7: <BLOCKINFO_BLOCK/>
+// CHECK-7-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-7-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-7-NEXT: </VersionBlock>
+// CHECK-7-NEXT: <FunctionBlock NumWords=44 BlockCodeSize=4>
+// CHECK-7-NEXT:   <USR abbrevid=4 op0=20 op1=222 op2=180 op3=172 op4=28 op5=217 op6=37 op7=60 op8=217 op9=239 op10=127 op11=190 op12=107 op13=202 op14=197 op15=6 op16=215 op17=121 op18=132 op19=171 op20=212/>
+// CHECK-7-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-7-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-7-NEXT:     <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-7-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-7-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-7-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-7-NEXT:   </ReferenceBlock>
+// CHECK-7-NEXT:   <IsMethod abbrevid=9 op0=1/>
+// CHECK-7-NEXT:   <DefLocation abbrevid=6 op0=27 op1=4/> blob data = '{{.*}}'
+// CHECK-7-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-7-NEXT:     <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-7-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-7-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-7-NEXT:     <Field abbrevid=7 op0=2/>
+// CHECK-7-NEXT:   </ReferenceBlock>
+// CHECK-7-NEXT:   <TypeBlock NumWords=6 BlockCodeSize=4>
+// CHECK-7-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-7-NEXT:       <Name abbrevid=5 op0=4/> blob data = 'void'
+// CHECK-7-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-7-NEXT:     </ReferenceBlock>
+// CHECK-7-NEXT:   </TypeBlock>
+// CHECK-7-NEXT: </FunctionBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/641AB4A3D36399954ACDE29C7A8833032BF40472.bc | FileCheck %s --check-prefix CHECK-8
+// CHECK-8: <BLOCKINFO_BLOCK/>
+// CHECK-8-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-8-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-8-NEXT: </VersionBlock>
+// CHECK-8-NEXT: <RecordBlock NumWords=24 BlockCodeSize=4>
+// CHECK-8-NEXT:   <USR abbrevid=4 op0=20 op1=100 op2=26 op3=180 op4=163 op5=211 op6=99 op7=153 op8=149 op9=74 op10=205 op11=226 op12=156 op13=122 op14=136 op15=51 op16=3 op17=43 op18=244 op19=4 op20=114/>
+// CHECK-8-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'Y'
+// CHECK-8-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-8-NEXT:     <USR abbrevid=4 op0=20 op1=202 op2=124 op3=121 op4=53 op5=115 op6=11 op7=94 op8=172 op9=210 op10=95 op11=8 op12=14 op13=156 op14=131 op15=250 op16=8 op17=124 op18=205 op19=199 op20=94/>
+// CHECK-8-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'X'
+// CHECK-8-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-8-NEXT:     <Field abbrevid=7 op0=1/>
+// CHECK-8-NEXT:   </ReferenceBlock>
+// CHECK-8-NEXT:   <DefLocation abbrevid=6 op0=39 op1=4/> blob data = '{{.*}}'
+// CHECK-8-NEXT:   <TagType abbrevid=8 op0=3/>
+// CHECK-8-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/FC07BD34D5E77782C263FA944447929EA8753740.bc | FileCheck %s --check-prefix CHECK-9
+// CHECK-9: <BLOCKINFO_BLOCK/>
+// CHECK-9-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-9-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-9-NEXT: </VersionBlock>
+// CHECK-9-NEXT: <EnumBlock NumWords=16 BlockCodeSize=4>
+// CHECK-9-NEXT:   <USR abbrevid=4 op0=20 op1=252 op2=7 op3=189 op4=52 op5=213 op6=231 op7=119 op8=130 op9=194 op10=99 op11=250 op12=148 op13=68 op14=71 op15=146 op16=158 op17=168 op18=117 op19=55 op20=64/>
+// CHECK-9-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'B'
+// CHECK-9-NEXT:   <DefLocation abbrevid=6 op0=17 op1=4/> blob data = '{{.*}}'
+// CHECK-9-NEXT:   <Member abbrevid=8 op0=1/> blob data = 'X'
+// CHECK-9-NEXT:   <Member abbrevid=8 op0=1/> blob data = 'Y'
+// CHECK-9-NEXT: </EnumBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/0921737541208B8FA9BB42B60F78AC1D779AA054.bc | FileCheck %s --check-prefix CHECK-10
+// CHECK-10: <BLOCKINFO_BLOCK/>
+// CHECK-10-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-10-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-10-NEXT: </VersionBlock>
+// CHECK-10-NEXT: <RecordBlock NumWords=12 BlockCodeSize=4>
+// CHECK-10-NEXT:   <USR abbrevid=4 op0=20 op1=9 op2=33 op3=115 op4=117 op5=65 op6=32 op7=139 op8=143 op9=169 op10=187 op11=66 op12=182 op13=15 op14=120 op15=172 op16=29 op17=119 op18=154 op19=160 op20=84/>
+// CHECK-10-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'D'
+// CHECK-10-NEXT:   <DefLocation abbrevid=6 op0=23 op1=4/> blob data = '{{.*}}'
+// CHECK-10-NEXT:   <TagType abbrevid=8 op0=3/>
+// CHECK-10-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/E3B54702FABFF4037025BA194FC27C47006330B5.bc | FileCheck %s --check-prefix CHECK-11
+// CHECK-11: <BLOCKINFO_BLOCK/>
+// CHECK-11-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-11-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-11-NEXT: </VersionBlock>
+// CHECK-11-NEXT: <RecordBlock NumWords=37 BlockCodeSize=4>
+// CHECK-11-NEXT:   <USR abbrevid=4 op0=20 op1=227 op2=181 op3=71 op4=2 op5=250 op6=191 op7=244 op8=3 op9=112 op10=37 op11=186 op12=25 op13=79 op14=194 op15=124 op16=71 op17=0 op18=99 op19=48 op20=181/>
+// CHECK-11-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'F'
+// CHECK-11-NEXT:   <DefLocation abbrevid=6 op0=36 op1=4/> blob data = '{{.*}}'
+// CHECK-11-NEXT:   <TagType abbrevid=8 op0=3/>
+// CHECK-11-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-11-NEXT:     <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/>
+// CHECK-11-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'E'
+// CHECK-11-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-11-NEXT:     <Field abbrevid=7 op0=2/>
+// CHECK-11-NEXT:   </ReferenceBlock>
+// CHECK-11-NEXT:   <ReferenceBlock NumWords=10 BlockCodeSize=4>
+// CHECK-11-NEXT:     <USR abbrevid=4 op0=20 op1=9 op2=33 op3=115 op4=117 op5=65 op6=32 op7=139 op8=143 op9=169 op10=187 op11=66 op12=182 op13=15 op14=120 op15=172 op16=29 op17=119 op18=154 op19=160 op20=84/>
+// CHECK-11-NEXT:     <Name abbrevid=5 op0=1/> blob data = 'D'
+// CHECK-11-NEXT:     <RefType abbrevid=6 op0=2/>
+// CHECK-11-NEXT:     <Field abbrevid=7 op0=3/>
+// CHECK-11-NEXT:   </ReferenceBlock>
+// CHECK-11-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/ACE81AFA6627B4CEF2B456FB6E1252925674AF7E.bc | FileCheck %s --check-prefix CHECK-12
+// CHECK-12: <BLOCKINFO_BLOCK/>
+// CHECK-12-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-12-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-12-NEXT: </VersionBlock>
+// CHECK-12-NEXT: <RecordBlock NumWords=33 BlockCodeSize=4>
+// CHECK-12-NEXT:   <USR abbrevid=4 op0=20 op1=172 op2=232 op3=26 op4=250 op5=102 op6=39 op7=180 op8=206 op9=242 op10=180 op11=86 op12=251 op13=110 op14=18 op15=82 op16=146 op17=86 op18=116 op19=175 op20=126/>
+// CHECK-12-NEXT:   <Name abbrevid=5 op0=1/> blob data = 'A'
+// CHECK-12-NEXT:   <DefLocation abbrevid=6 op0=15 op1=4/> blob data = '{{.*}}'
+// CHECK-12-NEXT:   <TagType abbrevid=8 op0=2/>
+// CHECK-12-NEXT:   <MemberTypeBlock NumWords=8 BlockCodeSize=4>
+// CHECK-12-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-12-NEXT:       <Name abbrevid=5 op0=3/> blob data = 'int'
+// CHECK-12-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-12-NEXT:     </ReferenceBlock>
+// CHECK-12-NEXT:     <Name abbrevid=4 op0=1/> blob data = 'X'
+// CHECK-12-NEXT:   </MemberTypeBlock>
+// CHECK-12-NEXT:   <MemberTypeBlock NumWords=8 BlockCodeSize=4>
+// CHECK-12-NEXT:     <ReferenceBlock NumWords=3 BlockCodeSize=4>
+// CHECK-12-NEXT:       <Name abbrevid=5 op0=3/> blob data = 'int'
+// CHECK-12-NEXT:       <Field abbrevid=7 op0=4/>
+// CHECK-12-NEXT:     </ReferenceBlock>
+// CHECK-12-NEXT:     <Name abbrevid=4 op0=1/> blob data = 'Y'
+// CHECK-12-NEXT:   </MemberTypeBlock>
+// CHECK-12-NEXT: </RecordBlock>
+
+// RUN: llvm-bcanalyzer --dump %t/docs/bc/1E3438A08BA22025C0B46289FF0686F92C8924C5.bc | FileCheck %s --check-prefix CHECK-13
+// CHECK-13: <BLOCKINFO_BLOCK/>
+// CHECK-13-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4>
+// CHECK-13-NEXT:   <Version abbrevid=4 op0=2/>
+// CHECK-13-NEXT: </VersionBlock>
+// CHECK-13-NEXT: <EnumBlock NumWords=16 BlockCodeSize=4>
+// CHECK-13-NEXT:   <USR abbrevid=4 op0=20 op1=30 op2=52 op3=56 op4=160 op5=139 op6=162 op7=32 op8=37 op9=192 op10=180 op11=98 op12=137 op13=255 op14=6 op15=134 op16=249 op17=44 op18=137 op19=36 op20=197/>
+// CHECK-13-NEXT:   <Name abbrevid=5 op0=2/> blob data = 'Bc'
+// CHECK-13-NEXT:   <DefLocation abbrevid=6 op0=19 op1=4/> blob data = '{{.*}}'
+// CHECK-13-NEXT:   <Scoped abbrevid=9 op0=1/>
+// CHECK-13-NEXT:   <Member abbrevid=8 op0=1/> blob data = 'A'
+// CHECK-13-NEXT:   <Member abbrevid=8 op0=1/> blob data = 'B'
+// CHECK-13-NEXT: </EnumBlock>
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/module.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/module.cpp
new file mode 100644
index 0000000..a2b5945
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/module.cpp
@@ -0,0 +1,61 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc --extra-arg=-fmodules-ts --doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: cat %t/docs/moduleFunction.yaml | FileCheck %s --check-prefix=CHECK-A
+// RUN: cat %t/docs/staticModuleFunction.yaml | FileCheck %s --check-prefix=CHECK-B
+// RUN: cat %t/docs/exportedModuleFunction.yaml | FileCheck %s --check-prefix=CHECK-C
+
+export module M;
+
+int moduleFunction(int x); //ModuleLinkage
+// CHECK-A: ---
+// CHECK-A-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-A-NEXT: Name:            'moduleFunction'
+// CHECK-A-NEXT: Location:
+// CHECK-A-NEXT:   - LineNumber:      12
+// CHECK-A-NEXT:     Filename:        {{.*}}
+// CHECK-A-NEXT: Params:
+// CHECK-A-NEXT:   - Type:
+// CHECK-A-NEXT:       Name:            'int'
+// CHECK-A-NEXT:     Name:            'x'
+// CHECK-A-NEXT: ReturnType:
+// CHECK-A-NEXT:   Type:
+// CHECK-A-NEXT:     Name:            'int'
+// CHECK-A-NEXT: ...
+
+static int staticModuleFunction(int x); //ModuleInternalLinkage
+// CHECK-B: ---
+// CHECK-B-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-B-NEXT: Name:            'staticModuleFunction'
+// CHECK-B-NEXT: Location:
+// CHECK-B-NEXT:   - LineNumber:      28
+// CHECK-B-NEXT:     Filename:        {{.*}}
+// CHECK-B-NEXT: Params:
+// CHECK-B-NEXT:   - Type:
+// CHECK-B-NEXT:       Name:            'int'
+// CHECK-B-NEXT:     Name:            'x'
+// CHECK-B-NEXT: ReturnType:
+// CHECK-B-NEXT:   Type:
+// CHECK-B-NEXT:     Name:            'int'
+// CHECK-B-NEXT: ...
+
+export double exportedModuleFunction(double y, int z); //ExternalLinkage
+// CHECK-C: ---
+// CHECK-C-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-C-NEXT: Name:            'exportedModuleFunction'
+// CHECK-C-NEXT: Location:
+// CHECK-C-NEXT:   - LineNumber:      44
+// CHECK-C-NEXT:     Filename:        {{.*}}
+// CHECK-C-NEXT: Params:
+// CHECK-C-NEXT:   - Type:
+// CHECK-C-NEXT:       Name:            'double'
+// CHECK-C-NEXT:     Name:            'y'
+// CHECK-C-NEXT:   - Type:
+// CHECK-C-NEXT:       Name:            'int'
+// CHECK-C-NEXT:     Name:            'z'
+// CHECK-C-NEXT: ReturnType:
+// CHECK-C-NEXT:   Type:
+// CHECK-C-NEXT:     Name:            'double'
+// CHECK-C-NEXT: ...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/public-module.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/public-module.cpp
new file mode 100644
index 0000000..c7ebadd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/public-module.cpp
@@ -0,0 +1,53 @@
+// This test requires linux because it uses `diff` and compares filepaths
+// REQUIRES: system-linux
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc --public --extra-arg=-fmodules-ts --doxygen -p %t %t/test.cpp -output=%t/docs-with-public-flag
+// RUN: clang-doc --extra-arg=-fmodules-ts --doxygen -p %t %t/test.cpp -output=%t/docs-without
+// RUN: cat %t/docs-with-public-flag/moduleFunction.yaml | FileCheck %s --check-prefix=CHECK-A
+// RUN: cat %t/docs-with-public-flag/exportedModuleFunction.yaml | FileCheck %s --check-prefix=CHECK-B
+// RUN: (diff -qry %t/docs-with-public-flag %t/docs-without | sed 's:.*/::' > %t/public.diff) || true
+// RUN: cat %t/public.diff | FileCheck %s --check-prefix=CHECK-C
+
+export module M;
+
+int moduleFunction(int x); //ModuleLinkage
+// CHECK-A: ---
+// CHECK-A-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-A-NEXT: Name:            'moduleFunction'
+// CHECK-A-NEXT: Location:
+// CHECK-A-NEXT:   - LineNumber:      16
+// CHECK-A-NEXT:     Filename:        {{.*}}
+// CHECK-A-NEXT: Params:
+// CHECK-A-NEXT:   - Type:
+// CHECK-A-NEXT:       Name:            'int'
+// CHECK-A-NEXT:     Name:            'x'
+// CHECK-A-NEXT: ReturnType:
+// CHECK-A-NEXT:   Type:
+// CHECK-A-NEXT:     Name:            'int'
+// CHECK-A-NEXT: ...
+
+static int staticModuleFunction(int x); //ModuleInternalLinkage
+
+export double exportedModuleFunction(double y, int z); //ExternalLinkage
+// CHECK-B: ---
+// CHECK-B-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-B-NEXT: Name:            'exportedModuleFunction'
+// CHECK-B-NEXT: Location:
+// CHECK-B-NEXT:   - LineNumber:      34
+// CHECK-B-NEXT:     Filename:        {{.*}}
+// CHECK-B-NEXT: Params:
+// CHECK-B-NEXT:   - Type:
+// CHECK-B-NEXT:       Name:            'double'
+// CHECK-B-NEXT:     Name:            'y'
+// CHECK-B-NEXT:   - Type:
+// CHECK-B-NEXT:       Name:            'int'
+// CHECK-B-NEXT:     Name:            'z'
+// CHECK-B-NEXT: ReturnType:
+// CHECK-B-NEXT:   Type:
+// CHECK-B-NEXT:     Name:            'double'
+// CHECK-B-NEXT: ...
+
+// CHECK-C: docs-without: staticModuleFunction.yaml
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/public-records.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/public-records.cpp
new file mode 100644
index 0000000..a00a23b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/public-records.cpp
@@ -0,0 +1,341 @@
+// This test requires linux because it uses `diff` and compares filepaths
+// REQUIRES: system-linux
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc --public --doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: clang-doc --doxygen -p %t %t/test.cpp -output=%t/docs-without-flag
+// RUN: cat %t/docs/function.yaml | FileCheck %s --check-prefix=CHECK-A
+// RUN: cat %t/docs/inlinedFunction.yaml | FileCheck %s --check-prefix=CHECK-B
+// RUN: cat %t/docs/functionWithInnerClass.yaml | FileCheck %s --check-prefix=CHECK-C
+// RUN: cat %t/docs/inlinedFunctionWithInnerClass.yaml | FileCheck %s --check-prefix=CHECK-D
+// RUN: cat %t/docs/Class/publicMethod.yaml| FileCheck %s --check-prefix=CHECK-E
+// RUN: cat %t/docs/Class.yaml| FileCheck %s --check-prefix=CHECK-F
+// RUN: cat %t/docs/Class/protectedMethod.yaml| FileCheck %s --check-prefix=CHECK-G
+// RUN: cat %t/docs/named.yaml| FileCheck %s --check-prefix=CHECK-H
+// RUN: cat %t/docs/named/NamedClass.yaml| FileCheck %s --check-prefix=CHECK-I
+// RUN: cat %t/docs/named/namedFunction.yaml| FileCheck %s --check-prefix=CHECK-J
+// RUN: cat %t/docs/named/namedInlineFunction.yaml| FileCheck %s --check-prefix=CHECK-K
+// RUN: cat %t/docs/named/NamedClass/namedPublicMethod.yaml| FileCheck %s --check-prefix=CHECK-L
+// RUN: cat %t/docs/named/NamedClass/namedProtectedMethod.yaml| FileCheck %s --check-prefix=CHECK-M
+// RUN: (diff -qry %t/docs-without-flag %t/docs | sed 's:.*/::' > %t/public.diff) || true
+// RUN: cat %t/public.diff | FileCheck %s --check-prefix=CHECK-N
+
+void function(int x);
+
+// CHECK-A: ---
+// CHECK-A-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-A-NEXT: Name:            'function'
+// CHECK-A-NEXT: Location:
+// CHECK-A-NEXT:   - LineNumber:      25
+// CHECK-A-NEXT:     Filename:        {{.*}}
+// CHECK-A-NEXT: Params:
+// CHECK-A-NEXT:   - Type:
+// CHECK-A-NEXT:       Name:            'int'
+// CHECK-A-NEXT:     Name:            'x'
+// CHECK-A-NEXT: ReturnType:
+// CHECK-A-NEXT:   Type:
+// CHECK-A-NEXT:     Name:            'void'
+// CHECK-A-NEXT: ...
+
+inline int inlinedFunction(int x);
+
+// CHECK-B: ---
+// CHECK-B-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-B-NEXT: Name:            'inlinedFunction'
+// CHECK-B-NEXT: Location:
+// CHECK-B-NEXT:   - LineNumber:      42
+// CHECK-B-NEXT:     Filename:        {{.*}}
+// CHECK-B-NEXT: Params:
+// CHECK-B-NEXT:   - Type:
+// CHECK-B-NEXT:       Name:            'int'
+// CHECK-B-NEXT:     Name:            'x'
+// CHECK-B-NEXT: ReturnType:
+// CHECK-B-NEXT:   Type:
+// CHECK-B-NEXT:     Name:            'int'
+// CHECK-B-NEXT: ...
+
+int functionWithInnerClass(int x){
+    class InnerClass { //NoLinkage
+      public:
+        int innerPublicMethod() { return 2; };
+    }; //end class
+    InnerClass temp;
+    return temp.innerPublicMethod();
+};
+
+// CHECK-C: ---
+// CHECK-C-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-C-NEXT: Name:            'functionWithInnerClass'
+// CHECK-C-NEXT: DefLocation:
+// CHECK-C-NEXT:   LineNumber:      59
+// CHECK-C-NEXT:   Filename:        {{.*}}
+// CHECK-C-NEXT: Params:
+// CHECK-C-NEXT:   - Type:
+// CHECK-C-NEXT:       Name:            'int'
+// CHECK-C-NEXT:     Name:            'x'
+// CHECK-C-NEXT: ReturnType:
+// CHECK-C-NEXT:   Type:
+// CHECK-C-NEXT:     Name:            'int'
+// CHECK-C-NEXT: ...
+
+inline int inlinedFunctionWithInnerClass(int x){
+    class InnerClass { //VisibleNoLinkage
+      public:
+        int innerPublicMethod() { return 2; };
+    }; //end class
+    InnerClass temp;
+    return temp.innerPublicMethod();
+};
+
+// CHECK-D: ---
+// CHECK-D-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-D-NEXT: Name:            'inlinedFunctionWithInnerClass'
+// CHECK-D-NEXT: DefLocation:
+// CHECK-D-NEXT:   LineNumber:      83
+// CHECK-D-NEXT:   Filename:        {{.*}}
+// CHECK-D-NEXT: Params:
+// CHECK-D-NEXT:   - Type:
+// CHECK-D-NEXT:       Name:            'int'
+// CHECK-D-NEXT:     Name:            'x'
+// CHECK-D-NEXT: ReturnType:
+// CHECK-D-NEXT:   Type:
+// CHECK-D-NEXT:     Name:            'int'
+// CHECK-D-NEXT: ...
+
+class Class {
+ public:
+  void publicMethod();
+  int  publicField;
+ protected:
+  void protectedMethod();
+  int  protectedField;
+ private:
+  void privateMethod();
+  int  privateField;
+};
+
+// CHECK-E: ---
+// CHECK-E-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-E-NEXT: Name:            'publicMethod'
+// CHECK-E-NEXT: Namespace:
+// CHECK-E-NEXT:   - Type:            Record
+// CHECK-E-NEXT:     Name:            'Class'
+// CHECK-E-NEXT:     USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-E-NEXT: Location:
+// CHECK-E-NEXT:   - LineNumber:      109
+// CHECK-E-NEXT:     Filename:        {{.*}}
+// CHECK-E-NEXT: IsMethod:        true
+// CHECK-E-NEXT: Parent:
+// CHECK-E-NEXT:   Type:            Record
+// CHECK-E-NEXT:   Name:            'Class'
+// CHECK-E-NEXT:   USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-E-NEXT: ReturnType:
+// CHECK-E-NEXT:   Type:
+// CHECK-E-NEXT:     Name:            'void'
+// CHECK-E-NEXT: ...
+
+// CHECK-F: ---
+// CHECK-F-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-F-NEXT: Name:            'Class'
+// CHECK-F-NEXT: DefLocation:
+// CHECK-F-NEXT:   LineNumber:      107
+// CHECK-F-NEXT:   Filename:        {{.*}}
+// CHECK-F-NEXT: TagType:         Class
+// CHECK-F-NEXT: Members:
+// CHECK-F-NEXT:   - Type:
+// CHECK-F-NEXT:       Name:            'int'
+// CHECK-F-NEXT:     Name:            'publicField'
+// CHECK-F-NEXT:   - Type:
+// CHECK-F-NEXT:       Name:            'int'
+// CHECK-F-NEXT:     Name:            'protectedField'
+// CHECK-F-NEXT:     Access:          Protected
+// CHECK-F-NEXT: ...
+
+// CHECK-G: ---
+// CHECK-G-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-G-NEXT: Name:            'protectedMethod'
+// CHECK-G-NEXT: Namespace:
+// CHECK-G-NEXT:   - Type:            Record
+// CHECK-G-NEXT:     Name:            'Class'
+// CHECK-G-NEXT:     USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-G-NEXT: Location:
+// CHECK-G-NEXT:   - LineNumber:      112
+// CHECK-G-NEXT:     Filename:        {{.*}}
+// CHECK-G-NEXT: IsMethod:        true
+// CHECK-G-NEXT: Parent:
+// CHECK-G-NEXT:   Type:            Record
+// CHECK-G-NEXT:   Name:            'Class'
+// CHECK-G-NEXT:   USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-G-NEXT: ReturnType:
+// CHECK-G-NEXT:   Type:
+// CHECK-G-NEXT:     Name:            'void'
+// CHECK-G-NEXT: ...
+
+namespace named{
+    class NamedClass {
+     public:
+      void namedPublicMethod();
+      int  namedPublicField;
+     protected:
+      void namedProtectedMethod();
+      int  namedProtectedField;
+     private:
+      void namedPrivateMethod();
+      int  namedPrivateField;
+    };
+
+    void namedFunction();
+    static void namedStaticFunction();
+    inline void namedInlineFunction();
+}
+
+// CHECK-H: ---
+// CHECK-H-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-H-NEXT: Name:            'named'
+// CHECK-H-NEXT: ...
+
+// CHECK-I: ---
+// CHECK-I-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-I-NEXT: Name:            'NamedClass'
+// CHECK-I-NEXT: Namespace:
+// CHECK-I-NEXT:   - Type:            Namespace
+// CHECK-I-NEXT:     Name:            'named'
+// CHECK-I-NEXT:     USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-I-NEXT: DefLocation:
+// CHECK-I-NEXT:   LineNumber:      177
+// CHECK-I-NEXT:   Filename:        {{.*}}
+// CHECK-I-NEXT: TagType:         Class
+// CHECK-I-NEXT: Members:
+// CHECK-I-NEXT:   - Type:
+// CHECK-I-NEXT:       Name:            'int'
+// CHECK-I-NEXT:     Name:            'namedPublicField'
+// CHECK-I-NEXT:   - Type:
+// CHECK-I-NEXT:       Name:            'int'
+// CHECK-I-NEXT:     Name:            'namedProtectedField'
+// CHECK-I-NEXT:     Access:          Protected
+// CHECK-I-NEXT: ...
+
+// CHECK-J: ---
+// CHECK-J-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-J-NEXT: Name:            'namedFunction'
+// CHECK-J-NEXT: Namespace:
+// CHECK-J-NEXT:   - Type:            Namespace
+// CHECK-J-NEXT:     Name:            'named'
+// CHECK-J-NEXT:     USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-J-NEXT: Location:
+// CHECK-J-NEXT:   - LineNumber:      189
+// CHECK-J-NEXT:     Filename:        {{.*}}
+// CHECK-J-NEXT: ReturnType:
+// CHECK-J-NEXT:   Type:
+// CHECK-J-NEXT:     Name:            'void'
+// CHECK-J-NEXT: ...
+
+// CHECK-K: ---
+// CHECK-K-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-K-NEXT: Name:            'namedInlineFunction'
+// CHECK-K-NEXT: Namespace:
+// CHECK-K-NEXT:   - Type:            Namespace
+// CHECK-K-NEXT:     Name:            'named'
+// CHECK-K-NEXT:     USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-K-NEXT: Location:
+// CHECK-K-NEXT:   - LineNumber:      191
+// CHECK-K-NEXT:     Filename:        {{.*}}
+// CHECK-K-NEXT: ReturnType:
+// CHECK-K-NEXT:   Type:
+// CHECK-K-NEXT:     Name:            'void'
+// CHECK-K-NEXT: ...
+
+// CHECK-L: ---
+// CHECK-L-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-L-NEXT: Name:            'namedPublicMethod'
+// CHECK-L-NEXT: Namespace:
+// CHECK-L-NEXT:   - Type:            Record
+// CHECK-L-NEXT:     Name:            'NamedClass'
+// CHECK-L-NEXT:     USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-L-NEXT:   - Type:            Namespace
+// CHECK-L-NEXT:     Name:            'named'
+// CHECK-L-NEXT:     USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-L-NEXT: Location:
+// CHECK-L-NEXT:   - LineNumber:      179
+// CHECK-L-NEXT:     Filename:        {{.*}}
+// CHECK-L-NEXT: IsMethod:        true
+// CHECK-L-NEXT: Parent:
+// CHECK-L-NEXT:   Type:            Record
+// CHECK-L-NEXT:   Name:            'NamedClass'
+// CHECK-L-NEXT:   USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-L-NEXT: ReturnType:
+// CHECK-L-NEXT:   Type:
+// CHECK-L-NEXT:     Name:            'void'
+// CHECK-L-NEXT: ...
+
+// CHECK-M: ---
+// CHECK-M-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-M-NEXT: Name:            'namedProtectedMethod'
+// CHECK-M-NEXT: Namespace:
+// CHECK-M-NEXT:   - Type:            Record
+// CHECK-M-NEXT:     Name:            'NamedClass'
+// CHECK-M-NEXT:     USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-M-NEXT:   - Type:            Namespace
+// CHECK-M-NEXT:     Name:            'named'
+// CHECK-M-NEXT:     USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-M-NEXT: Location:
+// CHECK-M-NEXT:   - LineNumber:      182
+// CHECK-M-NEXT:     Filename:        {{.*}}
+// CHECK-M-NEXT: IsMethod:        true
+// CHECK-M-NEXT: Parent:
+// CHECK-M-NEXT:   Type:            Record
+// CHECK-M-NEXT:   Name:            'NamedClass'
+// CHECK-M-NEXT:   USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-M-NEXT: ReturnType:
+// CHECK-M-NEXT:   Type:
+// CHECK-M-NEXT:     Name:            'void'
+// CHECK-M-NEXT: ...
+
+
+static void staticFunction(int x); //Internal Linkage
+
+static int staticFunctionWithInnerClass(int x){
+    class InnerClass { //NoLinkage
+      public:
+        int innerPublicMethod() { return 2; };
+    }; //end class
+    InnerClass temp;
+    return temp.innerPublicMethod();
+};
+
+namespace{
+    class AnonClass {
+     public:
+      void anonPublicMethod();
+      int  anonPublicField;
+     protected:
+      void anonProtectedMethod();
+      int  anonProtectedField;
+     private:
+      void anonPrivateMethod();
+      int  anonPrivateField;
+    };
+
+    void anonFunction();
+    static void anonStaticFunction();
+    inline void anonInlineFunction();
+}
+
+// CHECK-N: docs-without-flag: .yaml
+// CHECK-N-NEXT: docs-without-flag: AnonClass
+// CHECK-N-NEXT: docs-without-flag: AnonClass.yaml
+// CHECK-N-NEXT: Class: privateMethod.yaml
+// CHECK-N-NEXT: Class.yaml differ
+// CHECK-N-NEXT: docs-without-flag: anonFunction.yaml
+// CHECK-N-NEXT: docs-without-flag: anonInlineFunction.yaml
+// CHECK-N-NEXT: docs-without-flag: anonStaticFunction.yaml
+// CHECK-N-NEXT: docs-without-flag: functionWithInnerClass
+// CHECK-N-NEXT: docs-without-flag: inlinedFunctionWithInnerClass
+// CHECK-N-NEXT: NamedClass: namedPrivateMethod.yaml
+// CHECK-N-NEXT: NamedClass.yaml differ
+// CHECK-N-NEXT: named: namedStaticFunction.yaml
+// CHECK-N-NEXT: docs-without-flag: staticFunction.yaml
+// CHECK-N-NEXT: docs-without-flag: staticFunctionWithInnerClass
+// CHECK-N-NEXT: docs-without-flag: staticFunctionWithInnerClass.yaml
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/test_cases/comment.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/test_cases/comment.cpp
new file mode 100644
index 0000000..9a4ae1b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/test_cases/comment.cpp
@@ -0,0 +1,28 @@
+// THIS IS A GENERATED TEST. DO NOT EDIT.
+// To regenerate, see clang-doc/gen_test.py docstring.
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+
+/// \brief Brief description.
+///
+/// Extended description that
+/// continues onto the next line.
+/// 
+/// <ul class="test">
+///   <li> Testing.
+/// </ul>
+///
+/// \verbatim
+/// The description continues.
+/// \endverbatim
+/// --
+/// \param [out] I is a parameter.
+/// \param J is a parameter.
+/// \return void
+void F(int I, int J);
+
+/// Bonus comment on definition
+void F(int I, int J) {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/test_cases/compile_flags.txt b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/test_cases/compile_flags.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/test_cases/compile_flags.txt
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/test_cases/namespace.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/test_cases/namespace.cpp
new file mode 100644
index 0000000..7fa6f8f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/test_cases/namespace.cpp
@@ -0,0 +1,26 @@
+// THIS IS A GENERATED TEST. DO NOT EDIT.
+// To regenerate, see clang-doc/gen_test.py docstring.
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+
+namespace A {
+  
+void f();
+
+}  // namespace A
+
+namespace A {
+
+void f(){};
+
+namespace B {
+
+enum E { X };
+
+E func(int i) { return X; }
+
+}  // namespace B
+}  // namespace A
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/test_cases/record.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/test_cases/record.cpp
new file mode 100644
index 0000000..03419a9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/test_cases/record.cpp
@@ -0,0 +1,40 @@
+// THIS IS A GENERATED TEST. DO NOT EDIT.
+// To regenerate, see clang-doc/gen_test.py docstring.
+//
+// This test requires Linux due to system-dependent USR for the inner class.
+// REQUIRES: system-linux
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+
+void H() {
+  class I {};
+}
+
+union A { int X; int Y; };
+
+enum B { X, Y };
+
+enum class Bc { A, B };
+
+struct C { int i; };
+
+class D {};
+
+class E {
+public:
+  E() {}
+  ~E() {}
+
+protected:
+  void ProtectedMethod();
+};
+
+void E::ProtectedMethod() {}
+
+class F : virtual private D, public E {};
+
+class X {
+  class Y {};
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/yaml-comment.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/yaml-comment.cpp
new file mode 100644
index 0000000..445e2be
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/yaml-comment.cpp
@@ -0,0 +1,136 @@
+// THIS IS A GENERATED TEST. DO NOT EDIT.
+// To regenerate, see clang-doc/gen_test.py docstring.
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+
+/// \brief Brief description.
+///
+/// Extended description that
+/// continues onto the next line.
+/// 
+/// <ul class="test">
+///   <li> Testing.
+/// </ul>
+///
+/// \verbatim
+/// The description continues.
+/// \endverbatim
+/// --
+/// \param [out] I is a parameter.
+/// \param J is a parameter.
+/// \return void
+void F(int I, int J);
+
+/// Bonus comment on definition
+void F(int I, int J) {}
+
+// RUN: clang-doc --format=yaml --doxygen -p %t %t/test.cpp -output=%t/docs
+
+
+// RUN: cat %t/docs/./F.yaml | FileCheck %s --check-prefix CHECK-0
+// CHECK-0: ---
+// CHECK-0-NEXT: USR:             '7574630614A535710E5A6ABCFFF98BCA2D06A4CA'
+// CHECK-0-NEXT: Name:            'F'
+// CHECK-0-NEXT: Description:     
+// CHECK-0-NEXT:   - Kind:            'FullComment'
+// CHECK-0-NEXT:     Children:        
+// CHECK-0-NEXT:       - Kind:            'ParagraphComment'
+// CHECK-0-NEXT:         Children:        
+// CHECK-0-NEXT:           - Kind:            'TextComment'
+// CHECK-0-NEXT:       - Kind:            'BlockCommandComment'
+// CHECK-0-NEXT:         Name:            'brief'
+// CHECK-0-NEXT:         Children:        
+// CHECK-0-NEXT:           - Kind:            'ParagraphComment'
+// CHECK-0-NEXT:             Children:        
+// CHECK-0-NEXT:               - Kind:            'TextComment'
+// CHECK-0-NEXT:                 Text:            ' Brief description.'
+// CHECK-0-NEXT:       - Kind:            'ParagraphComment'
+// CHECK-0-NEXT:         Children:        
+// CHECK-0-NEXT:           - Kind:            'TextComment'
+// CHECK-0-NEXT:             Text:            ' Extended description that'
+// CHECK-0-NEXT:           - Kind:            'TextComment'
+// CHECK-0-NEXT:             Text:            ' continues onto the next line.'
+// CHECK-0-NEXT:       - Kind:            'ParagraphComment'
+// CHECK-0-NEXT:         Children:        
+// CHECK-0-NEXT:           - Kind:            'TextComment'
+// CHECK-0-NEXT:           - Kind:            'HTMLStartTagComment'
+// CHECK-0-NEXT:             Name:            'ul'
+// CHECK-0-NEXT:             AttrKeys:        
+// CHECK-0-NEXT:               - 'class'
+// CHECK-0-NEXT:             AttrValues:      
+// CHECK-0-NEXT:               - 'test'
+// CHECK-0-NEXT:           - Kind:            'TextComment'
+// CHECK-0-NEXT:           - Kind:            'HTMLStartTagComment'
+// CHECK-0-NEXT:             Name:            'li'
+// CHECK-0-NEXT:           - Kind:            'TextComment'
+// CHECK-0-NEXT:             Text:            ' Testing.'
+// CHECK-0-NEXT:           - Kind:            'TextComment'
+// CHECK-0-NEXT:           - Kind:            'HTMLEndTagComment'
+// CHECK-0-NEXT:             Name:            'ul'
+// CHECK-0-NEXT:             SelfClosing:     true
+// CHECK-0-NEXT:       - Kind:            'ParagraphComment'
+// CHECK-0-NEXT:         Children:        
+// CHECK-0-NEXT:           - Kind:            'TextComment'
+// CHECK-0-NEXT:       - Kind:            'VerbatimBlockComment'
+// CHECK-0-NEXT:         Name:            'verbatim'
+// CHECK-0-NEXT:         CloseName:       'endverbatim'
+// CHECK-0-NEXT:         Children:        
+// CHECK-0-NEXT:           - Kind:            'VerbatimBlockLineComment'
+// CHECK-0-NEXT:             Text:            ' The description continues.'
+// CHECK-0-NEXT:       - Kind:            'ParagraphComment'
+// CHECK-0-NEXT:         Children:        
+// CHECK-0-NEXT:           - Kind:            'TextComment'
+// CHECK-0-NEXT:             Text:            ' --'
+// CHECK-0-NEXT:           - Kind:            'TextComment'
+// CHECK-0-NEXT:       - Kind:            'ParamCommandComment'
+// CHECK-0-NEXT:         Direction:       '[out]'
+// CHECK-0-NEXT:         ParamName:       'I'
+// CHECK-0-NEXT:         Explicit:        true
+// CHECK-0-NEXT:         Children:        
+// CHECK-0-NEXT:           - Kind:            'ParagraphComment'
+// CHECK-0-NEXT:             Children:        
+// CHECK-0-NEXT:               - Kind:            'TextComment'
+// CHECK-0-NEXT:                 Text:            ' is a parameter.'
+// CHECK-0-NEXT:               - Kind:            'TextComment'
+// CHECK-0-NEXT:       - Kind:            'ParamCommandComment'
+// CHECK-0-NEXT:         Direction:       '[in]'
+// CHECK-0-NEXT:         ParamName:       'J'
+// CHECK-0-NEXT:         Children:        
+// CHECK-0-NEXT:           - Kind:            'ParagraphComment'
+// CHECK-0-NEXT:             Children:        
+// CHECK-0-NEXT:               - Kind:            'TextComment'
+// CHECK-0-NEXT:                 Text:            ' is a parameter.'
+// CHECK-0-NEXT:               - Kind:            'TextComment'
+// CHECK-0-NEXT:       - Kind:            'BlockCommandComment'
+// CHECK-0-NEXT:         Name:            'return'
+// CHECK-0-NEXT:         Children:        
+// CHECK-0-NEXT:           - Kind:            'ParagraphComment'
+// CHECK-0-NEXT:             Children:        
+// CHECK-0-NEXT:               - Kind:            'TextComment'
+// CHECK-0-NEXT:                 Text:            ' void'
+// CHECK-0-NEXT:   - Kind:            'FullComment'
+// CHECK-0-NEXT:     Children:        
+// CHECK-0-NEXT:       - Kind:            'ParagraphComment'
+// CHECK-0-NEXT:         Children:        
+// CHECK-0-NEXT:           - Kind:            'TextComment'
+// CHECK-0-NEXT:             Text:            ' Bonus comment on definition'
+// CHECK-0-NEXT: DefLocation:     
+// CHECK-0-NEXT:   LineNumber:      28
+// CHECK-0-NEXT:   Filename:        'test'
+// CHECK-0-NEXT: Location:        
+// CHECK-0-NEXT:   - LineNumber:      25
+// CHECK-0-NEXT:     Filename:        'test'
+// CHECK-0-NEXT: Params:          
+// CHECK-0-NEXT:   - Type:            
+// CHECK-0-NEXT:       Name:            'int'
+// CHECK-0-NEXT:     Name:            'I'
+// CHECK-0-NEXT:   - Type:            
+// CHECK-0-NEXT:       Name:            'int'
+// CHECK-0-NEXT:     Name:            'J'
+// CHECK-0-NEXT: ReturnType:      
+// CHECK-0-NEXT:   Type:            
+// CHECK-0-NEXT:     Name:            'void'
+// CHECK-0-NEXT: ...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/yaml-namespace.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/yaml-namespace.cpp
new file mode 100644
index 0000000..c547c5c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/yaml-namespace.cpp
@@ -0,0 +1,105 @@
+// THIS IS A GENERATED TEST. DO NOT EDIT.
+// To regenerate, see clang-doc/gen_test.py docstring.
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+
+namespace A {
+  
+void f();
+
+}  // namespace A
+
+namespace A {
+
+void f(){};
+
+namespace B {
+
+enum E { X };
+
+E func(int i) { return X; }
+
+}  // namespace B
+}  // namespace A
+
+// RUN: clang-doc --format=yaml --doxygen -p %t %t/test.cpp -output=%t/docs
+
+
+// RUN: cat %t/docs/./A.yaml | FileCheck %s --check-prefix CHECK-0
+// CHECK-0: ---
+// CHECK-0-NEXT: USR:             '8D042EFFC98B373450BC6B5B90A330C25A150E9C'
+// CHECK-0-NEXT: Name:            'A'
+// CHECK-0-NEXT: ...
+
+// RUN: cat %t/docs/A/f.yaml | FileCheck %s --check-prefix CHECK-1
+// CHECK-1: ---
+// CHECK-1-NEXT: USR:             '39D3C95A5F7CE2BA4937BD7B01BAE09EBC2AD8AC'
+// CHECK-1-NEXT: Name:            'f'
+// CHECK-1-NEXT: Namespace:       
+// CHECK-1-NEXT:   - Type:            Namespace
+// CHECK-1-NEXT:     Name:            'A'
+// CHECK-1-NEXT:     USR:             '8D042EFFC98B373450BC6B5B90A330C25A150E9C'
+// CHECK-1-NEXT: DefLocation:     
+// CHECK-1-NEXT:   LineNumber:      17
+// CHECK-1-NEXT:   Filename:        'test'
+// CHECK-1-NEXT: Location:        
+// CHECK-1-NEXT:   - LineNumber:      11
+// CHECK-1-NEXT:     Filename:        'test'
+// CHECK-1-NEXT: ReturnType:      
+// CHECK-1-NEXT:   Type:            
+// CHECK-1-NEXT:     Name:            'void'
+// CHECK-1-NEXT: ...
+
+// RUN: cat %t/docs/A/B.yaml | FileCheck %s --check-prefix CHECK-2
+// CHECK-2: ---
+// CHECK-2-NEXT: USR:             'E21AF79E2A9D02554BA090D10DF39FE273F5CDB5'
+// CHECK-2-NEXT: Name:            'B'
+// CHECK-2-NEXT: Namespace:       
+// CHECK-2-NEXT:   - Type:            Namespace
+// CHECK-2-NEXT:     Name:            'A'
+// CHECK-2-NEXT:     USR:             '8D042EFFC98B373450BC6B5B90A330C25A150E9C'
+// CHECK-2-NEXT: ...
+
+// RUN: cat %t/docs/A/B/E.yaml | FileCheck %s --check-prefix CHECK-3
+// CHECK-3: ---
+// CHECK-3-NEXT: USR:             'E9ABF7E7E2425B626723D41E76E4BC7E7A5BD775'
+// CHECK-3-NEXT: Name:            'E'
+// CHECK-3-NEXT: Namespace:       
+// CHECK-3-NEXT:   - Type:            Namespace
+// CHECK-3-NEXT:     Name:            'B'
+// CHECK-3-NEXT:     USR:             'E21AF79E2A9D02554BA090D10DF39FE273F5CDB5'
+// CHECK-3-NEXT:   - Type:            Namespace
+// CHECK-3-NEXT:     Name:            'A'
+// CHECK-3-NEXT:     USR:             '8D042EFFC98B373450BC6B5B90A330C25A150E9C'
+// CHECK-3-NEXT: DefLocation:     
+// CHECK-3-NEXT:   LineNumber:      21
+// CHECK-3-NEXT:   Filename:        'test'
+// CHECK-3-NEXT: Members:         
+// CHECK-3-NEXT:   - 'X'
+// CHECK-3-NEXT: ...
+
+// RUN: cat %t/docs/A/B/func.yaml | FileCheck %s --check-prefix CHECK-4
+// CHECK-4: ---
+// CHECK-4-NEXT: USR:             '9A82CB33ED0FDF81EE383D31CD0957D153C5E840'
+// CHECK-4-NEXT: Name:            'func'
+// CHECK-4-NEXT: Namespace:       
+// CHECK-4-NEXT:   - Type:            Namespace
+// CHECK-4-NEXT:     Name:            'B'
+// CHECK-4-NEXT:     USR:             'E21AF79E2A9D02554BA090D10DF39FE273F5CDB5'
+// CHECK-4-NEXT:   - Type:            Namespace
+// CHECK-4-NEXT:     Name:            'A'
+// CHECK-4-NEXT:     USR:             '8D042EFFC98B373450BC6B5B90A330C25A150E9C'
+// CHECK-4-NEXT: DefLocation:     
+// CHECK-4-NEXT:   LineNumber:      23
+// CHECK-4-NEXT:   Filename:        'test'
+// CHECK-4-NEXT: Params:          
+// CHECK-4-NEXT:   - Type:            
+// CHECK-4-NEXT:       Name:            'int'
+// CHECK-4-NEXT:     Name:            'i'
+// CHECK-4-NEXT: ReturnType:      
+// CHECK-4-NEXT:   Type:            
+// CHECK-4-NEXT:     Name:            'enum A::B::E'
+// CHECK-4-NEXT: ...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/yaml-record.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/yaml-record.cpp
new file mode 100644
index 0000000..1d5235f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-doc/yaml-record.cpp
@@ -0,0 +1,252 @@
+// THIS IS A GENERATED TEST. DO NOT EDIT.
+// To regenerate, see clang-doc/gen_test.py docstring.
+//
+// This test requires Linux due to system-dependent USR for the inner class.
+// REQUIRES: system-linux
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+
+void H() {
+  class I {};
+}
+
+union A { int X; int Y; };
+
+enum B { X, Y };
+
+enum class Bc { A, B };
+
+struct C { int i; };
+
+class D {};
+
+class E {
+public:
+  E() {}
+  ~E() {}
+
+protected:
+  void ProtectedMethod();
+};
+
+void E::ProtectedMethod() {}
+
+class F : virtual private D, public E {};
+
+class X {
+  class Y {};
+};
+
+// RUN: clang-doc --format=yaml --doxygen -p %t %t/test.cpp -output=%t/docs
+
+
+// RUN: cat %t/docs/./C.yaml | FileCheck %s --check-prefix CHECK-0
+// CHECK-0: ---
+// CHECK-0-NEXT: USR:             '06B5F6A19BA9F6A832E127C9968282B94619B210'
+// CHECK-0-NEXT: Name:            'C'
+// CHECK-0-NEXT: DefLocation:     
+// CHECK-0-NEXT:   LineNumber:      21
+// CHECK-0-NEXT:   Filename:        'test'
+// CHECK-0-NEXT: Members:         
+// CHECK-0-NEXT:   - Type:            
+// CHECK-0-NEXT:       Name:            'int'
+// CHECK-0-NEXT:     Name:            'i'
+// CHECK-0-NEXT: ...
+
+// RUN: cat %t/docs/./A.yaml | FileCheck %s --check-prefix CHECK-1
+// CHECK-1: ---
+// CHECK-1-NEXT: USR:             'ACE81AFA6627B4CEF2B456FB6E1252925674AF7E'
+// CHECK-1-NEXT: Name:            'A'
+// CHECK-1-NEXT: DefLocation:     
+// CHECK-1-NEXT:   LineNumber:      15
+// CHECK-1-NEXT:   Filename:        'test'
+// CHECK-1-NEXT: TagType:         Union
+// CHECK-1-NEXT: Members:         
+// CHECK-1-NEXT:   - Type:            
+// CHECK-1-NEXT:       Name:            'int'
+// CHECK-1-NEXT:     Name:            'X'
+// CHECK-1-NEXT:   - Type:            
+// CHECK-1-NEXT:       Name:            'int'
+// CHECK-1-NEXT:     Name:            'Y'
+// CHECK-1-NEXT: ...
+
+// RUN: cat %t/docs/./F.yaml | FileCheck %s --check-prefix CHECK-2
+// CHECK-2: ---
+// CHECK-2-NEXT: USR:             'E3B54702FABFF4037025BA194FC27C47006330B5'
+// CHECK-2-NEXT: Name:            'F'
+// CHECK-2-NEXT: DefLocation:     
+// CHECK-2-NEXT:   LineNumber:      36
+// CHECK-2-NEXT:   Filename:        'test'
+// CHECK-2-NEXT: TagType:         Class
+// CHECK-2-NEXT: Parents:         
+// CHECK-2-NEXT:   - Type:            Record
+// CHECK-2-NEXT:     Name:            'E'
+// CHECK-2-NEXT:     USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-2-NEXT: VirtualParents:  
+// CHECK-2-NEXT:   - Type:            Record
+// CHECK-2-NEXT:     Name:            'D'
+// CHECK-2-NEXT:     USR:             '0921737541208B8FA9BB42B60F78AC1D779AA054'
+// CHECK-2-NEXT: ...
+
+// RUN: cat %t/docs/./E.yaml | FileCheck %s --check-prefix CHECK-3
+// CHECK-3: ---
+// CHECK-3-NEXT: USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-3-NEXT: Name:            'E'
+// CHECK-3-NEXT: DefLocation:     
+// CHECK-3-NEXT:   LineNumber:      25
+// CHECK-3-NEXT:   Filename:        'test'
+// CHECK-3-NEXT: TagType:         Class
+// CHECK-3-NEXT: ...
+
+// RUN: cat %t/docs/./D.yaml | FileCheck %s --check-prefix CHECK-4
+// CHECK-4: ---
+// CHECK-4-NEXT: USR:             '0921737541208B8FA9BB42B60F78AC1D779AA054'
+// CHECK-4-NEXT: Name:            'D'
+// CHECK-4-NEXT: DefLocation:     
+// CHECK-4-NEXT:   LineNumber:      23
+// CHECK-4-NEXT:   Filename:        'test'
+// CHECK-4-NEXT: TagType:         Class
+// CHECK-4-NEXT: ...
+
+// RUN: cat %t/docs/./B.yaml | FileCheck %s --check-prefix CHECK-5
+// CHECK-5: ---
+// CHECK-5-NEXT: USR:             'FC07BD34D5E77782C263FA944447929EA8753740'
+// CHECK-5-NEXT: Name:            'B'
+// CHECK-5-NEXT: DefLocation:     
+// CHECK-5-NEXT:   LineNumber:      17
+// CHECK-5-NEXT:   Filename:        'test'
+// CHECK-5-NEXT: Members:         
+// CHECK-5-NEXT:   - 'X'
+// CHECK-5-NEXT:   - 'Y'
+// CHECK-5-NEXT: ...
+
+// RUN: cat %t/docs/./X.yaml | FileCheck %s --check-prefix CHECK-6
+// CHECK-6: ---
+// CHECK-6-NEXT: USR:             'CA7C7935730B5EACD25F080E9C83FA087CCDC75E'
+// CHECK-6-NEXT: Name:            'X'
+// CHECK-6-NEXT: DefLocation:     
+// CHECK-6-NEXT:   LineNumber:      38
+// CHECK-6-NEXT:   Filename:        'test'
+// CHECK-6-NEXT: TagType:         Class
+// CHECK-6-NEXT: ...
+
+// RUN: cat %t/docs/./H.yaml | FileCheck %s --check-prefix CHECK-7
+// CHECK-7: ---
+// CHECK-7-NEXT: USR:             'B6AC4C5C9F2EA3F2B3ECE1A33D349F4EE502B24E'
+// CHECK-7-NEXT: Name:            'H'
+// CHECK-7-NEXT: DefLocation:     
+// CHECK-7-NEXT:   LineNumber:      11
+// CHECK-7-NEXT:   Filename:        'test'
+// CHECK-7-NEXT: ReturnType:      
+// CHECK-7-NEXT:   Type:            
+// CHECK-7-NEXT:     Name:            'void'
+// CHECK-7-NEXT: ...
+
+// RUN: cat %t/docs/./Bc.yaml | FileCheck %s --check-prefix CHECK-8
+// CHECK-8: ---
+// CHECK-8-NEXT: USR:             '1E3438A08BA22025C0B46289FF0686F92C8924C5'
+// CHECK-8-NEXT: Name:            'Bc'
+// CHECK-8-NEXT: DefLocation:     
+// CHECK-8-NEXT:   LineNumber:      19
+// CHECK-8-NEXT:   Filename:        'test'
+// CHECK-8-NEXT: Scoped:          true
+// CHECK-8-NEXT: Members:         
+// CHECK-8-NEXT:   - 'A'
+// CHECK-8-NEXT:   - 'B'
+// CHECK-8-NEXT: ...
+
+// RUN: cat %t/docs/H/I.yaml | FileCheck %s --check-prefix CHECK-9
+// CHECK-9: ---
+// CHECK-9-NEXT: USR:             '3FB542274573CAEAD54CEBFFCAEE3D77FB9713D8'
+// CHECK-9-NEXT: Name:            'I'
+// CHECK-9-NEXT: Namespace:       
+// CHECK-9-NEXT:   - Type:            Function
+// CHECK-9-NEXT:     Name:            'H'
+// CHECK-9-NEXT:     USR:             'B6AC4C5C9F2EA3F2B3ECE1A33D349F4EE502B24E'
+// CHECK-9-NEXT: DefLocation:     
+// CHECK-9-NEXT:   LineNumber:      12
+// CHECK-9-NEXT:   Filename:        'test'
+// CHECK-9-NEXT: TagType:         Class
+// CHECK-9-NEXT: ...
+
+// RUN: cat %t/docs/X/Y.yaml | FileCheck %s --check-prefix CHECK-10
+// CHECK-10: ---
+// CHECK-10-NEXT: USR:             '641AB4A3D36399954ACDE29C7A8833032BF40472'
+// CHECK-10-NEXT: Name:            'Y'
+// CHECK-10-NEXT: Namespace:       
+// CHECK-10-NEXT:   - Type:            Record
+// CHECK-10-NEXT:     Name:            'X'
+// CHECK-10-NEXT:     USR:             'CA7C7935730B5EACD25F080E9C83FA087CCDC75E'
+// CHECK-10-NEXT: DefLocation:     
+// CHECK-10-NEXT:   LineNumber:      39
+// CHECK-10-NEXT:   Filename:        'test'
+// CHECK-10-NEXT: TagType:         Class
+// CHECK-10-NEXT: ...
+
+// RUN: cat %t/docs/E/ProtectedMethod.yaml | FileCheck %s --check-prefix CHECK-11
+// CHECK-11: ---
+// CHECK-11-NEXT: USR:             '5093D428CDC62096A67547BA52566E4FB9404EEE'
+// CHECK-11-NEXT: Name:            'ProtectedMethod'
+// CHECK-11-NEXT: Namespace:       
+// CHECK-11-NEXT:   - Type:            Record
+// CHECK-11-NEXT:     Name:            'E'
+// CHECK-11-NEXT:     USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-11-NEXT: DefLocation:     
+// CHECK-11-NEXT:   LineNumber:      34
+// CHECK-11-NEXT:   Filename:        'test'
+// CHECK-11-NEXT: Location:        
+// CHECK-11-NEXT:   - LineNumber:      31
+// CHECK-11-NEXT:     Filename:        'test'
+// CHECK-11-NEXT: IsMethod:        true
+// CHECK-11-NEXT: Parent:          
+// CHECK-11-NEXT:   Type:            Record
+// CHECK-11-NEXT:   Name:            'E'
+// CHECK-11-NEXT:   USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-11-NEXT: ReturnType:      
+// CHECK-11-NEXT:   Type:            
+// CHECK-11-NEXT:     Name:            'void'
+// CHECK-11-NEXT: ...
+
+// RUN: cat %t/docs/E/E.yaml | FileCheck %s --check-prefix CHECK-12
+// CHECK-12: ---
+// CHECK-12-NEXT: USR:             'DEB4AC1CD9253CD9EF7FBE6BCAC506D77984ABD4'
+// CHECK-12-NEXT: Name:            'E'
+// CHECK-12-NEXT: Namespace:       
+// CHECK-12-NEXT:   - Type:            Record
+// CHECK-12-NEXT:     Name:            'E'
+// CHECK-12-NEXT:     USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-12-NEXT: DefLocation:     
+// CHECK-12-NEXT:   LineNumber:      27
+// CHECK-12-NEXT:   Filename:        'test'
+// CHECK-12-NEXT: IsMethod:        true
+// CHECK-12-NEXT: Parent:          
+// CHECK-12-NEXT:   Type:            Record
+// CHECK-12-NEXT:   Name:            'E'
+// CHECK-12-NEXT:   USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-12-NEXT: ReturnType:      
+// CHECK-12-NEXT:   Type:            
+// CHECK-12-NEXT:     Name:            'void'
+// CHECK-12-NEXT: ...
+
+// RUN: cat %t/docs/E/~E.yaml | FileCheck %s --check-prefix CHECK-13
+// CHECK-13: ---
+// CHECK-13-NEXT: USR:             'BD2BDEBD423F80BACCEA75DE6D6622D355FC2D17'
+// CHECK-13-NEXT: Name:            '~E'
+// CHECK-13-NEXT: Namespace:       
+// CHECK-13-NEXT:   - Type:            Record
+// CHECK-13-NEXT:     Name:            'E'
+// CHECK-13-NEXT:     USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-13-NEXT: DefLocation:     
+// CHECK-13-NEXT:   LineNumber:      28
+// CHECK-13-NEXT:   Filename:        'test'
+// CHECK-13-NEXT: IsMethod:        true
+// CHECK-13-NEXT: Parent:          
+// CHECK-13-NEXT:   Type:            Record
+// CHECK-13-NEXT:   Name:            'E'
+// CHECK-13-NEXT:   USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-13-NEXT: ReturnType:      
+// CHECK-13-NEXT:   Type:            
+// CHECK-13-NEXT:     Name:            'void'
+// CHECK-13-NEXT: ...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/database_template.json b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/database_template.json
new file mode 100644
index 0000000..ceb499c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/database_template.json
@@ -0,0 +1,7 @@
+[
+{
+  "directory": "$test_dir/build",
+  "command": "clang++ -o test.o -I../include $test_dir/src/test.cpp",
+  "file": "$test_dir/src/test.cpp"
+}
+]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/enum.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/enum.h
new file mode 100644
index 0000000..9ec3926
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/enum.h
@@ -0,0 +1,9 @@
+namespace a {
+enum E1 { Green, Red };
+
+enum class E2 { Yellow };
+
+class C {
+  enum E3 { Blue };
+};
+} // namespace a
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/function_test.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/function_test.cpp
new file mode 100644
index 0000000..5e86f59
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/function_test.cpp
@@ -0,0 +1,5 @@
+#include "function_test.h"
+
+void f() {}
+
+void A::f() {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/function_test.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/function_test.h
new file mode 100644
index 0000000..810f803
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/function_test.h
@@ -0,0 +1,14 @@
+void f();
+
+inline int g() { return 0; }
+
+template<typename T>
+void h(T t) {}
+
+template<>
+void h(int t) {}
+
+class A {
+ public:
+  void f();
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/helper_decls_test.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/helper_decls_test.cpp
new file mode 100644
index 0000000..32d2a23
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/helper_decls_test.cpp
@@ -0,0 +1,97 @@
+#include "helper_decls_test.h"
+
+namespace {
+class HelperC1 {
+public:
+  static int I;
+};
+
+int HelperC1::I = 0;
+
+class HelperC2 {};
+
+class HelperC3 {
+ public:
+  static int I;
+};
+
+int HelperC3::I = 0;
+
+void HelperFun1() {}
+
+void HelperFun2() { HelperFun1(); }
+
+const int K1 = 1;
+} // namespace
+
+static const int K2 = 2;
+static void HelperFun3() { K2; }
+
+namespace a {
+
+static const int K3 = 3;
+static const int K4 = HelperC3::I;
+static const int K5 = 5;
+static const int K6 = 6;
+
+static void HelperFun4() {}
+static void HelperFun6() {}
+
+void Class1::f() { HelperFun2(); }
+
+void Class2::f() {
+  HelperFun1();
+  HelperFun3();
+}
+
+void Class3::f() { HelperC1::I; }
+
+void Class4::f() { HelperC2 c2; }
+
+void Class5::f() {
+  int Result = K1 + K2 + K3;
+  HelperFun4();
+}
+
+int Class6::f() {
+  int R = K4;
+  return R;
+}
+
+int Class7::f() {
+  int R = K6;
+  return R;
+}
+
+int Class7::g() {
+  HelperFun6();
+  return 1;
+}
+
+static int HelperFun5() {
+  int R = K5;
+  return R;
+}
+
+void Fun1() { HelperFun5(); }
+
+} // namespace a
+
+namespace b {
+namespace {
+void HelperFun7();
+
+class HelperC4;
+} // namespace
+
+void Fun3() {
+  HelperFun7();
+  HelperC4 *t;
+}
+
+namespace {
+void HelperFun7() {}
+
+class HelperC4 {};
+} // namespace
+} // namespace b
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/helper_decls_test.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/helper_decls_test.h
new file mode 100644
index 0000000..d8927c4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/helper_decls_test.h
@@ -0,0 +1,39 @@
+namespace a {
+class Class1 {
+  void f();
+};
+
+class Class2 {
+  void f();
+};
+
+class Class3 {
+  void f();
+};
+
+class Class4 {
+  void f();
+};
+
+class Class5 {
+  void f();
+};
+
+class Class6 {
+  int f();
+};
+
+class Class7 {
+  int f();
+  int g();
+};
+
+void Fun1();
+
+inline void Fun2() {}
+
+} // namespace a
+
+namespace b {
+void Fun3();
+} // namespace b
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/macro_helper_test.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/macro_helper_test.cpp
new file mode 100644
index 0000000..c2c1e1e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/macro_helper_test.cpp
@@ -0,0 +1,13 @@
+#include "macro_helper_test.h"
+
+#define DEFINE(name) \
+  namespace ns { \
+  static const bool t1 = false; \
+  bool t2_##name = t1; \
+  bool t3_##name = t1; \
+  } \
+  using ns::t2_##name;
+
+DEFINE(test)
+
+void f1() {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/macro_helper_test.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/macro_helper_test.h
new file mode 100644
index 0000000..0ddfaae
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/macro_helper_test.h
@@ -0,0 +1,2 @@
+class A {};
+void f1();
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/multiple_class_test.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/multiple_class_test.cpp
new file mode 100644
index 0000000..5eb4bf3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/multiple_class_test.cpp
@@ -0,0 +1,52 @@
+#include "multiple_class_test.h"
+
+using a::Move1;
+using namespace a;
+using A = a::Move1;
+static int g = 0;
+
+namespace a {
+int Move1::f() {
+  return 0;
+}
+} // namespace a
+
+namespace {
+using a::Move1;
+using namespace a;
+static int k = 0;
+} // namespace
+
+namespace b {
+using a::Move1;
+using namespace a;
+using T = a::Move1;
+int Move2::f() {
+  return 0;
+}
+} // namespace b
+
+namespace c {
+int Move3::f() {
+  using a::Move1;
+  using namespace b;
+  return 0;
+}
+
+int Move4::f() {
+  return k;
+}
+
+int EnclosingMove5::a = 1;
+
+int EnclosingMove5::Nested::f() {
+  return g;
+}
+
+int EnclosingMove5::Nested::b = 1;
+
+int NoMove::f() {
+  static int F = 0;
+  return g;
+}
+} // namespace c
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/multiple_class_test.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/multiple_class_test.h
new file mode 100644
index 0000000..113a261
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/multiple_class_test.h
@@ -0,0 +1,39 @@
+namespace a {
+class Move1 {
+public:
+  int f();
+};
+} // namespace a
+
+namespace b {
+class Move2 {
+public:
+  int f();
+};
+} // namespace b
+
+namespace c {
+class Move3 {
+public:
+  int f();
+};
+
+class Move4 {
+public:
+  int f();
+};
+
+class EnclosingMove5 {
+public:
+  class Nested {
+    int f();
+    static int b;
+  };
+  static int a;
+};
+
+class NoMove {
+public:
+  int f();
+};
+} // namespace c
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/template_class_test.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/template_class_test.cpp
new file mode 100644
index 0000000..8ad2dcb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/template_class_test.cpp
@@ -0,0 +1,13 @@
+#include "template_class_test.h"
+
+template <typename T>
+void A<T>::g() {}
+
+template <typename T>
+template <typename U>
+void A<T>::k() {}
+
+template <typename T>
+int A<T>::c = 2;
+
+void B::f() {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/template_class_test.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/template_class_test.h
new file mode 100644
index 0000000..d42a158
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/template_class_test.h
@@ -0,0 +1,30 @@
+#ifndef TEMPLATE_CLASS_TEST_H // comment 1
+#define TEMPLATE_CLASS_TEST_H
+
+template <typename T>
+class A {
+ public:
+  void f();
+  void g();
+  template <typename U> void h();
+  template <typename U> void k();
+  static int b;
+  static int c;
+};
+
+template <typename T>
+void A<T>::f() {}
+
+template <typename T>
+template <typename U>
+void A<T>::h() {}
+
+template <typename T>
+int A<T>::b = 2;
+
+class B {
+ public:
+  void f();
+};
+
+#endif // TEMPLATE_CLASS_TEST_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/test.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/test.cpp
new file mode 100644
index 0000000..fa777f0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/test.cpp
@@ -0,0 +1,11 @@
+#include "test.h"
+#include "test2.h"
+
+namespace a {
+int Foo::f() {
+  return 0;
+}
+int Foo::f2(int a, int b) {
+  return a + b;
+}
+} // namespace a
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/test.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/test.h
new file mode 100644
index 0000000..8006c34
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/test.h
@@ -0,0 +1,10 @@
+#ifndef TEST_H // comment 1
+#define TEST_H
+namespace a {
+class Foo {
+public:
+  int f();
+  int f2(int a, int b);
+};
+} // namespace a
+#endif // TEST_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/type_alias.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/type_alias.h
new file mode 100644
index 0000000..7a900f6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/type_alias.h
@@ -0,0 +1,11 @@
+typedef int Int1;
+using Int2 = int;
+
+template<class T>
+struct A {};
+
+template <class T> using B = A<T>;
+
+class C {
+  typedef int Int3;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/var_test.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/var_test.cpp
new file mode 100644
index 0000000..9023abc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/var_test.cpp
@@ -0,0 +1,6 @@
+#include "var_test.h"
+
+namespace a{
+int kGlobalInt = 1;
+const char *const kGlobalStr = "Hello";
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/var_test.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/var_test.h
new file mode 100644
index 0000000..1bfd54c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/Inputs/var_test.h
@@ -0,0 +1,11 @@
+namespace a {
+extern int kGlobalInt;
+extern const char *const kGlobalStr;
+}
+
+int kEvilInt = 2;
+
+inline void f1() {
+  int kGlobalInt = 3;
+  const char *const kGlobalStr = "Hello2";
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-class.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-class.cpp
new file mode 100644
index 0000000..a30cb4d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-class.cpp
@@ -0,0 +1,43 @@
+// RUN: mkdir -p %T/clang-move/build
+// RUN: mkdir -p %T/clang-move/include
+// RUN: mkdir -p %T/clang-move/src
+// RUN: sed 's|$test_dir|%/T/clang-move|g' %S/Inputs/database_template.json > %T/clang-move/compile_commands.json
+// RUN: cp %S/Inputs/test.h  %T/clang-move/include
+// RUN: cp %S/Inputs/test.cpp %T/clang-move/src
+// RUN: touch %T/clang-move/include/test2.h
+// RUN: cd %T/clang-move/build
+// RUN: clang-move -names="a::Foo" -new_cc=%T/clang-move/new_test.cpp -new_header=%T/clang-move/new_test.h -old_cc=../src/test.cpp -old_header=../include/test.h %T/clang-move/src/test.cpp
+// RUN: FileCheck -input-file=%T/clang-move/new_test.cpp -check-prefix=CHECK-NEW-TEST-CPP %s
+// RUN: FileCheck -input-file=%T/clang-move/new_test.h -check-prefix=CHECK-NEW-TEST-H %s
+// RUN: FileCheck -input-file=%T/clang-move/src/test.cpp -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
+// RUN: FileCheck -input-file=%T/clang-move/include/test.h -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
+//
+// RUN: cp %S/Inputs/test.h  %T/clang-move/include
+// RUN: cp %S/Inputs/test.cpp %T/clang-move/src
+// RUN: cd %T/clang-move/build
+// RUN: clang-move -names="a::Foo" -new_cc=%T/clang-move/new_test.cpp -new_header=%T/clang-move/new_test.h -old_cc=%T/clang-move/src/test.cpp -old_header=%T/clang-move/include/test.h %T/clang-move/src/test.cpp
+// RUN: FileCheck -input-file=%T/clang-move/new_test.cpp -check-prefix=CHECK-NEW-TEST-CPP %s
+// RUN: FileCheck -input-file=%T/clang-move/new_test.h -check-prefix=CHECK-NEW-TEST-H %s
+// RUN: FileCheck -input-file=%T/clang-move/src/test.cpp -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
+// RUN: FileCheck -input-file=%T/clang-move/include/test.h -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
+//
+//
+// CHECK-NEW-TEST-H: #ifndef TEST_H // comment 1
+// CHECK-NEW-TEST-H: #define TEST_H
+// CHECK-NEW-TEST-H: namespace a {
+// CHECK-NEW-TEST-H: class Foo {
+// CHECK-NEW-TEST-H: public:
+// CHECK-NEW-TEST-H:   int f();
+// CHECK-NEW-TEST-H:   int f2(int a, int b);
+// CHECK-NEW-TEST-H: };
+// CHECK-NEW-TEST-H: } // namespace a
+// CHECK-NEW-TEST-H: #endif // TEST_H
+//
+// CHECK-NEW-TEST-CPP: #include "{{.*}}new_test.h"
+// CHECK-NEW-TEST-CPP: #include "test2.h"
+// CHECK-NEW-TEST-CPP: namespace a {
+// CHECK-NEW-TEST-CPP: int Foo::f() { return 0; }
+// CHECK-NEW-TEST-CPP: int Foo::f2(int a, int b) { return a + b; }
+// CHECK-NEW-TEST-CPP: } // namespace a
+//
+// CHECK-OLD-TEST-EMPTY: {{^}}{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-enum-decl.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-enum-decl.cpp
new file mode 100644
index 0000000..42f6f99
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-enum-decl.cpp
@@ -0,0 +1,44 @@
+// RUN: mkdir -p %T/move-enum
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: cd %T/move-enum
+//
+// -----------------------------------------------------------------------------
+// Test moving enum declarations.
+// -----------------------------------------------------------------------------
+// RUN: clang-move -names="a::E1" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE1 %s
+//
+// CHECK-NEW-TEST-H-CASE1: namespace a {
+// CHECK-NEW-TEST-H-CASE1-NEXT: enum E1 { Green, Red };
+// CHECK-NEW-TEST-H-CASE1-NEXT: }
+
+// CHECK-OLD-TEST-H-CASE1-NOT: enum E1 { Green, Red };
+
+
+// -----------------------------------------------------------------------------
+// Test moving scoped enum declarations.
+// -----------------------------------------------------------------------------
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: clang-move -names="a::E2" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s
+
+// CHECK-NEW-TEST-H-CASE2: namespace a {
+// CHECK-NEW-TEST-H-CASE2-NEXT: enum class E2 { Yellow };
+// CHECK-NEW-TEST-H-CASE2-NEXT: }
+
+// CHECK-OLD-TEST-H-CASE2-NOT: enum class E2 { Yellow };
+
+
+// -----------------------------------------------------------------------------
+// Test not moving class-insided enum declarations.
+// -----------------------------------------------------------------------------
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: clang-move -names="a::C::E3" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
+
+// CHECK-EMPTY: {{^}}{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-function.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-function.cpp
new file mode 100644
index 0000000..0324b80
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-function.cpp
@@ -0,0 +1,70 @@
+// RUN: mkdir -p %T/move-function
+// RUN: cat %S/Inputs/function_test.h > %T/move-function/function_test.h
+// RUN: cat %S/Inputs/function_test.cpp > %T/move-function/function_test.cpp
+// RUN: cd %T/move-function
+// RUN: clang-move -names="g" -new_header=%T/move-function/new_function_test.h -old_header=../move-function/function_test.h %T/move-function/function_test.cpp --
+// RUN: FileCheck -input-file=%T/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
+//
+// CHECK-NEW-TEST-H-CASE1: #ifndef {{.*}}NEW_FUNCTION_TEST_H
+// CHECK-NEW-TEST-H-CASE1: #define {{.*}}NEW_FUNCTION_TEST_H
+// CHECK-NEW-TEST-H-CASE1: {{[[:space:]]+}}
+// CHECK-NEW-TEST-H-CASE1: inline int g() { return 0; }
+// CHECK-NEW-TEST-H-CASE1: {{[[:space:]]+}}
+// CHECK-NEW-TEST-H-CASE1: #endif // {{.*}}NEW_FUNCTION_TEST_H
+//
+// RUN: cp %S/Inputs/function_test*  %T/move-function
+// RUN: clang-move -names="h" -new_header=%T/move-function/new_function_test.h -old_header=../move-function/function_test.h %T/move-function/function_test.cpp --
+// RUN: FileCheck -input-file=%T/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
+//
+// CHECK-NEW-TEST-H-CASE2: #ifndef {{.*}}NEW_FUNCTION_TEST_H
+// CHECK-NEW-TEST-H-CASE2: #define {{.*}}NEW_FUNCTION_TEST_H
+// CHECK-NEW-TEST-H-CASE2: {{[[:space:]]+}}
+// CHECK-NEW-TEST-H-CASE2: template <typename T> void h(T t) {}
+// CHECK-NEW-TEST-H-CASE2: {{[[:space:]]+}}
+// CHECK-NEW-TEST-H-CASE2: template <> void h(int t) {}
+// CHECK-NEW-TEST-H-CASE2: {{[[:space:]]+}}
+// CHECK-NEW-TEST-H-CASE2: #endif // {{.*}}NEW_FUNCTION_TEST_H
+//
+// RUN: cp %S/Inputs/function_test*  %T/move-function
+// RUN: clang-move -names="f" -new_header=%T/move-function/new_function_test.h -new_cc=%T/move-function/new_function_test.cpp -old_header=../move-function/function_test.h -old_cc=../move-function/function_test.cpp %T/move-function/function_test.cpp --
+// RUN: FileCheck -input-file=%T/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE3 %s
+// RUN: FileCheck -input-file=%T/move-function/new_function_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE3 %s
+//
+// CHECK-NEW-TEST-H-CASE3: #ifndef {{.*}}NEW_FUNCTION_TEST_H
+// CHECK-NEW-TEST-H-CASE3: #define {{.*}}NEW_FUNCTION_TEST_H
+// CHECK-NEW-TEST-H-CASE3: {{[[:space:]]+}}
+// CHECK-NEW-TEST-H-CASE3: void f();
+// CHECK-NEW-TEST-H-CASE3: {{[[:space:]]+}}
+// CHECK-NEW-TEST-H-CASE3: #endif // {{.*}}NEW_FUNCTION_TEST_H
+// CHECK-NEW-TEST-CPP-CASE3: #include "{{.*}}new_function_test.h"
+// CHECK-NEW-TEST-CPP-CASE3: {{[[:space:]]+}}
+// CHECK-NEW-TEST-CPP-CASE3: void f() {}
+//
+// RUN: cat %S/Inputs/function_test.h > %T/move-function/function_test.h
+// RUN: cat %S/Inputs/function_test.cpp > %T/move-function/function_test.cpp
+// RUN: clang-move -names="A::f" -new_header=%T/move-function/new_function_test.h -new_cc=%T/move-function/new_function_test.cpp -old_header=../move-function/function_test.h -old_cc=../move-function/function_test.cpp %T/move-function/function_test.cpp -dump_result -- | FileCheck %s -check-prefix=CHECK-EMPTY
+//
+// CHECK-EMPTY: [{{[[:space:]]*}}]
+//
+// RUN: cat %S/Inputs/function_test.h > %T/move-function/function_test.h
+// RUN: cat %S/Inputs/function_test.cpp > %T/move-function/function_test.cpp
+// RUN: clang-move -names="f,A" -new_header=%T/move-function/new_function_test.h -new_cc=%T/move-function/new_function_test.cpp -old_header=../move-function/function_test.h -old_cc=../move-function/function_test.cpp %T/move-function/function_test.cpp --
+// RUN: FileCheck -input-file=%T/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE4 %s
+// RUN: FileCheck -input-file=%T/move-function/new_function_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE4 %s
+
+// CHECK-NEW-TEST-H-CASE4: #ifndef {{.*}}NEW_FUNCTION_TEST_H
+// CHECK-NEW-TEST-H-CASE4: #define {{.*}}NEW_FUNCTION_TEST_H
+// CHECK-NEW-TEST-H-CASE4: {{[[:space:]]+}}
+// CHECK-NEW-TEST-H-CASE4: void f();
+// CHECK-NEW-TEST-H-CASE4: {{[[:space:]]+}}
+// CHECK-NEW-TEST-H-CASE4: class A {
+// CHECK-NEW-TEST-H-CASE4: public:
+// CHECK-NEW-TEST-H-CASE4:   void f();
+// CHECK-NEW-TEST-H-CASE4: };
+// CHECK-NEW-TEST-H-CASE4: {{[[:space:]]+}}
+// CHECK-NEW-TEST-H-CASE4: #endif // {{.*}}NEW_FUNCTION_TEST_H
+// CHECK-NEW-TEST-CPP-CASE4: #include "{{.*}}new_function_test.h"
+// CHECK-NEW-TEST-CPP-CASE4: {{[[:space:]]+}}
+// CHECK-NEW-TEST-CPP-CASE4: void f() {}
+// CHECK-NEW-TEST-CPP-CASE4: {{[[:space:]]+}}
+// CHECK-NEW-TEST-CPP-CASE4: void A::f() {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-multiple-classes.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-multiple-classes.cpp
new file mode 100644
index 0000000..821d567
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-multiple-classes.cpp
@@ -0,0 +1,104 @@
+// RUN: mkdir -p %T/move-multiple-classes
+// RUN: cp %S/Inputs/multiple_class_test*  %T/move-multiple-classes/
+// RUN: cd %T/move-multiple-classes
+// RUN: clang-move -names="c::EnclosingMove5::Nested" -new_cc=%T/move-multiple-classes/new_multiple_class_test.cpp -new_header=%T/move-multiple-classes/new_multiple_class_test.h -old_cc=%T/move-multiple-classes/multiple_class_test.cpp -old_header=../move-multiple-classes/multiple_class_test.h -dump_result %T/move-multiple-classes/multiple_class_test.cpp -- -std=c++11| FileCheck %s -check-prefix=CHECK-EMPTY
+// RUN: clang-move -names="a::Move1, b::Move2,c::Move3,c::Move4,c::EnclosingMove5" -new_cc=%T/move-multiple-classes/new_multiple_class_test.cpp -new_header=%T/move-multiple-classes/new_multiple_class_test.h -old_cc=%T/move-multiple-classes/multiple_class_test.cpp -old_header=../move-multiple-classes/multiple_class_test.h %T/move-multiple-classes/multiple_class_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-multiple-classes/new_multiple_class_test.cpp -check-prefix=CHECK-NEW-TEST-CPP %s
+// RUN: FileCheck -input-file=%T/move-multiple-classes/new_multiple_class_test.h -check-prefix=CHECK-NEW-TEST-H %s
+// RUN: FileCheck -input-file=%T/move-multiple-classes/multiple_class_test.cpp -check-prefix=CHECK-OLD-TEST-CPP %s
+// RUN: FileCheck -input-file=%T/move-multiple-classes/multiple_class_test.h -check-prefix=CHECK-OLD-TEST-H %s
+//
+// CHECK-EMPTY: [{{[[:space:]]*}}]
+//
+// CHECK-OLD-TEST-H: namespace c {
+// CHECK-OLD-TEST-H: class NoMove {
+// CHECK-OLD-TEST-H: public:
+// CHECK-OLD-TEST-H:   int f();
+// CHECK-OLD-TEST-H: };
+// CHECK-OLD-TEST-H: } // namespace c
+
+// CHECK-OLD-TEST-CPP: #include "{{.*}}multiple_class_test.h"
+// CHECK-OLD-TEST-CPP: using a::Move1;
+// CHECK-OLD-TEST-CPP: using namespace a;
+// CHECK-OLD-TEST-CPP: using A = a::Move1;
+// CHECK-OLD-TEST-CPP: static int g = 0;
+// CHECK-OLD-TEST-CPP: namespace {
+// CHECK-OLD-TEST-CPP: using a::Move1;
+// CHECK-OLD-TEST-CPP: using namespace a;
+// CHECK-OLD-TEST-CPP: } // namespace
+// CHECK-OLD-TEST-CPP: namespace b {
+// CHECK-OLD-TEST-CPP: using a::Move1;
+// CHECK-OLD-TEST-CPP: using namespace a;
+// CHECK-OLD-TEST-CPP: using T = a::Move1;
+// CHECK-OLD-TEST-CPP: } // namespace b
+// CHECK-OLD-TEST-CPP: namespace c {
+// CHECK-OLD-TEST-CPP: int NoMove::f() {
+// CHECK-OLD-TEST-CPP:   static int F = 0;
+// CHECK-OLD-TEST-CPP:   return g;
+// CHECK-OLD-TEST-CPP: }
+// CHECK-OLD-TEST-CPP: } // namespace c
+
+// CHECK-NEW-TEST-H: #ifndef {{.*}}NEW_MULTIPLE_CLASS_TEST_H
+// CHECK-NEW-TEST-H: #define {{.*}}NEW_MULTIPLE_CLASS_TEST_H
+// CHECK-NEW-TEST-H: namespace a {
+// CHECK-NEW-TEST-H: class Move1 {
+// CHECK-NEW-TEST-H: public:
+// CHECK-NEW-TEST-H:   int f();
+// CHECK-NEW-TEST-H: };
+// CHECK-NEW-TEST-H: } // namespace a
+// CHECK-NEW-TEST-H: namespace b {
+// CHECK-NEW-TEST-H: class Move2 {
+// CHECK-NEW-TEST-H: public:
+// CHECK-NEW-TEST-H:   int f();
+// CHECK-NEW-TEST-H: };
+// CHECK-NEW-TEST-H: } // namespace b
+// CHECK-NEW-TEST-H: namespace c {
+// CHECK-NEW-TEST-H: class Move3 {
+// CHECK-NEW-TEST-H: public:
+// CHECK-NEW-TEST-H:   int f();
+// CHECK-NEW-TEST-H: };
+// CHECK-NEW-TEST-H: class Move4 {
+// CHECK-NEW-TEST-H: public:
+// CHECK-NEW-TEST-H:   int f();
+// CHECK-NEW-TEST-H: };
+// CHECK-NEW-TEST-H: class EnclosingMove5 {
+// CHECK-NEW-TEST-H: public:
+// CHECK-NEW-TEST-H:   class Nested {
+// CHECK-NEW-TEST-H:     int f();
+// CHECK-NEW-TEST-H:     static int b;
+// CHECK-NEW-TEST-H:   };
+// CHECK-NEW-TEST-H:   static int a;
+// CHECK-NEW-TEST-H: };
+// CHECK-NEW-TEST-H: } // namespace c
+// CHECK-NEW-TEST-H: #endif // {{.*}}NEW_MULTIPLE_CLASS_TEST_H
+
+// CHECK-NEW-TEST-CPP: #include "{{.*}}new_multiple_class_test.h"
+// CHECK-NEW-TEST-CPP: using a::Move1;
+// CHECK-NEW-TEST-CPP: using namespace a;
+// CHECK-NEW-TEST-CPP: using A = a::Move1;
+// CHECK-NEW-TEST-CPP: static int g = 0;
+// CHECK-NEW-TEST-CPP: namespace a {
+// CHECK-NEW-TEST-CPP: int Move1::f() { return 0; }
+// CHECK-NEW-TEST-CPP: } // namespace a
+// CHECK-NEW-TEST-CPP: namespace {
+// CHECK-NEW-TEST-CPP: using a::Move1;
+// CHECK-NEW-TEST-CPP: using namespace a;
+// CHECK-NEW-TEST-CPP: static int k = 0;
+// CHECK-NEW-TEST-CPP: } // namespace
+// CHECK-NEW-TEST-CPP: namespace b {
+// CHECK-NEW-TEST-CPP: using a::Move1;
+// CHECK-NEW-TEST-CPP: using namespace a;
+// CHECK-NEW-TEST-CPP: using T = a::Move1;
+// CHECK-NEW-TEST-CPP: int Move2::f() { return 0; }
+// CHECK-NEW-TEST-CPP: } // namespace b
+// CHECK-NEW-TEST-CPP: namespace c {
+// CHECK-NEW-TEST-CPP: int Move3::f() {
+// CHECK-NEW-TEST-CPP:   using a::Move1;
+// CHECK-NEW-TEST-CPP:   using namespace b;
+// CHECK-NEW-TEST-CPP:   return 0;
+// CHECK-NEW-TEST-CPP: }
+// CHECK-NEW-TEST-CPP: int Move4::f() { return k; }
+// CHECK-NEW-TEST-CPP: int EnclosingMove5::a = 1;
+// CHECK-NEW-TEST-CPP: int EnclosingMove5::Nested::f() { return g; }
+// CHECK-NEW-TEST-CPP: int EnclosingMove5::Nested::b = 1;
+// CHECK-NEW-TEST-CPP: } // namespace c
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-template-class.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-template-class.cpp
new file mode 100644
index 0000000..1a6a60b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-template-class.cpp
@@ -0,0 +1,86 @@
+// RUN: mkdir -p %T/move-template-class
+// RUN: cp %S/Inputs/template_class_test*  %T/move-template-class
+// RUN: cd %T/move-template-class
+// RUN: clang-move -names="A,B" -new_cc=%T/move-template-class/new_template_class_test.cpp -new_header=%T/move-template-class/new_template_class_test.h -old_cc=%T/move-template-class/template_class_test.cpp -old_header=../move-template-class/template_class_test.h %T/move-template-class/template_class_test.cpp --
+// RUN: FileCheck -input-file=%T/move-template-class/template_class_test.cpp -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
+// RUN: FileCheck -input-file=%T/move-template-class/template_class_test.h -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
+// RUN: FileCheck -input-file=%T/move-template-class/new_template_class_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-template-class/new_template_class_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
+//
+// RUN: cp %S/Inputs/template_class_test*  %T/move-template-class
+// RUN: clang-move -names="A" -new_cc=%T/move-template-class/new_template_class_test.cpp -new_header=%T/move-template-class/new_template_class_test.h -old_cc=%T/move-template-class/template_class_test.cpp -old_header=../move-template-class/template_class_test.h %T/move-template-class/template_class_test.cpp --
+// RUN: FileCheck -input-file=%T/move-template-class/template_class_test.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-template-class/template_class_test.cpp -check-prefix=CHECK-OLD-TEST-CPP-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-template-class/new_template_class_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-template-class/new_template_class_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE2 %s
+//
+//
+// CHECK-OLD-TEST-EMPTY: {{^}}{{$}}
+//
+// CHECK-NEW-TEST-H-CASE1: #ifndef TEMPLATE_CLASS_TEST_H // comment 1
+// CHECK-NEW-TEST-H-CASE1: #define TEMPLATE_CLASS_TEST_H
+// CHECK-NEW-TEST-H-CASE1: template <typename T>
+// CHECK-NEW-TEST-H-CASE1: class A {
+// CHECK-NEW-TEST-H-CASE1:  public:
+// CHECK-NEW-TEST-H-CASE1:   void f();
+// CHECK-NEW-TEST-H-CASE1:   void g();
+// CHECK-NEW-TEST-H-CASE1:   template <typename U> void h();
+// CHECK-NEW-TEST-H-CASE1:   template <typename U> void k();
+// CHECK-NEW-TEST-H-CASE1:   static int b;
+// CHECK-NEW-TEST-H-CASE1:   static int c;
+// CHECK-NEW-TEST-H-CASE1: };
+// CHECK-NEW-TEST-H-CASE1: template <typename T>
+// CHECK-NEW-TEST-H-CASE1: void A<T>::f() {}
+// CHECK-NEW-TEST-H-CASE1: template <typename T>
+// CHECK-NEW-TEST-H-CASE1: template <typename U>
+// CHECK-NEW-TEST-H-CASE1: void A<T>::h() {}
+// CHECK-NEW-TEST-H-CASE1: template <typename T>
+// CHECK-NEW-TEST-H-CASE1: int A<T>::b = 2;
+// CHECK-NEW-TEST-H-CASE1: class B {
+// CHECK-NEW-TEST-H-CASE1:  public:
+// CHECK-NEW-TEST-H-CASE1:   void f();
+// CHECK-NEW-TEST-H-CASE1: };
+// CHECK-NEW-TEST-H-CASE1: #endif // TEMPLATE_CLASS_TEST_H
+//
+// CHECK-NEW-TEST-CPP-CASE1: #include "{{.*}}new_template_class_test.h"
+// CHECK-NEW-TEST-CPP-CASE1: template <typename T>
+// CHECK-NEW-TEST-CPP-CASE1: void A<T>::g() {}
+// CHECK-NEW-TEST-CPP-CASE1: template <typename T>
+// CHECK-NEW-TEST-CPP-CASE1: template <typename U>
+// CHECK-NEW-TEST-CPP-CASE1: void A<T>::k() {}
+// CHECK-NEW-TEST-CPP-CASE1: template <typename T>
+// CHECK-NEW-TEST-CPP-CASE1: int A<T>::c = 2;
+// CHECK-NEW-TEST-CPP-CASE1: void B::f() {}
+//
+// CHECK-OLD-TEST-H-CASE2: #ifndef TEMPLATE_CLASS_TEST_H // comment 1
+// CHECK-OLD-TEST-H-CASE2: #define TEMPLATE_CLASS_TEST_H
+// CHECK-OLD-TEST-H-CASE2: class B {
+// CHECK-OLD-TEST-H-CASE2:  public:
+// CHECK-OLD-TEST-H-CASE2:   void f();
+// CHECK-OLD-TEST-H-CASE2: };
+// CHECK-OLD-TEST-H-CASE2: #endif // TEMPLATE_CLASS_TEST_H
+//
+// CHECK-OLD-TEST-CPP-CASE2: #include "template_class_test.h"
+// CHECK-OLD-TEST-CPP-CASE2:  void B::f() {}
+//
+// CHECK-NEW-TEST-H-CASE2: #ifndef {{.*}}NEW_TEMPLATE_CLASS_TEST_H
+// CHECK-NEW-TEST-H-CASE2: #define {{.*}}NEW_TEMPLATE_CLASS_TEST_H
+// CHECK-NEW-TEST-H-CASE2: template <typename T>
+// CHECK-NEW-TEST-H-CASE2: class A {
+// CHECK-NEW-TEST-H-CASE2:  public:
+// CHECK-NEW-TEST-H-CASE2:   void f();
+// CHECK-NEW-TEST-H-CASE2:   void g();
+// CHECK-NEW-TEST-H-CASE2:   template <typename U> void h();
+// CHECK-NEW-TEST-H-CASE2:   template <typename U> void k();
+// CHECK-NEW-TEST-H-CASE2:   static int b;
+// CHECK-NEW-TEST-H-CASE2:   static int c;
+// CHECK-NEW-TEST-H-CASE2: };
+// CHECK-NEW-TEST-H-CASE2: template <typename T> void A<T>::f() {}
+// CHECK-NEW-TEST-H-CASE2: template <typename T> template <typename U> void A<T>::h() {}
+// CHECK-NEW-TEST-H-CASE2: template <typename T> int A<T>::b = 2;
+// CHECK-NEW-TEST-H-CASE2: #endif // {{.*}}NEW_TEMPLATE_CLASS_TEST_H
+//
+// CHECK-NEW-TEST-CPP-CASE2: #include "{{.*}}new_template_class_test.h"
+// CHECK-NEW-TEST-CPP-CASE2: template <typename T> void A<T>::g() {}
+// CHECK-NEW-TEST-CPP-CASE2: template <typename T> template <typename U> void A<T>::k() {}
+// CHECK-NEW-TEST-CPP-CASE2: template <typename T> int A<T>::c = 2;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-type-alias.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-type-alias.cpp
new file mode 100644
index 0000000..ab70237
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-type-alias.cpp
@@ -0,0 +1,52 @@
+// RUN: mkdir -p %T/move-type-alias
+// RUN: cp %S/Inputs/type_alias.h  %T/move-type-alias/type_alias.h
+// RUN: echo '#include "type_alias.h"' > %T/move-type-alias/type_alias.cpp
+// RUN: cd %T/move-type-alias
+//
+// -----------------------------------------------------------------------------
+// Test moving typedef declarations.
+// -----------------------------------------------------------------------------
+// RUN: clang-move -names="Int1" -new_cc=%T/move-type-alias/new_test.cpp -new_header=%T/move-type-alias/new_test.h -old_cc=%T/move-type-alias/type_alias.cpp -old_header=%T/move-type-alias/type_alias.h %T/move-type-alias/type_alias.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-type-alias/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-type-alias/type_alias.h -check-prefix=CHECK-OLD-TEST-H-CASE1 %s
+
+// CHECK-NEW-TEST-H-CASE1: typedef int Int1;
+
+// CHECK-OLD-TEST-H-CASE1-NOT: typedef int Int1;
+
+
+// -----------------------------------------------------------------------------
+// Test moving type alias declarations.
+// -----------------------------------------------------------------------------
+// RUN: cp %S/Inputs/type_alias.h  %T/move-type-alias/type_alias.h
+// RUN: echo '#include "type_alias.h"' > %T/move-type-alias/type_alias.cpp
+// RUN: clang-move -names="Int2" -new_cc=%T/move-type-alias/new_test.cpp -new_header=%T/move-type-alias/new_test.h -old_cc=%T/move-type-alias/type_alias.cpp -old_header=%T/move-type-alias/type_alias.h %T/move-type-alias/type_alias.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-type-alias/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-type-alias/type_alias.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s
+
+// CHECK-NEW-TEST-H-CASE2: using Int2 = int;
+
+// CHECK-OLD-TEST-H-CASE2-NOT: using Int2 = int;
+
+
+// -----------------------------------------------------------------------------
+// Test moving template type alias declarations.
+// -----------------------------------------------------------------------------
+// RUN: cp %S/Inputs/type_alias.h  %T/move-type-alias/type_alias.h
+// RUN: echo '#include "type_alias.h"' > %T/move-type-alias/type_alias.cpp
+// RUN: clang-move -names="B" -new_cc=%T/move-type-alias/new_test.cpp -new_header=%T/move-type-alias/new_test.h -old_cc=%T/move-type-alias/type_alias.cpp -old_header=%T/move-type-alias/type_alias.h %T/move-type-alias/type_alias.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-type-alias/new_test.h -check-prefix=CHECK-OLD-TEST-H-CASE3 %s
+
+// CHECK-NEW-TEST-H-CASE3: template<class T> using B = A<T>;
+// CHECK-OLD-TEST-H-CASE3-NOT: template<class T> using B = A<T>;
+
+
+// -----------------------------------------------------------------------------
+// Test not moving class-insided typedef declarations.
+// -----------------------------------------------------------------------------
+// RUN: cp %S/Inputs/type_alias.h  %T/move-type-alias/type_alias.h
+// RUN: echo '#include "type_alias.h"' > %T/move-type-alias/type_alias.cpp
+// RUN: clang-move -names="C::Int3" -new_cc=%T/move-type-alias/new_test.cpp -new_header=%T/move-type-alias/new_test.h -old_cc=%T/move-type-alias/type_alias.cpp -old_header=%T/move-type-alias/type_alias.h %T/move-type-alias/type_alias.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-type-alias/new_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
+
+// CHECK-EMPTY: {{^}}{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-used-helper-decls.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-used-helper-decls.cpp
new file mode 100644
index 0000000..45bd4be
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-used-helper-decls.cpp
@@ -0,0 +1,438 @@
+// RUN: mkdir -p %T/used-helper-decls
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: cd %T/used-helper-decls
+
+// ----------------------------------------------------------------------------
+// Test moving used helper function and its transively used functions.
+// ----------------------------------------------------------------------------
+// RUN: clang-move -names="a::Class1" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS1-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS1-CPP %s
+
+// CHECK-NEW-CLASS1-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace {
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun1() {}
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun2() { HelperFun1(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace a {
+// CHECK-NEW-CLASS1-CPP-NEXT: void Class1::f() { HelperFun2(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace a
+//
+// CHECK-OLD-CLASS1-CPP: void HelperFun1() {}
+// CHECK-OLD-CLASS1-CPP-NOT: void HelperFun2() { HelperFun1(); }
+// CHECK-OLD-CLASS1-CPP-NOT: void Class1::f() { HelperFun2(); }
+// CHECK-OLD-CLASS1-CPP: void Class2::f() {
+// CHECK-OLD-CLASS1-CPP:   HelperFun1();
+
+
+// ----------------------------------------------------------------------------
+// Test moving used helper function and its transively used static variables.
+// ----------------------------------------------------------------------------
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="a::Class2" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS2-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS2-CPP %s
+
+// CHECK-NEW-CLASS2-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-CLASS2-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS2-CPP-NEXT: namespace {
+// CHECK-NEW-CLASS2-CPP-NEXT: void HelperFun1() {}
+// CHECK-NEW-CLASS2-CPP-NEXT: } // namespace
+// CHECK-NEW-CLASS2-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS2-CPP-NEXT: static const int K2 = 2;
+// CHECK-NEW-CLASS2-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS2-CPP-NEXT: static void HelperFun3() { K2; }
+// CHECK-NEW-CLASS2-CPP-NEXT: namespace a {
+// CHECK-NEW-CLASS2-CPP-NEXT: void Class2::f() {
+// CHECK-NEW-CLASS2-CPP-NEXT:   HelperFun1();
+// CHECK-NEW-CLASS2-CPP-NEXT:   HelperFun3();
+// CHECK-NEW-CLASS2-CPP-NEXT: }
+// CHECK-NEW-CLASS2-CPP-NEXT: } // namespace a
+
+// CHECK-OLD-CLASS2-CPP: void HelperFun1() {}
+// CHECK-OLD-CLASS2-CPP: void HelperFun2() { HelperFun1(); }
+// CHECK-OLD-CLASS2-CPP: const int K1 = 1;
+// CHECK-OLD-CLASS2-CPP: static const int K2 = 2;
+// CHECK-OLD-CLASS2-CPP-NOT: static void HelperFun3() { K2; }
+// CHECK-OLD-CLASS2-CPP-NOT: void Class2::f() {
+// CHECK-OLD-CLASS2-CPP-NOT:   HelperFun1();
+// CHECK-OLD-CLASS2-CPP-NOT:   HelperFun3();
+// CHECK-OLD-CLASS2-CPP: void Class5::f() {
+// CHECK-OLD-CLASS2-CPP-NEXT: int Result = K1 + K2 + K3;
+
+
+// ----------------------------------------------------------------------------
+// Test using a static member variable of a helper class.
+// ----------------------------------------------------------------------------
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="a::Class3" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS3-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS3-CPP %s
+
+// CHECK-NEW-CLASS3-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-CLASS3-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS3-CPP-NEXT: namespace {
+// CHECK-NEW-CLASS3-CPP-NEXT: class HelperC1 {
+// CHECK-NEW-CLASS3-CPP-NEXT: public:
+// CHECK-NEW-CLASS3-CPP-NEXT:   static int I;
+// CHECK-NEW-CLASS3-CPP-NEXT: };
+// CHECK-NEW-CLASS3-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS3-CPP-NEXT: int HelperC1::I = 0;
+// CHECK-NEW-CLASS3-CPP-NEXT: } // namespace
+// CHECK-NEW-CLASS3-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS3-CPP-NEXT: namespace a {
+// CHECK-NEW-CLASS3-CPP-NEXT: void Class3::f() { HelperC1::I; }
+// CHECK-NEW-CLASS3-CPP-NEXT: } // namespace a
+
+// CHECK-OLD-CLASS3-CPP: namespace {
+// CHECK-OLD-CLASS3-CPP-NOT: class HelperC1 {
+// CHECK-OLD-CLASS3-CPP-NOT: public:
+// CHECK-OLD-CLASS3-CPP-NOT:   static int I;
+// CHECK-OLD-CLASS3-CPP-NOT: };
+// CHECK-OLD-CLASS3-CPP-NOT: int HelperC1::I = 0;
+// CHECK-OLD-CLASS3-CPP: class HelperC2 {};
+
+
+// ----------------------------------------------------------------------------
+// Test moving helper classes.
+// ----------------------------------------------------------------------------
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="a::Class4" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS4-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS4-CPP %s
+
+// CHECK-NEW-CLASS4-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-CLASS4-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS4-CPP-NEXT: namespace {
+// CHECK-NEW-CLASS4-CPP-NEXT: class HelperC2 {};
+// CHECK-NEW-CLASS4-CPP-NEXT: } // namespace
+// CHECK-NEW-CLASS4-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS4-CPP-NEXT: namespace a {
+// CHECK-NEW-CLASS4-CPP-NEXT: void Class4::f() { HelperC2 c2; }
+// CHECK-NEW-CLASS4-CPP-NEXT: } // namespace a
+
+// CHECK-OLD-CLASS4-CPP-NOT: class HelperC2 {};
+
+
+// ----------------------------------------------------------------------------
+// Test moving helper variables and helper functions together.
+// ----------------------------------------------------------------------------
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="a::Class5" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS5-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS5-CPP %s
+
+// CHECK-NEW-CLASS5-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-CLASS5-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS5-CPP-NEXT: namespace {
+// CHECK-NEW-CLASS5-CPP-NEXT: const int K1 = 1;
+// CHECK-NEW-CLASS5-CPP-NEXT: } // namespace
+// CHECK-NEW-CLASS5-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS5-CPP-NEXT: static const int K2 = 2;
+// CHECK-NEW-CLASS5-CPP-NEXT: namespace a {
+// CHECK-NEW-CLASS5-CPP-NEXT: static const int K3 = 3;
+// CHECK-NEW-CLASS5-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS5-CPP-NEXT: static void HelperFun4() {}
+// CHECK-NEW-CLASS5-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS5-CPP-NEXT: void Class5::f() {
+// CHECK-NEW-CLASS5-CPP-NEXT:   int Result = K1 + K2 + K3;
+// CHECK-NEW-CLASS5-CPP-NEXT:   HelperFun4();
+// CHECK-NEW-CLASS5-CPP-NEXT: }
+// CHECK-NEW-CLASS5-CPP-NEXT: } // namespace a
+
+// CHECK-OLD-CLASS5-CPP-NOT: const int K1 = 1;
+// CHECK-OLD-CLASS5-CPP: static const int K2 = 2;
+// CHECK-OLD-CLASS5-CPP: static void HelperFun3() { K2; }
+// CHECK-OLD-CLASS5-CPP: static const int K4 = HelperC3::I;
+// CHECK-OLD-CLASS5-CPP-NOT: void Class5::f() {
+
+
+// ----------------------------------------------------------------------------
+// Test moving helper variables and their transively used helper classes.
+// ----------------------------------------------------------------------------
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="a::Class6" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS6-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS6-CPP %s
+
+// CHECK-NEW-CLASS6-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-CLASS6-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS6-CPP-NEXT: namespace {
+// CHECK-NEW-CLASS6-CPP-NEXT: class HelperC3 {
+// CHECK-NEW-CLASS6-CPP-NEXT: public:
+// CHECK-NEW-CLASS6-CPP-NEXT:   static int I;
+// CHECK-NEW-CLASS6-CPP-NEXT: };
+// CHECK-NEW-CLASS6-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS6-CPP-NEXT: int HelperC3::I = 0;
+// CHECK-NEW-CLASS6-CPP-NEXT: } // namespace
+// CHECK-NEW-CLASS6-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS6-CPP-NEXT: namespace a {
+// CHECK-NEW-CLASS6-CPP-NEXT: static const int K4 = HelperC3::I;
+// CHECK-NEW-CLASS6-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS6-CPP-NEXT: int Class6::f() {
+// CHECK-NEW-CLASS6-CPP-NEXT:   int R = K4;
+// CHECK-NEW-CLASS6-CPP-NEXT:   return R;
+// CHECK-NEW-CLASS6-CPP-NEXT: }
+// CHECK-NEW-CLASS6-CPP-NEXT: } // namespace a
+
+// CHECK-OLD-CLASS6-CPP-NOT: class HelperC3 {
+// CHECK-OLD-CLASS6-CPP-NOT: int HelperC3::I = 0;
+// CHECK-OLD-CLASS6-CPP-NOT: static const int K4 = HelperC3::I;
+
+
+// ----------------------------------------------------------------------------
+// Test moving classes where its methods use helpers.
+// ----------------------------------------------------------------------------
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="a::Class7" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS7-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS7-CPP %s
+
+// CHECK-NEW-CLASS7-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-CLASS7-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS7-CPP-NEXT: namespace a {
+// CHECK-NEW-CLASS7-CPP-NEXT: static const int K6 = 6;
+// CHECK-NEW-CLASS7-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS7-CPP-NEXT: static void HelperFun6() {}
+// CHECK-NEW-CLASS7-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS7-CPP-NEXT: int Class7::f() {
+// CHECK-NEW-CLASS7-CPP-NEXT:   int R = K6;
+// CHECK-NEW-CLASS7-CPP-NEXT:   return R;
+// CHECK-NEW-CLASS7-CPP-NEXT: }
+// CHECK-NEW-CLASS7-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS7-CPP-NEXT: int Class7::g() {
+// CHECK-NEW-CLASS7-CPP-NEXT:   HelperFun6();
+// CHECK-NEW-CLASS7-CPP-NEXT:   return 1;
+// CHECK-NEW-CLASS7-CPP-NEXT: }
+// CHECK-NEW-CLASS7-CPP-NEXT: } // namespace a
+//
+// CHECK-OLD-CLASS7-CPP-NOT: static const int K6 = 6;
+// CHECK-OLD-CLASS7-CPP-NOT: static void HelperFun6() {}
+// CHECK-OLD-CLASS7-CPP-NOT: int Class7::f() {
+// CHECK-OLD-CLASS7-CPP-NOT: int Class7::g() {
+
+
+// ----------------------------------------------------------------------------
+// Test moving helper function and its transively used helper variables.
+// ----------------------------------------------------------------------------
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="a::Fun1" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-FUN1-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-FUN1-CPP %s
+
+// CHECK-NEW-FUN1-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-FUN1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-FUN1-CPP-NEXT: namespace a {
+// CHECK-NEW-FUN1-CPP-NEXT: static const int K5 = 5;
+// CHECK-NEW-FUN1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-FUN1-CPP-NEXT: static int HelperFun5() {
+// CHECK-NEW-FUN1-CPP-NEXT:   int R = K5;
+// CHECK-NEW-FUN1-CPP-NEXT:   return R;
+// CHECK-NEW-FUN1-CPP-NEXT: }
+// CHECK-NEW-FUN1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-FUN1-CPP-NEXT: void Fun1() { HelperFun5(); }
+// CHECK-NEW-FUN1-CPP-NEXT: } // namespace a
+
+// CHECK-OLD-FUN1-CPP-NOT: static const int K5 = 5;
+// CHECK-OLD-FUN1-CPP-NOT: static int HelperFun5() {
+// CHECK-OLD-FUN1-CPP-NOT: void Fun1() { HelperFun5(); }
+
+
+// ----------------------------------------------------------------------------
+// Test no moving helpers when moving inline functions in header.
+// ----------------------------------------------------------------------------
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="a::Fun2" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-FUN2-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.h -check-prefix=CHECK-NEW-FUN2-H %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.h -check-prefix=CHECK-OLD-FUN2-H %s
+
+// CHECK-NEW-FUN2-H: namespace a {
+// CHECK-NEW-FUN2-H-NEXT: inline void Fun2() {}
+// CHECK-NEW-FUN2-H-NEXT: } // namespace a
+
+// CHECK-NEW-FUN2-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-FUN2-CPP-SAME: {{[[:space:]]}}
+
+// CHECK-OLD-FUN2-H-NOT: inline void Fun2() {}
+
+// ----------------------------------------------------------------------------
+// Test moving used helper function and its transively used functions.
+// ----------------------------------------------------------------------------
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="b::Fun3" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-FUN3-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-FUN3-CPP %s
+
+// CHECK-NEW-FUN3-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-FUN3-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-FUN3-CPP-NEXT: namespace b {
+// CHECK-NEW-FUN3-CPP-NEXT: namespace {
+// CHECK-NEW-FUN3-CPP-NEXT: void HelperFun7();
+// CHECK-NEW-FUN3-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-FUN3-CPP-NEXT: class HelperC4;
+// CHECK-NEW-FUN3-CPP-NEXT: } // namespace
+// CHECK-NEW-FUN3-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-FUN3-CPP-NEXT: void Fun3() {
+// CHECK-NEW-FUN3-CPP-NEXT:   HelperFun7();
+// CHECK-NEW-FUN3-CPP-NEXT:   HelperC4 *t;
+// CHECK-NEW-FUN3-CPP-NEXT: }
+// CHECK-NEW-FUN3-CPP-NEXT: namespace {
+// CHECK-NEW-FUN3-CPP-NEXT: void HelperFun7() {}
+// CHECK-NEW-FUN3-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-FUN3-CPP-NEXT: class HelperC4 {};
+// CHECK-NEW-FUN3-CPP-NEXT: } // namespace
+// CHECK-NEW-FUN3-CPP-NEXT: } // namespace b
+//
+// CHECK-OLD-FUN3-CPP-NOT: void HelperFun7();
+// CHECK-OLD-FUN3-CPP-NOT: void HelperFun7() {}
+// CHECK-OLD-FUN3-CPP-NOT: void Fun3() { HelperFun7(); }
+
+// ----------------------------------------------------------------------------
+// Test moving all symbols in headers.
+// ----------------------------------------------------------------------------
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="a::Class1, a::Class2, a::Class3, a::Class4, a::Class5, a::Class5, a::Class6, a::Class7, a::Fun1, a::Fun2, b::Fun3" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.h -check-prefix=CHECK-NEW-H %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -allow-empty -check-prefix=CHECK-EMPTY %s
+
+
+// CHECK-NEW-H: namespace a {
+// CHECK-NEW-H-NEXT: class Class1 {
+// CHECK-NEW-H-NEXT:   void f();
+// CHECK-NEW-H-NEXT: };
+// CHECK-NEW-H-SAME: {{[[:space:]]}}
+// CHECK-NEW-H-NEXT: class Class2 {
+// CHECK-NEW-H-NEXT:   void f();
+// CHECK-NEW-H-NEXT: };
+// CHECK-NEW-H-SAME: {{[[:space:]]}}
+// CHECK-NEW-H-NEXT: class Class3 {
+// CHECK-NEW-H-NEXT:   void f();
+// CHECK-NEW-H-NEXT: };
+// CHECK-NEW-H-SAME: {{[[:space:]]}}
+// CHECK-NEW-H-NEXT: class Class4 {
+// CHECK-NEW-H-NEXT:   void f();
+// CHECK-NEW-H-NEXT: };
+// CHECK-NEW-H-SAME: {{[[:space:]]}}
+// CHECK-NEW-H-NEXT: class Class5 {
+// CHECK-NEW-H-NEXT:   void f();
+// CHECK-NEW-H-NEXT: };
+// CHECK-NEW-H-SAME: {{[[:space:]]}}
+// CHECK-NEW-H-NEXT: class Class6 {
+// CHECK-NEW-H-NEXT:   int f();
+// CHECK-NEW-H-NEXT: };
+// CHECK-NEW-H-SAME: {{[[:space:]]}}
+// CHECK-NEW-H-NEXT: class Class7 {
+// CHECK-NEW-H-NEXT:   int f();
+// CHECK-NEW-H-NEXT:   int g();
+// CHECK-NEW-H-NEXT: };
+// CHECK-NEW-H-SAME: {{[[:space:]]}}
+// CHECK-NEW-H-NEXT: void Fun1();
+// CHECK-NEW-H-SAME: {{[[:space:]]}}
+// CHECK-NEW-H-NEXT: inline void Fun2() {}
+// CHECK-NEW-H-SAME: {{[[:space:]]}}
+// CHECK-NEW-H-NEXT: } // namespace a
+
+
+// CHECK-NEW-CPP: namespace {
+// CHECK-NEW-CPP-NEXT: class HelperC1 {
+// CHECK-NEW-CPP-NEXT: public:
+// CHECK-NEW-CPP-NEXT:   static int I;
+// CHECK-NEW-CPP-NEXT: };
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: int HelperC1::I = 0;
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: class HelperC2 {};
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: class HelperC3 {
+// CHECK-NEW-CPP-NEXT:  public:
+// CHECK-NEW-CPP-NEXT:   static int I;
+// CHECK-NEW-CPP-NEXT: };
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: int HelperC3::I = 0;
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: void HelperFun1() {}
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: void HelperFun2() { HelperFun1(); }
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: const int K1 = 1;
+// CHECK-NEW-CPP-NEXT: } // namespace
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: static const int K2 = 2;
+// CHECK-NEW-CPP-NEXT: static void HelperFun3() { K2; }
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: namespace a {
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: static const int K3 = 3;
+// CHECK-NEW-CPP-NEXT: static const int K4 = HelperC3::I;
+// CHECK-NEW-CPP-NEXT: static const int K5 = 5;
+// CHECK-NEW-CPP-NEXT: static const int K6 = 6;
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: static void HelperFun4() {}
+// CHECK-NEW-CPP-NEXT: static void HelperFun6() {}
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: void Class1::f() { HelperFun2(); }
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: void Class2::f() {
+// CHECK-NEW-CPP-NEXT:   HelperFun1();
+// CHECK-NEW-CPP-NEXT:   HelperFun3();
+// CHECK-NEW-CPP-NEXT: }
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: void Class3::f() { HelperC1::I; }
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: void Class4::f() { HelperC2 c2; }
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: void Class5::f() {
+// CHECK-NEW-CPP-NEXT:   int Result = K1 + K2 + K3;
+// CHECK-NEW-CPP-NEXT:   HelperFun4();
+// CHECK-NEW-CPP-NEXT: }
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: int Class6::f() {
+// CHECK-NEW-CPP-NEXT:   int R = K4;
+// CHECK-NEW-CPP-NEXT:   return R;
+// CHECK-NEW-CPP-NEXT: }
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: int Class7::f() {
+// CHECK-NEW-CPP-NEXT:   int R = K6;
+// CHECK-NEW-CPP-NEXT:   return R;
+// CHECK-NEW-CPP-NEXT: }
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: int Class7::g() {
+// CHECK-NEW-CPP-NEXT:   HelperFun6();
+// CHECK-NEW-CPP-NEXT:   return 1;
+// CHECK-NEW-CPP-NEXT: }
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: static int HelperFun5() {
+// CHECK-NEW-CPP-NEXT:   int R = K5;
+// CHECK-NEW-CPP-NEXT:   return R;
+// CHECK-NEW-CPP-NEXT: }
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: void Fun1() { HelperFun5(); }
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: } // namespace a
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: namespace b {
+// CHECK-NEW-CPP-NEXT: namespace {
+// CHECK-NEW-CPP-NEXT: void HelperFun7();
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: class HelperC4;
+// CHECK-NEW-CPP-NEXT: } // namespace
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: void Fun3() {
+// CHECK-NEW-CPP-NEXT:   HelperFun7();
+// CHECK-NEW-CPP-NEXT:   HelperC4 *t;
+// CHECK-NEW-CPP-NEXT: }
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: namespace {
+// CHECK-NEW-CPP-NEXT: void HelperFun7() {}
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: class HelperC4 {};
+// CHECK-NEW-CPP-NEXT: } // namespace
+// CHECK-NEW-CPP-NEXT: } // namespace b
+
+// CHECK-EMPTY: {{^}}{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-var.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-var.cpp
new file mode 100644
index 0000000..4a3554c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/move-var.cpp
@@ -0,0 +1,46 @@
+// RUN: mkdir -p %T/move-var
+// RUN: cp %S/Inputs/var_test*  %T/move-var
+// RUN: cd %T/move-var
+// RUN: clang-move -names="a::kGlobalInt" -new_header=%T/move-var/new_var_test.h -old_header=../move-var/var_test.h -old_cc=../move-var/var_test.cpp -new_cc=%T/move-var/new_var_test.cpp %T/move-var/var_test.cpp --
+// RUN: FileCheck -input-file=%T/move-var/var_test.h -check-prefix=CHECK-OLD-VAR-H-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-var/var_test.cpp -check-prefix=CHECK-OLD-VAR-CPP-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-var/new_var_test.h -check-prefix=CHECK-NEW-VAR-H-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-var/new_var_test.cpp -check-prefix=CHECK-NEW-VAR-CPP-CASE1 %s
+
+// CHECK-OLD-VAR-H-CASE1-NOT: extern int kGlobalInt;
+// CHECK-OLD-VAR-H-CASE1: int kGlobalInt = 3;
+
+// CHECK-OLD-VAR-CPP-CASE1-NOT: int kGlobalInt = 1;
+
+// CHECK-NEW-VAR-H-CASE1: extern int kGlobalInt;
+// CHECK-NEW-VAR-H-CASE1-NOT: int kGlobalInt = 3;
+
+// CHECK-NEW-VAR-CPP-CASE1: int kGlobalInt = 1;
+
+
+// RUN: cp %S/Inputs/var_test*  %T/move-var
+// RUN: clang-move -names="a::kGlobalStr" -new_header=%T/move-var/new_var_test.h -old_header=../move-var/var_test.h -old_cc=../move-var/var_test.cpp -new_cc=%T/move-var/new_var_test.cpp %T/move-var/var_test.cpp --
+// RUN: FileCheck -input-file=%T/move-var/var_test.h -check-prefix=CHECK-OLD-VAR-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-var/var_test.cpp -check-prefix=CHECK-OLD-VAR-CPP-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-var/new_var_test.h -check-prefix=CHECK-NEW-VAR-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-var/new_var_test.cpp -check-prefix=CHECK-NEW-VAR-CPP-CASE2 %s
+
+// CHECK-OLD-VAR-H-CASE2-NOT: extern const char *const kGlobalStr;
+// CHECK-OLD-VAR-H-CASE2: const char *const kGlobalStr = "Hello2";
+
+// CHECK-OLD-VAR-CPP-CASE2-NOT: const char *const kGlobalStr = "Hello";
+
+// CHECK-NEW-VAR-H-CASE2: extern const char *const kGlobalStr;
+// CHECK-NEW-VAR-H-CASE2-NOT: const char *const kGlobalStr = "Hello2";
+
+// CHECK-NEW-VAR-CPP-CASE2: const char *const kGlobalStr = "Hello";
+
+
+// RUN: cp %S/Inputs/var_test*  %T/move-var
+// RUN: clang-move -names="kEvilInt" -new_header=%T/move-var/new_var_test.h -old_header=../move-var/var_test.h -old_cc=../move-var/var_test.cpp -new_cc=%T/move-var/new_var_test.cpp %T/move-var/var_test.cpp --
+// RUN: FileCheck -input-file=%T/move-var/var_test.h -check-prefix=CHECK-OLD-VAR-H-CASE3 %s
+// RUN: FileCheck -input-file=%T/move-var/new_var_test.h -check-prefix=CHECK-NEW-VAR-H-CASE3 %s
+
+// CHECK-OLD-VAR-H-CASE3-NOT: int kEvilInt = 2;
+
+// CHECK-NEW-VAR-H-CASE3: int kEvilInt = 2;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-move/no-move-macro-helpers.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/no-move-macro-helpers.cpp
new file mode 100644
index 0000000..282eee0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-move/no-move-macro-helpers.cpp
@@ -0,0 +1,43 @@
+// RUN: mkdir -p %T/no-move-macro-helper
+// RUN: cat %S/Inputs/macro_helper_test.h > %T/no-move-macro-helper/macro_helper_test.h
+// RUN: cat %S/Inputs/macro_helper_test.cpp > %T/no-move-macro-helper/macro_helper_test.cpp
+// RUN: cd %T/no-move-macro-helper
+//
+// -----------------------------------------------------------------------------
+// Test no moving helpers in macro.
+// -----------------------------------------------------------------------------
+// RUN: clang-move -names="A" -new_cc=%T/no-move-macro-helper/new_test.cpp -new_header=%T/no-move-macro-helper/new_test.h -old_cc=%T/no-move-macro-helper/macro_helper_test.cpp -old_header=%T/no-move-macro-helper/macro_helper_test.h %T/no-move-macro-helper/macro_helper_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/new_test.h -check-prefix=CHECK-NEW-TEST-CASE1-H %s
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/new_test.cpp -check-prefix=CHECK-NEW-TEST-CASE1-CPP %s
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/macro_helper_test.h -check-prefix=CHECK-OLD-TEST-CASE1-H %s
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/macro_helper_test.cpp -check-prefix=CHECK-OLD-TEST-CASE1-CPP %s
+
+// CHECK-NEW-TEST-CASE1-H: class A {};
+
+// CHECK-OLD-TEST-CASE1-H-NOT: class A {};
+
+// CHECK-OLD-TEST-CASE1-CPP: DEFINE(test)
+
+// CHECK-NEW-TEST-CASE1-CPP-NOT: DEFINE(test)
+
+
+// -----------------------------------------------------------------------------
+// Test moving all.
+// -----------------------------------------------------------------------------
+// RUN: cat %S/Inputs/macro_helper_test.h > %T/no-move-macro-helper/macro_helper_test.h
+// RUN: cat %S/Inputs/macro_helper_test.cpp > %T/no-move-macro-helper/macro_helper_test.cpp
+// RUN: clang-move -names="A, f1" -new_cc=%T/no-move-macro-helper/new_test.cpp -new_header=%T/no-move-macro-helper/new_test.h -old_cc=%T/no-move-macro-helper/macro_helper_test.cpp -old_header=%T/no-move-macro-helper/macro_helper_test.h %T/no-move-macro-helper/macro_helper_test.cpp -- -std=c++11
+//
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/new_test.h -check-prefix=CHECK-NEW-TEST-CASE2-H %s
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/new_test.cpp -check-prefix=CHECK-NEW-TEST-CASE2-CPP %s
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/macro_helper_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/macro_helper_test.cpp -allow-empty -check-prefix=CHECK-EMPTY %s
+
+// CHECK-NEW-TEST-CASE2-H: class A {};
+// CHECK-NEW-TEST-CASE2-H-NEXT:void f1();
+
+
+// CHECK-NEW-TEST-CASE2-CPP: DEFINE(test)
+// CHECK-NEW-TEST-CASE2-CPP: void f1() {}
+
+// CHECK-EMPTY: {{^}}{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-query/Inputs/foo.script b/src/third_party/llvm-project/clang-tools-extra/test/clang-query/Inputs/foo.script
new file mode 100644
index 0000000..3bd1f0e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-query/Inputs/foo.script
@@ -0,0 +1,2 @@
+foo
+bar
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-query/errors.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-query/errors.c
new file mode 100644
index 0000000..bbb7421
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-query/errors.c
@@ -0,0 +1,10 @@
+// RUN: not clang-query -c foo -c bar %s -- | FileCheck %s
+// RUN: not clang-query -f %S/Inputs/foo.script %s -- | FileCheck %s
+// RUN: not clang-query -f %S/Inputs/nonexistent.script %s -- 2>&1 | FileCheck --check-prefix=CHECK-NONEXISTENT %s
+// RUN: not clang-query -c foo -f foo %s -- 2>&1 | FileCheck --check-prefix=CHECK-BOTH %s
+
+// CHECK: unknown command: foo
+// CHECK-NOT: unknown command: bar
+
+// CHECK-NONEXISTENT: cannot open {{.*}}nonexistent.script
+// CHECK-BOTH: cannot specify both -c and -f
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-query/function-decl.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-query/function-decl.c
new file mode 100644
index 0000000..f35cba0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-query/function-decl.c
@@ -0,0 +1,4 @@
+// RUN: clang-query -c "match functionDecl()" %s -- | FileCheck %s
+
+// CHECK: function-decl.c:4:1: note: "root" binds here
+void foo(void) {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/AggregatePartialInitialization.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/AggregatePartialInitialization.cpp
new file mode 100644
index 0000000..9d09c81
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/AggregatePartialInitialization.cpp
@@ -0,0 +1,14 @@
+// RUN: clang-reorder-fields -record-name Foo -fields-order z,y,x %s -- | FileCheck %s
+
+// The order of fields should not change.
+class Foo {
+public:
+  int x;  // CHECK:       {{^  int x;}}
+  int y;  // CHECK-NEXT:  {{^  int y;}}
+  int z;  // CHECK-NEXT:  {{^  int z;}}
+};
+
+int main() {
+  Foo foo = { 0, 1 }; // CHECK: {{^  Foo foo = { 0, 1 };}}
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/CStructAmbiguousName.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/CStructAmbiguousName.cpp
new file mode 100644
index 0000000..e1e6645
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/CStructAmbiguousName.cpp
@@ -0,0 +1,18 @@
+// RUN: clang-reorder-fields -record-name ::Foo -fields-order y,x %s -- | FileCheck %s
+
+struct Foo {
+  int x;    // CHECK:      {{^  double y;}}
+  double y; // CHECK-NEXT: {{^  int x;}}
+};
+
+namespace bar {
+struct Foo {
+  int x;    // CHECK:      {{^  int x;}}
+  double y; // CHECK-NEXT: {{^  double y;}}
+};
+} // end namespace bar
+
+int main() {
+  bar::Foo foo = { 1, 1.7 }; // CHECK: {{^  bar::Foo foo = { 1, 1.7 };}}
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/CStructFieldsOrder.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/CStructFieldsOrder.cpp
new file mode 100644
index 0000000..2ed3578
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/CStructFieldsOrder.cpp
@@ -0,0 +1,16 @@
+// RUN: clang-reorder-fields -record-name ::bar::Foo -fields-order z,w,y,x %s -- | FileCheck %s
+
+namespace bar {
+struct Foo {
+  const int* x; // CHECK:      {{^  double z;}}
+  int y;        // CHECK-NEXT: {{^  int w;}}
+  double z;     // CHECK-NEXT: {{^  int y;}}
+  int w;        // CHECK-NEXT: {{^  const int\* x}}
+};
+} // end namespace bar
+
+int main() {
+  const int x = 13;
+  bar::Foo foo = { &x, 0, 1.29, 17 }; // CHECK: {{^  bar::Foo foo = { 1.29, 17, 0, &x };}} 
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/ClassDerived.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/ClassDerived.cpp
new file mode 100644
index 0000000..e7e9ac1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/ClassDerived.cpp
@@ -0,0 +1,33 @@
+// RUN: clang-reorder-fields -record-name bar::Derived -fields-order z,y %s -- | FileCheck %s
+
+namespace bar {
+class Base {
+public:
+  Base(int nx, int np) : x(nx), p(np) {}
+  int x;
+  int p;
+};
+
+
+class Derived : public Base {
+public:
+  Derived(long ny);
+  Derived(char nz);
+private:
+  long y;
+  char z;
+};
+
+Derived::Derived(long ny) : 
+    Base(ny, 0),
+    y(ny),                   // CHECK:       {{^  z\(static_cast<char>\(ny\)\),}}
+    z(static_cast<char>(ny)) // CHECK-NEXT:  {{^  y\(ny\)}}
+{}
+
+Derived::Derived(char nz) : 
+    Base(1, 2),
+    y(nz),  // CHECK:       {{^  z\(x\),}}
+    z(x)    // CHECK-NEXT:  {{^  y\(nz\)}}
+{}
+
+} // namespace bar
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/ClassDifferentFieldsAccesses.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/ClassDifferentFieldsAccesses.cpp
new file mode 100644
index 0000000..dd0a555
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/ClassDifferentFieldsAccesses.cpp
@@ -0,0 +1,16 @@
+// RUN: clang-reorder-fields -record-name Foo -fields-order z,y,x %s -- | FileCheck %s
+
+// The order of fields should not change.
+class Foo {
+public:
+  int x;  // CHECK:       {{^  int x;}}
+
+private:
+  int y;  // CHECK:       {{^  int y;}}
+  int z;  // CHECK-NEXT:  {{^  int z;}}
+};
+
+int main() {
+  Foo foo;
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/ClassMixedInitialization.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/ClassMixedInitialization.cpp
new file mode 100644
index 0000000..888649a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/ClassMixedInitialization.cpp
@@ -0,0 +1,24 @@
+// RUN: clang-reorder-fields -record-name Foo -fields-order e,x,pi,s2,s1 %s -- -std=c++11 | FileCheck %s
+
+class Foo {
+public:
+  Foo();
+
+private:
+  int x;              // CHECK:      {{^  double e = 2.71;}}
+  const char *s1;     // CHECK-NEXT: {{^  int x;}}
+  const char *s2;     // CHECK-NEXT: {{^  double pi = 3.14;}}
+  double pi = 3.14;   // CHECK-NEXT: {{^  const char \*s2;}}
+  double e = 2.71;    // CHECK-NEXT: {{^  const char \*s1;}}
+};
+
+Foo::Foo():
+  x(12),      // CHECK:      {{^  x\(12\)}},
+  s1("abc"),  // CHECK-NEXT: {{^  s2\("def"\)}},
+  s2("def")   // CHECK-NEXT: {{^  s1\("abc"\)}}
+{}
+
+int main() {
+  Foo foo;
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/ClassSimpleCtor.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/ClassSimpleCtor.cpp
new file mode 100644
index 0000000..6dc2722
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/ClassSimpleCtor.cpp
@@ -0,0 +1,24 @@
+// RUN: clang-reorder-fields -record-name Foo -fields-order s1,x,z,s2 %s -- | FileCheck %s
+
+class Foo {
+public:
+  Foo();
+
+private:
+  int x;              // CHECK:      {{^  const char \*s1;}}
+  const char *s1;     // CHECK-NEXT: {{^  int x;}}
+  const char *s2;     // CHECK-NEXT: {{^  double z;}}
+  double z;           // CHECK-NEXT: {{^  const char \*s2;}}
+};
+
+Foo::Foo():
+  x(12),      // CHECK:      {{^  s1\("abc"\),}}
+  s1("abc"),  // CHECK-NEXT: {{^  x\(12\),}}
+  s2("def"),  // CHECK-NEXT: {{^  z\(3.14\),}}
+  z(3.14)     // CHECK-NEXT: {{^  s2\("def"\)}}
+{}
+
+int main() {
+  Foo foo;
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/FieldDependencyWarning.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/FieldDependencyWarning.cpp
new file mode 100644
index 0000000..bbe0e7f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/FieldDependencyWarning.cpp
@@ -0,0 +1,54 @@
+// RUN: clang-reorder-fields -record-name bar::Foo -fields-order y,z,c,x %s -- 2>&1 | FileCheck --check-prefix=CHECK-MESSAGES %s
+// FIXME: clang-reorder-fields should provide -verify mode to make writing these checks
+// easier and more accurate, for now we follow clang-tidy's approach.
+
+namespace bar {
+
+struct Dummy {
+  Dummy(int x, char c) : x(x), c(c) {}
+  int x;
+  char c;
+};
+
+class Foo {
+public:
+  Foo(int x, double y, char cin);
+  Foo(int nx);
+  Foo();
+  int x;
+  double y;
+  char c;
+  Dummy z;
+};
+
+static char bar(char c) {
+  return c + 1;
+}
+
+Foo::Foo() : x(), y(), c(), z(0, 'a') {}
+
+Foo::Foo(int x, double y, char cin) :  
+  x(x),                 
+  y(y),                 
+  c(cin),               
+  z(this->x, bar(c))    
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: reordering field x after z makes x uninitialized when used in init expression
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: reordering field c after z makes c uninitialized when used in init expression
+{}
+
+Foo::Foo(int nx) :
+  x(nx),              
+  y(x),
+  c(0),            
+  z(bar(bar(x)), c)     
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: reordering field x after y makes x uninitialized when used in init expression
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: reordering field x after z makes x uninitialized when used in init expression
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: reordering field c after z makes c uninitialized when used in init expression
+{}
+
+} // namespace bar
+
+int main() {
+  bar::Foo F(5, 12.8, 'c');
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/FieldDependencyWarningDerived.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/FieldDependencyWarningDerived.cpp
new file mode 100644
index 0000000..bbc58ae
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/FieldDependencyWarningDerived.cpp
@@ -0,0 +1,36 @@
+// RUN: clang-reorder-fields -record-name bar::Derived -fields-order z,y %s -- 2>&1 | FileCheck --check-prefix=CHECK-MESSAGES %s
+// FIXME: clang-reorder-fields should provide -verify mode to make writing these checks
+// easier and more accurate, for now we follow clang-tidy's approach.
+
+namespace bar {
+struct Base {
+  int x;
+  int p;
+};
+
+class Derived : public Base {
+public:
+  Derived(long ny);
+  Derived(char nz);
+private:
+  long y;
+  char z;
+};
+
+Derived::Derived(long ny) : 
+  Base(),
+  y(ny), 
+  z(static_cast<char>(y)) 
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: reordering field y after z makes y uninitialized when used in init expression
+{}
+
+Derived::Derived(char nz) : 
+  Base(),
+  y(nz),
+  // Check that base class fields are correctly ignored in reordering checks
+  // x has field index 1 and so would improperly warn if this wasn't the case since the command for this file swaps field indexes 1 and 2
+  z(x) 
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: reordering field x after z makes x uninitialized when used in init expression
+{}
+
+} // namespace bar
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/PlainCStructFieldsOrder.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/PlainCStructFieldsOrder.c
new file mode 100644
index 0000000..5b4fe9e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-reorder-fields/PlainCStructFieldsOrder.c
@@ -0,0 +1,14 @@
+// RUN: clang-reorder-fields -record-name Foo -fields-order z,w,y,x %s -- | FileCheck %s
+
+struct Foo {
+  const int* x; // CHECK:      {{^  double z;}}
+  int y;        // CHECK-NEXT: {{^  int w;}}
+  double z;     // CHECK-NEXT: {{^  int y;}}
+  int w;        // CHECK-NEXT: {{^  const int\* x}}
+};
+
+int main() {
+  const int x = 13;
+  struct Foo foo = { &x, 0, 1.29, 17 }; // CHECK: {{^  struct Foo foo = { 1.29, 17, 0, &x };}} 
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/a.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/a.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/a.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/b.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/b.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/b.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/clang-c/c.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/clang-c/c.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/clang-c/c.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/clang/b.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/clang/b.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/clang/b.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-a.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-a.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-a.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-b.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-b.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-b.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-c.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-c.h
new file mode 100644
index 0000000..342dd34
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/cross-file-c.h
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// The line number of the following include should match the location of the
+// corresponding comment in llvm-include-order.cpp
+#include "cross-file-b.h"
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/gtest/foo.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/gtest/foo.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/gtest/foo.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/i.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/i.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/i.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/j.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/j.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/j.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/llvm-c/d.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/llvm-c/d.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/llvm-c/d.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/llvm/a.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/llvm/a.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/llvm/a.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/s.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/s.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/s.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/system-header-simulation.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/system-header-simulation.h
new file mode 100644
index 0000000..0df5305
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/Headers/system-header-simulation.h
@@ -0,0 +1,24 @@
+#pragma clang system_header
+
+namespace std {
+
+template<class T, T v>
+struct integral_constant {
+    static constexpr T value = v;
+    typedef T value_type;
+    typedef integral_constant type;
+    constexpr operator value_type() const noexcept { return value; }
+};
+
+template <bool B>
+using bool_constant = integral_constant<bool, B>;
+using true_type = bool_constant<true>;
+using false_type = bool_constant<false>;
+
+template<class T>
+struct is_error_code_enum : false_type {};
+
+template<class T>
+void swap(T &a, T &b);
+}
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/compilation-database/template.json b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/compilation-database/template.json
new file mode 100644
index 0000000..74275d9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/compilation-database/template.json
@@ -0,0 +1,32 @@
+[
+{
+  "directory": "test_dir/a",
+  "command": "clang++ -o test.o test_dir/a/a.cpp",
+  "file": "test_dir/a/a.cpp"
+},
+{
+  "directory": "test_dir/a",
+  "command": "clang++ -o test.o test_dir/a/b.cpp",
+  "file": "test_dir/a/b.cpp"
+},
+{
+  "directory": "test_dir/",
+  "command": "clang++ -o test.o test_dir/b/b.cpp",
+  "file": "test_dir/b/b.cpp"
+},
+{
+  "directory": "test_dir/b",
+  "command": "clang++ -o test.o ../b/c.cpp",
+  "file": "test_dir/b/c.cpp"
+},
+{
+  "directory": "test_dir/b",
+  "command": "clang++ -I../include -o test.o ../b/d.cpp",
+  "file": "test_dir/b/d.cpp"
+},
+{
+  "directory": "test_dir/",
+  "command": "clang++ -o test.o test_dir/b/not-exist.cpp",
+  "file": "test_dir/b/not-exist.cpp"
+}
+]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/config-files/.clang-tidy b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/config-files/.clang-tidy
new file mode 100644
index 0000000..942169f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/config-files/.clang-tidy
@@ -0,0 +1,2 @@
+Checks: 'from-parent'
+HeaderFilterRegex: 'parent'
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/config-files/1/.clang-tidy b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/config-files/1/.clang-tidy
new file mode 100644
index 0000000..800fd4e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/config-files/1/.clang-tidy
@@ -0,0 +1,2 @@
+Checks: 'from-child1'
+HeaderFilterRegex: 'child1'
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/explain-config/.clang-tidy b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/explain-config/.clang-tidy
new file mode 100644
index 0000000..4fbd09c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/explain-config/.clang-tidy
@@ -0,0 +1 @@
+Checks: '-*,modernize-use-nullptr'
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/header1.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/header1.h
new file mode 100644
index 0000000..ba9e3d1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/header1.h
@@ -0,0 +1 @@
+class A1 { A1(int); };
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/header2.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/header2.h
new file mode 100644
index 0000000..09bfeab
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/header2.h
@@ -0,0 +1 @@
+class A2 { A2(int); };
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/system/system-header.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/system/system-header.h
new file mode 100644
index 0000000..98482c4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/file-filter/system/system-header.h
@@ -0,0 +1 @@
+class A0 { A0(int); };
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/a.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/a.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/a.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/cstdarg.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/cstdarg.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/cstdarg.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/cstdlib.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/cstdlib.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/cstdlib.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/j.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/j.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/j.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/r.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/r.h
new file mode 100644
index 0000000..56757a7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/r.h
@@ -0,0 +1 @@
+void f() {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/s.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/s.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/s.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/t.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/t.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/t.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/transitive.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/transitive.h
new file mode 100644
index 0000000..6dba769
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/system/transitive.h
@@ -0,0 +1,3 @@
+#include <r.h>
+#include <t.h>
+#include <s.h>
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/transitive2.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/transitive2.h
new file mode 100644
index 0000000..ea56788
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/fuchsia-restrict-system-includes/transitive2.h
@@ -0,0 +1,2 @@
+#include <s.h>
+#include <t.h>
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/google-namespaces.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/google-namespaces.h
new file mode 100644
index 0000000..f4d87f5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/google-namespaces.h
@@ -0,0 +1,7 @@
+namespace {
+int x;
+}
+
+namespace spaaaace {
+class core;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header1.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header1.h
new file mode 100644
index 0000000..35d59ce
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header1.h
@@ -0,0 +1,3 @@
+class A1 { A1(int); };
+class B1 { B1(int); };
+class C1 { C1(int); };
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header2.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header2.h
new file mode 100644
index 0000000..bb12598
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header2.h
@@ -0,0 +1,3 @@
+class A2 { A2(int); };
+class B2 { B2(int); };
+class C2 { C2(int); };
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header3.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header3.h
new file mode 100644
index 0000000..b5198ca
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/line-filter/header3.h
@@ -0,0 +1 @@
+class A3 { A3(int); };
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/assert.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/assert.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/assert.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/complex.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/complex.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/complex.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/ctype.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/ctype.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/ctype.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/errno.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/errno.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/errno.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/fenv.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/fenv.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/fenv.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/float.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/float.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/float.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/inttypes.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/inttypes.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/inttypes.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/iso646.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/iso646.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/iso646.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/limits.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/limits.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/limits.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/locale.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/locale.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/locale.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/math.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/math.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/math.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/setjmp.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/setjmp.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/setjmp.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/signal.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/signal.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/signal.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdalign.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdalign.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdalign.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdarg.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdarg.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdarg.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdbool.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdbool.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdbool.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stddef.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stddef.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stddef.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdint.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdint.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdint.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdio.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdio.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdio.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdlib.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdlib.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/stdlib.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/string.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/string.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/string.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/tgmath.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/tgmath.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/tgmath.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/time.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/time.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/time.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/uchar.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/uchar.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/uchar.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/wchar.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/wchar.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/wchar.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/wctype.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/wctype.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-deprecated-headers/wctype.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-loop-convert/structures.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-loop-convert/structures.h
new file mode 100644
index 0000000..02d440c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-loop-convert/structures.h
@@ -0,0 +1,206 @@
+#ifndef STRUCTURES_H
+#define STRUCTURES_H
+
+extern "C" {
+extern int printf(const char *restrict, ...);
+}
+
+struct Val {int X; void g(); };
+
+struct MutableVal {
+  void constFun(int) const;
+  void nonConstFun(int, int);
+  void constFun(MutableVal &) const;
+  void constParamFun(const MutableVal &) const;
+  void nonConstParamFun(const MutableVal &);
+  int X;
+};
+
+struct NonTriviallyCopyable {
+  NonTriviallyCopyable() = default;
+  // Define this constructor to make this class non-trivially copyable.
+  NonTriviallyCopyable(const NonTriviallyCopyable& Ntc);
+  int X;
+};
+
+struct TriviallyCopyableButBig {
+  int X;
+  char Array[16];
+};
+
+struct S {
+  typedef MutableVal *iterator;
+  typedef const MutableVal *const_iterator;
+  const_iterator begin() const;
+  const_iterator end() const;
+  const_iterator cbegin() const;
+  const_iterator cend() const;
+  iterator begin();
+  iterator end();
+};
+
+struct T {
+  struct iterator {
+    int& operator*();
+    const int& operator*()const;
+    iterator& operator ++();
+    bool operator!=(const iterator &other);
+    void insert(int);
+    int X;
+  };
+  iterator begin();
+  iterator end();
+};
+
+struct U {
+  struct iterator {
+    Val& operator*();
+    const Val& operator*()const;
+    iterator& operator ++();
+    bool operator!=(const iterator &other);
+    Val *operator->();
+  };
+  iterator begin();
+  iterator end();
+  int X;
+};
+
+struct X {
+  S Ss;
+  T Tt;
+  U Uu;
+  S getS();
+};
+
+template<typename ElemType>
+class dependent {
+ public:
+  dependent<ElemType>();
+  struct iterator_base {
+    const ElemType& operator*()const;
+    iterator_base& operator ++();
+    bool operator!=(const iterator_base &other) const;
+    const ElemType *operator->() const;
+  };
+
+  struct iterator : iterator_base {
+    ElemType& operator*();
+    iterator& operator ++();
+    ElemType *operator->();
+  };
+
+  typedef iterator_base const_iterator;
+  const_iterator begin() const;
+  const_iterator end() const;
+  iterator begin();
+  iterator end();
+  unsigned size() const;
+  ElemType & operator[](unsigned);
+  const ElemType & operator[](unsigned) const;
+  ElemType & at(unsigned);
+  ElemType & at(unsigned, unsigned);
+  const ElemType & at(unsigned) const;
+
+  // Intentionally evil.
+  dependent<ElemType> operator*();
+
+  void foo();
+  void constFoo() const;
+};
+
+template<typename First, typename Second>
+class doublyDependent{
+ public:
+  struct Value {
+    First first;
+    Second second;
+  };
+
+  struct iterator_base {
+    const Value& operator*()const;
+    iterator_base& operator ++();
+    bool operator!=(const iterator_base &other) const;
+    const Value *operator->() const;
+  };
+
+  struct iterator : iterator_base {
+    Value& operator*();
+    Value& operator ++();
+    Value *operator->();
+  };
+
+  typedef iterator_base const_iterator;
+  const_iterator begin() const;
+  const_iterator end() const;
+  iterator begin();
+  iterator end();
+};
+
+template<typename Contained>
+class transparent {
+ public:
+  Contained *at();
+  Contained *operator->();
+  Contained operator*();
+};
+
+template<typename IteratorType>
+struct Nested {
+  typedef IteratorType* iterator;
+  typedef const IteratorType* const_iterator;
+  IteratorType *operator->();
+  IteratorType operator*();
+  iterator begin();
+  iterator end();
+  const_iterator begin() const;
+  const_iterator end() const;
+};
+
+// Like llvm::SmallPtrSet, the iterator has a dereference operator that returns
+// by value instead of by reference.
+template <typename T>
+struct PtrSet {
+  struct iterator {
+    bool operator!=(const iterator &other) const;
+    const T operator*();
+    iterator &operator++();
+  };
+  iterator begin() const;
+  iterator end() const;
+};
+
+template <typename T>
+struct TypedefDerefContainer {
+  struct iterator {
+    typedef T &deref_type;
+    bool operator!=(const iterator &other) const;
+    deref_type operator*();
+    iterator &operator++();
+  };
+  iterator begin() const;
+  iterator end() const;
+};
+
+template <typename T>
+struct RValueDerefContainer {
+  struct iterator {
+    typedef T &&deref_type;
+    bool operator!=(const iterator &other) const;
+    deref_type operator*();
+    iterator &operator++();
+  };
+  iterator begin() const;
+  iterator end() const;
+};
+
+namespace Macros {
+
+struct MacroStruct {
+  int Arr[10];
+};
+static MacroStruct *MacroSt;
+#define CONT MacroSt->
+
+} // namespace Macros
+
+#endif  // STRUCTURES_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-pass-by-value/header-with-fix.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-pass-by-value/header-with-fix.h
new file mode 100644
index 0000000..62609e2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-pass-by-value/header-with-fix.h
@@ -0,0 +1,8 @@
+struct S {
+  S(S&&);
+  S(const S&);
+};
+struct Foo {
+  Foo(const S &s);
+  S s;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-pass-by-value/header.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-pass-by-value/header.h
new file mode 100644
index 0000000..c2103cb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-pass-by-value/header.h
@@ -0,0 +1,10 @@
+class ThreadId {
+public:
+  ThreadId(const ThreadId &) {}
+  ThreadId(ThreadId &&) {}
+};
+
+struct A {
+  A(const ThreadId &tid) : threadid(tid) {}
+  ThreadId threadid;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-replace-auto-ptr/memory.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-replace-auto-ptr/memory.h
new file mode 100644
index 0000000..bc476ce
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-replace-auto-ptr/memory.h
@@ -0,0 +1,45 @@
+#ifndef INPUTS_MEMORY_H
+#define INPUTS_MEMORY_H
+
+namespace std {
+
+inline namespace _1 {
+
+template <class Y> struct auto_ptr_ref {
+  Y *y_;
+};
+
+template <class X> class auto_ptr {
+public:
+  typedef X element_type;
+  explicit auto_ptr(X *p = 0) throw() {}
+  auto_ptr(auto_ptr &) throw() {}
+  template <class Y> auto_ptr(auto_ptr<Y> &) throw() {}
+  auto_ptr &operator=(auto_ptr &) throw() { return *this; }
+  template <class Y> auto_ptr &operator=(auto_ptr<Y> &) throw() {
+    return *this;
+  }
+  auto_ptr &operator=(auto_ptr_ref<X> r) throw() { return *this; }
+  ~auto_ptr() throw() {}
+  auto_ptr(auto_ptr_ref<X> r) throw() : x_(r.y_) {}
+  template <class Y> operator auto_ptr_ref<Y>() throw() {
+    auto_ptr_ref<Y> r;
+    r.y_ = x_;
+    return r;
+  }
+  template <class Y> operator auto_ptr<Y>() throw() { return auto_ptr<Y>(x_); }
+
+private:
+  X *x_;
+};
+
+template <> class auto_ptr<void> {
+public:
+  typedef void element_type;
+};
+
+} // namespace _1
+
+} // end namespace std
+
+#endif // INPUTS_MEMORY_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/initializer_list.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/initializer_list.h
new file mode 100644
index 0000000..28592cf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/initializer_list.h
@@ -0,0 +1,32 @@
+namespace std {
+typedef decltype(sizeof(int)) size_t;
+
+template <class _E> class initializer_list {
+  const _E *__begin_;
+  size_t __size_;
+
+  initializer_list(const _E *__b, size_t __s) : __begin_(__b), __size_(__s) {}
+
+public:
+  typedef _E value_type;
+  typedef const _E &reference;
+  typedef const _E &const_reference;
+  typedef size_t size_type;
+
+  typedef const _E *iterator;
+  typedef const _E *const_iterator;
+
+  initializer_list() : __begin_(nullptr), __size_(0) {}
+
+  size_t size() const { return __size_; }
+  const _E *begin() const { return __begin_; }
+  const _E *end() const { return __begin_ + __size_; }
+};
+
+template <class _E>
+class vector {
+ public:
+  vector(initializer_list<_E> init);
+  ~vector();
+};
+} // namespace std
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/shared_ptr.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/shared_ptr.h
new file mode 100644
index 0000000..0f4f2a9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/shared_ptr.h
@@ -0,0 +1,24 @@
+namespace std {
+
+template <typename type>
+class shared_ptr {
+public:
+  shared_ptr();
+  shared_ptr(type *ptr);
+  shared_ptr(const shared_ptr<type> &t) {}
+  shared_ptr(shared_ptr<type> &&t) {}
+  ~shared_ptr();
+  type &operator*() { return *ptr; }
+  type *operator->() { return ptr; }
+  type *release();
+  void reset();
+  void reset(type *pt);
+  shared_ptr &operator=(shared_ptr &&);
+  template <typename T>
+  shared_ptr &operator=(shared_ptr<T> &&);
+
+private:
+  type *ptr;
+};
+
+}  // namespace std
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/unique_ptr.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/unique_ptr.h
new file mode 100644
index 0000000..5dc9e02
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-smart-ptr/unique_ptr.h
@@ -0,0 +1,28 @@
+namespace std {
+
+template <typename T>
+class default_delete {};
+
+template <typename type, typename Deleter = std::default_delete<type>>
+class unique_ptr {
+public:
+  unique_ptr() {}
+  unique_ptr(type *ptr) {}
+  unique_ptr(const unique_ptr<type> &t) = delete;
+  unique_ptr(unique_ptr<type> &&t) {}
+  ~unique_ptr() {}
+  type &operator*() { return *ptr; }
+  type *operator->() { return ptr; }
+  type *release() { return ptr; }
+  void reset() {}
+  void reset(type *pt) {}
+  void reset(type pt) {}
+  unique_ptr &operator=(unique_ptr &&) { return *this; }
+  template <typename T>
+  unique_ptr &operator=(unique_ptr<T> &&) { return *this; }
+
+private:
+  type *ptr;
+};
+
+}  // namespace std
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-use-auto/containers.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-use-auto/containers.h
new file mode 100644
index 0000000..c99b7a4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/modernize-use-auto/containers.h
@@ -0,0 +1,253 @@
+#ifndef CONTAINERS_H
+#define CONTAINERS_H
+
+namespace std {
+
+template <typename T>
+class iterator {
+public:
+  iterator() {}
+  iterator(const iterator<T> &iter) : ptr(iter.ptr) {}
+
+  typedef T value_type;
+  typedef T *pointer;
+  typedef T &reference;
+
+  reference operator*() const { return *ptr; }
+  pointer operator->() const { return ptr; }
+  iterator &operator++() {
+    ++ptr;
+    return *this;
+  }
+  iterator &operator--() {
+    --ptr;
+    return *this;
+  }
+  iterator operator++(int) {
+    iterator res(*this);
+    ++ptr;
+    return res;
+  }
+  iterator operator--(int) {
+    iterator res(*this);
+    --ptr;
+    return res;
+  }
+  bool operator!=(const iterator<T> &iter) const {
+    return ptr != iter.operator->();
+  }
+
+private:
+  T *ptr;
+};
+
+template <class Iterator>
+class const_iterator {
+public:
+  const_iterator() {}
+  const_iterator(const Iterator &iter) : iter(iter) {}
+  const_iterator(const const_iterator<Iterator> &citer) : iter(citer.iter) {}
+
+  typedef const typename Iterator::value_type value_type;
+  typedef const typename Iterator::pointer pointer;
+  typedef const typename Iterator::reference reference;
+
+  reference operator*() const { return *iter; }
+  pointer operator->() const { return iter.operator->(); }
+
+  const_iterator &operator++() { return ++iter; }
+  const_iterator &operator--() { return --iter; }
+  const_iterator operator++(int) { return iter--; }
+  const_iterator operator--(int) { return iter--; }
+
+  bool operator!=(const Iterator &it) const {
+    return iter->operator->() != it.operator->();
+  }
+  bool operator!=(const const_iterator<Iterator> &it) const {
+    return iter.operator->() != it.operator->();
+  }
+
+private:
+  Iterator iter;
+};
+
+template <class Iterator>
+class forward_iterable {
+public:
+  forward_iterable() {}
+  typedef Iterator iterator;
+  typedef const_iterator<Iterator> const_iterator;
+
+  iterator begin() { return _begin; }
+  iterator end() { return _end; }
+
+  const_iterator begin() const { return _begin; }
+  const_iterator end() const { return _end; }
+
+  const_iterator cbegin() const { return _begin; }
+  const_iterator cend() const { return _end; }
+
+private:
+  iterator _begin, _end;
+};
+
+template <class Iterator>
+class reverse_iterator {
+public:
+  reverse_iterator() {}
+  reverse_iterator(const Iterator &iter) : iter(iter) {}
+  reverse_iterator(const reverse_iterator<Iterator> &rit) : iter(rit.iter) {}
+
+  typedef typename Iterator::value_type value_type;
+  typedef typename Iterator::pointer pointer;
+  typedef typename Iterator::reference reference;
+
+  reference operator*() { return *iter; }
+  pointer operator->() { return iter.operator->(); }
+
+  reverse_iterator &operator++() { return --iter; }
+  reverse_iterator &operator--() { return ++iter; }
+  reverse_iterator operator++(int) { return iter--; }
+  reverse_iterator operator--(int) { return iter++; }
+
+private:
+  Iterator iter;
+};
+
+template <class Iterator>
+class backward_iterable {
+public:
+  backward_iterable() {}
+
+  typedef reverse_iterator<Iterator> reverse_iterator;
+  typedef const_iterator<reverse_iterator> const_reverse_iterator;
+
+  reverse_iterator rbegin() { return _rbegin; }
+  reverse_iterator rend() { return _rend; }
+
+  const_reverse_iterator rbegin() const { return _rbegin; }
+  const_reverse_iterator rend() const { return _rend; }
+
+  const_reverse_iterator crbegin() const { return _rbegin; }
+  const_reverse_iterator crend() const { return _rend; }
+
+private:
+  reverse_iterator _rbegin, _rend;
+};
+
+template <class Iterator>
+class bidirectional_iterable : public forward_iterable<Iterator>,
+                               public backward_iterable<Iterator> {};
+
+template <typename A, typename B>
+struct pair {
+  pair(A f, B s) : first(f), second(s) {}
+  A first;
+  B second;
+};
+
+class string {
+public:
+  string() {}
+  string(const char *) {}
+};
+
+template <typename T, int n>
+class array : public backward_iterable<iterator<T>> {
+public:
+  array() {}
+
+  typedef T *iterator;
+  typedef const T *const_iterator;
+
+  iterator begin() { return &v[0]; }
+  iterator end() { return &v[n - 1]; }
+
+  const_iterator begin() const { return &v[0]; }
+  const_iterator end() const { return &v[n - 1]; }
+
+  const_iterator cbegin() const { return &v[0]; }
+  const_iterator cend() const { return &v[n - 1]; }
+
+private:
+  T v[n];
+};
+
+template <typename T>
+class deque : public bidirectional_iterable<iterator<T>> {
+public:
+  deque() {}
+};
+
+template <typename T>
+class list : public bidirectional_iterable<iterator<T>> {
+public:
+  list() {}
+};
+
+template <typename T>
+class forward_list : public forward_iterable<iterator<T>> {
+public:
+  forward_list() {}
+};
+
+template <typename T>
+class vector : public bidirectional_iterable<iterator<T>> {
+public:
+  vector() {}
+};
+
+template <typename T>
+class set : public bidirectional_iterable<iterator<T>> {
+public:
+  set() {}
+};
+
+template <typename T>
+class multiset : public bidirectional_iterable<iterator<T>> {
+public:
+  multiset() {}
+};
+
+template <typename key, typename value>
+class map : public bidirectional_iterable<iterator<pair<key, value>>> {
+public:
+  map() {}
+
+  iterator<pair<key, value>> find(const key &) {}
+  const_iterator<iterator<pair<key, value>>> find(const key &) const {}
+};
+
+template <typename key, typename value>
+class multimap : public bidirectional_iterable<iterator<pair<key, value>>> {
+public:
+  multimap() {}
+};
+
+template <typename T>
+class unordered_set : public forward_iterable<iterator<T>> {
+public:
+  unordered_set() {}
+};
+
+template <typename T>
+class unordered_multiset : public forward_iterable<iterator<T>> {
+public:
+  unordered_multiset() {}
+};
+
+template <typename key, typename value>
+class unordered_map : public forward_iterable<iterator<pair<key, value>>> {
+public:
+  unordered_map() {}
+};
+
+template <typename key, typename value>
+class unordered_multimap : public forward_iterable<iterator<pair<key, value>>> {
+public:
+  unordered_multimap() {}
+};
+
+} // namespace std
+
+#endif // CONTAINERS_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/mpi-type-mismatch/mpimock.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/mpi-type-mismatch/mpimock.h
new file mode 100644
index 0000000..cb90028
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/mpi-type-mismatch/mpimock.h
@@ -0,0 +1,64 @@
+// This Message Passing Interface mock header is used, to mock typedefs,
+// constants and functions, required for integration tests being part of
+// clang-tidy MPI checks.
+
+#ifndef MPIMOCK_H
+#define MPIMOCK_H
+
+#define NULL 0
+
+// These typedefs are used to mock MPI types, fixed width integer types and the
+// templated C++ complex number type.
+typedef int MPI_Datatype;
+typedef int MPI_Comm;
+typedef int MPI_Request;
+typedef int MPI_Status;
+typedef int MPI_Op;
+typedef int int8_t;
+typedef int uint8_t;
+typedef int uint16_t;
+typedef int int64_t;
+namespace std { template<class T> struct complex { T real; T imag; }; }
+
+// These defines are used to mock MPI constants.
+#define MPI_DATATYPE_NULL 0
+#define MPI_CHAR 0
+#define MPI_BYTE 0
+#define MPI_SHORT 0
+#define MPI_INT 0
+#define MPI_LONG 0
+#define MPI_LONG_DOUBLE 0
+#define MPI_UNSIGNED 0
+#define MPI_INT8_T 0
+#define MPI_UINT8_T 0
+#define MPI_UINT16_T 0
+#define MPI_C_FLOAT_COMPLEX 0
+#define MPI_C_LONG_DOUBLE_COMPLEX 0
+#define MPI_FLOAT 0
+#define MPI_DOUBLE 0
+#define MPI_CXX_BOOL 0
+#define MPI_CXX_FLOAT_COMPLEX 0
+#define MPI_CXX_DOUBLE_COMPLEX 0
+#define MPI_CXX_LONG_DOUBLE_COMPLEX 0
+#define MPI_IN_PLACE 0
+#define MPI_COMM_WORLD 0
+#define MPI_STATUS_IGNORE 0
+#define MPI_STATUSES_IGNORE 0
+#define MPI_SUM 0
+
+// These declarations are used to mock MPI functions.
+int MPI_Comm_size(MPI_Comm, int *);
+int MPI_Comm_rank(MPI_Comm, int *);
+int MPI_Send(const void *, int, MPI_Datatype, int, int, MPI_Comm);
+int MPI_Recv(void *, int, MPI_Datatype, int, int, MPI_Comm, MPI_Status *);
+int MPI_Isend(const void *, int, MPI_Datatype, int, int, MPI_Comm,
+    MPI_Request *);
+int MPI_Irecv(void *, int, MPI_Datatype, int, int, MPI_Comm, MPI_Request *);
+int MPI_Wait(MPI_Request *, MPI_Status *);
+int MPI_Waitall(int, MPI_Request[], MPI_Status[]);
+int MPI_Reduce(const void *, void *, int, MPI_Datatype, MPI_Op, int, MPI_Comm);
+int MPI_Ireduce(const void *, void *, int, MPI_Datatype, MPI_Op, int, MPI_Comm,
+    MPI_Request *);
+int MPI_Bcast(void *, int count, MPI_Datatype, int, MPI_Comm);
+
+#endif  // end of include guard: MPIMOCK_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/nolint/trigger_warning.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/nolint/trigger_warning.h
new file mode 100644
index 0000000..e8ebed2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/nolint/trigger_warning.h
@@ -0,0 +1,5 @@
+void A1(const int &In, int &Out) {
+  if (In > 123) // NOLINT
+    Out = 123;
+}
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/overlapping/o.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/overlapping/o.h
new file mode 100644
index 0000000..bfa7a0a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/overlapping/o.h
@@ -0,0 +1,9 @@
+// run: clang-tidy -checks=-*,llvm-include-order -header-filter=.* %s \
+// run:   -- -isystem %S/Inputs/Headers -I %S/Inputs/overlapping | \
+// run:   not grep "note: this fix will not be applied because it overlaps with another fix"
+
+#include "b.h"
+#include "a.h"
+
+// The comments above are there to match the offset of the #include with the
+// offset of the #includes in the .cpp file.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/performance-unnecessary-value-param/header-fixed.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/performance-unnecessary-value-param/header-fixed.h
new file mode 100644
index 0000000..f3e9e72
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/performance-unnecessary-value-param/header-fixed.h
@@ -0,0 +1,15 @@
+// struct ABC is expensive to copy and should be
+// passed as a const referece.
+struct ABC {
+  ABC(const ABC&);
+  int get(int) const;
+};
+
+
+int f1(int n,              const ABC& v1,   const ABC& v2); // line 9
+
+int f1(int n, ABC v1); // line 11
+
+
+
+int f2(        int n,       const ABC& v2); // line 15
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/performance-unnecessary-value-param/header.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/performance-unnecessary-value-param/header.h
new file mode 100644
index 0000000..3f55c79
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/performance-unnecessary-value-param/header.h
@@ -0,0 +1,15 @@
+// struct ABC is expensive to copy and should be
+// passed as a const referece.
+struct ABC {
+  ABC(const ABC&);
+  int get(int) const;
+};
+
+
+int f1(int n,              ABC v1,   ABC v2); // line 9
+
+int f1(int n, ABC v1); // line 11
+
+
+
+int f2(        int n,       ABC v2); // line 15
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/readability-identifier-naming/system/system-header.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/readability-identifier-naming/system/system-header.h
new file mode 100644
index 0000000..8a394a9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/readability-identifier-naming/system/system-header.h
@@ -0,0 +1,17 @@
+#ifndef SYSTEM_HEADER_H
+#define SYSTEM_HEADER_H
+
+#define SYSTEM_MACRO(m) int m = 0
+
+namespace SYSTEM_NS {
+class structure {
+  int member;
+};
+
+float global;
+
+void function() {
+}
+}
+
+#endif // SYSTEM_HEADER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/readability-identifier-naming/user-header.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/readability-identifier-naming/user-header.h
new file mode 100644
index 0000000..f03982c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/readability-identifier-naming/user-header.h
@@ -0,0 +1,17 @@
+#ifndef USER_HEADER_H
+#define USER_HEADER_H
+
+#define USER_MACRO(m) int m = 0
+
+namespace USER_NS {
+class object {
+  int member;
+};
+
+float global;
+
+void function() {
+}
+}
+
+#endif // USER_HEADER_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/unused-using-decls.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/unused-using-decls.h
new file mode 100644
index 0000000..8245cb1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/unused-using-decls.h
@@ -0,0 +1,11 @@
+class MyClass {
+public:
+  template <template <typename> class S, typename T>
+  S<T> *func1(T *a) {
+    return new S<T>();
+  }
+  template <typename T, T (*S)()>
+  void func2(T a) {
+    S();
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/vfsoverlay/actual_header.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/vfsoverlay/actual_header.h
new file mode 100644
index 0000000..8e1b9ae
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/vfsoverlay/actual_header.h
@@ -0,0 +1 @@
+struct X {};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/vfsoverlay/vfsoverlay.yaml b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/vfsoverlay/vfsoverlay.yaml
new file mode 100644
index 0000000..80d8fba
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/Inputs/vfsoverlay/vfsoverlay.yaml
@@ -0,0 +1,12 @@
+{
+  'version': 0,
+  'roots': [
+    { 'name': 'OUT_DIR', 'type': 'directory',
+      'contents': [
+        { 'name': 'not_real.h', 'type': 'file',
+          'external-contents': 'INPUT_DIR/actual_header.h'
+        }
+      ]
+    }
+  ]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/abseil-string-find-startswith.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/abseil-string-find-startswith.cpp
new file mode 100644
index 0000000..7d5fd73
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/abseil-string-find-startswith.cpp
@@ -0,0 +1,70 @@
+// RUN: %check_clang_tidy %s abseil-string-find-startswith %t -- \
+// RUN:   -config="{CheckOptions: [{key: 'abseil-string-find-startswith.StringLikeClasses', value: '::std::basic_string;::basic_string'}]}" \
+// RUN:   -- -std=c++11
+
+namespace std {
+template <typename T> class allocator {};
+template <typename T> class char_traits {};
+template <typename C, typename T = std::char_traits<C>,
+          typename A = std::allocator<C>>
+struct basic_string {
+  basic_string();
+  basic_string(const basic_string &);
+  basic_string(const C *, const A &a = A());
+  ~basic_string();
+  int find(basic_string<C> s, int pos = 0);
+  int find(const char *s, int pos = 0);
+};
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+
+struct cxx_string {
+  int find(const char *s, int pos = 0);
+};
+} // namespace std
+
+struct basic_string : public std::cxx_string {
+  basic_string();
+};
+typedef basic_string global_string;
+
+std::string foo(std::string);
+std::string bar();
+
+#define A_MACRO(x, y) ((x) == (y))
+
+void tests(std::string s, global_string s2) {
+  s.find("a") == 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith instead of find() == 0 [abseil-string-find-startswith]
+  // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, "a");{{$}}
+
+  s.find(s) == 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, s);{{$}}
+
+  s.find("aaa") != 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "aaa");{{$}}
+
+  s.find(foo(foo(bar()))) != 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, foo(foo(bar())));{{$}}
+
+  if (s.find("....") == 0) { /* do something */ }
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}if (absl::StartsWith(s, "....")) { /* do something */ }{{$}}
+
+  0 != s.find("a");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "a");{{$}}
+
+  s2.find("a") == 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s2, "a");{{$}}
+
+  // expressions that don't trigger the check are here.
+  A_MACRO(s.find("a"), 0);
+  s.find("a", 1) == 0;
+  s.find("a", 1) == 1;
+  s.find("a") == 1;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-accept.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-accept.cpp
new file mode 100644
index 0000000..9990594
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-accept.cpp
@@ -0,0 +1,28 @@
+// RUN: %check_clang_tidy %s android-cloexec-accept %t
+
+struct sockaddr {};
+typedef int socklen_t;
+#define NULL 0
+
+extern "C" int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+
+void f() {
+  accept(0, NULL, NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer accept4() to accept() because accept4() allows SOCK_CLOEXEC [android-cloexec-accept]
+  // CHECK-FIXES: accept4(0, NULL, NULL, SOCK_CLOEXEC);
+}
+
+namespace i {
+int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+void g() {
+  accept(0, NULL, NULL);
+}
+} // namespace i
+
+class C {
+public:
+  int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+  void h() {
+    accept(0, NULL, NULL);
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-accept4.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-accept4.cpp
new file mode 100644
index 0000000..448d4a9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-accept4.cpp
@@ -0,0 +1,66 @@
+// RUN: %check_clang_tidy %s android-cloexec-accept4 %t
+
+typedef int socklen_t;
+struct sockaddr {};
+
+#define SOCK_NONBLOCK 1
+#define __O_CLOEXEC 3
+#define SOCK_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+  ({                            \
+    int _rc;                    \
+    do {                        \
+      _rc = (exp);              \
+    } while (_rc == -1);        \
+  })
+#define NULL 0
+
+extern "C" int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
+
+void a() {
+  accept4(0, NULL, NULL, SOCK_NONBLOCK);
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: 'accept4' should use SOCK_CLOEXEC where possible [android-cloexec-accept4]
+  // CHECK-FIXES: accept4(0, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
+  TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_NONBLOCK));
+  // CHECK-MESSAGES: :[[@LINE-1]]:58: warning: 'accept4'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC));
+}
+
+void f() {
+  accept4(0, NULL, NULL, 3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 'accept4'
+  // CHECK-FIXES: accept4(0, NULL, NULL, 3 | SOCK_CLOEXEC);
+  TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, 3));
+  // CHECK-MESSAGES: :[[@LINE-1]]:46: warning: 'accept4'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, 3 | SOCK_CLOEXEC));
+
+  int flag = SOCK_NONBLOCK;
+  accept4(0, NULL, NULL, flag);
+  TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, flag));
+}
+
+namespace i {
+int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
+
+void d() {
+  accept4(0, NULL, NULL, SOCK_NONBLOCK);
+  TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_NONBLOCK));
+}
+
+} // namespace i
+
+void e() {
+  accept4(0, NULL, NULL, SOCK_CLOEXEC);
+  TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_CLOEXEC));
+  accept4(0, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
+  TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC));
+}
+
+class G {
+public:
+  int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
+  void d() {
+    accept4(0, NULL, NULL, SOCK_NONBLOCK);
+    TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_NONBLOCK));
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-creat.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-creat.cpp
new file mode 100644
index 0000000..df57b10
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-creat.cpp
@@ -0,0 +1,35 @@
+// RUN: %check_clang_tidy %s android-cloexec-creat %t
+
+typedef int mode_t;
+
+extern "C" int creat(const char *path, mode_t, ...);
+extern "C" int create(const char *path, mode_t, ...);
+
+void f() {
+  creat("filename", 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer open() to creat() because open() allows O_CLOEXEC [android-cloexec-creat]
+  // CHECK-FIXES: open ("filename", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0);
+  create("filename", 0);
+  // CHECK-MESSAGES-NOT: warning:
+  mode_t mode = 0755;
+  creat("filename", mode);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning:
+  // CHECK-FIXES: open ("filename", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
+}
+
+namespace i {
+int creat(const char *path, mode_t, ...);
+void g() {
+  creat("filename", 0);
+  // CHECK-MESSAGES-NOT: warning:
+}
+} // namespace i
+
+class C {
+public:
+  int creat(const char *path, mode_t, ...);
+  void h() {
+    creat("filename", 0);
+    // CHECK-MESSAGES-NOT: warning:
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-dup.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-dup.cpp
new file mode 100644
index 0000000..f7011b8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-dup.cpp
@@ -0,0 +1,31 @@
+// RUN: %check_clang_tidy %s android-cloexec-dup %t
+
+extern "C" int dup(int oldfd);
+void f() {
+  dup(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer fcntl() to dup() because fcntl() allows F_DUPFD_CLOEXEC [android-cloexec-dup]
+  // CHECK-FIXES: fcntl(1, F_DUPFD_CLOEXEC);
+  int oldfd = 0;
+  dup(oldfd);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer
+  // CHECK-FIXES: fcntl(oldfd, F_DUPFD_CLOEXEC);
+}
+
+namespace i {
+int dup(int oldfd);
+void g() {
+  dup(0);
+  int oldfd = 1;
+  dup(oldfd);
+}
+} // namespace i
+
+class C {
+public:
+  int dup(int oldfd);
+  void h() {
+    dup(0);
+    int oldfd = 1;
+    dup(oldfd);
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-epoll-create.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-epoll-create.cpp
new file mode 100644
index 0000000..d58e493
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-epoll-create.cpp
@@ -0,0 +1,24 @@
+// RUN: %check_clang_tidy %s android-cloexec-epoll-create %t
+
+extern "C" int epoll_create(int size);
+
+void f() {
+  epoll_create(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer epoll_create() to epoll_create1() because epoll_create1() allows EPOLL_CLOEXEC [android-cloexec-epoll-create]
+  // CHECK-FIXES: epoll_create1(EPOLL_CLOEXEC);
+}
+
+namespace i {
+int epoll_create(int size);
+void g() {
+  epoll_create(0);
+}
+} // namespace i
+
+class C {
+public:
+  int epoll_create(int size);
+  void h() {
+    epoll_create(0);
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-epoll-create1.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-epoll-create1.cpp
new file mode 100644
index 0000000..696a20c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-epoll-create1.cpp
@@ -0,0 +1,59 @@
+// RUN: %check_clang_tidy %s android-cloexec-epoll-create1 %t
+
+#define __O_CLOEXEC 3
+#define EPOLL_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+  ({                            \
+    int _rc;                    \
+    do {                        \
+      _rc = (exp);              \
+    } while (_rc == -1);        \
+  })
+
+extern "C" int epoll_create1(int flags);
+
+void a() {
+  epoll_create1(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'epoll_create1' should use EPOLL_CLOEXEC where possible [android-cloexec-epoll-create1]
+  // CHECK-FIXES: epoll_create1(EPOLL_CLOEXEC);
+  TEMP_FAILURE_RETRY(epoll_create1(0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'epoll_create1'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
+}
+
+void f() {
+  epoll_create1(3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'epoll_create1'
+  // CHECK-FIXES: epoll_create1(EPOLL_CLOEXEC);
+  TEMP_FAILURE_RETRY(epoll_create1(3));
+  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'epoll_create1'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
+
+  int flag = 0;
+  epoll_create1(EPOLL_CLOEXEC);
+  TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
+}
+
+namespace i {
+int epoll_create1(int flags);
+
+void d() {
+  epoll_create1(0);
+  TEMP_FAILURE_RETRY(epoll_create1(0));
+}
+
+} // namespace i
+
+void e() {
+  epoll_create1(EPOLL_CLOEXEC);
+  TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
+}
+
+class G {
+public:
+  int epoll_create1(int flags);
+  void d() {
+    epoll_create1(EPOLL_CLOEXEC);
+    TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-fopen.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-fopen.cpp
new file mode 100644
index 0000000..6b6c655
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-fopen.cpp
@@ -0,0 +1,57 @@
+// RUN: %check_clang_tidy %s android-cloexec-fopen %t
+
+#define FILE_OPEN_RO "r"
+
+typedef int FILE;
+
+extern "C" FILE *fopen(const char *filename, const char *mode, ...);
+extern "C" FILE *open(const char *filename, const char *mode, ...);
+
+void f() {
+  fopen("filename", "r");
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use 'fopen' mode 'e' to set O_CLOEXEC [android-cloexec-fopen]
+  // CHECK-FIXES: fopen("filename", "re");
+
+  fopen("filename", FILE_OPEN_RO);
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use 'fopen' mode 'e'
+  // CHECK-FIXES: fopen("filename", FILE_OPEN_RO "e");
+
+  fopen("filename", "er");
+  // CHECK-MESSAGES-NOT: warning:
+  fopen("filename", "re");
+  // CHECK-MESSAGES-NOT: warning:
+  fopen("filename", "e");
+  // CHECK-MESSAGES-NOT: warning:
+  open("filename", "e");
+  // CHECK-MESSAGES-NOT: warning:
+
+  char *str = "r";
+  fopen("filename", str);
+  // CHECK-MESSAGES-NOT: warning:
+  str = "re";
+  fopen("filename", str);
+  // CHECK-MESSAGES-NOT: warning:
+  char arr[2] = "r";
+  fopen("filename", arr);
+  // CHECK-MESSAGES-NOT: warning:
+  char arr2[3] = "re";
+  fopen("filename", arr2);
+  // CHECK-MESSAGES-NOT: warning:
+}
+
+namespace i {
+int *fopen(const char *filename, const char *mode, ...);
+void g() {
+  fopen("filename", "e");
+  // CHECK-MESSAGES-NOT: warning:
+}
+} // namespace i
+
+class C {
+public:
+  int *fopen(const char *filename, const char *mode, ...);
+  void h() {
+    fopen("filename", "e");
+    // CHECK-MESSAGES-NOT: warning:
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-inotify-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-inotify-init.cpp
new file mode 100644
index 0000000..01eb51e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-inotify-init.cpp
@@ -0,0 +1,24 @@
+// RUN: %check_clang_tidy %s android-cloexec-inotify-init %t
+
+extern "C" int inotify_init();
+
+void f() {
+  inotify_init();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer inotify_init() to inotify_init1() because inotify_init1() allows IN_CLOEXEC [android-cloexec-inotify-init]
+  // CHECK-FIXES: inotify_init1(IN_CLOEXEC);
+}
+
+namespace i {
+int inotify_init();
+void g() {
+  inotify_init();
+}
+} // namespace i
+
+class C {
+public:
+  int inotify_init();
+  void h() {
+    inotify_init();
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-inotify-init1.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-inotify-init1.cpp
new file mode 100644
index 0000000..2b74fad
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-inotify-init1.cpp
@@ -0,0 +1,64 @@
+// RUN: %check_clang_tidy %s android-cloexec-inotify-init1 %t
+
+#define IN_NONBLOCK 1
+#define __O_CLOEXEC 3
+#define IN_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+  ({                            \
+    int _rc;                    \
+    do {                        \
+      _rc = (exp);              \
+    } while (_rc == -1);        \
+  })
+
+extern "C" int inotify_init1(int flags);
+
+void a() {
+  inotify_init1(IN_NONBLOCK);
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: 'inotify_init1' should use IN_CLOEXEC where possible [android-cloexec-inotify-init1]
+  // CHECK-FIXES: inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+  TEMP_FAILURE_RETRY(inotify_init1(IN_NONBLOCK));
+  // CHECK-MESSAGES: :[[@LINE-1]]:47: warning: 'inotify_init1'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(inotify_init1(IN_NONBLOCK | IN_CLOEXEC));
+}
+
+void f() {
+  inotify_init1(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'inotify_init1'
+  // CHECK-FIXES: inotify_init1(IN_CLOEXEC);
+  TEMP_FAILURE_RETRY(inotify_init1(0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'inotify_init1'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(inotify_init1(IN_CLOEXEC));
+
+  int flag = 1;
+  inotify_init1(flag);
+  TEMP_FAILURE_RETRY(inotify_init1(flag));
+}
+
+namespace i {
+int inotify_init1(int flags);
+
+void d() {
+  inotify_init1(IN_NONBLOCK);
+  TEMP_FAILURE_RETRY(inotify_init1(IN_NONBLOCK));
+}
+
+} // namespace i
+
+void e() {
+  inotify_init1(IN_CLOEXEC);
+  TEMP_FAILURE_RETRY(inotify_init1(IN_CLOEXEC));
+  inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+  TEMP_FAILURE_RETRY(inotify_init1(IN_NONBLOCK | IN_CLOEXEC));
+}
+
+class G {
+public:
+  int inotify_init1(int flags);
+  void d() {
+    inotify_init1(IN_CLOEXEC);
+    TEMP_FAILURE_RETRY(inotify_init1(IN_CLOEXEC));
+    inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+    TEMP_FAILURE_RETRY(inotify_init1(IN_NONBLOCK | IN_CLOEXEC));
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-memfd-create.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-memfd-create.cpp
new file mode 100644
index 0000000..a8dafd5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-memfd-create.cpp
@@ -0,0 +1,63 @@
+// RUN: %check_clang_tidy %s android-cloexec-memfd-create %t
+
+#define MFD_ALLOW_SEALING 1
+#define __O_CLOEXEC 3
+#define MFD_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+  ({                            \
+    int _rc;                    \
+    do {                        \
+      _rc = (exp);              \
+    } while (_rc == -1);        \
+  })
+#define NULL 0
+
+extern "C" int memfd_create(const char *name, unsigned int flags);
+
+void a() {
+  memfd_create(NULL, MFD_ALLOW_SEALING);
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: 'memfd_create' should use MFD_CLOEXEC where possible [android-cloexec-memfd-create]
+  // CHECK-FIXES: memfd_create(NULL, MFD_ALLOW_SEALING | MFD_CLOEXEC)
+  TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_ALLOW_SEALING));
+  // CHECK-MESSAGES: :[[@LINE-1]]:58: warning: 'memfd_create'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_ALLOW_SEALING | MFD_CLOEXEC))
+}
+
+void f() {
+  memfd_create(NULL, 3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 'memfd_create'
+  // CHECK-FIXES: memfd_create(NULL, 3 | MFD_CLOEXEC)
+  TEMP_FAILURE_RETRY(memfd_create(NULL, 3));
+  // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: 'memfd_create'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(memfd_create(NULL, 3 | MFD_CLOEXEC))
+
+  int flag = 3;
+  memfd_create(NULL, flag);
+  TEMP_FAILURE_RETRY(memfd_create(NULL, flag));
+}
+
+namespace i {
+int memfd_create(const char *name, unsigned int flags);
+
+void d() {
+  memfd_create(NULL, MFD_ALLOW_SEALING);
+  TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_ALLOW_SEALING));
+}
+
+} // namespace i
+
+void e() {
+  memfd_create(NULL, MFD_CLOEXEC);
+  TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_CLOEXEC));
+  memfd_create(NULL, MFD_ALLOW_SEALING | MFD_CLOEXEC);
+  TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_ALLOW_SEALING | MFD_CLOEXEC));
+}
+
+class G {
+public:
+  int memfd_create(const char *name, unsigned int flags);
+  void d() {
+    memfd_create(NULL, MFD_ALLOW_SEALING);
+    TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_ALLOW_SEALING));
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-open.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-open.cpp
new file mode 100644
index 0000000..4ef1f40
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-open.cpp
@@ -0,0 +1,180 @@
+// RUN: %check_clang_tidy %s android-cloexec-open %t
+
+#define O_RDWR 1
+#define O_EXCL 2
+#define __O_CLOEXEC 3
+#define O_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+  ({                            \
+    int _rc;                    \
+    do {                        \
+      _rc = (exp);              \
+    } while (_rc == -1);        \
+  })
+
+extern "C" int open(const char *fn, int flags, ...);
+extern "C" int open64(const char *fn, int flags, ...);
+extern "C" int openat(int dirfd, const char *pathname, int flags, ...);
+
+void a() {
+  open("filename", O_RDWR);
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: 'open' should use O_CLOEXEC where possible [android-cloexec-open]
+  // CHECK-FIXES: O_RDWR | O_CLOEXEC
+  TEMP_FAILURE_RETRY(open("filename", O_RDWR));
+  // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: 'open' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_CLOEXEC
+  open("filename", O_RDWR | O_EXCL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: 'open' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+  TEMP_FAILURE_RETRY(open("filename", O_RDWR | O_EXCL));
+  // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: 'open' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+}
+
+void b() {
+  open64("filename", O_RDWR);
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: 'open64' should use O_CLOEXEC where possible [android-cloexec-open]
+  // CHECK-FIXES: O_RDWR | O_CLOEXEC
+  TEMP_FAILURE_RETRY(open64("filename", O_RDWR));
+  // CHECK-MESSAGES: :[[@LINE-1]]:47: warning: 'open64' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_CLOEXEC
+  open64("filename", O_RDWR | O_EXCL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'open64' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+  TEMP_FAILURE_RETRY(open64("filename", O_RDWR | O_EXCL));
+  // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: 'open64' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+}
+
+void c() {
+  openat(0, "filename", O_RDWR);
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: 'openat' should use O_CLOEXEC where possible [android-cloexec-open]
+  // CHECK-FIXES: O_RDWR | O_CLOEXEC
+  TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR));
+  // CHECK-MESSAGES: :[[@LINE-1]]:50: warning: 'openat' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_CLOEXEC
+  openat(0, "filename", O_RDWR | O_EXCL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: 'openat' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+  TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR | O_EXCL));
+  // CHECK-MESSAGES: :[[@LINE-1]]:59: warning: 'openat' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+}
+
+void f() {
+  open("filename", 3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 'open' should use O_CLOEXEC where possible [android-cloexec-open]
+  // CHECK-FIXES: 3 | O_CLOEXEC
+  TEMP_FAILURE_RETRY(open("filename", 3));
+  // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: 'open' should use O_CLOEXEC where
+  // CHECK-FIXES: 3 | O_CLOEXEC
+  open64("filename", 3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 'open64' should use O_CLOEXEC where possible [android-cloexec-open]
+  // CHECK-FIXES: 3 | O_CLOEXEC
+  TEMP_FAILURE_RETRY(open64("filename", 3));
+  // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: 'open64' should use O_CLOEXEC where
+  // CHECK-FIXES: 3 | O_CLOEXEC
+  openat(0, "filename", 3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: 'openat' should use O_CLOEXEC where possible [android-cloexec-open]
+  // CHECK-FIXES: 3 | O_CLOEXEC
+  TEMP_FAILURE_RETRY(openat(0, "filename", 3));
+  // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: 'openat' should use O_CLOEXEC where
+  // CHECK-FIXES: 3 | O_CLOEXEC
+
+  int flag = 3;
+  open("filename", flag);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open("filename", flag));
+  // CHECK-MESSAGES-NOT: warning:
+  open64("filename", flag);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open64("filename", flag));
+  // CHECK-MESSAGES-NOT: warning:
+  openat(0, "filename", flag);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(openat(0, "filename", flag));
+  // CHECK-MESSAGES-NOT: warning:
+}
+
+namespace i {
+int open(const char *pathname, int flags, ...);
+int open64(const char *pathname, int flags, ...);
+int openat(int dirfd, const char *pathname, int flags, ...);
+
+void d() {
+  open("filename", O_RDWR);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open("filename", O_RDWR));
+  // CHECK-MESSAGES-NOT: warning:
+  open64("filename", O_RDWR);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open64("filename", O_RDWR));
+  // CHECK-MESSAGES-NOT: warning:
+  openat(0, "filename", O_RDWR);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR));
+  // CHECK-MESSAGES-NOT: warning:
+}
+
+} // namespace i
+
+void e() {
+  open("filename", O_CLOEXEC);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open("filename", O_CLOEXEC));
+  // CHECK-MESSAGES-NOT: warning:
+  open("filename", O_RDWR | O_CLOEXEC);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open("filename", O_RDWR | O_CLOEXEC));
+  // CHECK-MESSAGES-NOT: warning:
+  open("filename", O_RDWR | O_CLOEXEC | O_EXCL);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open("filename", O_RDWR | O_CLOEXEC | O_EXCL));
+  // CHECK-MESSAGES-NOT: warning:
+  open64("filename", O_CLOEXEC);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open64("filename", O_CLOEXEC));
+  // CHECK-MESSAGES-NOT: warning:
+  open64("filename", O_RDWR | O_CLOEXEC);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open64("filename", O_RDWR | O_CLOEXEC));
+  // CHECK-MESSAGES-NOT: warning:
+  open64("filename", O_RDWR | O_CLOEXEC | O_EXCL);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open64("filename", O_RDWR | O_CLOEXEC | O_EXCL));
+  // CHECK-MESSAGES-NOT: warning:
+  openat(0, "filename", O_CLOEXEC);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(openat(0, "filename", O_CLOEXEC));
+  // CHECK-MESSAGES-NOT: warning:
+  openat(0, "filename", O_RDWR | O_CLOEXEC);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR | O_CLOEXEC));
+  // CHECK-MESSAGES-NOT: warning:
+  openat(0, "filename", O_RDWR | O_CLOEXEC | O_EXCL);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR | O_CLOEXEC | O_EXCL));
+  // CHECK-MESSAGES-NOT: warning:
+}
+
+class G {
+public:
+  int open(const char *pathname, int flags, ...);
+  int open64(const char *pathname, int flags, ...);
+  int openat(int dirfd, const char *pathname, int flags, ...);
+
+  void h() {
+    open("filename", O_RDWR);
+    // CHECK-MESSAGES-NOT: warning:
+    TEMP_FAILURE_RETRY(open("filename", O_RDWR));
+    // CHECK-MESSAGES-NOT: warning:
+    open64("filename", O_RDWR);
+    // CHECK-MESSAGES-NOT: warning:
+    TEMP_FAILURE_RETRY(open64("filename", O_RDWR));
+    // CHECK-MESSAGES-NOT: warning:
+    openat(0, "filename", O_RDWR);
+    // CHECK-MESSAGES-NOT: warning:
+    TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR));
+    // CHECK-MESSAGES-NOT: warning:
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-socket.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-socket.cpp
new file mode 100644
index 0000000..25f332d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-cloexec-socket.cpp
@@ -0,0 +1,75 @@
+// RUN: %check_clang_tidy %s android-cloexec-socket %t
+
+#define SOCK_STREAM 1
+#define SOCK_DGRAM 2
+#define __O_CLOEXEC 3
+#define SOCK_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+  ({                            \
+    int _rc;                    \
+    do {                        \
+      _rc = (exp);              \
+    } while (_rc == -1);        \
+  })
+
+extern "C" int socket(int domain, int type, int protocol);
+
+void a() {
+  socket(0, SOCK_STREAM, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: 'socket' should use SOCK_CLOEXEC where possible [android-cloexec-socket]
+  // CHECK-FIXES: socket(0, SOCK_STREAM | SOCK_CLOEXEC, 0)
+  TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM, 0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: 'socket'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_CLOEXEC, 0))
+  socket(0, SOCK_STREAM | SOCK_DGRAM, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'socket'
+  // CHECK-FIXES: socket(0, SOCK_STREAM | SOCK_DGRAM | SOCK_CLOEXEC, 0)
+  TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_DGRAM, 0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: 'socket'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_DGRAM | SOCK_CLOEXEC, 0))
+}
+
+void f() {
+  socket(0, 3, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: 'socket'
+  // CHECK-FIXES: socket(0, 3 | SOCK_CLOEXEC, 0)
+  TEMP_FAILURE_RETRY(socket(0, 3, 0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: 'socket'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(socket(0, 3 | SOCK_CLOEXEC, 0))
+
+  int flag = 3;
+  socket(0, flag, 0);
+  TEMP_FAILURE_RETRY(socket(0, flag, 0));
+}
+
+namespace i {
+int socket(int domain, int type, int protocol);
+
+void d() {
+  socket(0, SOCK_STREAM, 0);
+  TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM, 0));
+  socket(0, SOCK_STREAM | SOCK_DGRAM, 0);
+  TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_DGRAM, 0));
+}
+
+} // namespace i
+
+void e() {
+  socket(0, SOCK_CLOEXEC, 0);
+  TEMP_FAILURE_RETRY(socket(0, SOCK_CLOEXEC, 0));
+  socket(0, SOCK_STREAM | SOCK_CLOEXEC, 0);
+  TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_CLOEXEC, 0));
+  socket(0, SOCK_STREAM | SOCK_CLOEXEC | SOCK_DGRAM, 0);
+  TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_CLOEXEC | SOCK_DGRAM, 0));
+}
+
+class G {
+public:
+  int socket(int domain, int type, int protocol);
+  void d() {
+    socket(0, SOCK_STREAM, 0);
+    TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM, 0));
+    socket(0, SOCK_STREAM | SOCK_DGRAM, 0);
+    TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_DGRAM, 0));
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-comparison-in-temp-failure-retry.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-comparison-in-temp-failure-retry.c
new file mode 100644
index 0000000..3be3eec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/android-comparison-in-temp-failure-retry.c
@@ -0,0 +1,148 @@
+// RUN: %check_clang_tidy %s android-comparison-in-temp-failure-retry %t
+
+#define TEMP_FAILURE_RETRY(x)                                                  \
+  ({                                                                           \
+    typeof(x) __z;                                                             \
+    do                                                                         \
+      __z = (x);                                                               \
+    while (__z == -1);                                                         \
+    __z;                                                                       \
+  })
+
+int foo();
+int bar(int a);
+
+void test() {
+  int i;
+  TEMP_FAILURE_RETRY((i = foo()));
+  TEMP_FAILURE_RETRY(foo());
+  TEMP_FAILURE_RETRY((foo()));
+
+  TEMP_FAILURE_RETRY(foo() == 1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: top-level comparison in TEMP_FAILURE_RETRY [android-comparison-in-temp-failure-retry]
+  TEMP_FAILURE_RETRY((foo() == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: top-level comparison in TEMP_FAILURE_RETRY
+  TEMP_FAILURE_RETRY((int)(foo() == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+  TEMP_FAILURE_RETRY(bar(foo() == 1));
+  TEMP_FAILURE_RETRY((bar(foo() == 1)));
+  TEMP_FAILURE_RETRY((bar(foo() == 1)) == 1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: top-level comparison in TEMP_FAILURE_RETRY
+  TEMP_FAILURE_RETRY(((bar(foo() == 1)) == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: top-level comparison in TEMP_FAILURE_RETRY
+  TEMP_FAILURE_RETRY((int)((bar(foo() == 1)) == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:46: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+#define INDIRECT TEMP_FAILURE_RETRY
+  INDIRECT(foo());
+  INDIRECT((foo() == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: top-level comparison in TEMP_FAILURE_RETRY
+  INDIRECT(bar(foo() == 1));
+  INDIRECT((int)((bar(foo() == 1)) == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+#define TFR(x) TEMP_FAILURE_RETRY(x)
+  TFR(foo());
+  TFR((foo() == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: top-level comparison in TEMP_FAILURE_RETRY
+  TFR(bar(foo() == 1));
+  TFR((int)((bar(foo() == 1)) == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+#define ADD_TFR(x) (1 + TEMP_FAILURE_RETRY(x) + 1)
+  ADD_TFR(foo());
+  ADD_TFR(foo() == 1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+  ADD_TFR(bar(foo() == 1));
+  ADD_TFR((int)((bar(foo() == 1)) == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+#define ADDP_TFR(x) (1 + TEMP_FAILURE_RETRY((x)) + 1)
+  ADDP_TFR(foo());
+  ADDP_TFR((foo() == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+  ADDP_TFR(bar(foo() == 1));
+  ADDP_TFR((int)((bar(foo() == 1)) == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+#define MACRO TEMP_FAILURE_RETRY(foo() == 1)
+  MACRO;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+  // Be sure that being a macro arg doesn't mess with this.
+#define ID(x) (x)
+  ID(ADDP_TFR(bar(foo() == 1)));
+  ID(ADDP_TFR(bar(foo() == 1) == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: top-level comparison in TEMP_FAILURE_RETRY
+  ID(MACRO);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: top-level comparison in TEMP_FAILURE_RETRY
+
+#define CMP(x) x == 1
+  TEMP_FAILURE_RETRY(CMP(foo()));
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: top-level comparison in TEMP_FAILURE_RETRY
+}
+
+// Be sure that it works inside of things like loops, if statements, etc.
+void control_flow() {
+  do {
+    if (TEMP_FAILURE_RETRY(foo())) {
+    }
+
+    if (TEMP_FAILURE_RETRY(foo() == 1)) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY
+    }
+
+    if (TEMP_FAILURE_RETRY(bar(foo() == 1))) {
+    }
+
+    if (TEMP_FAILURE_RETRY(bar(foo() == 1) == 1)) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: top-level comparison in TEMP_FAILURE_RETRY
+    }
+  } while (TEMP_FAILURE_RETRY(foo() == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: top-level comparison in TEMP_FAILURE_RETRY
+}
+
+void with_nondependent_variable_type() {
+#undef TEMP_FAILURE_RETRY
+#define TEMP_FAILURE_RETRY(x)                                                  \
+  ({                                                                           \
+    long int __z;                                                              \
+    do                                                                         \
+      __z = (x);                                                               \
+    while (__z == -1);                                                         \
+    __z;                                                                       \
+  })
+
+  TEMP_FAILURE_RETRY((foo()));
+  TEMP_FAILURE_RETRY((int)(foo() == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY
+  TEMP_FAILURE_RETRY((bar(foo() == 1)));
+  TEMP_FAILURE_RETRY((int)((bar(foo() == 1)) == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:46: warning: top-level comparison in TEMP_FAILURE_RETRY
+}
+
+// I can't find a case where TEMP_FAILURE_RETRY is implemented like this, but if
+// we can cheaply support it, I don't see why not.
+void obscured_temp_failure_retry() {
+#undef TEMP_FAILURE_RETRY
+#define IMPL(x)                                                                \
+  ({                                                                           \
+    typeof(x) __z;                                                             \
+    do                                                                         \
+      __z = (x);                                                               \
+    while (__z == -1);                                                         \
+    __z;                                                                       \
+  })
+
+#define IMPL2(x) IMPL(x)
+#define TEMP_FAILURE_RETRY(x) IMPL2(x)
+  TEMP_FAILURE_RETRY((foo()));
+  TEMP_FAILURE_RETRY((int)(foo() == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY
+  TEMP_FAILURE_RETRY((bar(foo() == 1)));
+  TEMP_FAILURE_RETRY((int)((bar(foo() == 1)) == 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:46: warning: top-level comparison in TEMP_FAILURE_RETRY
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/basic.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/basic.cpp
new file mode 100644
index 0000000..12eb6fe
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/basic.cpp
@@ -0,0 +1,6 @@
+// RUN: clang-tidy %s -checks='-*,llvm-namespace-comment' -- | FileCheck %s
+// RUN: c-index-test -test-load-source-reparse 2 all %s -Xclang -add-plugin -Xclang clang-tidy -Xclang -plugin-arg-clang-tidy -Xclang -checks='-*,llvm-namespace-comment' 2>&1 | FileCheck %s
+
+namespace i {
+}
+// CHECK: warning: namespace 'i' not terminated with a closing comment [llvm-namespace-comment]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/boost-use-to-string.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/boost-use-to-string.cpp
new file mode 100644
index 0000000..44ba172
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/boost-use-to-string.cpp
@@ -0,0 +1,169 @@
+// RUN: %check_clang_tidy %s boost-use-to-string %t
+
+namespace std {
+
+template <typename T>
+class basic_string {};
+
+using string = basic_string<char>;
+using wstring = basic_string<wchar_t>;
+}
+
+namespace boost {
+template <typename T, typename V>
+T lexical_cast(const V &) {
+  return T();
+};
+}
+
+struct my_weird_type {};
+
+std::string fun(const std::string &) {}
+
+void test_to_string1() {
+
+  auto xa = boost::lexical_cast<std::string>(5);
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
+  // CHECK-FIXES: auto xa = std::to_string(5);
+
+  auto z = boost::lexical_cast<std::string>(42LL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::to_string
+  // CHECK-FIXES: auto z = std::to_string(42LL);
+
+  // this should not trigger
+  fun(boost::lexical_cast<std::string>(42.0));
+  auto non = boost::lexical_cast<my_weird_type>(42);
+  boost::lexical_cast<int>("12");
+}
+
+void test_to_string2() {
+  int a;
+  long b;
+  long long c;
+  unsigned d;
+  unsigned long e;
+  unsigned long long f;
+  float g;
+  double h;
+  long double i;
+  bool j;
+
+  fun(boost::lexical_cast<std::string>(a));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
+  // CHECK-FIXES: fun(std::to_string(a));
+  fun(boost::lexical_cast<std::string>(b));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
+  // CHECK-FIXES: fun(std::to_string(b));
+  fun(boost::lexical_cast<std::string>(c));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
+  // CHECK-FIXES: fun(std::to_string(c));
+  fun(boost::lexical_cast<std::string>(d));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
+  // CHECK-FIXES: fun(std::to_string(d));
+  fun(boost::lexical_cast<std::string>(e));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
+  // CHECK-FIXES: fun(std::to_string(e));
+  fun(boost::lexical_cast<std::string>(f));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
+  // CHECK-FIXES: fun(std::to_string(f));
+
+  // No change for floating numbers.
+  fun(boost::lexical_cast<std::string>(g));
+  fun(boost::lexical_cast<std::string>(h));
+  fun(boost::lexical_cast<std::string>(i));
+  // And bool.
+  fun(boost::lexical_cast<std::string>(j));
+}
+
+std::string fun(const std::wstring &) {}
+
+void test_to_wstring() {
+  int a;
+  long b;
+  long long c;
+  unsigned d;
+  unsigned long e;
+  unsigned long long f;
+  float g;
+  double h;
+  long double i;
+  bool j;
+
+  fun(boost::lexical_cast<std::wstring>(a));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring instead of boost::lexical_cast<std::wstring> [boost-use-to-string]
+  // CHECK-FIXES: fun(std::to_wstring(a));
+  fun(boost::lexical_cast<std::wstring>(b));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring
+  // CHECK-FIXES: fun(std::to_wstring(b));
+  fun(boost::lexical_cast<std::wstring>(c));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring
+  // CHECK-FIXES: fun(std::to_wstring(c));
+  fun(boost::lexical_cast<std::wstring>(d));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring
+  // CHECK-FIXES: fun(std::to_wstring(d));
+  fun(boost::lexical_cast<std::wstring>(e));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring
+  // CHECK-FIXES: fun(std::to_wstring(e));
+  fun(boost::lexical_cast<std::wstring>(f));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring
+  // CHECK-FIXES: fun(std::to_wstring(f));
+
+  // No change for floating numbers
+  fun(boost::lexical_cast<std::wstring>(g));
+  fun(boost::lexical_cast<std::wstring>(h));
+  fun(boost::lexical_cast<std::wstring>(i));
+  // and bool.
+  fun(boost::lexical_cast<std::wstring>(j));
+}
+
+const auto glob = boost::lexical_cast<std::string>(42);
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use std::to_string
+// CHECK-FIXES: const auto glob = std::to_string(42);
+
+template <typename T>
+void string_as_T(T t = T()) {
+  boost::lexical_cast<std::string>(42);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use std::to_string
+  // CHECK-FIXES: std::to_string(42);
+
+  boost::lexical_cast<T>(42);
+  string_as_T(boost::lexical_cast<T>(42));
+  auto p = boost::lexical_cast<T>(42);
+  auto p2 = (T)boost::lexical_cast<T>(42);
+  auto p3 = static_cast<T>(boost::lexical_cast<T>(42));
+}
+
+#define my_to_string boost::lexical_cast<std::string>
+
+void no_fixup_inside_macro() {
+  my_to_string(12);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use std::to_string
+}
+
+void no_warnings() {
+  fun(boost::lexical_cast<std::string>("abc"));
+  fun(boost::lexical_cast<std::wstring>("abc"));
+  fun(boost::lexical_cast<std::string>(my_weird_type{}));
+  string_as_T<int>();
+  string_as_T<std::string>();
+}
+
+struct Fields {
+  int integer;
+  float floating;
+  Fields* wierd;
+  const int &getConstInteger() const {return integer;}
+};
+
+void testFields() {
+  Fields fields;
+  auto s1 = boost::lexical_cast<std::string>(fields.integer);
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::to_string
+  // CHECK-FIXES: auto s1 = std::to_string(fields.integer);
+
+  auto s2 = boost::lexical_cast<std::string>(fields.floating);
+  auto s3 = boost::lexical_cast<std::string>(fields.wierd);
+  auto s4 = boost::lexical_cast<std::string>(fields.getConstInteger());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::to_string
+  // CHECK-FIXES: auto s4 = std::to_string(fields.getConstInteger());
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment-gmock.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment-gmock.cpp
new file mode 100644
index 0000000..e79395e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment-gmock.cpp
@@ -0,0 +1,108 @@
+// RUN: %check_clang_tidy %s bugprone-argument-comment %t
+
+namespace testing {
+namespace internal {
+
+template <typename F>
+struct Function;
+
+template <typename R>
+struct Function<R()> {
+  typedef R Result;
+};
+
+template <typename R, typename A1>
+struct Function<R(A1)>
+    : Function<R()> {
+  typedef A1 Argument1;
+};
+
+template <typename R, typename A1, typename A2>
+struct Function<R(A1, A2)>
+    : Function<R(A1)> {
+  typedef A2 Argument2;
+};
+
+} // namespace internal
+
+template <typename F>
+class MockSpec {
+ public:
+  void f();
+};
+
+template <typename T>
+class Matcher {
+ public:
+  explicit Matcher();
+  Matcher(T value);
+};
+
+} // namespace testing
+
+#define GMOCK_RESULT_(tn, ...) \
+    tn ::testing::internal::Function<__VA_ARGS__>::Result
+#define GMOCK_ARG_(tn, N, ...) \
+    tn ::testing::internal::Function<__VA_ARGS__>::Argument##N
+#define GMOCK_MATCHER_(tn, N, ...) \
+    const ::testing::Matcher<GMOCK_ARG_(tn, N, __VA_ARGS__)>&
+#define GMOCK_METHOD2_(tn, constness, ct, Method, ...)            \
+  GMOCK_RESULT_(tn, __VA_ARGS__)                                  \
+  ct Method(                                                      \
+      GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1,                    \
+      GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2) constness;         \
+  ::testing::MockSpec<__VA_ARGS__>                                \
+      gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
+                     GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2) constness
+#define MOCK_METHOD2(m, ...) GMOCK_METHOD2_(, , , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD2(m, ...) GMOCK_METHOD2_(, const, , m, __VA_ARGS__)
+#define GMOCK_EXPECT_CALL_IMPL_(obj, call) \
+    ((obj).gmock_##call).f()
+#define EXPECT_CALL(obj, call) GMOCK_EXPECT_CALL_IMPL_(obj, call)
+
+class Base {
+ public:
+  virtual void Method(int param_one_base, int param_two_base);
+};
+class Derived : public Base {
+ public:
+  virtual void Method(int param_one, int param_two);
+  virtual void Method2(int p_one, int p_two) const;
+};
+class MockDerived : public Derived {
+ public:
+  MOCK_METHOD2(Method, void(int a, int b));
+  MOCK_CONST_METHOD2(Method2, void(int c, int d));
+};
+
+class MockStandalone {
+ public:
+  MOCK_METHOD2(Method, void(int aaa, int bbb));
+};
+
+void test_gmock_expectations() {
+  MockDerived m;
+  EXPECT_CALL(m, Method(/*param_one=*/1, /*param_tw=*/2));
+// CHECK-MESSAGES: [[@LINE-1]]:42: warning: argument name 'param_tw' in comment does not match parameter name 'param_two'
+// CHECK-FIXES:   EXPECT_CALL(m, Method(/*param_one=*/1, /*param_two=*/2));
+  EXPECT_CALL(m, Method2(/*p_on=*/3, /*p_two=*/4));
+// CHECK-MESSAGES: [[@LINE-1]]:26: warning: argument name 'p_on' in comment does not match parameter name 'p_one'
+// CHECK-FIXES:   EXPECT_CALL(m, Method2(/*p_one=*/3, /*p_two=*/4));
+
+  #define PARAM1 11
+  #define PARAM2 22
+  EXPECT_CALL(m, Method2(/*p_on1=*/PARAM1, /*p_tw2=*/PARAM2));
+// CHECK-MESSAGES: [[@LINE-1]]:26: warning: argument name 'p_on1' in comment does not match parameter name 'p_one'
+// CHECK-MESSAGES: [[@LINE-2]]:44: warning: argument name 'p_tw2' in comment does not match parameter name 'p_two'
+// CHECK-FIXES:   EXPECT_CALL(m, Method2(/*p_one=*/PARAM1, /*p_two=*/PARAM2));
+
+  MockStandalone m2;
+  EXPECT_CALL(m2, Method(/*aaa=*/5, /*bbc=*/6));
+}
+
+void test_gmock_direct_calls() {
+  MockDerived m;
+  m.Method(/*param_one=*/1, /*param_tw=*/2);
+// CHECK-MESSAGES: [[@LINE-1]]:29: warning: argument name 'param_tw' in comment does not match parameter name 'param_two'
+// CHECK-FIXES:   m.Method(/*param_one=*/1, /*param_two=*/2);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment-strict.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment-strict.cpp
new file mode 100644
index 0000000..0e06a4c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment-strict.cpp
@@ -0,0 +1,19 @@
+// RUN: %check_clang_tidy %s bugprone-argument-comment %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: 1}]}" --
+
+void f(int _with_underscores_);
+void g(int x_);
+void ignores_underscores() {
+  f(/*With_Underscores=*/0);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: argument name 'With_Underscores' in comment does not match parameter name '_with_underscores_'
+// CHECK-FIXES: f(/*_with_underscores_=*/0);
+  f(/*with_underscores=*/1);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: argument name 'with_underscores' in comment does not match parameter name '_with_underscores_'
+// CHECK-FIXES: f(/*_with_underscores_=*/1);
+  f(/*_With_Underscores_=*/2);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: argument name '_With_Underscores_' in comment does not match parameter name '_with_underscores_'
+// CHECK-FIXES: f(/*_with_underscores_=*/2);
+  g(/*X=*/3);
+// CHECK-MESSAGES: [[@LINE-1]]:5: warning: argument name 'X' in comment does not match parameter name 'x_'
+// CHECK-FIXES: g(/*x_=*/3);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment.cpp
new file mode 100644
index 0000000..6452791
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-argument-comment.cpp
@@ -0,0 +1,89 @@
+// RUN: %check_clang_tidy %s bugprone-argument-comment %t
+
+// FIXME: clang-tidy should provide a -verify mode to make writing these checks
+// easier and more accurate.
+
+void ffff(int xxxx, int yyyy);
+
+void f(int x, int y);
+void g() {
+  // CHECK-MESSAGES: [[@LINE+4]]:5: warning: argument name 'y' in comment does not match parameter name 'x'
+  // CHECK-MESSAGES: :[[@LINE-3]]:12: note: 'x' declared here
+  // CHECK-MESSAGES: [[@LINE+2]]:14: warning: argument name 'z' in comment does not match parameter name 'y'
+  // CHECK-MESSAGES: :[[@LINE-5]]:19: note: 'y' declared here
+  f(/*y=*/0, /*z=*/0);
+  // CHECK-FIXES: {{^}}  f(/*y=*/0, /*z=*/0);
+
+  f(/*x=*/1, /*y=*/1);
+
+  ffff(0 /*aaaa=*/, /*bbbb*/ 0); // Unsupported formats.
+}
+
+struct C {
+  C(int x, int y);
+};
+C c(/*x=*/0, /*y=*/0);
+
+struct Closure {};
+
+template <typename T1, typename T2>
+Closure *NewCallback(void (*f)(T1, T2), T1 arg1, T2 arg2) { return nullptr; }
+
+template <typename T1, typename T2>
+Closure *NewPermanentCallback(void (*f)(T1, T2), T1 arg1, T2 arg2) { return nullptr; }
+
+void h() {
+  (void)NewCallback(&ffff, /*xxxx=*/11, /*yyyy=*/22);
+  (void)NewPermanentCallback(&ffff, /*xxxx=*/11, /*yyyy=*/22);
+}
+
+template<typename... Args>
+void variadic(Args&&... args);
+
+template<typename... Args>
+void variadic2(int zzz, Args&&... args);
+
+void templates() {
+  variadic(/*xxx=*/0, /*yyy=*/1);
+  variadic2(/*zzU=*/0, /*xxx=*/1, /*yyy=*/2);
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: argument name 'zzU' in comment does not match parameter name 'zzz'
+  // CHECK-FIXES: variadic2(/*zzz=*/0, /*xxx=*/1, /*yyy=*/2);
+}
+
+#define FALSE 0
+void qqq(bool aaa);
+void f2() { qqq(/*bbb=*/FALSE); }
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: argument name 'bbb' in comment does not match parameter name 'aaa'
+// CHECK-FIXES: void f2() { qqq(/*bbb=*/FALSE); }
+
+void f3(bool _with_underscores_);
+void ignores_underscores() {
+  f3(/*With_Underscores=*/false);
+}
+
+namespace ThisEditDistanceAboveThreshold {
+void f4(int xxx);
+void g() { f4(/*xyz=*/0); }
+// CHECK-MESSAGES: [[@LINE-1]]:15: warning: argument name 'xyz' in comment does not match parameter name 'xxx'
+// CHECK-FIXES: void g() { f4(/*xyz=*/0); }
+}
+
+namespace OtherEditDistanceAboveThreshold {
+void f5(int xxx, int yyy);
+void g() { f5(/*Zxx=*/0, 0); }
+// CHECK-MESSAGES: [[@LINE-1]]:15: warning: argument name 'Zxx' in comment does not match parameter name 'xxx'
+// CHECK-FIXES: void g() { f5(/*xxx=*/0, 0); }
+struct C2 {
+  C2(int xxx, int yyy);
+};
+C2 c2(/*Zxx=*/0, 0);
+// CHECK-MESSAGES: [[@LINE-1]]:7: warning: argument name 'Zxx' in comment does not match parameter name 'xxx'
+// CHECK-FIXES: C2 c2(/*xxx=*/0, 0);
+}
+
+namespace OtherEditDistanceBelowThreshold {
+void f6(int xxx, int yyy);
+void g() { f6(/*xxy=*/0, 0); }
+// CHECK-MESSAGES: [[@LINE-1]]:15: warning: argument name 'xxy' in comment does not match parameter name 'xxx'
+// CHECK-FIXES: void g() { f6(/*xxy=*/0, 0); }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-assert-side-effect.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-assert-side-effect.cpp
new file mode 100644
index 0000000..0933402
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-assert-side-effect.cpp
@@ -0,0 +1,114 @@
+// RUN: %check_clang_tidy %s bugprone-assert-side-effect %t -- -config="{CheckOptions: [{key: bugprone-assert-side-effect.CheckFunctionCalls, value: 1}, {key: bugprone-assert-side-effect.AssertMacros, value: 'assert,assert2,my_assert,convoluted_assert,msvc_assert'}]}" -- -fexceptions
+
+//===--- assert definition block ------------------------------------------===//
+int abort() { return 0; }
+
+#ifdef NDEBUG
+#define assert(x) 1
+#else
+#define assert(x)                                                              \
+  if (!(x))                                                                    \
+  (void)abort()
+#endif
+
+void print(...);
+#define assert2(e) (__builtin_expect(!(e), 0) ?                                \
+                       print (#e, __FILE__, __LINE__) : (void)0)
+
+#ifdef NDEBUG
+#define my_assert(x) 1
+#else
+#define my_assert(x)                                                           \
+  ((void)((x) ? 1 : abort()))
+#endif
+
+#ifdef NDEBUG
+#define not_my_assert(x) 1
+#else
+#define not_my_assert(x)                                                       \
+  if (!(x))                                                                    \
+  (void)abort()
+#endif
+
+#define real_assert(x) ((void)((x) ? 1 : abort()))
+#define wrap1(x) real_assert(x)
+#define wrap2(x) wrap1(x)
+#define convoluted_assert(x) wrap2(x)
+
+#define msvc_assert(expression) (void)(                                        \
+            (!!(expression)) ||                                                \
+            (abort(), 0)                                                       \
+        )
+
+
+//===----------------------------------------------------------------------===//
+
+class MyClass {
+public:
+  bool badFunc(int a, int b) { return a * b > 0; }
+  bool goodFunc(int a, int b) const { return a * b > 0; }
+
+  MyClass &operator=(const MyClass &rhs) { return *this; }
+
+  int operator-() { return 1; }
+
+  operator bool() const { return true; }
+
+  void operator delete(void *p) {}
+};
+
+bool freeFunction() {
+  return true;
+}
+
+int main() {
+
+  int X = 0;
+  bool B = false;
+  assert(X == 1);
+
+  assert(X = 1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect [bugprone-assert-side-effect]
+  my_assert(X = 1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found my_assert() with side effect
+  convoluted_assert(X = 1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found convoluted_assert() with side effect
+  not_my_assert(X = 1);
+
+  assert(++X);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect
+  assert(!B);
+
+  assert(B || true);
+
+  assert(freeFunction());
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect
+
+  MyClass mc;
+  assert(mc.badFunc(0, 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect
+  assert(mc.goodFunc(0, 1));
+
+  MyClass mc2;
+  assert(mc2 = mc);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect
+
+  assert(-mc > 0);
+
+  MyClass *mcp;
+  assert(mcp = new MyClass);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect
+
+  assert((delete mcp, false));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect
+
+  assert((throw 1, false));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() with side effect
+
+  assert2(1 == 2 - 1);
+
+  msvc_assert(mc2 = mc);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found msvc_assert() with side effect
+
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-bool-pointer-implicit-conversion.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-bool-pointer-implicit-conversion.cpp
new file mode 100644
index 0000000..37c6939
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-bool-pointer-implicit-conversion.cpp
@@ -0,0 +1,82 @@
+// RUN: %check_clang_tidy %s bugprone-bool-pointer-implicit-conversion %t
+
+bool *SomeFunction();
+void SomeOtherFunction(bool*);
+bool F();
+void G(bool);
+
+
+template <typename T>
+void t(T b) {
+  if (b) {
+  }
+}
+
+void foo() {
+  bool *b = SomeFunction();
+  if (b) {
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: dubious check of 'bool *' against 'nullptr'
+// CHECK-FIXES: if (*b) {
+  }
+
+  if (F() && b) {
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: dubious check of 'bool *' against 'nullptr'
+// CHECK-FIXES: if (F() && *b) {
+  }
+
+  // TODO: warn here.
+  if (b) {
+    G(b);
+  }
+
+#define TESTMACRO if (b || F())
+
+  TESTMACRO {
+  }
+
+  t(b);
+
+  if (!b) {
+    // no-warning
+  }
+
+  if (SomeFunction()) {
+    // no-warning
+  }
+
+  bool *c = SomeFunction();
+  if (c) {
+    (void)c;
+    (void)*c; // no-warning
+  }
+
+  if (c) {
+    *c = true; // no-warning
+  }
+
+  if (c) {
+    c[0] = false; // no-warning
+  }
+
+  if (c) {
+    SomeOtherFunction(c); // no-warning
+  }
+
+  if (c) {
+    delete[] c; // no-warning
+  }
+
+  if (c) {
+    *(c) = false; // no-warning
+  }
+
+  struct {
+    bool *b;
+  } d = { SomeFunction() };
+
+  if (d.b)
+    (void)*d.b; // no-warning
+
+#define CHECK(b) if (b) {}
+  CHECK(c)
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-copy-constructor-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-copy-constructor-init.cpp
new file mode 100644
index 0000000..981d0b5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-copy-constructor-init.cpp
@@ -0,0 +1,188 @@
+// RUN: %check_clang_tidy %s bugprone-copy-constructor-init %t
+
+class NonCopyable {
+public:
+  NonCopyable() = default;
+  NonCopyable(const NonCopyable &) = delete;
+
+private:
+  int a;
+};
+
+class NonCopyable2 {
+public:
+  NonCopyable2() = default;
+
+private:
+  NonCopyable2(const NonCopyable2 &);
+  int a;
+};
+
+class Copyable {
+public:
+  Copyable() = default;
+  Copyable(const Copyable &) = default;
+
+private:
+  int a;
+};
+
+class Copyable2 {
+public:
+  Copyable2() = default;
+  Copyable2(const Copyable2 &) = default;
+
+private:
+  int a;
+};
+
+class Copyable3 : public Copyable {
+public:
+  Copyable3() = default;
+  Copyable3(const Copyable3 &) = default;
+};
+
+template <class C>
+class Copyable4 {
+public:
+  Copyable4() = default;
+  Copyable4(const Copyable4 &) = default;
+
+private:
+  int a;
+};
+
+template <class T, class S>
+class Copyable5 {
+public:
+  Copyable5() = default;
+  Copyable5(const Copyable5 &) = default;
+
+private:
+  int a;
+};
+
+class EmptyCopyable {
+public:
+  EmptyCopyable() = default;
+  EmptyCopyable(const EmptyCopyable &) = default;
+};
+
+template <typename T>
+using CopyableAlias = Copyable5<T, int>;
+
+typedef Copyable5<int, int> CopyableAlias2;
+
+class X : public Copyable, public EmptyCopyable {
+  X(const X &other) : Copyable(other) {}
+};
+
+class X2 : public Copyable2 {
+  X2(const X2 &other) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor other than the copy constructor [bugprone-copy-constructor-init]
+  // CHECK-FIXES: X2(const X2 &other)  : Copyable2(other) {}
+};
+
+class X2_A : public Copyable2 {
+  X2_A(const X2_A &) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+  // CHECK-FIXES: X2_A(const X2_A &) {}
+};
+
+class X3 : public Copyable, public Copyable2 {
+  X3(const X3 &other) : Copyable(other) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+  // CHECK-FIXES: X3(const X3 &other) : Copyable(other) {}
+};
+
+class X4 : public Copyable {
+  X4(const X4 &other) : Copyable() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+  // CHECK-FIXES: X4(const X4 &other) : Copyable(other) {}
+};
+
+class X5 : public Copyable3 {
+  X5(const X5 &other) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+  // CHECK-FIXES: X5(const X5 &other)  : Copyable3(other) {}
+};
+
+class X6 : public Copyable2, public Copyable3 {
+  X6(const X6 &other) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+  // CHECK-FIXES: X6(const X6 &other)  : Copyable2(other), Copyable3(other) {}
+};
+
+class X7 : public Copyable, public Copyable2 {
+  X7(const X7 &other) : Copyable() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+  // CHECK-FIXES: X7(const X7 &other) : Copyable(other) {}
+};
+
+class X8 : public Copyable4<int> {
+  X8(const X8 &other) : Copyable4(other) {}
+};
+
+class X9 : public Copyable4<int> {
+  X9(const X9 &other) : Copyable4() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+  // CHECK-FIXES: X9(const X9 &other) : Copyable4(other) {}
+};
+
+class X10 : public Copyable4<int> {
+  X10(const X10 &other) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+  // CHECK-FIXES: X10(const X10 &other)  : Copyable4(other) {}
+};
+
+class X11 : public Copyable5<int, float> {
+  X11(const X11 &other) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+  // CHECK-FIXES: X11(const X11 &other)  : Copyable5(other) {}
+};
+
+class X12 : public CopyableAlias<float> {
+  X12(const X12 &other) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+  // CHECK-FIXES: X12(const X12 &other) {}
+};
+
+template <typename T>
+class X13 : T {
+  X13(const X13 &other) {}
+};
+
+template class X13<EmptyCopyable>;
+template class X13<Copyable>;
+
+#define FROMMACRO                \
+  class X14 : public Copyable2 { \
+    X14(const X14 &other) {}     \
+  };
+
+FROMMACRO
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: calling a base constructor
+
+class X15 : public CopyableAlias2 {
+  X15(const X15 &other) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+  // CHECK-FIXES: X15(const X15 &other) {}
+};
+
+class X16 : public NonCopyable {
+  X16(const X16 &other) {}
+};
+
+class X17 : public NonCopyable2 {
+  X17(const X17 &other) {}
+};
+
+class X18 : private Copyable {
+  X18(const X18 &other) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor
+  // CHECK-FIXES: X18(const X18 &other)  : Copyable(other) {}
+};
+
+class X19 : private Copyable {
+  X19(const X19 &other) : Copyable(other) {}
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-dangling-handle.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-dangling-handle.cpp
new file mode 100644
index 0000000..d11a2f2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-dangling-handle.cpp
@@ -0,0 +1,195 @@
+// RUN: %check_clang_tidy %s bugprone-dangling-handle %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:             [{key: bugprone-dangling-handle.HandleClasses, \
+// RUN:               value: 'std::basic_string_view; ::llvm::StringRef;'}]}" \
+// RUN:   -- -std=c++11
+
+namespace std {
+
+template <typename T>
+class vector {
+ public:
+  using const_iterator = const T*;
+  using iterator = T*;
+  using size_type = int;
+
+  void assign(size_type count, const T& value);
+  iterator insert(const_iterator pos, const T& value);
+  iterator insert(const_iterator pos, T&& value);
+  iterator insert(const_iterator pos, size_type count, const T& value);
+  void push_back(const T&);
+  void push_back(T&&);
+  void resize(size_type count, const T& value);
+};
+
+template <typename, typename>
+class pair {};
+
+template <typename T>
+class set {
+ public:
+  using const_iterator = const T*;
+  using iterator = T*;
+
+  std::pair<iterator, bool> insert(const T& value);
+  std::pair<iterator, bool> insert(T&& value);
+  iterator insert(const_iterator hint, const T& value);
+  iterator insert(const_iterator hint, T&& value);
+};
+
+template <typename Key, typename Value>
+class map {
+ public:
+  using value_type = pair<Key, Value>;
+  value_type& operator[](const Key& key);
+  value_type& operator[](Key&& key);
+};
+
+class basic_string_view;
+
+class basic_string {
+ public:
+  basic_string();
+  basic_string(const char*);
+
+  operator basic_string_view() const noexcept;
+
+  ~basic_string();
+};
+
+typedef basic_string string;
+
+class basic_string_view {
+ public:
+  basic_string_view(const char*);
+};
+
+typedef basic_string_view string_view;
+
+}  // namespace std
+
+namespace llvm {
+
+class StringRef {
+ public:
+  StringRef();
+  StringRef(const char*);
+  StringRef(const std::string&);
+};
+
+}  // namespace llvm
+
+std::string ReturnsAString();
+
+void Positives() {
+  std::string_view view1 = std::string();
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
+
+  std::string_view view_2 = ReturnsAString();
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+
+  view1 = std::string();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+
+  const std::string& str_ref = "";
+  std::string_view view3 = true ? "A" : str_ref;
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+  view3 = true ? "A" : str_ref;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+
+  std::string_view view4(ReturnsAString());
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+}
+
+void OtherTypes() {
+  llvm::StringRef ref = std::string();
+  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: llvm::StringRef outlives its value
+}
+
+const char static_array[] = "A";
+std::string_view ReturnStatements(int i, std::string value_arg,
+                                  const std::string &ref_arg) {
+  const char array[] = "A";
+  const char* ptr = "A";
+  std::string s;
+  static std::string ss;
+  switch (i) {
+    // Bad cases
+    case 0:
+      return array;  // refers to local
+      // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
+    case 1:
+      return s;  // refers to local
+      // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
+    case 2:
+      return std::string();  // refers to temporary
+      // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
+    case 3:
+      return value_arg;  // refers to by-value arg
+      // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
+
+    // Ok cases
+    case 100:
+      return ss;  // refers to static
+    case 101:
+      return static_array;  // refers to static
+    case 102:
+      return ptr;  // pointer is ok
+    case 103:
+      return ref_arg;  // refers to by-ref arg
+  }
+
+  struct S {
+    std::string_view view() { return value; }
+    std::string value;
+  };
+
+  (void)[&]()->std::string_view {
+    // This should not warn. The string is bound by reference.
+    return s;
+  };
+  (void)[=]() -> std::string_view {
+    // This should not warn. The reference is valid as long as the lambda.
+    return s;
+  };
+  (void)[=]() -> std::string_view {
+    // FIXME: This one should warn. We are returning a reference to a local
+    // lambda variable.
+    std::string local;
+    return local;
+  };
+  return "";
+}
+
+void Containers() {
+  std::vector<std::string_view> v;
+  v.assign(3, std::string());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+  v.insert(nullptr, std::string());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+  v.insert(nullptr, 3, std::string());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+  v.push_back(std::string());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+  v.resize(3, std::string());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+
+  std::set<std::string_view> s;
+  s.insert(std::string());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+  s.insert(nullptr, std::string());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+
+  std::map<std::string_view, int> m;
+  m[std::string()];
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
+}
+
+void TakesAStringView(std::string_view);
+
+void Negatives(std::string_view default_arg = ReturnsAString()) {
+  std::string str;
+  std::string_view view = str;
+
+  TakesAStringView(std::string());
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-exception-escape.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-exception-escape.cpp
new file mode 100644
index 0000000..eba14bf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-exception-escape.cpp
@@ -0,0 +1,290 @@
+// RUN: %check_clang_tidy %s bugprone-exception-escape %t -- -extra-arg=-std=c++11 -extra-arg=-fexceptions -config="{CheckOptions: [{key: bugprone-exception-escape.IgnoredExceptions, value: 'ignored1,ignored2'}, {key: bugprone-exception-escape.FunctionsThatShouldNotThrow, value: 'enabled1,enabled2,enabled3'}]}" --
+
+struct throwing_destructor {
+  ~throwing_destructor() {
+    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function '~throwing_destructor' which should not throw exceptions
+    throw 1;
+  }
+};
+
+struct throwing_move_constructor {
+  throwing_move_constructor(throwing_move_constructor&&) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'throwing_move_constructor' which should not throw exceptions
+    throw 1;
+  }
+};
+
+struct throwing_move_assignment {
+  throwing_move_assignment& operator=(throwing_move_assignment&&) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: an exception may be thrown in function 'operator=' which should not throw exceptions
+    throw 1;
+  }
+};
+
+void throwing_noexcept() noexcept {
+    // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_noexcept' which should not throw exceptions
+  throw 1;
+}
+
+void throwing_throw_nothing() throw() {
+    // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_throw_nothing' which should not throw exceptions
+  throw 1;
+}
+
+void throw_and_catch() noexcept {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch' which should not throw exceptions
+  try {
+    throw 1;
+  } catch(int &) {
+  }
+}
+
+void throw_and_catch_some(int n) noexcept {
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_some' which should not throw exceptions
+  try {
+    if (n) throw 1;
+    throw 1.1;
+  } catch(int &) {
+  }
+}
+
+void throw_and_catch_each(int n) noexcept {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_each' which should not throw exceptions
+  try {
+    if (n) throw 1;
+    throw 1.1;
+  } catch(int &) {
+  } catch(double &) {
+  }
+}
+
+void throw_and_catch_all(int n) noexcept {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_all' which should not throw exceptions
+  try {
+    if (n) throw 1;
+    throw 1.1;
+  } catch(...) {
+  }
+}
+
+void throw_and_rethrow() noexcept {
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_rethrow' which should not throw exceptions
+  try {
+    throw 1;
+  } catch(int &) {
+    throw;
+  }
+}
+
+void throw_catch_throw() noexcept {
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_throw' which should not throw exceptions
+  try {
+    throw 1;
+  } catch(int &) {
+    throw 2;
+  }
+}
+
+void throw_catch_rethrow_the_rest(int n) noexcept {
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_rethrow_the_rest' which should not throw exceptions
+  try {
+    if (n) throw 1;
+    throw 1.1;
+  } catch(int &) {
+  } catch(...) {
+    throw;
+  }
+}
+
+class base {};
+class derived: public base {};
+
+void throw_derived_catch_base() noexcept {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base' which should not throw exceptions
+  try {
+    throw derived();
+  } catch(base &) {
+  }
+}
+
+void try_nested_try(int n) noexcept {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_try' which should not throw exceptions
+  try {
+    try {
+      if (n) throw 1;
+      throw 1.1;
+    } catch(int &) {
+    }
+  } catch(double &) {
+  }
+}
+
+void bad_try_nested_try(int n) noexcept {
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_try_nested_try' which should not throw exceptions
+  try {
+    if (n) throw 1;
+    try {
+      throw 1.1;
+    } catch(int &) {
+    }
+  } catch(double &) {
+  }
+}
+
+void try_nested_catch() noexcept {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_catch' which should not throw exceptions
+  try {
+    try {
+      throw 1;
+    } catch(int &) {
+      throw 1.1;
+    }
+  } catch(double &) {
+  }
+}
+
+void catch_nested_try() noexcept {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'catch_nested_try' which should not throw exceptions
+  try {
+    throw 1;
+  } catch(int &) {
+    try {
+      throw 1;
+    } catch(int &) {
+    }
+  }
+}
+
+void bad_catch_nested_try() noexcept {
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_catch_nested_try' which should not throw exceptions
+  try {
+    throw 1;
+  } catch(int &) {
+    try {
+      throw 1.1;
+    } catch(int &) {
+    }
+  } catch(double &) {
+  }
+}
+
+void implicit_int_thrower() {
+  throw 1;
+}
+
+void explicit_int_thrower() throw(int);
+
+void indirect_implicit() noexcept {
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions
+  implicit_int_thrower();
+}
+
+void indirect_explicit() noexcept {
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions
+  explicit_int_thrower();
+}
+
+void indirect_catch() noexcept {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_catch' which should not throw exceptions
+  try {
+    implicit_int_thrower();
+  } catch(int&) {
+  }
+}
+
+template<typename T>
+void dependent_throw() noexcept(sizeof(T)<4) {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'dependent_throw' which should not throw exceptions
+  if (sizeof(T) > 4)
+    throw 1;
+}
+
+void swap(int&, int&) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'swap' which should not throw exceptions
+  throw 1;
+}
+
+namespace std {
+class bad_alloc {};
+}
+
+void alloc() {
+  throw std::bad_alloc();
+}
+
+void allocator() noexcept {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'allocator' which should not throw exceptions
+  alloc();
+}
+
+void enabled1() {
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled1' which should not throw exceptions
+  throw 1;
+}
+
+void enabled2() {
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled2' which should not throw exceptions
+  enabled1();
+}
+
+void enabled3() {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled3' which should not throw exceptions
+  try {
+    enabled1();
+  } catch(...) {
+  }
+}
+
+class ignored1 {};
+class ignored2 {};
+
+void this_does_not_count() noexcept {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count' which should not throw exceptions
+  throw ignored1();
+}
+
+void this_does_not_count_either(int n) noexcept {
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count_either' which should not throw exceptions
+  try {
+    throw 1;
+    if (n) throw ignored2();
+  } catch(int &) {
+  }
+}
+
+void this_counts(int n) noexcept {
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_counts' which should not throw exceptions
+  if (n) throw 1;
+  throw ignored1();
+}
+
+void thrower(int n) {
+  throw n;
+}
+
+int directly_recursive(int n) noexcept {
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'directly_recursive' which should not throw exceptions
+  if (n == 0)
+    thrower(n);
+  return directly_recursive(n);
+}
+
+int indirectly_recursive(int n) noexcept;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'indirectly_recursive' which should not throw exceptions
+
+int recursion_helper(int n) {
+  indirectly_recursive(n);
+}
+
+int indirectly_recursive(int n) noexcept {
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'indirectly_recursive' which should not throw exceptions
+  if (n == 0)
+    thrower(n);
+  return recursion_helper(n);
+}
+
+int main() {
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'main' which should not throw exceptions
+  throw 1;
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-fold-init-type.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-fold-init-type.cpp
new file mode 100644
index 0000000..e7fdf39
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-fold-init-type.cpp
@@ -0,0 +1,158 @@
+// RUN: %check_clang_tidy %s bugprone-fold-init-type %t
+
+namespace std {
+template <class InputIt, class T>
+T accumulate(InputIt first, InputIt last, T init);
+
+template <class InputIt, class T>
+T reduce(InputIt first, InputIt last, T init);
+template <class ExecutionPolicy, class InputIt, class T>
+T reduce(ExecutionPolicy &&policy,
+         InputIt first, InputIt last, T init);
+
+struct parallel_execution_policy {};
+constexpr parallel_execution_policy par{};
+
+template <class InputIt1, class InputIt2, class T>
+T inner_product(InputIt1 first1, InputIt1 last1,
+                InputIt2 first2, T value);
+
+template <class ExecutionPolicy, class InputIt1, class InputIt2, class T>
+T inner_product(ExecutionPolicy &&policy, InputIt1 first1, InputIt1 last1,
+                InputIt2 first2, T value);
+
+} // namespace std
+
+struct FloatIterator {
+  typedef float value_type;
+};
+template <typename ValueType>
+struct TypedefTemplateIterator { typedef ValueType value_type; };
+template <typename ValueType>
+struct UsingTemplateIterator { using value_type = ValueType; };
+template <typename ValueType>
+struct DependentTypedefTemplateIterator { typedef typename ValueType::value_type value_type; };
+template <typename ValueType>
+struct DependentUsingTemplateIterator : public TypedefTemplateIterator<ValueType> { using typename TypedefTemplateIterator<ValueType>::value_type; };
+using TypedeffedIterator = FloatIterator;
+
+// Positives.
+
+int accumulatePositive1() {
+  float a[1] = {0.5f};
+  return std::accumulate(a, a + 1, 0);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
+}
+
+int accumulatePositive2() {
+  FloatIterator it;
+  return std::accumulate(it, it, 0);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
+}
+
+int accumulatePositive3() {
+  double a[1] = {0.0};
+  return std::accumulate(a, a + 1, 0.0f);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'double' into type 'float'
+}
+
+int accumulatePositive4() {
+  TypedefTemplateIterator<unsigned> it;
+  return std::accumulate(it, it, 0);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int'
+}
+
+int accumulatePositive5() {
+  UsingTemplateIterator<unsigned> it;
+  return std::accumulate(it, it, 0);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int'
+}
+
+int accumulatePositive6() {
+  DependentTypedefTemplateIterator<UsingTemplateIterator<unsigned>> it;
+  return std::accumulate(it, it, 0);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int'
+}
+
+int accumulatePositive7() {
+  TypedeffedIterator it;
+  return std::accumulate(it, it, 0);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
+}
+
+int accumulatePositive8() {
+  DependentUsingTemplateIterator<unsigned> it;
+  return std::accumulate(it, it, 0);
+  // FIXME: this one should trigger too.
+}
+
+int reducePositive1() {
+  float a[1] = {0.5f};
+  return std::reduce(a, a + 1, 0);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
+}
+
+int reducePositive2() {
+  float a[1] = {0.5f};
+  return std::reduce(std::par, a, a + 1, 0);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
+}
+
+int innerProductPositive1() {
+  float a[1] = {0.5f};
+  int b[1] = {1};
+  return std::inner_product(std::par, a, a + 1, b, 0);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
+}
+
+int innerProductPositive2() {
+  float a[1] = {0.5f};
+  int b[1] = {1};
+  return std::inner_product(std::par, a, a + 1, b, 0);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
+}
+
+// Negatives.
+
+int negative1() {
+  float a[1] = {0.5f};
+  // This is OK because types match.
+  return std::accumulate(a, a + 1, 0.0);
+}
+
+int negative2() {
+  float a[1] = {0.5f};
+  // This is OK because double is bigger than float.
+  return std::accumulate(a, a + 1, 0.0);
+}
+
+int negative3() {
+  float a[1] = {0.5f};
+  // This is OK because the user explicitly specified T.
+  return std::accumulate<float *, float>(a, a + 1, 0);
+}
+
+int negative4() {
+  TypedefTemplateIterator<unsigned> it;
+  // For now this is OK.
+  return std::accumulate(it, it, 0.0);
+}
+
+int negative5() {
+  float a[1] = {0.5f};
+  float b[1] = {1.0f};
+  return std::inner_product(std::par, a, a + 1, b, 0.0f);
+}
+
+namespace blah {
+namespace std {
+template <class InputIt, class T>
+T accumulate(InputIt, InputIt, T); // We should not care about this one.
+}
+
+int negative5() {
+  float a[1] = {0.5f};
+  // Note that this is using blah::std::accumulate.
+  return std::accumulate(a, a + 1, 0);
+}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-forward-declaration-namespace.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-forward-declaration-namespace.cpp
new file mode 100644
index 0000000..d938148
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-forward-declaration-namespace.cpp
@@ -0,0 +1,163 @@
+// RUN: %check_clang_tidy %s bugprone-forward-declaration-namespace %t
+
+namespace {
+// This is a declaration in a wrong namespace.
+class T_A;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'T_A' is never referenced, but a declaration with the same name found in another namespace 'na' [bugprone-forward-declaration-namespace]
+// CHECK-MESSAGES: note: a declaration of 'T_A' is found here
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: no definition found for 'T_A', but a definition with the same name 'T_A' found in another namespace '(global)' [bugprone-forward-declaration-namespace]
+// CHECK-MESSAGES: note: a definition of 'T_A' is found here
+}
+
+namespace na {
+// This is a declaration in a wrong namespace.
+class T_A;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'T_A' is never referenced, but a declaration with the same name found in another namespace '(anonymous)'
+// CHECK-MESSAGES: note: a declaration of 'T_A' is found here
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: no definition found for 'T_A', but a definition with the same name 'T_A' found in another namespace '(global)'
+// CHECK-MESSAGES: note: a definition of 'T_A' is found here
+}
+
+class T_A;
+
+class T_A {
+  int x;
+};
+
+class NESTED;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: no definition found for 'NESTED', but a definition with the same name 'NESTED' found in another namespace '(anonymous namespace)::nq::(anonymous)'
+// CHECK-MESSAGES: note: a definition of 'NESTED' is found here
+
+namespace {
+namespace nq {
+namespace {
+class NESTED {};
+}
+}
+}
+
+namespace na {
+class T_B;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'T_B' is never referenced, but a declaration with the same name found in another namespace 'nb'
+// CHECK-MESSAGES: note: a declaration of 'T_B' is found here
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: no definition found for 'T_B', but a definition with the same name 'T_B' found in another namespace 'nb'
+// CHECK-MESSAGES: note: a definition of 'T_B' is found here
+}
+
+namespace nb {
+class T_B;
+}
+
+namespace nb {
+class T_B {
+  int x;
+};
+}
+
+namespace na {
+class T_B;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'T_B' is never referenced, but a declaration with the same name found in another namespace 'nb'
+// CHECK-MESSAGES: note: a declaration of 'T_B' is found here
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: no definition found for 'T_B', but a definition with the same name 'T_B' found in another namespace 'nb'
+// CHECK-MESSAGES: note: a definition of 'T_B' is found here
+}
+
+// A simple forward declaration. Although it is never used, but no declaration
+// with the same name is found in other namespace.
+class OUTSIDER;
+
+namespace na {
+// This class is referenced declaration, we don't generate warning.
+class OUTSIDER_1;
+}
+
+void f(na::OUTSIDER_1);
+
+namespace nc {
+// This class is referenced as friend in OOP.
+class OUTSIDER_1;
+
+class OOP {
+  friend struct OUTSIDER_1;
+};
+}
+
+namespace nd {
+class OUTSIDER_1;
+void f(OUTSIDER_1 *);
+}
+
+namespace nb {
+class OUTSIDER_1;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'OUTSIDER_1' is never referenced, but a declaration with the same name found in another namespace 'na'
+// CHECK-MESSAGES: note: a declaration of 'OUTSIDER_1' is found here
+}
+
+
+namespace na {
+template<typename T>
+class T_C;
+}
+
+namespace nb {
+// FIXME: this is an error, but we don't consider template class declaration
+// now.
+template<typename T>
+class T_C;
+}
+
+namespace na {
+template<typename T>
+class T_C {
+  int x;
+};
+}
+
+namespace na {
+
+template <typename T>
+class T_TEMP {
+  template <typename _Tp1>
+  struct rebind { typedef T_TEMP<_Tp1> other; };
+};
+
+// We ignore class template specialization.
+template class T_TEMP<char>;
+}
+
+namespace nb {
+
+template <typename T>
+class T_TEMP_1 {
+  template <typename _Tp1>
+  struct rebind { typedef T_TEMP_1<_Tp1> other; };
+};
+
+// We ignore class template specialization.
+extern template class T_TEMP_1<char>;
+}
+
+namespace nd {
+class D;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'D' is never referenced, but a declaration with the same name found in another namespace 'nd::ne'
+// CHECK-MESSAGES: note: a declaration of 'D' is found here
+}
+
+namespace nd {
+namespace ne {
+class D;
+}
+}
+
+int f(nd::ne::D &d);
+
+
+// This should be ignored by the check.
+template <typename... Args>
+class Observer {
+  class Impl;
+};
+
+template <typename... Args>
+class Observer<Args...>::Impl {
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-forwarding-reference-overload.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-forwarding-reference-overload.cpp
new file mode 100644
index 0000000..3510685
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-forwarding-reference-overload.cpp
@@ -0,0 +1,145 @@
+// RUN: %check_clang_tidy %s bugprone-forwarding-reference-overload %t -- -- -std=c++14
+
+namespace std {
+template <bool B, class T = void> struct enable_if { typedef T type; };
+
+template <class T> struct enable_if<true, T> { typedef T type; };
+
+template <bool B, class T = void>
+using enable_if_t = typename enable_if<B, T>::type;
+
+template <class T> struct enable_if_nice { typedef T type; };
+} // namespace std
+
+namespace foo {
+template <class T> struct enable_if { typedef T type; };
+} // namespace foo
+
+template <typename T> constexpr bool just_true = true;
+
+class Test1 {
+public:
+  template <typename T> Test1(T &&n);
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: constructor accepting a forwarding reference can hide the copy and move constructors [bugprone-forwarding-reference-overload]
+
+  template <typename T> Test1(T &&n, int i = 5, ...);
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: constructor accepting a forwarding reference can hide the copy and move constructors
+
+  template <typename T, typename U = typename std::enable_if_nice<T>::type>
+  Test1(T &&n);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor accepting a forwarding reference can hide the copy and move constructors
+
+  template <typename T>
+  Test1(T &&n, typename foo::enable_if<long>::type i = 5, ...);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor accepting a forwarding reference can hide the copy and move constructors
+
+  Test1(const Test1 &other) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: note: copy constructor declared here
+
+  Test1(Test1 &other) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: note: copy constructor declared here
+
+  Test1(Test1 &&other) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: note: move constructor declared here
+};
+
+template <typename U> class Test2 {
+public:
+  // Two parameters without default value, can't act as copy / move constructor.
+  template <typename T, class V> Test2(T &&n, V &&m, int i = 5, ...);
+
+  // Guarded with enable_if.
+  template <typename T>
+  Test2(T &&n, int i = 5,
+        std::enable_if_t<sizeof(int) < sizeof(long), int> a = 5, ...);
+
+  // Guarded with enable_if.
+  template <typename T, typename X = typename std::enable_if<
+                            sizeof(int) < sizeof(long), double>::type &>
+  Test2(T &&n);
+
+  // Guarded with enable_if.
+  template <typename T>
+  Test2(T &&n, typename std::enable_if<just_true<T>>::type **a = nullptr);
+
+  // Guarded with enable_if.
+  template <typename T, typename X = std::enable_if_t<just_true<T>> *&&>
+  Test2(T &&n, double d = 0.0);
+
+  // Not a forwarding reference parameter.
+  template <typename T> Test2(const T &&n);
+
+  // Not a forwarding reference parameter.
+  Test2(int &&x);
+
+  // Two parameters without default value, can't act as copy / move constructor.
+  template <typename T> Test2(T &&n, int x);
+
+  // Not a forwarding reference parameter.
+  template <typename T> Test2(U &&n);
+};
+
+// The copy and move constructors are both disabled.
+class Test3 {
+public:
+  template <typename T> Test3(T &&n);
+
+  template <typename T> Test3(T &&n, int I = 5, ...);
+
+  Test3(const Test3 &rhs) = delete;
+
+private:
+  Test3(Test3 &&rhs);
+};
+
+// Both the copy and the (compiler generated) move constructors can be hidden.
+class Test4 {
+public:
+  template <typename T> Test4(T &&n);
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: constructor accepting a forwarding reference can hide the copy and move constructors
+
+  Test4(const Test4 &rhs);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: note: copy constructor declared here
+};
+
+// Nothing can be hidden, the copy constructor is implicitly deleted.
+class Test5 {
+public:
+  template <typename T> Test5(T &&n);
+
+  Test5(Test5 &&rhs) = delete;
+};
+
+// Only the move constructor can be hidden.
+class Test6 {
+public:
+  template <typename T> Test6(T &&n);
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: constructor accepting a forwarding reference can hide the move constructor
+
+  Test6(Test6 &&rhs);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: note: move constructor declared here
+private:
+  Test6(const Test6 &rhs);
+};
+
+// Do not dereference a null BaseType.
+template <class _Callable> class result_of;
+template <class _Fp, class ..._Args> class result_of<_Fp(_Args...)> { };
+template <class _Tp> using result_of_t = typename result_of<_Tp>::type;
+
+template <class... _Types> struct __overload;
+template <class _Tp, class... _Types>
+struct __overload<_Tp, _Types...> : __overload<_Types...> {
+  using __overload<_Types...>::operator();
+};
+
+template <class _Tp, class... _Types>
+using __best_match_t = typename result_of_t<__overload<_Types...>(_Tp&&)>::type;
+
+template <class... _Types>
+class variant {
+public:
+  template <class _Arg, class _Tp = __best_match_t<_Arg, _Types...> >
+  constexpr variant(_Arg&& __arg) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: constructor accepting a forwarding reference can hide the copy and move constructors
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-inaccurate-erase.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-inaccurate-erase.cpp
new file mode 100644
index 0000000..d29fa9c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-inaccurate-erase.cpp
@@ -0,0 +1,100 @@
+// RUN: %check_clang_tidy %s bugprone-inaccurate-erase %t
+
+namespace std {
+template <typename T> struct vec_iterator {
+  T ptr;
+  vec_iterator operator++(int);
+
+  template <typename X>
+  vec_iterator(const vec_iterator<X> &); // Omit enable_if<...>.
+};
+
+template <typename T> struct vector {
+  typedef vec_iterator<T*> iterator;
+
+  iterator begin();
+  iterator end();
+
+  void erase(iterator);
+  void erase(iterator, iterator);
+};
+
+template <typename T> struct vector_with_const_iterator {
+  typedef vec_iterator<T*> iterator;
+  typedef vec_iterator<const T*> const_iterator;
+
+  iterator begin();
+  iterator end();
+
+  void erase(const_iterator);
+  void erase(const_iterator, const_iterator);
+};
+
+template <typename FwIt, typename T>
+FwIt remove(FwIt begin, FwIt end, const T &val);
+
+template <typename FwIt, typename Func>
+FwIt remove_if(FwIt begin, FwIt end, Func f);
+
+template <typename FwIt> FwIt unique(FwIt begin, FwIt end);
+
+template <typename T> struct unique_ptr {};
+} // namespace std
+
+struct custom_iter {};
+struct custom_container {
+  void erase(...);
+  custom_iter begin();
+  custom_iter end();
+};
+
+template <typename T> void g() {
+  T t;
+  t.erase(std::remove(t.begin(), t.end(), 10));
+  // CHECK-FIXES: {{^  }}t.erase(std::remove(t.begin(), t.end(), 10));{{$}}
+
+  std::vector<int> v;
+  v.erase(remove(v.begin(), v.end(), 10));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one
+  // CHECK-FIXES: {{^  }}v.erase(remove(v.begin(), v.end(), 10), v.end());{{$}}
+}
+
+#define ERASE(x, y) x.erase(remove(x.begin(), x.end(), y))
+// CHECK-FIXES: #define ERASE(x, y) x.erase(remove(x.begin(), x.end(), y))
+
+int main() {
+  std::vector<int> v;
+
+  v.erase(remove(v.begin(), v.end(), 10));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one item even when multiple items should be removed [bugprone-inaccurate-erase]
+  // CHECK-FIXES: {{^  }}v.erase(remove(v.begin(), v.end(), 10), v.end());{{$}}
+  v.erase(remove(v.begin(), v.end(), 20), v.end());
+
+  auto *p = &v;
+  p->erase(remove(p->begin(), p->end(), 11));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one
+  // CHECK-FIXES: {{^  }}p->erase(remove(p->begin(), p->end(), 11), p->end());{{$}}
+
+  std::vector_with_const_iterator<int> v2;
+  v2.erase(remove(v2.begin(), v2.end(), 12));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one
+  // CHECK-FIXES: {{^  }}v2.erase(remove(v2.begin(), v2.end(), 12), v2.end());{{$}}
+
+  // Fix is not trivial.
+  auto it = v.end();
+  v.erase(remove(v.begin(), it, 10));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one
+  // CHECK-FIXES: {{^  }}v.erase(remove(v.begin(), it, 10));{{$}}
+
+  g<std::vector<int>>();
+  g<custom_container>();
+
+  ERASE(v, 15);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: this call will remove at most one
+  // CHECK-FIXES: {{^  }}ERASE(v, 15);{{$}}
+
+  std::vector<std::unique_ptr<int>> vupi;
+  auto iter = vupi.begin();
+  vupi.erase(iter++);
+  // CHECK-FIXES: {{^  }}vupi.erase(iter++);{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-incorrect-roundings.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-incorrect-roundings.cpp
new file mode 100644
index 0000000..7ada061
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-incorrect-roundings.cpp
@@ -0,0 +1,86 @@
+// RUN: %check_clang_tidy %s bugprone-incorrect-roundings %t
+
+void b(int x) {}
+
+void f1() {
+  float f;
+  double d;
+  long double ld;
+  int x;
+
+  x = (d + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5) to integer leads to incorrect rounding; consider using lround (#include <cmath>) instead [bugprone-incorrect-roundings]
+  x = (d + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (f + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (f + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (0.5 + d);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (0.5f + d);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (0.5 + ld);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (0.5f + ld);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (0.5 + f);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (0.5f + f);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: casting (double + 0.5)
+  x = (int)(d + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(d + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(ld + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(ld + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(f + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(f + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(0.5 + d);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(0.5f + d);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(0.5 + ld);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(0.5f + ld);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(0.5 + f);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = (int)(0.5f + f);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: casting (double + 0.5)
+  x = static_cast<int>(d + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(d + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(ld + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(ld + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(f + 0.5);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(f + 0.5f);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(0.5 + d);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(0.5f + d);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(0.5 + ld);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(0.5f + ld);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(0.5 + f);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+  x = static_cast<int>(0.5f + f);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: casting (double + 0.5)
+
+  // Don't warn if constant is not 0.5.
+  x = (int)(d + 0.6);
+  x = (int)(0.6 + d);
+
+  // Don't warn if binary operator is not directly beneath cast.
+  x = (int)(1 + (0.5 + f));
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-integer-division.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-integer-division.cpp
new file mode 100644
index 0000000..243ad46
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-integer-division.cpp
@@ -0,0 +1,130 @@
+// RUN: %check_clang_tidy %s bugprone-integer-division %t
+
+// Functions expecting a floating-point parameter.
+void floatArg(float x) {}
+void doubleArg(double x) {}
+void longDoubleArg(long double x) {}
+
+// Functions expected to return a floating-point value.
+float singleDiv() {
+  int x = -5;
+  int y = 2;
+  return x/y;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: result of integer division used in
+}
+
+double wrongOrder(int x, int y) {
+  return x/y/0.1;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: result of integer division used in
+}
+
+long double rightOrder(int x, int y) {
+  return 0.1/x/y; // OK
+}
+
+// Typical mathematical functions.
+float sin(float);
+double acos(double);
+long double tanh(long double);
+
+namespace std {
+  using ::sin;
+}
+
+template <typename T>
+void intDivSin(T x) {
+  sin(x);
+}
+
+int intFunc(int);
+
+struct X {
+  int n;
+  void m() {
+    sin(n / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: result of integer division used in
+  }
+};
+
+void integerDivision() {
+  char a = 2;
+  short b = -5;
+  int c = 9784;
+  enum third { x, y, z=2 };
+  third d = z;
+  char e[] = {'a', 'b', 'c'};
+  char f = *(e + 1 / a);
+  bool g = 1;
+
+  sin(1 + c / (2 + 2));
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: result of integer division used in
+  sin(c / (1 + .5));
+  sin((c + .5) / 3);
+
+  sin(intFunc(3) / 5);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: result of integer division used in
+  acos(2 / intFunc(7));
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: result of integer division used in
+
+  floatArg(1 + 2 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: result of integer division used in
+  sin(1 + 2 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: result of integer division used in
+  intFunc(sin(1 + 2 / 3));
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: result of integer division used in
+
+  floatArg(1 + intFunc(1 + 2 / 3));
+  floatArg(1 + 3 * intFunc(a / b));
+
+  1 << (2 / 3);
+  1 << intFunc(2 / 3);
+
+#define M_SIN sin(a / b);
+  M_SIN
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: result of integer division used in
+
+  intDivSin<float>(a / b);
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: result of integer division used in
+  intDivSin<double>(c / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: result of integer division used in
+  intDivSin<long double>(f / g);
+// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: result of integer division used in
+
+  floatArg(1 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: result of integer division used in
+  doubleArg(a / b);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: result of integer division used in
+  longDoubleArg(3 / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: result of integer division used in
+  floatArg(a / b / 0.1);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: result of integer division used in
+  doubleArg(1 / 3 / 0.1);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: result of integer division used in
+  longDoubleArg(2 / 3 / 5);
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: result of integer division used in
+
+  std::sin(2 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: result of integer division used in
+  ::acos(7 / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: result of integer division used in
+  tanh(f / g);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: result of integer division used in
+
+  floatArg(0.1 / a / b);
+  doubleArg(0.1 / 3 / 1);
+
+  singleDiv();
+  wrongOrder(a,b);
+  rightOrder(a,b);
+
+  sin(a / b);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: result of integer division used in
+  acos(f / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: result of integer division used in
+  tanh(c / g);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: result of integer division used in
+
+  sin(3.0 / a);
+  acos(b / 3.14);
+  tanh(3.14 / f / g);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-lambda-function-name.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-lambda-function-name.cpp
new file mode 100644
index 0000000..145928b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-lambda-function-name.cpp
@@ -0,0 +1,41 @@
+// RUN: %check_clang_tidy %s bugprone-lambda-function-name %t
+
+void Foo(const char* a, const char* b, int c) {}
+
+#define FUNC_MACRO Foo(__func__, "", 0)
+#define FUNCTION_MACRO Foo(__FUNCTION__, "", 0)
+#define EMBED_IN_ANOTHER_MACRO1 FUNC_MACRO
+
+void Positives() {
+  [] { __func__; }();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name]
+  [] { __FUNCTION__; }();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: inside a lambda, '__FUNCTION__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name]
+  [] { FUNC_MACRO; }();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name]
+  [] { FUNCTION_MACRO; }();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: inside a lambda, '__FUNCTION__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name]
+  [] { EMBED_IN_ANOTHER_MACRO1; }();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name]
+}
+
+#define FUNC_MACRO_WITH_FILE_AND_LINE Foo(__func__, __FILE__, __LINE__)
+#define FUNCTION_MACRO_WITH_FILE_AND_LINE Foo(__FUNCTION__, __FILE__, __LINE__)
+#define EMBED_IN_ANOTHER_MACRO2 FUNC_MACRO_WITH_FILE_AND_LINE
+
+void Negatives() {
+  __func__;
+  __FUNCTION__;
+
+  // __PRETTY_FUNCTION__ should not trigger a warning because its value is
+  // actually potentially useful.
+  __PRETTY_FUNCTION__;
+  [] { __PRETTY_FUNCTION__; }();
+
+  // Don't warn if __func__/__FUNCTION is used inside a macro that also uses
+  // __FILE__ and __LINE__, on the assumption that __FILE__ and __LINE__ will
+  // be useful even if __func__/__FUNCTION__ is not.
+  [] { FUNC_MACRO_WITH_FILE_AND_LINE; }();
+  [] { FUNCTION_MACRO_WITH_FILE_AND_LINE; }();
+  [] { EMBED_IN_ANOTHER_MACRO2; }();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-parentheses-cmdline.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-parentheses-cmdline.cpp
new file mode 100644
index 0000000..9ff757d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-parentheses-cmdline.cpp
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s bugprone-macro-parentheses %t -- -- -DVAL=0+0
+
+// The previous command-line is producing warnings and fixes with the source
+// locations from a virtual buffer. VAL is replaced by '0+0'.
+// Fixes could not be applied and should not be reported.
+int foo() { return VAL; }
+
+#define V 0+0
+int bar() { return V; }
+// CHECK-FIXES: #define V (0+0)
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-parentheses.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-parentheses.cpp
new file mode 100644
index 0000000..2cc45e8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-parentheses.cpp
@@ -0,0 +1,49 @@
+// RUN: %check_clang_tidy %s bugprone-macro-parentheses %t
+
+#define BAD1              -1
+// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: macro replacement list should be enclosed in parentheses [bugprone-macro-parentheses]
+#define BAD2              1+2
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: macro replacement list should be enclosed in parentheses [bugprone-macro-parentheses]
+#define BAD3(A)           (A+1)
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses]
+#define BAD4(x)           ((unsigned char)(x & 0xff))
+// CHECK-MESSAGES: :[[@LINE-1]]:44: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses]
+#define BAD5(X)           A*B=(C*)X+2
+// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses]
+
+#define GOOD1             1
+#define GOOD2             (1+2)
+#define GOOD3(A)          #A
+#define GOOD4(A,B)        A ## B
+#define GOOD5(T)          ((T*)0)
+#define GOOD6(B)          "A" B "C"
+#define GOOD7(b)          A b
+#define GOOD8(a)          a B
+#define GOOD9(type)       (type(123))
+#define GOOD10(car, ...)  car
+#define GOOD11            a[b+c]
+#define GOOD12(x)         a[x]
+#define GOOD13(x)         a.x
+#define GOOD14(x)         a->x
+#define GOOD15(x)         ({ int a = x; a+4; })
+#define GOOD16(x)         a_ ## x, b_ ## x = c_ ## x - 1,
+#define GOOD17            case 123: x=4+5; break;
+#define GOOD18(x)         ;x;
+#define GOOD19            ;-2;
+#define GOOD20            void*
+#define GOOD21(a)         case Fred::a:
+#define GOOD22(a)         if (verbose) return a;
+#define GOOD23(type)      (type::Field)
+#define GOOD24(t)         std::set<t> s
+#define GOOD25(t)         std::set<t,t,t> s
+#define GOOD26(x)         (a->*x)
+#define GOOD27(x)         (a.*x)
+#define GOOD28(x)         namespace x {int b;}
+#define GOOD29(...)       std::cout << __VA_ARGS__;
+#define GOOD30(args...)   std::cout << args;
+#define GOOD31(X)         A*X=2
+#define GOOD32(X)         std::vector<X>
+
+// These are allowed for now..
+#define MAYBE1            *12.34
+#define MAYBE2            <<3
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-repeated-side-effects.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-repeated-side-effects.c
new file mode 100644
index 0000000..bcea47a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-macro-repeated-side-effects.c
@@ -0,0 +1,106 @@
+// RUN: %check_clang_tidy %s bugprone-macro-repeated-side-effects %t
+
+#define badA(x,y)  ((x)+((x)+(y))+(y))
+void bad(int ret, int a, int b) {
+  ret = badA(a++, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: side effects in the 1st macro argument 'x' are repeated in macro expansion [bugprone-macro-repeated-side-effects]
+  ret = badA(++a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: side effects in the 1st macro argument 'x'
+  ret = badA(a--, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: side effects in the 1st macro argument 'x'
+  ret = badA(--a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: side effects in the 1st macro argument 'x'
+  ret = badA(a, b++);
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: side effects in the 2nd macro argument 'y'
+  ret = badA(a, ++b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: side effects in the 2nd macro argument 'y'
+  ret = badA(a, b--);
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: side effects in the 2nd macro argument 'y'
+  ret = badA(a, --b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: side effects in the 2nd macro argument 'y'
+}
+
+
+#define MIN(A,B)     ((A) < (B) ? (A) : (B))                        // single ?:
+#define LIMIT(X,A,B) ((X) < (A) ? (A) : ((X) > (B) ? (B) : (X)))    // two ?:
+void question(int x) {
+  MIN(x++, 12);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: side effects in the 1st macro argument 'A'
+  MIN(34, x++);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: side effects in the 2nd macro argument 'B'
+  LIMIT(x++, 0, 100);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: side effects in the 1st macro argument 'X'
+  LIMIT(20, x++, 100);
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: side effects in the 2nd macro argument 'A'
+  LIMIT(20, 0, x++);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: side effects in the 3rd macro argument 'B'
+}
+
+// False positive: Repeated side effects is intentional.
+// It is hard to know when it's done by intention so right now we warn.
+#define UNROLL(A)    {A A}
+void fp1(int i) {
+  UNROLL({ i++; });
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: side effects in the 1st macro argument 'A'
+}
+
+// Do not produce a false positive on a strchr() macro. Explanation; Currently the '?'
+// triggers the test to bail out, because it cannot evaluate __builtin_constant_p(c).
+#  define strchrs(s, c) \
+  (__extension__ (__builtin_constant_p (c) && !__builtin_constant_p (s)	      \
+		  && (c) == '\0'					      \
+		  ? (char *) __rawmemchr (s, c)				      \
+		  : __builtin_strchr (s, c)))
+char* __rawmemchr(char* a, char b) {
+  return a;
+}
+void pass(char* pstr, char ch) {
+  strchrs(pstr, ch++); // No error.
+}
+
+// Check large arguments (t=20, u=21).
+#define largeA(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, x, y, z) \
+  ((a) + (a) + (b) + (b) + (c) + (c) + (d) + (d) + (e) + (e) + (f) + (f) + (g) + (g) +    \
+   (h) + (h) + (i) + (i) + (j) + (j) + (k) + (k) + (l) + (l) + (m) + (m) + (n) + (n) +    \
+   (o) + (o) + (p) + (p) + (q) + (q) + (r) + (r) + (s) + (s) + (t) + (t) + (u) + (u) +    \
+   (v) + (v) + (x) + (x) + (y) + (y) + (z) + (z))
+void large(int a) {
+  largeA(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a++, 0, 0, 0, 0, 0, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:64: warning: side effects in the 19th macro argument 's'
+  largeA(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a++, 0, 0, 0, 0, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:67: warning: side effects in the 20th macro argument 't'
+  largeA(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a++, 0, 0, 0, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:70: warning: side effects in the 21st macro argument 'u'
+}
+
+// Passing macro argument as argument to __builtin_constant_p and macros.
+#define builtinbad(x)      (__builtin_constant_p(x) + (x) + (x))
+#define builtingood1(x)    (__builtin_constant_p(x) + (x))
+#define builtingood2(x)    ((__builtin_constant_p(x) && (x)) || (x))
+#define macrobad(x)        (builtingood1(x) + (x) + (x))
+#define macrogood(x)       (builtingood1(x) + (x))
+void builtins(int ret, int a) {
+  ret += builtinbad(a++);
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: side effects in the 1st macro argument 'x'
+
+  ret += builtingood1(a++);
+  ret += builtingood2(a++);
+
+  ret += macrobad(a++);
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: side effects in the 1st macro argument 'x'
+
+  ret += macrogood(a++);
+}
+
+// Bail out for conditionals.
+#define condB(x,y)  if(x) {x=y;} else {x=y + 1;}
+void conditionals(int a, int b)
+{
+  condB(a, b++);
+}
+
+void log(const char *s, int v);
+#define LOG(val) log(#val, (val))
+void test_log(int a) {
+  LOG(a++);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c
new file mode 100644
index 0000000..c5deb25
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c
@@ -0,0 +1,85 @@
+// RUN: %check_clang_tidy %s bugprone-misplaced-operator-in-strlen-in-alloc %t
+
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+void *alloca(size_t);
+void *calloc(size_t, size_t);
+void *realloc(void *, size_t);
+
+size_t strlen(const char *);
+size_t strnlen(const char *, size_t);
+size_t strnlen_s(const char *, size_t);
+
+typedef unsigned wchar_t;
+
+size_t wcslen(const wchar_t *);
+size_t wcsnlen(const wchar_t *, size_t);
+size_t wcsnlen_s(const wchar_t *, size_t);
+
+void bad_malloc(char *name) {
+  char *new_name = (char *)malloc(strlen(name + 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+  // CHECK-FIXES: {{^  char \*new_name = \(char \*\)malloc\(}}strlen(name) + 1{{\);$}}
+  new_name = (char *)malloc(strnlen(name + 1, 10));
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: addition operator is applied to the argument of strnlen
+  // CHECK-FIXES: {{^  new_name = \(char \*\)malloc\(}}strnlen(name, 10) + 1{{\);$}}
+  new_name = (char *)malloc(strnlen_s(name + 1, 10));
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: addition operator is applied to the argument of strnlen_s
+  // CHECK-FIXES: {{^  new_name = \(char \*\)malloc\(}}strnlen_s(name, 10) + 1{{\);$}}
+}
+
+void bad_malloc_wide(wchar_t *name) {
+  wchar_t *new_name = (wchar_t *)malloc(wcslen(name + 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: addition operator is applied to the argument of wcslen
+  // CHECK-FIXES: {{^  wchar_t \*new_name = \(wchar_t \*\)malloc\(}}wcslen(name) + 1{{\);$}}
+  new_name = (wchar_t *)malloc(wcsnlen(name + 1, 10));
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: addition operator is applied to the argument of wcsnlen
+  // CHECK-FIXES: {{^  new_name = \(wchar_t \*\)malloc\(}}wcsnlen(name, 10) + 1{{\);$}}
+  new_name = (wchar_t *)malloc(wcsnlen_s(name + 1, 10));
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: addition operator is applied to the argument of wcsnlen_s
+  // CHECK-FIXES: {{^  new_name = \(wchar_t \*\)malloc\(}}wcsnlen_s(name, 10) + 1{{\);$}}
+}
+
+void bad_alloca(char *name) {
+  char *new_name = (char *)alloca(strlen(name + 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+  // CHECK-FIXES: {{^  char \*new_name = \(char \*\)alloca\(}}strlen(name) + 1{{\);$}}
+}
+
+void bad_calloc(char *name) {
+  char *new_names = (char *)calloc(2, strlen(name + 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: addition operator is applied to the argument of strlen
+  // CHECK-FIXES: {{^  char \*new_names = \(char \*\)calloc\(2, }}strlen(name) + 1{{\);$}}
+}
+
+void bad_realloc(char *old_name, char *name) {
+  char *new_name = (char *)realloc(old_name, strlen(name + 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+  // CHECK-FIXES: {{^  char \*new_name = \(char \*\)realloc\(old_name, }}strlen(name) + 1{{\);$}}
+}
+
+void intentional1(char *name) {
+  char *new_name = (char *)malloc(strlen(name + 1) + 1);
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+  // We have + 1 outside as well so we assume this is intentional
+}
+
+void intentional2(char *name) {
+  char *new_name = (char *)malloc(strlen(name + 2));
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+  // Only give warning for + 1, not + 2
+}
+
+void intentional3(char *name) {
+  char *new_name = (char *)malloc(strlen((name + 1)));
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+  // If expression is in extra parentheses, consider it as intentional
+}
+
+void (*(*const alloc_ptr)(size_t)) = malloc;
+
+void bad_indirect_alloc(char *name) {
+  char *new_name = (char *)alloc_ptr(strlen(name + 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+  // CHECK-FIXES: {{^  char \*new_name = \(char \*\)alloc_ptr\(}}strlen(name) + 1{{\);$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.cpp
new file mode 100644
index 0000000..58d63fa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.cpp
@@ -0,0 +1,58 @@
+// RUN: %check_clang_tidy %s bugprone-misplaced-operator-in-strlen-in-alloc %t
+
+namespace std {
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+
+size_t strlen(const char *);
+} // namespace std
+
+namespace non_std {
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+
+size_t strlen(const char *);
+} // namespace non_std
+
+void bad_std_malloc_std_strlen(char *name) {
+  char *new_name = (char *)std::malloc(std::strlen(name + 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+  // CHECK-FIXES: {{^  char \*new_name = \(char \*\)std::malloc\(}}std::strlen(name) + 1{{\);$}}
+}
+
+void ignore_non_std_malloc_std_strlen(char *name) {
+  char *new_name = (char *)non_std::malloc(std::strlen(name + 1));
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+  // Ignore functions of the malloc family in custom namespaces
+}
+
+void ignore_std_malloc_non_std_strlen(char *name) {
+  char *new_name = (char *)std::malloc(non_std::strlen(name + 1));
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
+  // Ignore functions of the strlen family in custom namespaces
+}
+
+void bad_new_strlen(char *name) {
+  char *new_name = new char[std::strlen(name + 1)];
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: addition operator is applied to the argument of strlen
+  // CHECK-FIXES: {{^  char \*new_name = new char\[}}std::strlen(name) + 1{{\];$}}
+}
+
+void good_new_strlen(char *name) {
+  char *new_name = new char[std::strlen(name) + 1];
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:20: warning: addition operator is applied to the argument of strlen
+}
+
+class C {
+  char c;
+public:
+  static void *operator new[](std::size_t count) {
+    return ::operator new(count);
+  }
+};
+
+void bad_custom_new_strlen(char *name) {
+  C *new_name = new C[std::strlen(name + 1)];
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: addition operator is applied to the argument of strlen
+  // CHECK-FIXES: {{^  C \*new_name = new C\[}}std::strlen(name) + 1{{\];$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-widening-cast-explicit-only.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-widening-cast-explicit-only.cpp
new file mode 100644
index 0000000..be12614
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-widening-cast-explicit-only.cpp
@@ -0,0 +1,64 @@
+// RUN: %check_clang_tidy %s bugprone-misplaced-widening-cast %t -- -config="{CheckOptions: [{key: bugprone-misplaced-widening-cast.CheckImplicitCasts, value: 0}]}" --
+
+void func(long arg) {}
+
+void assign(int a, int b) {
+  long l;
+
+  l = a * b;
+  l = (long)(a * b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long' is ineffective, or there is loss of precision before the conversion [bugprone-misplaced-widening-cast]
+  l = (long)a * b;
+
+  l = a << 8;
+  l = (long)(a << 8);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+  l = (long)b << 8;
+
+  l = static_cast<long>(a * b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+}
+
+void compare(int a, int b, long c) {
+  bool l;
+
+  l = a * b == c;
+  l = c == a * b;
+  l = (long)(a * b) == c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+  l = c == (long)(a * b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: either cast from 'int' to 'long'
+  l = (long)a * b == c;
+  l = c == (long)a * b;
+}
+
+void init(unsigned int n) {
+  long l1 = n << 8;
+  long l2 = (long)(n << 8);
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: either cast from 'unsigned int' to 'long'
+  long l3 = (long)n << 8;
+}
+
+void call(unsigned int n) {
+  func(n << 8);
+  func((long)(n << 8));
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: either cast from 'unsigned int' to 'long'
+  func((long)n << 8);
+}
+
+long ret(int a) {
+  if (a < 0) {
+    return a * 1000;
+  } else if (a > 0) {
+    return (long)(a * 1000);
+    // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: either cast from 'int' to 'long'
+  } else {
+    return (long)a * 1000;
+  }
+}
+
+// Shall not generate an assert. https://bugs.llvm.org/show_bug.cgi?id=33660
+template <class> class A {
+  enum Type {};
+  static char *m_fn1() { char p = (Type)(&p - m_fn1()); }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-widening-cast-implicit-enabled.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-widening-cast-implicit-enabled.cpp
new file mode 100644
index 0000000..5487b33
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-misplaced-widening-cast-implicit-enabled.cpp
@@ -0,0 +1,101 @@
+// RUN: %check_clang_tidy %s bugprone-misplaced-widening-cast %t -- -config="{CheckOptions: [{key: bugprone-misplaced-widening-cast.CheckImplicitCasts, value: 1}]}" --
+
+void func(long arg) {}
+
+void assign(int a, int b) {
+  long l;
+
+  l = a * b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long' is ineffective, or there is loss of precision before the conversion [bugprone-misplaced-widening-cast]
+  l = (long)(a * b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+  l = (long)a * b;
+
+  l = a << 8;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+  l = (long)(a << 8);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+  l = (long)b << 8;
+
+  l = static_cast<long>(a * b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+}
+
+void compare(int a, int b, long c) {
+  bool l;
+
+  l = a * b == c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+  l = c == a * b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: either cast from 'int' to 'long'
+  l = (long)(a * b) == c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: either cast from 'int' to 'long'
+  l = c == (long)(a * b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: either cast from 'int' to 'long'
+  l = (long)a * b == c;
+  l = c == (long)a * b;
+}
+
+void init(unsigned int n) {
+  long l1 = n << 8;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: either cast from 'unsigned int' to 'long'
+  long l2 = (long)(n << 8);
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: either cast from 'unsigned int' to 'long'
+  long l3 = (long)n << 8;
+}
+
+void call(unsigned int n) {
+  func(n << 8);
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: either cast from 'unsigned int' to 'long'
+  func((long)(n << 8));
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: either cast from 'unsigned int' to 'long'
+  func((long)n << 8);
+}
+
+long ret(int a) {
+  if (a < 0) {
+    return a * 1000;
+    // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: either cast from 'int' to 'long'
+  } else if (a > 0) {
+    return (long)(a * 1000);
+    // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: either cast from 'int' to 'long'
+  } else {
+    return (long)a * 1000;
+  }
+}
+
+void dontwarn1(unsigned char a, int i, unsigned char *p) {
+  long l;
+  // The result is a 9 bit value, there is no truncation in the implicit cast.
+  l = (long)(a + 15);
+  // The result is a 12 bit value, there is no truncation in the implicit cast.
+  l = (long)(a << 4);
+  // The result is a 3 bit value, there is no truncation in the implicit cast.
+  l = (long)((i % 5) + 1);
+  // The result is a 16 bit value, there is no truncation in the implicit cast.
+  l = (long)(((*p) << 8) + *(p + 1));
+}
+
+template <class T> struct DontWarn2 {
+  void assign(T a, T b) {
+    long l;
+    l = (long)(a * b);
+  }
+};
+DontWarn2<int> DW2;
+
+// Cast is not suspicious when casting macro.
+#define A  (X<<2)
+long macro1(int X) {
+  return (long)A;
+}
+
+// Don't warn about cast in macro.
+#define B(X,Y)   (long)(X*Y)
+long macro2(int x, int y) {
+  return B(x,y);
+}
+
+void floatingpoint(float a, float b) {
+  double d = (double)(a * b); // Currently we don't warn for this.
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-move-forwarding-reference.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-move-forwarding-reference.cpp
new file mode 100644
index 0000000..befca29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-move-forwarding-reference.cpp
@@ -0,0 +1,125 @@
+// RUN: %check_clang_tidy %s bugprone-move-forwarding-reference %t -- -- -std=c++14 -fno-delayed-template-parsing
+
+namespace std {
+template <typename> struct remove_reference;
+
+template <typename _Tp> struct remove_reference { typedef _Tp type; };
+
+template <typename _Tp> struct remove_reference<_Tp &> { typedef _Tp type; };
+
+template <typename _Tp> struct remove_reference<_Tp &&> { typedef _Tp type; };
+
+template <typename _Tp>
+constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t);
+
+} // namespace std
+
+// Standard case.
+template <typename T, typename U> void f1(U &&SomeU) {
+  T SomeT(std::move(SomeU));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to
+  // CHECK-FIXES: T SomeT(std::forward<U>(SomeU));
+}
+
+// Ignore parentheses around the argument to std::move().
+template <typename T, typename U> void f2(U &&SomeU) {
+  T SomeT(std::move((SomeU)));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to
+  // CHECK-FIXES: T SomeT(std::forward<U>((SomeU)));
+}
+
+// Handle the case correctly where std::move() is being used through a using
+// declaration.
+template <typename T, typename U> void f3(U &&SomeU) {
+  using std::move;
+  T SomeT(move(SomeU));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to
+  // CHECK-FIXES: T SomeT(std::forward<U>(SomeU));
+}
+
+// Handle the case correctly where a global specifier is prepended to
+// std::move().
+template <typename T, typename U> void f4(U &&SomeU) {
+  T SomeT(::std::move(SomeU));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to
+  // CHECK-FIXES: T SomeT(::std::forward<U>(SomeU));
+}
+
+// Create a correct fix if there are spaces around the scope resolution
+// operator.
+template <typename T, typename U> void f5(U &&SomeU) {
+  {
+    T SomeT(::  std  ::  move(SomeU));
+    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: forwarding reference passed to
+    // CHECK-FIXES: T SomeT(::std::forward<U>(SomeU));
+  }
+  {
+    T SomeT(std  ::  move(SomeU));
+    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: forwarding reference passed to
+    // CHECK-FIXES: T SomeT(std::forward<U>(SomeU));
+  }
+}
+
+// Ignore const rvalue reference parameters.
+template <typename T, typename U> void f6(const U &&SomeU) {
+  T SomeT(std::move(SomeU));
+}
+
+// Ignore the case where the argument to std::move() is a lambda parameter (and
+// thus not actually a parameter of the function template).
+template <typename T, typename U> void f7() {
+  [](U &&SomeU) { T SomeT(std::move(SomeU)); };
+}
+
+// Ignore the case where the argument is a lvalue reference.
+template <typename T, typename U> void f8(U &SomeU) {
+  T SomeT(std::move(SomeU));
+}
+
+// Ignore the case where the template parameter is a class template parameter
+// (i.e. no template argument deduction is taking place).
+template <typename T, typename U> class SomeClass {
+  void f(U &&SomeU) { T SomeT(std::move(SomeU)); }
+};
+
+// Ignore the case where the function parameter in the template isn't an rvalue
+// reference but the template argument is explicitly set to be an rvalue
+// reference.
+class A {};
+template <typename T> void foo(T);
+void f8() {
+  A a;
+  foo<A &&>(std::move(a));
+}
+
+// A warning is output, but no fix is suggested, if a macro is used to rename
+// std::move.
+#define MOVE(x) std::move((x))
+template <typename T, typename U> void f9(U &&SomeU) {
+  T SomeT(MOVE(SomeU));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to
+}
+
+// Same result if the argument is passed outside of the macro.
+#undef MOVE
+#define MOVE std::move
+template <typename T, typename U> void f10(U &&SomeU) {
+  T SomeT(MOVE(SomeU));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to
+}
+
+// Same result if the macro does not include the "std" namespace.
+#undef MOVE
+#define MOVE move
+template <typename T, typename U> void f11(U &&SomeU) {
+  T SomeT(std::MOVE(SomeU));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: forwarding reference passed to
+}
+
+// Handle the case correctly where the forwarding reference is a parameter of a
+// generic lambda.
+template <typename T> void f12() {
+  [] (auto&& x) { T SomeT(std::move(x)); };
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference passed to
+  // CHECK-FIXES: [] (auto&& x) { T SomeT(std::forward<decltype(x)>(x)); }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-multiple-statement-macro.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-multiple-statement-macro.cpp
new file mode 100644
index 0000000..5b88d8d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-multiple-statement-macro.cpp
@@ -0,0 +1,85 @@
+// RUN: %check_clang_tidy %s bugprone-multiple-statement-macro %t
+
+void F();
+
+#define BAD_MACRO(x) \
+  F();               \
+  F()
+
+#define GOOD_MACRO(x) \
+  do {                \
+    F();              \
+    F();              \
+  } while (0)
+
+#define GOOD_MACRO2(x) F()
+
+#define GOOD_MACRO3(x) F();
+
+#define MACRO_ARG_MACRO(X) \
+  if (54)                  \
+  X(2)
+
+#define ALL_IN_MACRO(X) \
+  if (43)               \
+    F();                \
+  F()
+
+#define GOOD_NESTED(x)   \
+  if (x)            \
+    GOOD_MACRO3(x); \
+  F();
+
+#define IF(x) if(x)
+
+void positives() {
+  if (1)
+    BAD_MACRO(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: multiple statement macro used without braces; some statements will be unconditionally executed [bugprone-multiple-statement-macro]
+  if (1) {
+  } else
+    BAD_MACRO(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: multiple statement macro used
+  while (1)
+    BAD_MACRO(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: multiple statement macro used
+  for (;;)
+    BAD_MACRO(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: multiple statement macro used
+
+  MACRO_ARG_MACRO(BAD_MACRO);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: multiple statement macro used
+  MACRO_ARG_MACRO(F(); int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: multiple statement macro used
+  IF(1) BAD_MACRO(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: multiple statement macro used
+}
+
+void negatives() {
+  if (1) {
+    BAD_MACRO(1);
+  } else {
+    BAD_MACRO(1);
+  }
+  while (1) {
+    BAD_MACRO(1);
+  }
+  for (;;) {
+    BAD_MACRO(1);
+  }
+
+  if (1)
+    GOOD_MACRO(1);
+  if (1) {
+    GOOD_MACRO(1);
+  }
+  if (1)
+    GOOD_MACRO2(1);
+  if (1)
+    GOOD_MACRO3(1);
+
+  MACRO_ARG_MACRO(GOOD_MACRO);
+  ALL_IN_MACRO(1);
+
+  IF(1) GOOD_MACRO(1);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-parent-virtual-call.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-parent-virtual-call.cpp
new file mode 100755
index 0000000..ad84588
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-parent-virtual-call.cpp
@@ -0,0 +1,179 @@
+// RUN: %check_clang_tidy %s bugprone-parent-virtual-call %t
+
+extern int foo();
+
+class A {
+public:
+  A() = default;
+  virtual ~A() = default;
+
+  virtual int virt_1() { return foo() + 1; }
+  virtual int virt_2() { return foo() + 2; }
+
+  int non_virt() { return foo() + 3; }
+  static int stat() { return foo() + 4; }
+};
+
+class B : public A {
+public:
+  B() = default;
+
+  // Nothing to fix: calls to direct parent.
+  int virt_1() override { return A::virt_1() + 3; }
+  int virt_2() override { return A::virt_2() + 4; }
+};
+
+class C : public B {
+public:
+  int virt_1() override { return A::virt_1() + B::virt_1(); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' refers to a member overridden in subclass; did you mean 'B'? [bugprone-parent-virtual-call]
+  // CHECK-FIXES:  int virt_1() override { return B::virt_1() + B::virt_1(); }
+  int virt_2() override { return A::virt_1() + B::virt_1(); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'B'? {{.*}}
+  // CHECK-FIXES:  int virt_2() override { return B::virt_1() + B::virt_1(); }
+
+  // Test that non-virtual and static methods are not affected by this cherker.
+  int method_c() { return A::stat() + A::non_virt(); }
+};
+
+// Check aliased type names
+using A1 = A;
+typedef A A2;
+#define A3 A
+
+class C2 : public B {
+public:
+  int virt_1() override { return A1::virt_1() + A2::virt_1() + A3::virt_1(); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A1::virt_1' {{.*}}; did you mean 'B'? {{.*}}
+  // CHECK-MESSAGES: :[[@LINE-2]]:49: warning: qualified name 'A2::virt_1' {{.*}}; did you mean 'B'? {{.*}}
+  // CHECK-MESSAGES: :[[@LINE-3]]:64: warning: qualified name 'A3::virt_1' {{.*}}; did you mean 'B'? {{.*}}
+  // CHECK-FIXES:  int virt_1() override { return B::virt_1() + B::virt_1() + B::virt_1(); }
+};
+
+// Test that the check affects grand-grand..-parent calls too.
+class D : public C {
+public:
+  int virt_1() override { return A::virt_1() + B::virt_1() + D::virt_1(); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'C'? {{.*}}
+  // CHECK-MESSAGES: :[[@LINE-2]]:48: warning: qualified name 'B::virt_1' {{.*}}; did you mean 'C'? {{.*}}
+  // CHECK-FIXES:  int virt_1() override { return C::virt_1() + C::virt_1() + D::virt_1(); }
+  int virt_2() override { return A::virt_1() + B::virt_1() + D::virt_1(); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'C'? {{.*}}
+  // CHECK-MESSAGES: :[[@LINE-2]]:48: warning: qualified name 'B::virt_1' {{.*}}; did you mean 'C'? {{.*}}
+  // CHECK-FIXES:  int virt_2() override { return C::virt_1() + C::virt_1() + D::virt_1(); }
+};
+
+// Test classes in namespaces.
+namespace {
+class BN : public A {
+public:
+  int virt_1() override { return A::virt_1() + 3; }
+  int virt_2() override { return A::virt_2() + 4; }
+};
+} // namespace
+
+namespace N1 {
+class A {
+public:
+  A() = default;
+  virtual int virt_1() { return foo() + 1; }
+  virtual int virt_2() { return foo() + 2; }
+};
+} // namespace N1
+
+namespace N2 {
+class BN : public N1::A {
+public:
+  int virt_1() override { return A::virt_1() + 3; }
+  int virt_2() override { return A::virt_2() + 4; }
+};
+} // namespace N2
+
+class CN : public BN {
+public:
+  int virt_1() override { return A::virt_1() + BN::virt_1(); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'BN'? {{.*}}
+  // CHECK-FIXES:  int virt_1() override { return BN::virt_1() + BN::virt_1(); }
+  int virt_2() override { return A::virt_1() + BN::virt_1(); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'BN'? {{.*}}
+  // CHECK-FIXES:  int virt_2() override { return BN::virt_1() + BN::virt_1(); }
+};
+
+class CNN : public N2::BN {
+public:
+  int virt_1() override { return N1::A::virt_1() + N2::BN::virt_1(); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'N1::A::virt_1' {{.*}}; did you mean 'N2::BN'? {{.*}}
+  // CHECK-FIXES:  int virt_1() override { return N2::BN::virt_1() + N2::BN::virt_1(); }
+  int virt_2() override { return N1::A::virt_1() + N2::BN::virt_1(); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'N1::A::virt_1' {{.*}}; did you mean 'N2::BN'? {{.*}}
+  // CHECK-FIXES:  int virt_2() override { return N2::BN::virt_1() + N2::BN::virt_1(); }
+};
+
+// Test multiple inheritance fixes
+class AA {
+public:
+  AA() = default;
+  virtual ~AA() = default;
+
+  virtual int virt_1() { return foo() + 1; }
+  virtual int virt_2() { return foo() + 2; }
+
+  int non_virt() { return foo() + 3; }
+  static int stat() { return foo() + 4; }
+};
+
+class BB_1 : virtual public AA {
+public:
+  BB_1() = default;
+
+  // Nothing to fix: calls to parent.
+  int virt_1() override { return AA::virt_1() + 3; }
+  int virt_2() override { return AA::virt_2() + 4; }
+};
+
+class BB_2 : virtual public AA {
+public:
+  BB_2() = default;
+  int virt_1() override { return AA::virt_1() + 3; }
+};
+
+class CC : public BB_1, public BB_2 {
+public:
+  int virt_1() override { return AA::virt_1() + 3; }
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'AA::virt_1' refers to a member overridden in subclasses; did you mean 'BB_1' or 'BB_2'? {{.*}}
+  // No fix available due to multiple choice of parent class.
+};
+
+// Test that virtual method is not diagnosed as not overridden in parent.
+class BI : public A {
+public:
+  BI() = default;
+};
+
+class CI : BI {
+  int virt_1() override { return A::virt_1(); }
+};
+
+// Test templated classes.
+template <class F> class BF : public A {
+public:
+  int virt_1() override { return A::virt_1() + 3; }
+};
+
+// Test templated parent class.
+class CF : public BF<int> {
+public:
+  int virt_1() override { return A::virt_1(); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'BF'? {{.*}}
+};
+
+// Test both templated class and its parent class.
+template <class F> class DF : public BF<F> {
+public:
+  DF() = default;
+  int virt_1() override { return A::virt_1(); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'BF'? {{.*}}
+};
+
+// Just to instantiate DF<F>.
+int bar() { return (new DF<int>())->virt_1(); }
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-sizeof-container.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-sizeof-container.cpp
new file mode 100644
index 0000000..27798d6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-sizeof-container.cpp
@@ -0,0 +1,103 @@
+// RUN: %check_clang_tidy %s bugprone-sizeof-container %t -- -- -std=c++11 -target x86_64-unknown-unknown
+
+namespace std {
+
+typedef unsigned int size_t;
+
+template <typename T>
+struct basic_string {
+  size_t size() const;
+};
+
+template <typename T>
+basic_string<T> operator+(const basic_string<T> &, const T *);
+
+typedef basic_string<char> string;
+
+template <typename T>
+struct vector {
+  size_t size() const;
+};
+
+// std::bitset<> is not a container. sizeof() is reasonable for it.
+template <size_t N>
+struct bitset {
+  size_t size() const;
+};
+
+// std::array<> is, well, an array. sizeof() is reasonable for it.
+template <typename T, size_t N>
+struct array {
+  size_t size() const;
+};
+
+class fake_container1 {
+  size_t size() const; // non-public
+};
+
+struct fake_container2 {
+  size_t size(); // non-const
+};
+
+}
+
+using std::size_t;
+
+#define ARRAYSIZE(a) \
+  ((sizeof(a) / sizeof(*(a))) / static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
+
+#define ARRAYSIZE2(a) \
+  (((sizeof(a)) / (sizeof(*(a)))) / static_cast<size_t>(!((sizeof(a)) % (sizeof(*(a))))))
+
+struct string {
+  std::size_t size() const;
+};
+
+template<typename T>
+void g(T t) {
+  (void)sizeof(t);
+}
+
+void f() {
+  string s1;
+  std::string s2;
+  std::vector<int> v;
+
+  int a = 42 + sizeof(s1);
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: sizeof() doesn't return the size of the container; did you mean .size()? [bugprone-sizeof-container]
+  a = 123 * sizeof(s2);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: sizeof() doesn't return the size
+  a = 45 + sizeof(s2 + "asdf");
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: sizeof() doesn't return the size
+  a = sizeof(v);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: sizeof() doesn't return the size
+  a = sizeof(std::vector<int>{});
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: sizeof() doesn't return the size
+
+  a = sizeof(a);
+  a = sizeof(int);
+  a = sizeof(std::string);
+  a = sizeof(std::vector<int>);
+
+  g(s1);
+  g(s2);
+  g(v);
+
+  std::fake_container1 fake1;
+  std::fake_container2 fake2;
+  std::bitset<7> std_bitset;
+  std::array<int, 3> std_array;
+
+  a = sizeof(fake1);
+  a = sizeof(fake2);
+  a = sizeof(std_bitset);
+  a = sizeof(std_array);
+
+
+  std::string arr[3];
+  a = ARRAYSIZE(arr);
+  a = ARRAYSIZE2(arr);
+  a = sizeof(arr) / sizeof(arr[0]);
+
+  (void)a;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-sizeof-expression.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-sizeof-expression.cpp
new file mode 100644
index 0000000..683ad08
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-sizeof-expression.cpp
@@ -0,0 +1,256 @@
+// RUN: %check_clang_tidy %s bugprone-sizeof-expression %t -- -config="{CheckOptions: [{key: bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression, value: 1}]}" --
+
+class C {
+  int size() { return sizeof(this); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(this)'
+};
+
+#define LEN 8
+
+int X;
+extern int A[10];
+extern short B[10];
+
+#pragma pack(1)
+struct  S { char a, b, c; };
+
+enum E { E_VALUE = 0 };
+enum class EC { VALUE = 0 };
+
+bool AsBool() { return false; }
+int AsInt() { return 0; }
+E AsEnum() { return E_VALUE; }
+EC AsEnumClass() { return EC::VALUE; }
+S AsStruct() { return {}; }
+
+struct M {
+  int AsInt() { return 0; }
+  E AsEnum() { return E_VALUE; }
+  S AsStruct() { return {}; }
+};
+
+int ReturnOverload(int) { return {}; }
+S ReturnOverload(S) { return {}; }
+
+template <class T>
+T ReturnTemplate(T) { return {}; }
+
+template <class T>
+bool TestTrait1() {
+  return sizeof(ReturnOverload(T{})) == sizeof(A);
+}
+
+template <class T>
+bool TestTrait2() {
+  return sizeof(ReturnTemplate(T{})) == sizeof(A);
+}
+
+template <class T>
+bool TestTrait3() {
+  return sizeof(ReturnOverload(0)) == sizeof(T{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+}
+
+template <class T>
+bool TestTrait4() {
+  return sizeof(ReturnTemplate(0)) == sizeof(T{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+}
+
+bool TestTemplates() {
+  bool b = true;
+  b &= TestTrait1<int>();
+  b &= TestTrait1<S>();
+  b &= TestTrait2<int>();
+  b &= TestTrait2<S>();
+  b &= TestTrait3<int>();
+  b &= TestTrait3<S>();
+  b &= TestTrait4<int>();
+  b &= TestTrait4<S>();
+  return b;
+}
+
+int Test1(const char* ptr) {
+  int sum = 0;
+  sum += sizeof(LEN);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(K)'
+  sum += sizeof(LEN + 1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(K)'
+  sum += sizeof(sum, LEN);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(..., ...)'
+  sum += sizeof(AsBool());
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+  sum += sizeof(AsInt());
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+  sum += sizeof(AsEnum());
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+  sum += sizeof(AsEnumClass());
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+  sum += sizeof(M{}.AsInt());
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+  sum += sizeof(M{}.AsEnum());
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
+  sum += sizeof(sizeof(X));
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
+  sum += sizeof(LEN + sizeof(X));
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
+  sum += sizeof(LEN + LEN + sizeof(X));
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
+  sum += sizeof(LEN + (LEN + sizeof(X)));
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
+  sum += sizeof(LEN + -sizeof(X));
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
+  sum += sizeof(LEN + - + -sizeof(X));
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
+  sum += sizeof(char) / sizeof(char);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
+  sum += sizeof(A) / sizeof(S);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
+  sum += sizeof(char) / sizeof(int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
+  sum += sizeof(char) / sizeof(A);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
+  sum += sizeof(B[0]) / sizeof(A);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
+  sum += sizeof(ptr) / sizeof(char);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'
+  sum += sizeof(ptr) / sizeof(ptr[0]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'
+  sum += sizeof(ptr) / sizeof(char*);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'
+  sum += sizeof(ptr) / sizeof(void*);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'
+  sum += sizeof(ptr) / sizeof(const void volatile*);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'
+  sum += sizeof(ptr) / sizeof(char);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'
+  sum += sizeof(ptr) / sizeof(ptr[0]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'
+  sum += sizeof(int) * sizeof(char);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious 'sizeof' by 'sizeof' multiplication
+  sum += sizeof(ptr) * sizeof(ptr[0]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious 'sizeof' by 'sizeof' multiplication
+  sum += sizeof(int) * (2 * sizeof(char));
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious 'sizeof' by 'sizeof' multiplication
+  sum += (2 * sizeof(char)) * sizeof(int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious 'sizeof' by 'sizeof' multiplication
+  if (sizeof(A) < 0x100000) sum += 42;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: suspicious comparison of 'sizeof(expr)' to a constant
+  if (sizeof(A) <= 0xFFFFFFFEU) sum += 42;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: suspicious comparison of 'sizeof(expr)' to a constant
+  return sum;
+}
+
+typedef char MyChar;
+typedef const MyChar MyConstChar;
+
+int CE0 = sizeof sizeof(char);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
+int CE1 = sizeof +sizeof(char);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
+int CE2 = sizeof sizeof(const char*);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
+int CE3 = sizeof sizeof(const volatile char* const*);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
+int CE4 = sizeof sizeof(MyConstChar);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
+
+int Test2(MyConstChar* A) {
+  int sum = 0;
+  sum += sizeof(MyConstChar) / sizeof(char);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
+  sum += sizeof(MyConstChar) / sizeof(MyChar);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
+  sum += sizeof(A[0]) / sizeof(char);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
+  return sum;
+}
+
+template <int T>
+int Foo() { int A[T]; return sizeof(T); }
+// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of 'sizeof(K)'
+template <typename T>
+int Bar() { T A[5]; return sizeof(A[0]) / sizeof(T); }
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
+int Test3() { return Foo<42>() + Bar<char>(); }
+
+static const char* kABC = "abc";
+static const wchar_t* kDEF = L"def";
+int Test4(const char A[10]) {
+  int sum = 0;
+  sum += sizeof(kABC);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(char*)'
+  sum += sizeof(kDEF);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(char*)'
+  return sum;
+}
+
+int Test5() {
+  typedef int Array10[10];
+
+  struct MyStruct {
+    Array10 arr;
+    Array10* ptr;
+  };
+  typedef const MyStruct TMyStruct;
+
+  static TMyStruct kGlocalMyStruct = {};
+  static TMyStruct volatile * kGlocalMyStructPtr = &kGlocalMyStruct;
+
+  MyStruct S;
+  Array10 A10;
+
+  int sum = 0;
+  sum += sizeof(&S.arr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+  sum += sizeof(&kGlocalMyStruct.arr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+  sum += sizeof(&kGlocalMyStructPtr->arr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+  sum += sizeof(S.arr + 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+  sum += sizeof(+ S.arr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+  sum += sizeof((int*)S.arr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+
+  sum += sizeof(S.ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+  sum += sizeof(kGlocalMyStruct.ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+  sum += sizeof(kGlocalMyStructPtr->ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+
+  sum += sizeof(&kGlocalMyStruct);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+  sum += sizeof(&S);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+  sum += sizeof(&A10);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
+
+  return sum;
+}
+
+int ValidExpressions() {
+  int A[] = {1, 2, 3, 4};
+  static const char str[] = "hello";
+  static const char* ptr[] { "aaa", "bbb", "ccc" };
+  int sum = 0;
+  if (sizeof(A) < 10)
+    sum += sizeof(A);
+  sum += sizeof(int);
+  sum += sizeof(AsStruct());
+  sum += sizeof(M{}.AsStruct());
+  sum += sizeof(A[sizeof(A) / sizeof(int)]);
+  sum += sizeof(&A[sizeof(A) / sizeof(int)]);
+  sum += sizeof(sizeof(0));  // Special case: sizeof size_t.
+  sum += sizeof(void*);
+  sum += sizeof(void const *);
+  sum += sizeof(void const *) / 4;
+  sum += sizeof(str);
+  sum += sizeof(str) / sizeof(char);
+  sum += sizeof(str) / sizeof(str[0]);
+  sum += sizeof(ptr) / sizeof(ptr[0]);
+  sum += sizeof(ptr) / sizeof(*(ptr));
+  return sum;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-constructor.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-constructor.cpp
new file mode 100644
index 0000000..51d9130
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-constructor.cpp
@@ -0,0 +1,56 @@
+// RUN: %check_clang_tidy %s bugprone-string-constructor %t
+
+namespace std {
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C> >
+struct basic_string {
+  basic_string();
+  basic_string(const C*, unsigned int size);
+  basic_string(unsigned int size, C c);
+};
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+}
+
+const char* kText = "";
+const char kText2[] = "";
+extern const char kText3[];
+
+void Test() {
+  std::string str('x', 4);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor parameters are probably swapped; expecting string(count, character) [bugprone-string-constructor]
+  // CHECK-FIXES: std::string str(4, 'x');
+  std::wstring wstr(L'x', 4);
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: string constructor parameters are probably swapped
+  // CHECK-FIXES: std::wstring wstr(4, L'x');
+  std::string s0(0, 'x');
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructor creating an empty string
+  std::string s1(-4, 'x');
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: negative value used as length parameter
+  std::string s2(0x1000000, 'x');
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: suspicious large length parameter
+
+  std::string q0("test", 0);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructor creating an empty string
+  std::string q1(kText, -4);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: negative value used as length parameter
+  std::string q2("test", 200);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger then string literal size
+  std::string q3(kText, 200);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger then string literal size
+  std::string q4(kText2, 200);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger then string literal size
+  std::string q5(kText3,  0x1000000);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: suspicious large length parameter
+}
+
+void Valid() {
+  std::string empty();
+  std::string str(4, 'x');
+  std::wstring wstr(4, L'x');
+  std::string s1("test", 4);
+  std::string s2("test", 3);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-integer-assignment.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-integer-assignment.cpp
new file mode 100644
index 0000000..c4e13fc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-integer-assignment.cpp
@@ -0,0 +1,53 @@
+// RUN: %check_clang_tidy %s bugprone-string-integer-assignment %t
+
+namespace std {
+template<typename T>
+struct basic_string {
+  basic_string& operator=(T);
+  basic_string& operator=(basic_string);
+  basic_string& operator+=(T);
+  basic_string& operator+=(basic_string);
+};
+
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+}
+
+typedef int MyArcaneChar;
+
+int main() {
+  std::string s;
+  std::wstring ws;
+  int x = 5;
+
+  s = 6;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: an integer is interpreted as a character code when assigning {{.*}} [bugprone-string-integer-assignment]
+// CHECK-FIXES: {{^}}  s = '6';{{$}}
+  s = 66;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}}  s = "66";{{$}}
+  s = x;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}}  s = std::to_string(x);{{$}}
+  s = 'c';
+  s = static_cast<char>(6);
+
+// +=
+  ws += 6;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}}  ws += L'6';{{$}}
+  ws += 66;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}}  ws += L"66";{{$}}
+  ws += x;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}}  ws += std::to_wstring(x);{{$}}
+  ws += L'c';
+  ws += (wchar_t)6;
+
+  std::basic_string<MyArcaneChar> as;
+  as = 6;
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}}  as = 6;{{$}}
+
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-literal-with-embedded-nul.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-literal-with-embedded-nul.cpp
new file mode 100644
index 0000000..f939f52
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-string-literal-with-embedded-nul.cpp
@@ -0,0 +1,85 @@
+// RUN: %check_clang_tidy %s bugprone-string-literal-with-embedded-nul %t
+
+namespace std {
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T, typename A>
+struct basic_string {
+  typedef basic_string<C, T, A> _Type;
+  basic_string();
+  basic_string(const C *p, const A &a = A());
+
+  _Type& operator+=(const C* s);
+  _Type& operator=(const C* s);
+};
+
+typedef basic_string<char, std::char_traits<char>, std::allocator<char>> string;
+typedef basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>> wstring;
+}
+
+bool operator==(const std::string&, const char*);
+bool operator==(const char*, const std::string&);
+
+
+const char Valid[] = "This is valid \x12.";
+const char Strange[] = "This is strange \0x12 and must be fixed";
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: suspicious embedded NUL character [bugprone-string-literal-with-embedded-nul]
+
+const char textA[] = "\0x01\0x02\0x03\0x04";
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious embedded NUL character
+const wchar_t textW[] = L"\0x01\0x02\0x03\0x04";
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: suspicious embedded NUL character
+
+const char A[] = "\0";
+const char B[] = "\0x";
+const char C[] = "\0x1";
+const char D[] = "\0x11";
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: suspicious embedded NUL character
+
+const wchar_t E[] = L"\0";
+const wchar_t F[] = L"\0x";
+const wchar_t G[] = L"\0x1";
+const wchar_t H[] = L"\0x11";
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: suspicious embedded NUL character
+
+const char I[] = "\000\000\000\000";
+const char J[] = "\0\0\0\0\0\0";
+const char K[] = "";
+
+const char L[] = "\0x12" "\0x12" "\0x12" "\0x12";
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: suspicious embedded NUL character
+
+void TestA() {
+  std::string str1 = "abc\0def";
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: truncated string literal
+  std::string str2 = "\0";
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: truncated string literal
+  std::string str3("\0");
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: truncated string literal
+  std::string str4{"\x00\x01\x02\x03"};
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: truncated string literal
+
+  std::string str;
+  str += "abc\0def";
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: truncated string literal
+  str = "abc\0def";
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: truncated string literal
+
+  if (str == "abc\0def") return;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: truncated string literal
+  if ("abc\0def" == str) return;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: truncated string literal
+}
+
+void TestW() {
+  std::wstring str1 = L"abc\0def";
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: truncated string literal
+  std::wstring str2 = L"\0";
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: truncated string literal
+  std::wstring str3(L"\0");
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: truncated string literal
+  std::wstring str4{L"\x00\x01\x02\x03"};
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: truncated string literal
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-enum-usage-strict.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-enum-usage-strict.cpp
new file mode 100644
index 0000000..d9ed8ce
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-enum-usage-strict.cpp
@@ -0,0 +1,98 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-enum-usage %t -- -config="{CheckOptions: [{key: bugprone-suspicious-enum-usage.StrictMode, value: 1}]}" --
+
+enum A {
+  A = 1,
+  B = 2,
+  C = 4,
+  D = 8,
+  E = 16,
+  F = 32,
+  G = 63
+};
+
+// CHECK-MESSAGES: :[[@LINE+2]]:1: warning: enum type seems like a bitmask (contains mostly power-of-2 literals) but a literal is not power-of-2
+// CHECK-MESSAGES: :76:7: note: used here as a bitmask
+enum X {
+  X = 8,
+  Y = 16,
+  Z = 4,
+  ZZ = 3
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: enum type seems like a bitmask (contains mostly power-of-2 literals), but this literal is not a power-of-2 [bugprone-suspicious-enum-usage]
+// CHECK-MESSAGES: :70:13: note: used here as a bitmask
+};
+// CHECK-MESSAGES: :[[@LINE+2]]:1: warning: enum type seems like a bitmask (contains mostly power-of-2 literals) but some literals are not power-of-2
+// CHECK-MESSAGES: :73:8: note: used here as a bitmask
+enum PP {
+  P = 2,
+  Q = 3,
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: enum type seems like a bitmask (contains mostly power-of-2 literals), but this literal is not a power-of-2
+  // CHECK-MESSAGES: :65:11: note: used here as a bitmask
+  R = 4,
+  S = 8,
+  T = 16,
+  U = 31
+};
+
+enum {
+  H,
+  I,
+  J,
+  K,
+  L
+};
+
+enum Days {
+  Monday,
+  Tuesday,
+  Wednesday,
+  Thursday,
+  Friday,
+  Saturday,
+  Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  if (bestDay() | A)
+    return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types
+  if (I | Y)
+    return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+  if (P + Q == R)
+    return 1;
+  else if ((S | R) == T)
+    return 1;
+  else
+    int k = ZZ | Z;
+  unsigned p = R;
+  PP pp = Q;
+  p |= pp;
+  
+  enum X x = Z;
+  p = x | Z;
+  return 0;
+}
+
+int dont_trigger() {
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+
+  unsigned bitflag;
+  enum A aa = B;
+  bitflag = aa | C;
+
+  if (Tuesday != Monday + 1 ||
+      Friday - Thursday != 1 ||
+      Sunday + Wednesday == (Sunday | Wednesday))
+    return 1;
+  if (H + I + L == 42)
+    return 1;
+  return 42;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-enum-usage.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-enum-usage.cpp
new file mode 100644
index 0000000..e1a54d4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-enum-usage.cpp
@@ -0,0 +1,96 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-enum-usage %t -- -config="{CheckOptions: [{key: bugprone-suspicious-enum-usage.StrictMode, value: 0}]}" --
+
+enum Empty {
+};
+
+enum A {
+  A = 1,
+  B = 2,
+  C = 4,
+  D = 8,
+  E = 16,
+  F = 32,
+  G = 63
+};
+
+enum X {
+  X = 8,
+  Y = 16,
+  Z = 4
+};
+
+enum {
+  P = 2,
+  Q = 3,
+  R = 4,
+  S = 8,
+  T = 16
+};
+
+enum {
+  H,
+  I,
+  J,
+  K,
+  L
+};
+
+enum Days {
+  Monday,
+  Tuesday,
+  Wednesday,
+  Thursday,
+  Friday,
+  Saturday,
+  Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  Empty EmptyVal;
+  int emptytest = EmptyVal | B;
+  if (bestDay() | A)
+    return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types
+  if (I | Y)
+    return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+}
+
+int dont_trigger() {
+  unsigned p;
+  p = Q | P;
+
+  if (A + G == E)
+    return 1;
+  else if ((Q | R) == T)
+    return 1;
+  else
+    int k = T | Q;
+
+  Empty EmptyVal;
+  int emptytest = EmptyVal | B;
+
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+  
+  if (Tuesday != Monday + 1 ||
+      Friday - Thursday != 1 ||
+      Sunday + Wednesday == (Sunday | Wednesday))
+    return 1;
+  if (H + I + L == 42)
+    return 1;
+  return 42;
+}
+
+namespace PR34400 {
+enum { E1 = 0 };
+enum { E2 = -1 };
+enum { l = E1 | E2 };
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-memset-usage.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-memset-usage.cpp
new file mode 100644
index 0000000..f33ae5a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-memset-usage.cpp
@@ -0,0 +1,77 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-memset-usage %t
+
+void *memset(void *, int, __SIZE_TYPE__);
+
+namespace std {
+  using ::memset;
+}
+
+template <typename T>
+void mtempl(int *ptr) {
+  memset(ptr, '0', sizeof(T));
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: memset fill value is char '0', potentially mistaken for int 0 [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: memset(ptr, 0, sizeof(T));
+  memset(ptr, 256, sizeof(T));
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: memset fill value is out of unsigned character range, gets truncated [bugprone-suspicious-memset-usage]
+  memset(0, sizeof(T), 0);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: memset(0, 0, sizeof(T));
+  memset(0, sizeof(int), 0);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: memset(0, 0, sizeof(int));
+}
+
+void foo(int xsize, int ysize) {
+  int i[5] = {1, 2, 3, 4, 5};
+  char ca[3] = {'a', 'b', 'c'};
+  int *p = i;
+  int l = 5;
+  char z = '1';
+  char *c = &z;
+  int v = 0;
+
+  memset(p, '0', l);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: memset fill value is char '0', potentially mistaken for int 0 [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: memset(p, 0, l);
+
+  memset(p, 0xabcd, l);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: memset fill value is out of unsigned character range, gets truncated [bugprone-suspicious-memset-usage]
+
+  memset(p, sizeof(int), 0);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: memset(p, 0, sizeof(int));
+  std::memset(p, sizeof(int), 0x00);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: std::memset(p, 0x00, sizeof(int));
+
+#define M_CHAR_ZERO memset(p, '0', l);
+  M_CHAR_ZERO
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset fill value is char '0', potentially mistaken for int 0 [bugprone-suspicious-memset-usage]
+
+#define M_OUTSIDE_RANGE memset(p, 0xabcd, l);
+  M_OUTSIDE_RANGE
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset fill value is out of unsigned character range, gets truncated [bugprone-suspicious-memset-usage]
+
+#define M_ZERO_LENGTH memset(p, sizeof(int), 0);
+  M_ZERO_LENGTH
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
+
+  memset(p, '2', l);
+  memset(p, 0, l);
+  memset(c, '0', 1);
+  memset(ca, '0', sizeof(ca));
+
+  memset(p, 0x00, l);
+  mtempl<int>(p);
+
+  memset(p, sizeof(int), v + 1);
+  memset(p, 0xcd, 1);
+
+  // Don't warn when the fill char and the length are both known to be
+  // zero.  No bug is possible.
+  memset(p, 0, v);
+
+  // -1 is clearly not a length by virtue of being negative, so no warning
+  // despite v == 0.
+  memset(p, -1, v);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-missing-comma.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-missing-comma.cpp
new file mode 100644
index 0000000..f039310
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-missing-comma.cpp
@@ -0,0 +1,82 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-missing-comma %t
+
+const char* Cartoons[] = {
+  "Bugs Bunny",
+  "Homer Simpson",
+  "Mickey Mouse",
+  "Bart Simpson",
+  "Charlie Brown"  // There is a missing comma here.
+  "Fred Flintstone",
+  "Popeye",
+};
+// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: suspicious string literal, probably missing a comma [bugprone-suspicious-missing-comma]
+
+const wchar_t* Colors[] = {
+  L"Red", L"Yellow", L"Blue", L"Green", L"Purple", L"Rose", L"White", L"Black"
+};
+
+// The following array should not trigger any warnings. There is more than 5
+// elements, but they are all concatenated string literals.
+const char* HttpCommands[] = {
+  "GET / HTTP/1.0\r\n"
+  "\r\n",
+
+  "GET /index.html HTTP/1.0\r\n"
+  "\r\n",
+
+  "GET /favicon.ico HTTP/1.0\r\n"
+  "header: dummy"
+  "\r\n",
+
+  "GET /index.html-en HTTP/1.0\r\n"
+  "\r\n",
+
+  "GET /index.html-fr HTTP/1.0\r\n"
+  "\r\n",
+
+  "GET /index.html-es HTTP/1.0\r\n"
+  "\r\n",
+};
+
+// This array is too small to trigger a warning.
+const char* SmallArray[] = {
+  "a" "b", "c"
+};
+
+// Parentheses should be enough to avoid warnings.
+const char* ParentheseArray[] = {
+  ("a" "b"), "c",
+  ("d"
+   "e"
+   "f"),
+  "g", "h", "i", "j", "k", "l"
+};
+
+// Indentation should be enough to avoid warnings.
+const char* CorrectlyIndentedArray[] = {
+  "This is a long message "
+      "which is spanning over multiple lines."
+      "And this should be fine.",
+  "a", "b", "c", "d", "e", "f",
+  "g", "h", "i", "j", "k", "l"
+};
+
+const char* IncorrectlyIndentedArray[] = {
+  "This is a long message "
+  "which is spanning over multiple lines."
+      "And this should be fine.",
+  "a", "b", "c", "d", "e", "f",
+  "g", "h", "i", "j", "k", "l"
+};
+// CHECK-MESSAGES: :[[@LINE-6]]:3: warning: suspicious string literal, probably missing a comma [bugprone-suspicious-missing-comma]
+
+const char* TooManyConcatenatedTokensArray[] = {
+  "Dummy line",
+  "Dummy line",
+  "a" "b" "c" "d" "e" "f",
+  "g" "h" "i" "j" "k" "l",
+  "Dummy line",
+  "Dummy line",
+  "Dummy line",
+  "Dummy line",
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-semicolon-fail.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-semicolon-fail.cpp
new file mode 100644
index 0000000..45fa226
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-semicolon-fail.cpp
@@ -0,0 +1,28 @@
+// RUN: not clang-tidy %s \
+// RUN:     -checks="-*,bugprone-suspicious-semicolon" -- -DERROR 2>&1 \
+// RUN:   | FileCheck %s -check-prefix=CHECK-ERROR \
+// RUN:       -implicit-check-not="{{warning|error}}:"
+// RUN: not clang-tidy %s \
+// RUN:     -checks="-*,bugprone-suspicious-semicolon,clang-diagnostic*" \
+// RUN:    -- -DWERROR -Wno-everything -Werror=unused-variable 2>&1 \
+// RUN:   | FileCheck %s -check-prefix=CHECK-WERROR \
+// RUN:       -implicit-check-not="{{warning|error}}:"
+
+// Note: This test verifies that, the checker does not emit any warning for
+//       files that do not compile.
+
+bool g();
+
+void f() {
+  if (g());
+  // CHECK-WERROR: :[[@LINE-1]]:11: warning: potentially unintended semicolon [bugprone-suspicious-semicolon]
+#if ERROR
+  int a
+  // CHECK-ERROR: :[[@LINE-1]]:8: error: expected ';' at end of declaration [clang-diagnostic-error]
+#elif WERROR
+  int a;
+  // CHECK-WERROR: :[[@LINE-1]]:7: error: unused variable 'a' [clang-diagnostic-unused-variable]
+#else
+#error "One of ERROR or WERROR should be defined.
+#endif
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-semicolon.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-semicolon.cpp
new file mode 100644
index 0000000..4f9f4c5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-semicolon.cpp
@@ -0,0 +1,117 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-semicolon %t
+
+int x = 5;
+
+void nop();
+
+void correct1()
+{
+	if(x < 5) nop();
+}
+
+void correct2()
+{
+	if(x == 5)
+		nop();
+}
+
+void correct3()
+{
+	if(x > 5)
+	{
+		nop();
+	}
+}
+
+void fail1()
+{
+  if(x > 5); nop();
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: potentially unintended semicolon [bugprone-suspicious-semicolon]
+  // CHECK-FIXES: if(x > 5) nop();
+}
+
+void fail2()
+{
+	if(x == 5);
+		nop();
+  // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: potentially unintended semicolon [bugprone-suspicious-semicolon]
+  // CHECK-FIXES: if(x == 5){{$}}
+}
+
+void fail3()
+{
+	if(x < 5);
+	{
+		nop();
+	}
+  // CHECK-MESSAGES: :[[@LINE-4]]:11: warning: potentially unintended semicolon
+  // CHECK-FIXES: if(x < 5){{$}}
+}
+
+void correct4()
+{
+  while(x % 5 == 1);
+  nop();
+}
+
+void correct5()
+{
+	for(int i = 0; i < x; ++i)
+		;
+}
+
+void fail4()
+{
+	for(int i = 0; i < x; ++i);
+		nop();
+  // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: potentially unintended semicolon
+  // CHECK-FIXES: for(int i = 0; i < x; ++i){{$}}
+}
+
+void fail5()
+{
+	if(x % 5 == 1);
+	  nop();
+  // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: potentially unintended semicolon
+  // CHECK-FIXES: if(x % 5 == 1){{$}}
+}
+
+void fail6() {
+  int a = 0;
+  if (a != 0) {
+  } else if (a != 1);
+    a = 2;
+  // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: potentially unintended semicolon
+  // CHECK-FIXES: } else if (a != 1){{$}}
+}
+
+void fail7() {
+  if (true)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: potentially unintended semicolon
+}
+
+void correct6()
+{
+	do; while(false);
+}
+
+int correct7()
+{
+  int t_num = 0;
+  char c = 'b';
+  char *s = "a";
+  if (s == "(" || s != "'" || c == '"') {
+    t_num += 3;
+    return (c == ')' && c == '\'');
+  }
+
+  return 0;
+}
+
+void correct8() {
+  if (true)
+    ;
+  else {
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-string-compare.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-string-compare.c
new file mode 100644
index 0000000..3b3175a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-string-compare.c
@@ -0,0 +1,79 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-string-compare %t -- \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: bugprone-suspicious-string-compare.WarnOnImplicitComparison, value: 1}, \
+// RUN:   {key: bugprone-suspicious-string-compare.WarnOnLogicalNotComparison, value: 1}]}' \
+// RUN: -- -std=c99
+
+static const char A[] = "abc";
+
+int strcmp(const char *, const char *);
+
+int test_warning_patterns() {
+  if (strcmp(A, "a"))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result [bugprone-suspicious-string-compare]
+  // CHECK-FIXES: if (strcmp(A, "a") != 0)
+
+  if (strcmp(A, "a") != 0 ||
+      strcmp(A, "b"))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result
+  // CHECK-FIXES: strcmp(A, "b") != 0)
+
+  if (strcmp(A, "a") == 1)
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+  if (strcmp(A, "a") == -1)
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+  if (strcmp(A, "a") < '0')
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+  if (strcmp(A, "a") < 0.)
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' has suspicious implicit cast
+
+  if (!strcmp(A, "a"))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:8: warning: function 'strcmp' is compared using logical not operator
+  // CHECK-FIXES: if (strcmp(A, "a") == 0)
+}
+
+void test_structure_patterns() {
+  if (strcmp(A, "a")) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: function 'strcmp' is called without explicitly comparing result
+  // CHECK-FIXES: if (strcmp(A, "a") != 0) {}
+
+  while (strcmp(A, "a")) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: function 'strcmp' is called without explicitly comparing result
+  // CHECK-FIXES: while (strcmp(A, "a") != 0) {}
+
+  for (;strcmp(A, "a");) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: function 'strcmp' is called without explicitly comparing result
+  // CHECK-FIXES: for (;strcmp(A, "a") != 0;) {}
+}
+
+int test_valid_patterns() {
+  // The following cases are valid.
+  if (strcmp(A, "a") < 0) return 0;
+  if (strcmp(A, "a") == 0) return 0;
+  if (strcmp(A, "a") <= 0) return 0;
+  if (strcmp(A, "a") == strcmp(A, "b")) return 0;
+  return 1;
+}
+
+int wrapper(const char* a, const char* b) {
+  return strcmp(a, b);
+}
+
+int assignment_wrapper(const char* a, const char* b) {
+  int cmp = strcmp(a, b);
+  return cmp;
+}
+
+int condexpr_wrapper(const char* a, const char* b) {
+  return (a < b) ? strcmp(a, b) : strcmp(b, a);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-string-compare.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-string-compare.cpp
new file mode 100644
index 0000000..c1c24ff
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-suspicious-string-compare.cpp
@@ -0,0 +1,337 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-string-compare %t -- \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: bugprone-suspicious-string-compare.WarnOnImplicitComparison, value: 1}, \
+// RUN:   {key: bugprone-suspicious-string-compare.WarnOnLogicalNotComparison, value: 1}]}' \
+// RUN: --
+
+typedef __SIZE_TYPE__ size;
+
+struct locale_t {
+  void* dummy;
+} locale;
+
+static const char A[] = "abc";
+static const unsigned char U[] = "abc";
+static const unsigned char V[] = "xyz";
+static const wchar_t W[] = L"abc";
+
+int strlen(const char *);
+
+int memcmp(const void *, const void *, size);
+int wmemcmp(const wchar_t *, const wchar_t *, size);
+int memicmp(const void *, const void *, size);
+int _memicmp(const void *, const void *, size);
+int _memicmp_l(const void *, const void *, size, locale_t);
+
+int strcmp(const char *, const char *);
+int strncmp(const char *, const char *, size);
+int strcasecmp(const char *, const char *);
+int strncasecmp(const char *, const char *, size);
+int stricmp(const char *, const char *);
+int strcmpi(const char *, const char *);
+int strnicmp(const char *, const char *, size);
+int _stricmp(const char *, const char * );
+int _strnicmp(const char *, const char *, size);
+int _stricmp_l(const char *, const char *, locale_t);
+int _strnicmp_l(const char *, const char *, size, locale_t);
+
+int wcscmp(const wchar_t *, const wchar_t *);
+int wcsncmp(const wchar_t *, const wchar_t *, size);
+int wcscasecmp(const wchar_t *, const wchar_t *);
+int wcsicmp(const wchar_t *, const wchar_t *);
+int wcsnicmp(const wchar_t *, const wchar_t *, size);
+int _wcsicmp(const wchar_t *, const wchar_t *);
+int _wcsnicmp(const wchar_t *, const wchar_t *, size);
+int _wcsicmp_l(const wchar_t *, const wchar_t *, locale_t);
+int _wcsnicmp_l(const wchar_t *, const wchar_t *, size, locale_t);
+
+int _mbscmp(const unsigned char *, const unsigned char *);
+int _mbsncmp(const unsigned char *, const unsigned char *, size);
+int _mbsnbcmp(const unsigned char *, const unsigned char *, size);
+int _mbsnbicmp(const unsigned char *, const unsigned char *, size);
+int _mbsicmp(const unsigned char *, const unsigned char *);
+int _mbsnicmp(const unsigned char *, const unsigned char *, size);
+int _mbscmp_l(const unsigned char *, const unsigned char *, locale_t);
+int _mbsncmp_l(const unsigned char *, const unsigned char *, size, locale_t);
+int _mbsicmp_l(const unsigned char *, const unsigned char *, locale_t);
+int _mbsnicmp_l(const unsigned char *, const unsigned char *, size, locale_t);
+int _mbsnbcmp_l(const unsigned char *, const unsigned char *, size, locale_t);
+int _mbsnbicmp_l(const unsigned char *, const unsigned char *, size, locale_t);
+
+int test_warning_patterns() {
+  if (strcmp(A, "a"))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result [bugprone-suspicious-string-compare]
+  // CHECK-FIXES: if (strcmp(A, "a") != 0)
+
+  if (strcmp(A, "a") == 0 ||
+      strcmp(A, "b"))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result
+  // CHECK-FIXES: strcmp(A, "b") != 0)
+
+  if (strcmp(A, "a") == 1)
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+  if (strcmp(A, "a") == -1)
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+  if (strcmp(A, "a") == true)
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+  if (strcmp(A, "a") < '0')
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+  if (strcmp(A, "a") < 0.)
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' has suspicious implicit cast
+}
+
+int test_valid_patterns() {
+  // The following cases are valid.
+  if (strcmp(A, "a") < 0)
+    return 0;
+  if (strcmp(A, "a") == 0)
+    return 0;
+  if (strcmp(A, "a") <= 0)
+    return 0;
+
+  if (wcscmp(W, L"a") < 0)
+    return 0;
+  if (wcscmp(W, L"a") == 0)
+    return 0;
+  if (wcscmp(W, L"a") <= 0)
+    return 0;
+
+  return 1;
+}
+
+int test_implicit_compare_with_functions() {
+
+  if (memcmp(A, "a", 1))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'memcmp' is called without explicitly comparing result
+  // CHECK-FIXES: memcmp(A, "a", 1) != 0)
+
+  if (wmemcmp(W, L"a", 1))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wmemcmp' is called without explicitly comparing result
+  // CHECK-FIXES: wmemcmp(W, L"a", 1) != 0)
+
+  if (memicmp(A, "a", 1))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'memicmp' is called without explicitly comparing result
+  // CHECK-FIXES: memicmp(A, "a", 1) != 0)
+
+  if (_memicmp(A, "a", 1))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_memicmp' is called without explicitly comparing result
+  // CHECK-FIXES: _memicmp(A, "a", 1) != 0)
+
+  if (_memicmp_l(A, "a", 1, locale))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_memicmp_l' is called without explicitly comparing result
+  // CHECK-FIXES: _memicmp_l(A, "a", 1, locale) != 0)
+
+  if (strcmp(A, "a"))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result
+  // CHECK-FIXES: strcmp(A, "a") != 0)
+
+  if (strncmp(A, "a", 1))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strncmp' is called without explicitly comparing result
+  // CHECK-FIXES: strncmp(A, "a", 1) != 0)
+
+  if (strcasecmp(A, "a"))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcasecmp' is called without explicitly comparing result
+  // CHECK-FIXES: strcasecmp(A, "a") != 0)
+
+  if (strncasecmp(A, "a", 1))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strncasecmp' is called without explicitly comparing result
+  // CHECK-FIXES: strncasecmp(A, "a", 1) != 0)
+
+  if (stricmp(A, "a"))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'stricmp' is called without explicitly comparing result
+  // CHECK-FIXES: stricmp(A, "a") != 0)
+
+  if (strcmpi(A, "a"))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmpi' is called without explicitly comparing result
+  // CHECK-FIXES: strcmpi(A, "a") != 0)
+
+  if (_stricmp(A, "a"))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_stricmp' is called without explicitly comparing result
+  // CHECK-FIXES: _stricmp(A, "a") != 0)
+
+  if (strnicmp(A, "a", 1))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strnicmp' is called without explicitly comparing result
+  // CHECK-FIXES: strnicmp(A, "a", 1) != 0)
+
+  if (_strnicmp(A, "a", 1))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_strnicmp' is called without explicitly comparing result
+  // CHECK-FIXES: _strnicmp(A, "a", 1) != 0)
+
+  if (_stricmp_l(A, "a", locale))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_stricmp_l' is called without explicitly comparing result
+  // CHECK-FIXES: _stricmp_l(A, "a", locale) != 0)
+
+  if (_strnicmp_l(A, "a", 1, locale))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_strnicmp_l' is called without explicitly comparing result
+  // CHECK-FIXES: _strnicmp_l(A, "a", 1, locale) != 0)
+
+  if (wcscmp(W, L"a"))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcscmp' is called without explicitly comparing result
+  // CHECK-FIXES: wcscmp(W, L"a") != 0)
+
+  if (wcsncmp(W, L"a", 1))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsncmp' is called without explicitly comparing result
+  // CHECK-FIXES: wcsncmp(W, L"a", 1) != 0)
+
+  if (wcscasecmp(W, L"a"))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcscasecmp' is called without explicitly comparing result
+  // CHECK-FIXES: wcscasecmp(W, L"a") != 0)
+
+  if (wcsicmp(W, L"a"))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsicmp' is called without explicitly comparing result
+  // CHECK-FIXES: wcsicmp(W, L"a") != 0)
+
+  if (_wcsicmp(W, L"a"))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsicmp' is called without explicitly comparing result
+  // CHECK-FIXES: _wcsicmp(W, L"a") != 0)
+
+  if (_wcsicmp_l(W, L"a", locale))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsicmp_l' is called without explicitly comparing result
+  // CHECK-FIXES: _wcsicmp_l(W, L"a", locale) != 0)
+
+  if (wcsnicmp(W, L"a", 1))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsnicmp' is called without explicitly comparing result
+  // CHECK-FIXES: wcsnicmp(W, L"a", 1) != 0)
+
+  if (_wcsnicmp(W, L"a", 1))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsnicmp' is called without explicitly comparing result
+  // CHECK-FIXES: _wcsnicmp(W, L"a", 1) != 0)
+
+  if (_wcsnicmp_l(W, L"a", 1, locale))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsnicmp_l' is called without explicitly comparing result
+  // CHECK-FIXES: _wcsnicmp_l(W, L"a", 1, locale) != 0)
+
+  if (_mbscmp(U, V))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbscmp' is called without explicitly comparing result
+  // CHECK-FIXES: _mbscmp(U, V) != 0)
+
+  if (_mbsncmp(U, V, 1))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsncmp' is called without explicitly comparing result
+  // CHECK-FIXES: _mbsncmp(U, V, 1) != 0)
+
+  if (_mbsnbcmp(U, V, 1))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbcmp' is called without explicitly comparing result
+  // CHECK-FIXES: _mbsnbcmp(U, V, 1) != 0)
+
+  if (_mbsnbicmp(U, V, 1))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbicmp' is called without explicitly comparing result
+  // CHECK-FIXES: _mbsnbicmp(U, V, 1) != 0)
+
+  if (_mbsicmp(U, V))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsicmp' is called without explicitly comparing result
+  // CHECK-FIXES: _mbsicmp(U, V) != 0)
+
+  if (_mbsnicmp(U, V, 1))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnicmp' is called without explicitly comparing result
+  // CHECK-FIXES: _mbsnicmp(U, V, 1) != 0)
+
+  if (_mbscmp_l(U, V, locale))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbscmp_l' is called without explicitly comparing result
+  // CHECK-FIXES: _mbscmp_l(U, V, locale) != 0)
+
+  if (_mbsncmp_l(U, V, 1, locale))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsncmp_l' is called without explicitly comparing result
+  // CHECK-FIXES: _mbsncmp_l(U, V, 1, locale) != 0)
+
+  if (_mbsicmp_l(U, V, locale))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsicmp_l' is called without explicitly comparing result
+  // CHECK-FIXES: _mbsicmp_l(U, V, locale) != 0)
+
+  if (_mbsnicmp_l(U, V, 1, locale))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnicmp_l' is called without explicitly comparing result
+  // CHECK-FIXES: _mbsnicmp_l(U, V, 1, locale) != 0)
+
+  if (_mbsnbcmp_l(U, V, 1, locale))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbcmp_l' is called without explicitly comparing result
+  // CHECK-FIXES: _mbsnbcmp_l(U, V, 1, locale) != 0)
+
+  if (_mbsnbicmp_l(U, V, 1, locale))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbicmp_l' is called without explicitly comparing result
+  // CHECK-FIXES: _mbsnbicmp_l(U, V, 1, locale) != 0)
+
+  return 1;
+}
+
+int strcmp_wrapper1(const char* a, const char* b) {
+  return strcmp(a, b);
+}
+
+int strcmp_wrapper2(const char* a, const char* b) {
+  return (a && b) ? strcmp(a, b) : 0;
+}
+
+#define macro_strncmp(s1, s2, n)                                              \
+  (__extension__ (__builtin_constant_p (n)                                    \
+                  && ((__builtin_constant_p (s1)                              \
+                       && strlen (s1) < ((size) (n)))                         \
+                      || (__builtin_constant_p (s2)                           \
+                          && strlen (s2) < ((size) (n))))                     \
+                  ? strcmp (s1, s2) : strncmp (s1, s2, n)))
+
+int strncmp_macro(const char* a, const char* b) {
+  if (macro_strncmp(a, b, 4))
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result
+
+  if (macro_strncmp(a, b, 4) == 2)
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
+
+  if (macro_strncmp(a, b, 4) <= .0)
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' has suspicious implicit cast
+
+  if (macro_strncmp(a, b, 4) + 0)
+    return 0;
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: results of function 'strcmp' used by operator '+'
+
+  return 1;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-swapped-arguments.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-swapped-arguments.cpp
new file mode 100644
index 0000000..06fb2d8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-swapped-arguments.cpp
@@ -0,0 +1,53 @@
+// RUN: %check_clang_tidy %s bugprone-swapped-arguments %t
+
+void F(int, double);
+
+int SomeFunction();
+
+template <typename T, typename U>
+void G(T a, U b) {
+  F(a, b); // no-warning
+  F(2.0, 4);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: argument with implicit conversion from 'int' to 'double' followed by argument converted from 'double' to 'int', potentially swapped arguments.
+// CHECK-FIXES: F(4, 2.0)
+}
+
+void foo() {
+  F(1.0, 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: argument with implicit conversion from 'int' to 'double' followed by argument converted from 'double' to 'int', potentially swapped arguments.
+// CHECK-FIXES: F(3, 1.0)
+
+#define M(x, y) x##y()
+
+  double b = 1.0;
+  F(b, M(Some, Function));
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: argument with implicit conversion from 'int' to 'double' followed by argument converted from 'double' to 'int', potentially swapped arguments.
+// CHECK-FIXES: F(M(Some, Function), b);
+
+#define N F(b, SomeFunction())
+
+  N;
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: argument with implicit conversion from 'int' to 'double' followed by argument converted from 'double' to 'int', potentially swapped arguments.
+// In macro, don't emit fixits.
+// CHECK-FIXES: #define N F(b, SomeFunction())
+
+  G(b, 3);
+  G(3, 1.0);
+  G(0, 0);
+
+  F(1.0, 1.0);    // no-warning
+  F(3, 1.0);      // no-warning
+  F(true, false); // no-warning
+  F(0, 'c');      // no-warning
+
+#define APPLY(f, x, y) f(x, y)
+  APPLY(F, 1.0, 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: argument with implicit conversion from 'int' to 'double' followed by argument converted from 'double' to 'int', potentially swapped arguments.
+// CHECK-FIXES: APPLY(F, 3, 1.0);
+
+#define PARAMS 1.0, 3
+#define CALL(P) F(P)
+  CALL(PARAMS);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: argument with implicit conversion from 'int' to 'double' followed by argument converted from 'double' to 'int', potentially swapped arguments.
+// In macro, don't emit fixits.
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-terminating-continue.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-terminating-continue.cpp
new file mode 100644
index 0000000..4bdcbc4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-terminating-continue.cpp
@@ -0,0 +1,65 @@
+// RUN: %check_clang_tidy %s bugprone-terminating-continue %t
+
+void f() {
+  do {
+    continue;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
+    // CHECK-FIXES: break;
+  } while(false);
+
+  do {
+    continue;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
+    // CHECK-FIXES: break;
+  } while(0);
+
+  do {
+    continue;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
+    // CHECK-FIXES: break;
+  } while(nullptr);
+
+  do {
+    continue;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
+    // CHECK-FIXES: break;
+  } while(__null);
+
+
+  do {
+    int x = 1;
+    if (x > 0) continue;
+    // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
+    // CHECK-FIXES: if (x > 0) break;
+  } while (false);
+}
+
+void g() {
+  do {
+    do {
+      continue;
+      int x = 1;
+    } while (1 == 1);
+  } while (false);
+
+  do {
+    for (int i = 0; i < 1; ++i) {
+      continue;
+      int x = 1;
+    }
+  } while (false);
+
+  do {
+    while (true) {
+      continue;
+      int x = 1;
+    }
+  } while (false);
+
+  int v[] = {1,2,3,34};
+  do {
+    for (int n : v) {
+      if (n>2) continue;
+    }
+  } while (false);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-throw-keyword-missing.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-throw-keyword-missing.cpp
new file mode 100644
index 0000000..93ecf06
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-throw-keyword-missing.cpp
@@ -0,0 +1,167 @@
+// RUN: %check_clang_tidy %s bugprone-throw-keyword-missing %t -- -- -fexceptions
+
+namespace std {
+
+// std::string declaration (taken from test/clang-tidy/readability-redundant-string-cstr-msvc.cpp).
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C>>
+struct basic_string {
+  basic_string();
+  basic_string(const basic_string &);
+  // MSVC headers define two constructors instead of using optional arguments.
+  basic_string(const C *);
+  basic_string(const C *, const A &);
+  ~basic_string();
+};
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+
+// std::exception and std::runtime_error declaration.
+struct exception {
+  exception();
+  exception(const exception &other);
+  virtual ~exception();
+};
+
+struct runtime_error : public exception {
+  explicit runtime_error(const std::string &what_arg);
+};
+
+} // namespace std
+
+// The usage of this class should never emit a warning.
+struct RegularClass {};
+
+// Class name contains the substring "exception", in certain cases using this class should emit a warning.
+struct RegularException {
+  RegularException() {}
+
+  // Constructors with a single argument are treated differently (cxxFunctionalCastExpr).
+  RegularException(int) {}
+};
+
+// --------------
+
+void stdExceptionNotTrownTest(int i) {
+  if (i < 0)
+    // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception object created but not thrown; did you mean 'throw {{.*}}'? [bugprone-throw-keyword-missing]
+    std::exception();
+
+  if (i > 0)
+    // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
+    std::runtime_error("Unexpected argument");
+}
+
+void stdExceptionThrownTest(int i) {
+  if (i < 0)
+    throw std::exception();
+
+  if (i > 0)
+    throw std::runtime_error("Unexpected argument");
+}
+
+void regularClassNotThrownTest(int i) {
+  if (i < 0)
+    RegularClass();
+}
+
+void regularClassThrownTest(int i) {
+  if (i < 0)
+    throw RegularClass();
+}
+
+void nameContainsExceptionNotThrownTest(int i) {
+  if (i < 0)
+    // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
+    RegularException();
+
+  if (i > 0)
+    // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
+    RegularException(5);
+}
+
+void nameContainsExceptionThrownTest(int i) {
+  if (i < 0)
+    throw RegularException();
+
+  if (i > 0)
+    throw RegularException(5);
+}
+
+template <class Exception>
+void f(int i, Exception excToBeThrown) {}
+
+void funcCallWithTempExcTest() {
+  f(5, RegularException());
+}
+
+// Global variable initilization test.
+RegularException exc = RegularException();
+RegularException *excptr = new RegularException();
+
+void localVariableInitTest() {
+  RegularException exc = RegularException();
+  RegularException *excptr = new RegularException();
+}
+
+class CtorInitializerListTest {
+  RegularException exc;
+
+  CtorInitializerListTest() : exc(RegularException()) {}
+
+  CtorInitializerListTest(int) try : exc(RegularException()) {
+    // Constructor body
+  } catch (...) {
+    // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
+    RegularException();
+  }
+
+  CtorInitializerListTest(float);
+};
+
+CtorInitializerListTest::CtorInitializerListTest(float) try : exc(RegularException()) {
+  // Constructor body
+} catch (...) {
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
+  RegularException();
+}
+
+RegularException funcReturningExceptionTest(int i) {
+  return RegularException();
+}
+
+void returnedValueTest() {
+  funcReturningExceptionTest(3);
+}
+
+struct ClassBracedInitListTest {
+  ClassBracedInitListTest(RegularException exc) {}
+};
+
+void foo(RegularException, ClassBracedInitListTest) {}
+
+void bracedInitListTest() {
+  RegularException exc{};
+  ClassBracedInitListTest test = {RegularException()};
+  foo({}, {RegularException()});
+}
+
+typedef std::exception ERROR_BASE;
+class RegularError : public ERROR_BASE {};
+
+void typedefTest() {
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
+  RegularError();
+}
+
+struct ExceptionRAII {
+  ExceptionRAII() {}
+  ~ExceptionRAII() {}
+};
+
+void exceptionRAIITest() {
+  ExceptionRAII E;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undefined-memory-manipulation.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undefined-memory-manipulation.cpp
new file mode 100644
index 0000000..8055010
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undefined-memory-manipulation.cpp
@@ -0,0 +1,213 @@
+// RUN: %check_clang_tidy %s bugprone-undefined-memory-manipulation %t
+
+void *memset(void *, int, __SIZE_TYPE__);
+void *memcpy(void *, const void *, __SIZE_TYPE__);
+void *memmove(void *, const void *, __SIZE_TYPE__);
+
+namespace std {
+using ::memcpy;
+using ::memmove;
+using ::memset;
+}
+
+namespace types {
+// TriviallyCopyable types:
+struct Plain {
+  int n;
+};
+
+enum E {
+  X,
+  Y,
+  Z
+};
+
+struct Base {
+  float b;
+};
+
+struct Derived : Base {
+  bool d;
+};
+
+// not TriviallyCopyable types:
+struct Destruct {
+  ~Destruct() {}
+};
+
+struct Copy {
+  Copy() {}
+  Copy(const Copy &) {}
+};
+
+struct Move {
+  Move() {}
+  Move(Move &&) {}
+};
+
+struct VirtualFunc {
+  virtual void f() {}
+};
+
+struct VirtualBase : virtual Base {
+  int vb;
+};
+
+// Incomplete type, assume it is TriviallyCopyable.
+struct NoDef;
+
+} // end namespace types
+
+void f(types::NoDef *s) {
+  memset(s, 0, 5);
+}
+
+template <typename T>
+void memset_temp(T *b) {
+  memset(b, 0, sizeof(T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc' is not TriviallyCopyable [bugprone-undefined-memory-manipulation]
+}
+
+template <typename S, typename T>
+void memcpy_temp(S *a, T *b) {
+  memcpy(a, b, sizeof(T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualFunc'
+}
+
+template <typename S, typename T>
+void memmove_temp(S *a, T *b) {
+  memmove(a, b, sizeof(T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualFunc'
+}
+
+namespace aliases {
+using Copy2 = types::Copy;
+typedef types::Move Move2;
+}
+
+void notTriviallyCopyable() {
+  types::Plain p; // TriviallyCopyable for variety
+  types::Destruct d;
+  types::Copy c;
+  types::Move m;
+  types::VirtualFunc vf;
+  types::VirtualBase vb;
+
+  memset(&vf, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc'
+  memset(&d, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct'
+  memset(&c, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Copy'
+  std::memset(&m, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Move'
+  ::memset(&vb, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualBase'
+
+  memcpy(&p, &vf, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualFunc'
+  memcpy(&p, &d, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Destruct'
+  memcpy(&c, &p, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Copy'
+  std::memcpy(&m, &p, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Move'
+  ::memcpy(&vb, &p, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualBase'
+
+  memmove(&vf, &p, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc'
+  memmove(&d, &p, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct'
+  memmove(&p, &c, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Copy'
+  std::memmove(&p, &m, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Move'
+  ::memmove(&p, &vb, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualBase'
+
+#define MEMSET memset(&vf, 0, sizeof(int));
+  MEMSET
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc'
+#define MEMCPY memcpy(&d, &p, sizeof(int));
+  MEMCPY
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct'
+#define MEMMOVE memmove(&p, &c, sizeof(int));
+  MEMMOVE
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Copy'
+
+  memset_temp<types::VirtualFunc>(&vf);
+  memcpy_temp<types::Plain, types::VirtualFunc>(&p, &vf);
+  memmove_temp<types::Plain, types::VirtualFunc>(&p, &vf);
+
+  aliases::Copy2 c2;
+  aliases::Move2 m2;
+  memset(&c2, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Copy2'
+  memset(&m2, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Move2'
+
+  typedef aliases::Copy2 Copy3;
+  typedef aliases::Copy2 *PCopy2;
+  typedef Copy3 *PCopy3;
+  Copy3 c3;
+  PCopy2 pc2;
+  PCopy3 pc3;
+  memset(&c3, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'Copy3'
+  memset(pc2, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Copy2'
+  memset(pc3, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'Copy3'
+}
+
+void triviallyCopyable() {
+  types::Plain p;
+  types::Base base;
+  types::Derived derived;
+
+  int i = 5;
+  int ia[3] = {1, 2, 3};
+  float f = 3.14;
+  float fa[3] = {1.1, 2.2, 3.3};
+  bool b = false;
+  bool ba[2] = {true, false};
+  types::E e = types::X;
+  p.n = 2;
+
+  memset(&p, 0, sizeof(int));
+  memset(&base, 0, sizeof(float));
+  memset(&derived, 0, sizeof(bool));
+  memset(&i, 0, sizeof(int));
+  memset(ia, 0, sizeof(int));
+  memset(&f, 0, sizeof(float));
+  memset(fa, 0, sizeof(float));
+  memset(&b, 0, sizeof(bool));
+  memset(ba, 0, sizeof(bool));
+  memset(&e, 0, sizeof(int));
+  memset(&p.n, 0, sizeof(int));
+
+  memcpy(&p, &p, sizeof(int));
+  memcpy(&base, &base, sizeof(float));
+  memcpy(&derived, &derived, sizeof(bool));
+  memcpy(&i, &i, sizeof(int));
+  memcpy(ia, ia, sizeof(int));
+  memcpy(&f, &f, sizeof(float));
+  memcpy(fa, fa, sizeof(float));
+  memcpy(&b, &b, sizeof(bool));
+  memcpy(ba, ba, sizeof(bool));
+  memcpy(&e, &e, sizeof(int));
+  memcpy(&p.n, &p.n, sizeof(int));
+
+  memmove(&p, &p, sizeof(int));
+  memmove(&base, &base, sizeof(float));
+  memmove(&derived, &derived, sizeof(bool));
+  memmove(&i, &i, sizeof(int));
+  memmove(ia, ia, sizeof(int));
+  memmove(&f, &f, sizeof(float));
+  memmove(fa, fa, sizeof(float));
+  memmove(&b, &b, sizeof(bool));
+  memmove(ba, ba, sizeof(bool));
+  memmove(&e, &e, sizeof(int));
+  memmove(&p.n, &p.n, sizeof(int));
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undelegated-constructor-cxx98.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undelegated-constructor-cxx98.cpp
new file mode 100644
index 0000000..f859f24
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undelegated-constructor-cxx98.cpp
@@ -0,0 +1,23 @@
+// RUN: clang-tidy %s -checks=-*,bugprone-undelegated-constructor -- -std=c++98 | count 0
+
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+
+struct Ctor;
+Ctor foo();
+
+struct Ctor {
+  Ctor();
+  Ctor(int);
+  Ctor(int, int);
+  Ctor(Ctor *i) {
+    Ctor();
+    Ctor(0);
+    Ctor(1, 2);
+    foo();
+  }
+};
+
+Ctor::Ctor() {
+  Ctor(1);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undelegated-constructor.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undelegated-constructor.cpp
new file mode 100644
index 0000000..09b20ac
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-undelegated-constructor.cpp
@@ -0,0 +1,54 @@
+// RUN: %check_clang_tidy %s bugprone-undelegated-constructor %t
+
+struct Ctor;
+Ctor foo();
+
+struct Ctor {
+  Ctor();
+  Ctor(int);
+  Ctor(int, int);
+  Ctor(Ctor *i) {
+    Ctor();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: did you intend to call a delegated constructor? A temporary object is created here instead [bugprone-undelegated-constructor]
+    Ctor(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: did you intend to call a delegated constructor?
+    Ctor(1, 2);
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: did you intend to call a delegated constructor?
+    foo();
+  }
+};
+
+Ctor::Ctor() {
+  Ctor(1);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: did you intend to call a delegated constructor?
+}
+
+Ctor::Ctor(int i) : Ctor(i, 1) {} // properly delegated.
+
+struct Dtor {
+  Dtor();
+  Dtor(int);
+  Dtor(int, int);
+  Dtor(Ctor *i) {
+    Dtor();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: did you intend to call a delegated constructor?
+    Dtor(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: did you intend to call a delegated constructor?
+    Dtor(1, 2);
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: did you intend to call a delegated constructor?
+  }
+  ~Dtor();
+};
+
+struct Base {};
+struct Derived : public Base {
+  Derived() { Base(); }
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: did you intend to call a delegated constructor?
+};
+
+template <typename T>
+struct TDerived : public Base {
+  TDerived() { Base(); }
+};
+
+TDerived<int> t;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-raii.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-raii.cpp
new file mode 100644
index 0000000..91ade52
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-raii.cpp
@@ -0,0 +1,68 @@
+// RUN: %check_clang_tidy %s bugprone-unused-raii %t
+
+struct Foo {
+  Foo();
+  Foo(int);
+  Foo(int, int);
+  ~Foo();
+};
+
+struct Bar {
+  Bar();
+};
+
+struct FooBar {
+  FooBar();
+  Foo f;
+};
+
+template <typename T>
+void qux() {
+  T(42);
+}
+
+template <typename T>
+struct TFoo {
+  TFoo(T);
+  ~TFoo();
+};
+
+Foo f();
+
+struct Ctor {
+  Ctor(int);
+  Ctor() {
+    Ctor(0); // TODO: warn here.
+  }
+};
+
+void test() {
+  Foo(42);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: object destroyed immediately after creation; did you mean to name the object?
+// CHECK-FIXES: Foo give_me_a_name(42);
+  Foo(23, 42);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: object destroyed immediately after creation; did you mean to name the object?
+// CHECK-FIXES: Foo give_me_a_name(23, 42);
+  Foo();
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: object destroyed immediately after creation; did you mean to name the object?
+// CHECK-FIXES: Foo give_me_a_name;
+  TFoo<int>(23);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: object destroyed immediately after creation; did you mean to name the object?
+// CHECK-FIXES: TFoo<int> give_me_a_name(23);
+
+  FooBar();
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: object destroyed immediately after creation; did you mean to name the object?
+// CHECK-FIXES: FooBar give_me_a_name;
+
+  Bar();
+  f();
+  qux<Foo>();
+
+#define M Foo();
+  M
+
+  {
+    Foo();
+  }
+  Foo();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-return-value-custom.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-return-value-custom.cpp
new file mode 100644
index 0000000..efe3705
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-return-value-custom.cpp
@@ -0,0 +1,100 @@
+// RUN: %check_clang_tidy %s bugprone-unused-return-value %t \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: bugprone-unused-return-value.CheckedFunctions, \
+// RUN:    value: "::fun;::ns::Outer::Inner::memFun;::ns::Type::staticFun;::ns::ClassTemplate::memFun;::ns::ClassTemplate::staticFun"}]}' \
+// RUN: --
+
+namespace std {
+
+template <typename T>
+T *launder(T *);
+
+} // namespace std
+
+namespace ns {
+
+struct Outer {
+  struct Inner {
+    bool memFun();
+  };
+};
+
+using AliasName = Outer;
+
+struct Derived : public Outer::Inner {};
+
+struct Retval {
+  int *P;
+  Retval() { P = new int; }
+  ~Retval() { delete P; }
+};
+
+struct Type {
+  Retval memFun();
+  static Retval staticFun();
+};
+
+template <typename T>
+struct ClassTemplate {
+  Retval memFun();
+  static Retval staticFun();
+};
+
+} // namespace ns
+
+int fun();
+void fun(int);
+
+void warning() {
+  fun();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  (fun());
+  // CHECK-MESSAGES: [[@LINE-1]]:4: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  ns::Outer::Inner ObjA1;
+  ObjA1.memFun();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  ns::AliasName::Inner ObjA2;
+  ObjA2.memFun();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  ns::Derived ObjA3;
+  ObjA3.memFun();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  ns::Type::staticFun();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  ns::ClassTemplate<int> ObjA4;
+  ObjA4.memFun();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  ns::ClassTemplate<int>::staticFun();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+}
+
+void noWarning() {
+  auto R1 = fun();
+
+  ns::Outer::Inner ObjB1;
+  auto R2 = ObjB1.memFun();
+
+  auto R3 = ns::Type::staticFun();
+
+  ns::ClassTemplate<int> ObjB2;
+  auto R4 = ObjB2.memFun();
+
+  auto R5 = ns::ClassTemplate<int>::staticFun();
+
+  // test calling a void overload of a checked function
+  fun(5);
+
+  // test discarding return value of functions that are not configured to be checked
+  int I = 1;
+  std::launder(&I);
+
+  ns::Type ObjB3;
+  ObjB3.memFun();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-return-value.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-return-value.cpp
new file mode 100644
index 0000000..b4f280e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-unused-return-value.cpp
@@ -0,0 +1,215 @@
+// RUN: %check_clang_tidy %s bugprone-unused-return-value %t -- -- -fexceptions
+
+namespace std {
+
+struct future {};
+
+enum class launch {
+  async,
+  deferred
+};
+
+template <typename Function, typename... Args>
+future async(Function &&, Args &&...);
+
+template <typename Function, typename... Args>
+future async(launch, Function &&, Args &&...);
+
+template <typename ForwardIt, typename T>
+ForwardIt remove(ForwardIt, ForwardIt, const T &);
+
+template <typename ForwardIt, typename UnaryPredicate>
+ForwardIt remove_if(ForwardIt, ForwardIt, UnaryPredicate);
+
+template <typename ForwardIt>
+ForwardIt unique(ForwardIt, ForwardIt);
+
+template <typename T>
+struct default_delete;
+
+template <typename T, typename Deleter = std::default_delete<T>>
+struct unique_ptr {
+  T *release() noexcept;
+};
+
+template <typename T>
+struct char_traits;
+
+template <typename T>
+struct allocator;
+
+template <typename CharT,
+          typename Traits = char_traits<CharT>,
+          typename Allocator = allocator<CharT>>
+struct basic_string {
+  bool empty() const;
+};
+
+typedef basic_string<char> string;
+
+template <typename T, typename Allocator = std::allocator<T>>
+struct vector {
+  bool empty() const noexcept;
+};
+
+// the check should be able to match std lib calls even if the functions are
+// declared inside inline namespaces
+inline namespace v1 {
+
+template <typename T>
+T *launder(T *);
+
+} // namespace v1
+} // namespace std
+
+struct Foo {
+  void f();
+};
+
+int increment(int i) {
+  return i + 1;
+}
+
+void useFuture(const std::future &fut);
+
+void warning() {
+  std::async(increment, 42);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  std::async(std::launch::async, increment, 42);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  Foo F;
+  std::launder(&F);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  std::remove(nullptr, nullptr, 1);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  std::remove_if(nullptr, nullptr, nullptr);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  std::unique(nullptr, nullptr);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  std::unique_ptr<Foo> UPtr;
+  UPtr.release();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  std::string Str;
+  Str.empty();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  std::vector<Foo> Vec;
+  Vec.empty();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  // test discarding return values inside different kinds of statements
+
+  auto Lambda = [] { std::remove(nullptr, nullptr, 1); };
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  if (true)
+    std::remove(nullptr, nullptr, 1);
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+  else if (true)
+    std::remove(nullptr, nullptr, 1);
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+  else
+    std::remove(nullptr, nullptr, 1);
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  while (true)
+    std::remove(nullptr, nullptr, 1);
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  do
+    std::remove(nullptr, nullptr, 1);
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+  while (true);
+
+  for (;;)
+    std::remove(nullptr, nullptr, 1);
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  for (std::remove(nullptr, nullptr, 1);;)
+    // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the value returned by this function should be used [bugprone-unused-return-value]
+    ;
+
+  for (;; std::remove(nullptr, nullptr, 1))
+    // CHECK-MESSAGES: [[@LINE-1]]:11: warning: the value returned by this function should be used [bugprone-unused-return-value]
+    ;
+
+  for (auto C : "foo")
+    std::remove(nullptr, nullptr, 1);
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+
+  switch (1) {
+  case 1:
+    std::remove(nullptr, nullptr, 1);
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+    break;
+  default:
+    std::remove(nullptr, nullptr, 1);
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+    break;
+  }
+
+  try {
+    std::remove(nullptr, nullptr, 1);
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+  } catch (...) {
+    std::remove(nullptr, nullptr, 1);
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should be used [bugprone-unused-return-value]
+  }
+}
+
+void noWarning() {
+  auto AsyncRetval1 = std::async(increment, 42);
+  auto AsyncRetval2 = std::async(std::launch::async, increment, 42);
+
+  Foo FNoWarning;
+  auto LaunderRetval = std::launder(&FNoWarning);
+
+  auto RemoveRetval = std::remove(nullptr, nullptr, 1);
+
+  auto RemoveIfRetval = std::remove_if(nullptr, nullptr, nullptr);
+
+  auto UniqueRetval = std::unique(nullptr, nullptr);
+
+  std::unique_ptr<Foo> UPtrNoWarning;
+  auto ReleaseRetval = UPtrNoWarning.release();
+
+  std::string StrNoWarning;
+  auto StrEmptyRetval = StrNoWarning.empty();
+
+  std::vector<Foo> VecNoWarning;
+  auto VecEmptyRetval = VecNoWarning.empty();
+
+  // test using the return value in different kinds of expressions
+  useFuture(std::async(increment, 42));
+  std::launder(&FNoWarning)->f();
+  delete std::launder(&FNoWarning);
+
+  if (std::launder(&FNoWarning))
+    ;
+  for (; std::launder(&FNoWarning);)
+    ;
+  while (std::launder(&FNoWarning))
+    ;
+  do
+    ;
+  while (std::launder(&FNoWarning));
+  switch (std::unique(1, 1))
+    ;
+
+  // cast to void should allow ignoring the return value
+  (void)std::async(increment, 42);
+
+  // test discarding return value of functions that are not configured to be checked
+  increment(1);
+
+  // test that the check is disabled inside GNU statement expressions
+  ({ std::async(increment, 42); });
+  auto StmtExprRetval = ({ std::async(increment, 42); });
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-use-after-move.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-use-after-move.cpp
new file mode 100644
index 0000000..43e6322
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-use-after-move.cpp
@@ -0,0 +1,1164 @@
+// RUN: %check_clang_tidy %s bugprone-use-after-move %t -- -- -std=c++11 -fno-delayed-template-parsing
+
+typedef decltype(nullptr) nullptr_t;
+
+namespace std {
+typedef unsigned size_t;
+
+template <typename T>
+struct unique_ptr {
+  unique_ptr();
+  T *get() const;
+  explicit operator bool() const;
+  void reset(T *ptr);
+  T &operator*() const;
+  T *operator->() const;
+  T& operator[](size_t i) const;
+};
+
+template <typename T>
+struct shared_ptr {
+  shared_ptr();
+  T *get() const;
+  explicit operator bool() const;
+  void reset(T *ptr);
+  T &operator*() const;
+  T *operator->() const;
+};
+
+template <typename T>
+struct weak_ptr {
+  weak_ptr();
+  bool expired() const;
+};
+
+#define DECLARE_STANDARD_CONTAINER(name) \
+  template <typename T>                  \
+  struct name {                          \
+    name();                              \
+    void clear();                        \
+    bool empty();                        \
+  }
+
+#define DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(name) \
+  template <typename T>                              \
+  struct name {                                      \
+    name();                                          \
+    void clear();                                    \
+    bool empty();                                    \
+    void assign(size_t, const T &);                  \
+  }
+
+DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(basic_string);
+DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(vector);
+DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(deque);
+DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(forward_list);
+DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(list);
+DECLARE_STANDARD_CONTAINER(set);
+DECLARE_STANDARD_CONTAINER(map);
+DECLARE_STANDARD_CONTAINER(multiset);
+DECLARE_STANDARD_CONTAINER(multimap);
+DECLARE_STANDARD_CONTAINER(unordered_set);
+DECLARE_STANDARD_CONTAINER(unordered_map);
+DECLARE_STANDARD_CONTAINER(unordered_multiset);
+DECLARE_STANDARD_CONTAINER(unordered_multimap);
+
+typedef basic_string<char> string;
+
+template <typename>
+struct remove_reference;
+
+template <typename _Tp>
+struct remove_reference {
+  typedef _Tp type;
+};
+
+template <typename _Tp>
+struct remove_reference<_Tp &> {
+  typedef _Tp type;
+};
+
+template <typename _Tp>
+struct remove_reference<_Tp &&> {
+  typedef _Tp type;
+};
+
+template <typename _Tp>
+constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) noexcept {
+  return static_cast<typename remove_reference<_Tp>::type &&>(__t);
+}
+
+} // namespace std
+
+class A {
+public:
+  A();
+  A(const A &);
+  A(A &&);
+
+  A &operator=(const A &);
+  A &operator=(A &&);
+
+  void foo() const;
+  int getInt() const;
+
+  operator bool() const;
+
+  int i;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// General tests.
+
+// Simple case.
+void simple() {
+  A a;
+  a.foo();
+  A other_a = std::move(a);
+  a.foo();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'a' used after it was moved
+  // CHECK-MESSAGES: [[@LINE-3]]:15: note: move occurred here
+}
+
+// A warning should only be emitted for one use-after-move.
+void onlyFlagOneUseAfterMove() {
+  A a;
+  a.foo();
+  A other_a = std::move(a);
+  a.foo();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'a' used after it was moved
+  // CHECK-MESSAGES: [[@LINE-3]]:15: note: move occurred here
+  a.foo();
+}
+
+void moveAfterMove() {
+  // Move-after-move also counts as a use.
+  {
+    A a;
+    std::move(a);
+    std::move(a);
+    // CHECK-MESSAGES: [[@LINE-1]]:15: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+  // This is also true if the move itself turns into the use on the second loop
+  // iteration.
+  {
+    A a;
+    for (int i = 0; i < 10; ++i) {
+      std::move(a);
+      // CHECK-MESSAGES: [[@LINE-1]]:17: warning: 'a' used after it was moved
+      // CHECK-MESSAGES: [[@LINE-2]]:7: note: move occurred here
+      // CHECK-MESSAGES: [[@LINE-3]]:17: note: the use happens in a later loop
+    }
+  }
+}
+
+// Checks also works on function parameters that have a use-after move.
+void parameters(A a) {
+  std::move(a);
+  a.foo();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'a' used after it was moved
+  // CHECK-MESSAGES: [[@LINE-3]]:3: note: move occurred here
+}
+
+void standardSmartPtr() {
+  // std::unique_ptr<>, std::shared_ptr<> and std::weak_ptr<> are guaranteed to
+  // be null after a std::move. So the check only flags accesses that would
+  // dereference the pointer.
+  {
+    std::unique_ptr<A> ptr;
+    std::move(ptr);
+    ptr.get();
+    static_cast<bool>(ptr);
+    *ptr;
+    // CHECK-MESSAGES: [[@LINE-1]]:6: warning: 'ptr' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-5]]:5: note: move occurred here
+  }
+  {
+    std::unique_ptr<A> ptr;
+    std::move(ptr);
+    ptr->foo();
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'ptr' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+  {
+    std::unique_ptr<A> ptr;
+    std::move(ptr);
+    ptr[0];
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'ptr' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+  {
+    std::shared_ptr<A> ptr;
+    std::move(ptr);
+    ptr.get();
+    static_cast<bool>(ptr);
+    *ptr;
+    // CHECK-MESSAGES: [[@LINE-1]]:6: warning: 'ptr' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-5]]:5: note: move occurred here
+  }
+  {
+    std::shared_ptr<A> ptr;
+    std::move(ptr);
+    ptr->foo();
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'ptr' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+  {
+    // std::weak_ptr<> cannot be dereferenced directly, so we only check that
+    // member functions may be called on it after a move.
+    std::weak_ptr<A> ptr;
+    std::move(ptr);
+    ptr.expired();
+  }
+  // Make sure we recognize std::unique_ptr<> or std::shared_ptr<> if they're
+  // wrapped in a typedef.
+  {
+    typedef std::unique_ptr<A> PtrToA;
+    PtrToA ptr;
+    std::move(ptr);
+    ptr.get();
+  }
+  {
+    typedef std::shared_ptr<A> PtrToA;
+    PtrToA ptr;
+    std::move(ptr);
+    ptr.get();
+  }
+  // And we don't get confused if the template argument is a little more
+  // involved.
+  {
+    struct B {
+      typedef A AnotherNameForA;
+    };
+    std::unique_ptr<B::AnotherNameForA> ptr;
+    std::move(ptr);
+    ptr.get();
+  }
+  // We don't give any special treatment to types that are called "unique_ptr"
+  // or "shared_ptr" but are not in the "::std" namespace.
+  {
+    struct unique_ptr {
+      void get();
+    } ptr;
+    std::move(ptr);
+    ptr.get();
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'ptr' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+}
+
+// The check also works in member functions.
+class Container {
+  void useAfterMoveInMemberFunction() {
+    A a;
+    std::move(a);
+    a.foo();
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+};
+
+// We see the std::move() if it's inside a declaration.
+void moveInDeclaration() {
+  A a;
+  A another_a(std::move(a));
+  a.foo();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'a' used after it was moved
+  // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+}
+
+// We see the std::move if it's inside an initializer list. Initializer lists
+// are a special case because they cause ASTContext::getParents() to return
+// multiple parents for certain nodes in their subtree. This is because
+// RecursiveASTVisitor visits both the syntactic and semantic forms of
+// InitListExpr, and the parent-child relationships are different between the
+// two forms.
+void moveInInitList() {
+  struct S {
+    A a;
+  };
+  A a;
+  S s{std::move(a)};
+  a.foo();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'a' used after it was moved
+  // CHECK-MESSAGES: [[@LINE-3]]:7: note: move occurred here
+}
+
+void lambdas() {
+  // Use-after-moves inside a lambda should be detected.
+  {
+    A a;
+    auto lambda = [a] {
+      std::move(a);
+      a.foo();
+      // CHECK-MESSAGES: [[@LINE-1]]:7: warning: 'a' used after it was moved
+      // CHECK-MESSAGES: [[@LINE-3]]:7: note: move occurred here
+    };
+  }
+  // This is just as true if the variable was declared inside the lambda.
+  {
+    auto lambda = [] {
+      A a;
+      std::move(a);
+      a.foo();
+      // CHECK-MESSAGES: [[@LINE-1]]:7: warning: 'a' used after it was moved
+      // CHECK-MESSAGES: [[@LINE-3]]:7: note: move occurred here
+    };
+  }
+  // But don't warn if the move happened inside the lambda but the use happened
+  // outside -- because
+  // - the 'a' inside the lambda is a copy, and
+  // - we don't know when the lambda will get called anyway
+  {
+    A a;
+    auto lambda = [a] {
+      std::move(a);
+    };
+    a.foo();
+  }
+  // Warn if the use consists of a capture that happens after a move.
+  {
+    A a;
+    std::move(a);
+    auto lambda = [a]() { a.foo(); };
+    // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+  // ...even if the capture was implicit.
+  {
+    A a;
+    std::move(a);
+    auto lambda = [=]() { a.foo(); };
+    // CHECK-MESSAGES: [[@LINE-1]]:27: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+  // Same tests but for capture by reference.
+  {
+    A a;
+    std::move(a);
+    auto lambda = [&a]() { a.foo(); };
+    // CHECK-MESSAGES: [[@LINE-1]]:21: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+  {
+    A a;
+    std::move(a);
+    auto lambda = [&]() { a.foo(); };
+    // CHECK-MESSAGES: [[@LINE-1]]:27: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+  // But don't warn if the move happened after the capture.
+  {
+    A a;
+    auto lambda = [a]() { a.foo(); };
+    std::move(a);
+  }
+  // ...and again, same thing with an implicit move.
+  {
+    A a;
+    auto lambda = [=]() { a.foo(); };
+    std::move(a);
+  }
+  // Same tests but for capture by reference.
+  {
+    A a;
+    auto lambda = [&a]() { a.foo(); };
+    std::move(a);
+  }
+  {
+    A a;
+    auto lambda = [&]() { a.foo(); };
+    std::move(a);
+  }
+}
+
+// Use-after-moves are detected in uninstantiated templates if the moved type
+// is not a dependent type.
+template <class T>
+void movedTypeIsNotDependentType() {
+  T t;
+  A a;
+  std::move(a);
+  a.foo();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'a' used after it was moved
+  // CHECK-MESSAGES: [[@LINE-3]]:3: note: move occurred here
+}
+
+// And if the moved type is a dependent type, the use-after-move is detected if
+// the template is instantiated.
+template <class T>
+void movedTypeIsDependentType() {
+  T t;
+  std::move(t);
+  t.foo();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 't' used after it was moved
+  // CHECK-MESSAGES: [[@LINE-3]]:3: note: move occurred here
+}
+template void movedTypeIsDependentType<A>();
+
+// We handle the case correctly where the move consists of an implicit call
+// to a conversion operator.
+void implicitConversionOperator() {
+  struct Convertible {
+    operator A() && { return A(); }
+  };
+  void takeA(A a);
+
+  Convertible convertible;
+  takeA(std::move(convertible));
+  convertible;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'convertible' used after it was moved
+  // CHECK-MESSAGES: [[@LINE-3]]:9: note: move occurred here
+}
+
+// Using decltype on an expression is not a use.
+void decltypeIsNotUse() {
+  A a;
+  std::move(a);
+  decltype(a) other_a;
+}
+
+// Ignore moves or uses that occur as part of template arguments.
+template <int>
+class ClassTemplate {
+public:
+  void foo(A a);
+};
+template <int>
+void functionTemplate(A a);
+void templateArgIsNotUse() {
+  {
+    // A pattern like this occurs in the EXPECT_EQ and ASSERT_EQ macros in
+    // Google Test.
+    A a;
+    ClassTemplate<sizeof(A(std::move(a)))>().foo(std::move(a));
+  }
+  {
+    A a;
+    functionTemplate<sizeof(A(std::move(a)))>(std::move(a));
+  }
+}
+
+// Ignore moves of global variables.
+A global_a;
+void ignoreGlobalVariables() {
+  std::move(global_a);
+  global_a.foo();
+}
+
+// Ignore moves of member variables.
+class IgnoreMemberVariables {
+  A a;
+  static A static_a;
+
+  void f() {
+    std::move(a);
+    a.foo();
+
+    std::move(static_a);
+    static_a.foo();
+  }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests involving control flow.
+
+void useAndMoveInLoop() {
+  // Warn about use-after-moves if they happen in a later loop iteration than
+  // the std::move().
+  {
+    A a;
+    for (int i = 0; i < 10; ++i) {
+      a.foo();
+      // CHECK-MESSAGES: [[@LINE-1]]:7: warning: 'a' used after it was moved
+      // CHECK-MESSAGES: [[@LINE+2]]:7: note: move occurred here
+      // CHECK-MESSAGES: [[@LINE-3]]:7: note: the use happens in a later loop
+      std::move(a);
+    }
+  }
+  // However, this case shouldn't be flagged -- the scope of the declaration of
+  // 'a' is important.
+  {
+    for (int i = 0; i < 10; ++i) {
+      A a;
+      a.foo();
+      std::move(a);
+    }
+  }
+  // Same as above, except that we have an unrelated variable being declared in
+  // the same declaration as 'a'. This case is interesting because it tests that
+  // the synthetic DeclStmts generated by the CFG are sequenced correctly
+  // relative to the other statements.
+  {
+    for (int i = 0; i < 10; ++i) {
+      A a, other;
+      a.foo();
+      std::move(a);
+    }
+  }
+  // Don't warn if we return after the move.
+  {
+    A a;
+    for (int i = 0; i < 10; ++i) {
+      a.foo();
+      if (a.getInt() > 0) {
+        std::move(a);
+        return;
+      }
+    }
+  }
+}
+
+void differentBranches(int i) {
+  // Don't warn if the use is in a different branch from the move.
+  {
+    A a;
+    if (i > 0) {
+      std::move(a);
+    } else {
+      a.foo();
+    }
+  }
+  // Same thing, but with a ternary operator.
+  {
+    A a;
+    i > 0 ? (void)std::move(a) : a.foo();
+  }
+  // A variation on the theme above.
+  {
+    A a;
+    a.getInt() > 0 ? a.getInt() : A(std::move(a)).getInt();
+  }
+  // Same thing, but with a switch statement.
+  {
+    A a;
+    switch (i) {
+    case 1:
+      std::move(a);
+      break;
+    case 2:
+      a.foo();
+      break;
+    }
+  }
+  // However, if there's a fallthrough, we do warn.
+  {
+    A a;
+    switch (i) {
+    case 1:
+      std::move(a);
+    case 2:
+      a.foo();
+      // CHECK-MESSAGES: [[@LINE-1]]:7: warning: 'a' used after it was moved
+      // CHECK-MESSAGES: [[@LINE-4]]:7: note: move occurred here
+      break;
+    }
+  }
+}
+
+// False positive: A use-after-move is flagged even though the "if (b)" and
+// "if (!b)" are mutually exclusive.
+void mutuallyExclusiveBranchesFalsePositive(bool b) {
+  A a;
+  if (b) {
+    std::move(a);
+  }
+  if (!b) {
+    a.foo();
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-5]]:5: note: move occurred here
+  }
+}
+
+// Destructors marked [[noreturn]] are handled correctly in the control flow
+// analysis. (These are used in some styles of assertion macros.)
+class FailureLogger {
+public:
+  FailureLogger();
+  [[noreturn]] ~FailureLogger();
+  void log(const char *);
+};
+#define ASSERT(x) \
+  while (x)       \
+  FailureLogger().log(#x)
+bool operationOnA(A);
+void noreturnDestructor() {
+  A a;
+  // The while loop in the ASSERT() would ordinarily have the potential to cause
+  // a use-after-move because the second iteration of the loop would be using a
+  // variable that had been moved from in the first iteration. Check that the
+  // CFG knows that the second iteration of the loop is never reached because
+  // the FailureLogger destructor is marked [[noreturn]].
+  ASSERT(operationOnA(std::move(a)));
+}
+#undef ASSERT
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests for reinitializations
+
+template <class T>
+void swap(T &a, T &b) {
+  T tmp = std::move(a);
+  a = std::move(b);
+  b = std::move(tmp);
+}
+void assignments(int i) {
+  // Don't report a use-after-move if the variable was assigned to in the
+  // meantime.
+  {
+    A a;
+    std::move(a);
+    a = A();
+    a.foo();
+  }
+  // The assignment should also be recognized if move, assignment and use don't
+  // all happen in the same block (but the assignment is still guaranteed to
+  // prevent a use-after-move).
+  {
+    A a;
+    if (i == 1) {
+      std::move(a);
+      a = A();
+    }
+    if (i == 2) {
+      a.foo();
+    }
+  }
+  {
+    A a;
+    if (i == 1) {
+      std::move(a);
+    }
+    if (i == 2) {
+      a = A();
+      a.foo();
+    }
+  }
+  // The built-in assignment operator should also be recognized as a
+  // reinitialization. (std::move() may be called on built-in types in template
+  // code.)
+  {
+    int a1 = 1, a2 = 2;
+    swap(a1, a2);
+  }
+  // A std::move() after the assignment makes the variable invalid again.
+  {
+    A a;
+    std::move(a);
+    a = A();
+    std::move(a);
+    a.foo();
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+  // Report a use-after-move if we can't be sure that the variable was assigned
+  // to.
+  {
+    A a;
+    std::move(a);
+    if (i < 10) {
+      a = A();
+    }
+    if (i > 5) {
+      a.foo();
+      // CHECK-MESSAGES: [[@LINE-1]]:7: warning: 'a' used after it was moved
+      // CHECK-MESSAGES: [[@LINE-7]]:5: note: move occurred here
+    }
+  }
+}
+
+// Passing the object to a function through a non-const pointer or reference
+// counts as a re-initialization.
+void passByNonConstPointer(A *);
+void passByNonConstReference(A &);
+void passByNonConstPointerIsReinit() {
+  {
+    A a;
+    std::move(a);
+    passByNonConstPointer(&a);
+    a.foo();
+  }
+  {
+    A a;
+    std::move(a);
+    passByNonConstReference(a);
+    a.foo();
+  }
+}
+
+// Passing the object through a const pointer or reference counts as a use --
+// since the called function cannot reinitialize the object.
+void passByConstPointer(const A *);
+void passByConstReference(const A &);
+void passByConstPointerIsUse() {
+  {
+    // Declaring 'a' as const so that no ImplicitCastExpr is inserted into the
+    // AST -- we wouldn't want the check to rely solely on that to detect a
+    // const pointer argument.
+    const A a;
+    std::move(a);
+    passByConstPointer(&a);
+    // CHECK-MESSAGES: [[@LINE-1]]:25: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+  const A a;
+  std::move(a);
+  passByConstReference(a);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: 'a' used after it was moved
+  // CHECK-MESSAGES: [[@LINE-3]]:3: note: move occurred here
+}
+
+// Clearing a standard container using clear() is treated as a
+// re-initialization.
+void standardContainerClearIsReinit() {
+  {
+    std::string container;
+    std::move(container);
+    container.clear();
+    container.empty();
+  }
+  {
+    std::vector<int> container;
+    std::move(container);
+    container.clear();
+    container.empty();
+
+    auto container2 = container;
+    std::move(container2);
+    container2.clear();
+    container2.empty();
+  }
+  {
+    std::deque<int> container;
+    std::move(container);
+    container.clear();
+    container.empty();
+  }
+  {
+    std::forward_list<int> container;
+    std::move(container);
+    container.clear();
+    container.empty();
+  }
+  {
+    std::list<int> container;
+    std::move(container);
+    container.clear();
+    container.empty();
+  }
+  {
+    std::set<int> container;
+    std::move(container);
+    container.clear();
+    container.empty();
+  }
+  {
+    std::map<int> container;
+    std::move(container);
+    container.clear();
+    container.empty();
+  }
+  {
+    std::multiset<int> container;
+    std::move(container);
+    container.clear();
+    container.empty();
+  }
+  {
+    std::multimap<int> container;
+    std::move(container);
+    container.clear();
+    container.empty();
+  }
+  {
+    std::unordered_set<int> container;
+    std::move(container);
+    container.clear();
+    container.empty();
+  }
+  {
+    std::unordered_map<int> container;
+    std::move(container);
+    container.clear();
+    container.empty();
+  }
+  {
+    std::unordered_multiset<int> container;
+    std::move(container);
+    container.clear();
+    container.empty();
+  }
+  {
+    std::unordered_multimap<int> container;
+    std::move(container);
+    container.clear();
+    container.empty();
+  }
+  // This should also work for typedefs of standard containers.
+  {
+    typedef std::vector<int> IntVector;
+    IntVector container;
+    std::move(container);
+    container.clear();
+    container.empty();
+  }
+  // But it shouldn't work for non-standard containers.
+  {
+    // This might be called "vector", but it's not in namespace "std".
+    struct vector {
+      void clear() {}
+    } container;
+    std::move(container);
+    container.clear();
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'container' used after it was
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+  // An intervening clear() on a different container does not reinitialize.
+  {
+    std::vector<int> container1, container2;
+    std::move(container1);
+    container2.clear();
+    container1.empty();
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'container1' used after it was
+    // CHECK-MESSAGES: [[@LINE-4]]:5: note: move occurred here
+  }
+}
+
+// Clearing a standard container using assign() is treated as a
+// re-initialization.
+void standardContainerAssignIsReinit() {
+  {
+    std::string container;
+    std::move(container);
+    container.assign(0, ' ');
+    container.empty();
+  }
+  {
+    std::vector<int> container;
+    std::move(container);
+    container.assign(0, 0);
+    container.empty();
+  }
+  {
+    std::deque<int> container;
+    std::move(container);
+    container.assign(0, 0);
+    container.empty();
+  }
+  {
+    std::forward_list<int> container;
+    std::move(container);
+    container.assign(0, 0);
+    container.empty();
+  }
+  {
+    std::list<int> container;
+    std::move(container);
+    container.clear();
+    container.empty();
+  }
+  // But it doesn't work for non-standard containers.
+  {
+    // This might be called "vector", but it's not in namespace "std".
+    struct vector {
+      void assign(std::size_t, int) {}
+    } container;
+    std::move(container);
+    container.assign(0, 0);
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'container' used after it was
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+  // An intervening assign() on a different container does not reinitialize.
+  {
+    std::vector<int> container1, container2;
+    std::move(container1);
+    container2.assign(0, 0);
+    container1.empty();
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'container1' used after it was
+    // CHECK-MESSAGES: [[@LINE-4]]:5: note: move occurred here
+  }
+}
+
+// Resetting the standard smart pointer types using reset() is treated as a
+// re-initialization. (We don't test std::weak_ptr<> because it can't be
+// dereferenced directly.)
+void standardSmartPointerResetIsReinit() {
+  {
+    std::unique_ptr<A> ptr;
+    std::move(ptr);
+    ptr.reset(new A);
+    *ptr;
+  }
+  {
+    std::shared_ptr<A> ptr;
+    std::move(ptr);
+    ptr.reset(new A);
+    *ptr;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests related to order of evaluation within expressions
+
+// Relative sequencing of move and use.
+void passByRvalueReference(int i, A &&a);
+void passByValue(int i, A a);
+void passByValue(A a, int i);
+A g(A, A &&);
+int intFromA(A &&);
+int intFromInt(int);
+void sequencingOfMoveAndUse() {
+  // This case is fine because the move only happens inside
+  // passByRvalueReference(). At this point, a.getInt() is guaranteed to have
+  // been evaluated.
+  {
+    A a;
+    passByRvalueReference(a.getInt(), std::move(a));
+  }
+  // However, if we pass by value, the move happens when the move constructor is
+  // called to create a temporary, and this happens before the call to
+  // passByValue(). Because the order in which arguments are evaluated isn't
+  // defined, the move may happen before the call to a.getInt().
+  //
+  // Check that we warn about a potential use-after move for both orderings of
+  // a.getInt() and std::move(a), independent of the order in which the
+  // arguments happen to get evaluated by the compiler.
+  {
+    A a;
+    passByValue(a.getInt(), std::move(a));
+    // CHECK-MESSAGES: [[@LINE-1]]:17: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-2]]:29: note: move occurred here
+    // CHECK-MESSAGES: [[@LINE-3]]:17: note: the use and move are unsequenced
+  }
+  {
+    A a;
+    passByValue(std::move(a), a.getInt());
+    // CHECK-MESSAGES: [[@LINE-1]]:31: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-2]]:17: note: move occurred here
+    // CHECK-MESSAGES: [[@LINE-3]]:31: note: the use and move are unsequenced
+  }
+  // An even more convoluted example.
+  {
+    A a;
+    g(g(a, std::move(a)), g(a, std::move(a)));
+    // CHECK-MESSAGES: [[@LINE-1]]:9: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-2]]:27: note: move occurred here
+    // CHECK-MESSAGES: [[@LINE-3]]:9: note: the use and move are unsequenced
+    // CHECK-MESSAGES: [[@LINE-4]]:29: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-5]]:7: note: move occurred here
+    // CHECK-MESSAGES: [[@LINE-6]]:29: note: the use and move are unsequenced
+  }
+  // This case is fine because the actual move only happens inside the call to
+  // operator=(). a.getInt(), by necessity, is evaluated before that call.
+  {
+    A a;
+    A vec[1];
+    vec[a.getInt()] = std::move(a);
+  }
+  // However, in the following case, the move happens before the assignment, and
+  // so the order of evaluation is not guaranteed.
+  {
+    A a;
+    int v[3];
+    v[a.getInt()] = intFromA(std::move(a));
+    // CHECK-MESSAGES: [[@LINE-1]]:7: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-2]]:21: note: move occurred here
+    // CHECK-MESSAGES: [[@LINE-3]]:7: note: the use and move are unsequenced
+  }
+  {
+    A a;
+    int v[3];
+    v[intFromA(std::move(a))] = intFromInt(a.i);
+    // CHECK-MESSAGES: [[@LINE-1]]:44: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-2]]:7: note: move occurred here
+    // CHECK-MESSAGES: [[@LINE-3]]:44: note: the use and move are unsequenced
+  }
+}
+
+// Relative sequencing of move and reinitialization. If the two are unsequenced,
+// we conservatively assume that the move happens after the reinitialization,
+// i.e. the that object does not get reinitialized after the move.
+A MutateA(A a);
+void passByValue(A a1, A a2);
+void sequencingOfMoveAndReinit() {
+  // Move and reinitialization as function arguments (which are indeterminately
+  // sequenced). Again, check that we warn for both orderings.
+  {
+    A a;
+    passByValue(std::move(a), (a = A()));
+    a.foo();
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:17: note: move occurred here
+  }
+  {
+    A a;
+    passByValue((a = A()), std::move(a));
+    a.foo();
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:28: note: move occurred here
+  }
+  // Common usage pattern: Move the object to a function that mutates it in some
+  // way, then reassign the result to the object. This pattern is fine.
+  {
+    A a;
+    a = MutateA(std::move(a));
+    a.foo();
+  }
+}
+
+// Relative sequencing of reinitialization and use. If the two are unsequenced,
+// we conservatively assume that the reinitialization happens after the use,
+// i.e. that the object is not reinitialized at the point in time when it is
+// used.
+void sequencingOfReinitAndUse() {
+  // Reinitialization and use in function arguments. Again, check both possible
+  // orderings.
+  {
+    A a;
+    std::move(a);
+    passByValue(a.getInt(), (a = A()));
+    // CHECK-MESSAGES: [[@LINE-1]]:17: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+  {
+    A a;
+    std::move(a);
+    passByValue((a = A()), a.getInt());
+    // CHECK-MESSAGES: [[@LINE-1]]:28: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
+  }
+}
+
+// The comma operator sequences its operands.
+void commaOperatorSequences() {
+  {
+    A a;
+    A(std::move(a))
+    , (a = A());
+    a.foo();
+  }
+  {
+    A a;
+    (a = A()), A(std::move(a));
+    a.foo();
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-3]]:16: note: move occurred here
+  }
+}
+
+// An initializer list sequences its initialization clauses.
+void initializerListSequences() {
+  {
+    struct S1 {
+      int i;
+      A a;
+    };
+    A a;
+    S1 s1{a.getInt(), std::move(a)};
+  }
+  {
+    struct S2 {
+      A a;
+      int i;
+    };
+    A a;
+    S2 s2{std::move(a), a.getInt()};
+    // CHECK-MESSAGES: [[@LINE-1]]:25: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-2]]:11: note: move occurred here
+  }
+}
+
+// A declaration statement containing multiple declarations sequences the
+// initializer expressions.
+void declarationSequences() {
+  {
+    A a;
+    A a1 = a, a2 = std::move(a);
+  }
+  {
+    A a;
+    A a1 = std::move(a), a2 = a;
+    // CHECK-MESSAGES: [[@LINE-1]]:31: warning: 'a' used after it was moved
+    // CHECK-MESSAGES: [[@LINE-2]]:12: note: move occurred here
+  }
+}
+
+// The logical operators && and || sequence their operands.
+void logicalOperatorsSequence() {
+  {
+    A a;
+    if (a.getInt() > 0 && A(std::move(a)).getInt() > 0) {
+      A().foo();
+    }
+  }
+  // A variation: Negate the result of the && (which pushes the && further down
+  // into the AST).
+  {
+    A a;
+    if (!(a.getInt() > 0 && A(std::move(a)).getInt() > 0)) {
+      A().foo();
+    }
+  }
+  {
+    A a;
+    if (A(std::move(a)).getInt() > 0 && a.getInt() > 0) {
+      // CHECK-MESSAGES: [[@LINE-1]]:41: warning: 'a' used after it was moved
+      // CHECK-MESSAGES: [[@LINE-2]]:9: note: move occurred here
+      A().foo();
+    }
+  }
+  {
+    A a;
+    if (a.getInt() > 0 || A(std::move(a)).getInt() > 0) {
+      A().foo();
+    }
+  }
+  {
+    A a;
+    if (A(std::move(a)).getInt() > 0 || a.getInt() > 0) {
+      // CHECK-MESSAGES: [[@LINE-1]]:41: warning: 'a' used after it was moved
+      // CHECK-MESSAGES: [[@LINE-2]]:9: note: move occurred here
+      A().foo();
+    }
+  }
+}
+
+// A range-based for sequences the loop variable declaration before the body.
+void forRangeSequences() {
+  A v[2] = {A(), A()};
+  for (A &a : v) {
+    std::move(a);
+  }
+}
+
+// If a variable is declared in an if statement, the declaration of the variable
+// (which is treated like a reinitialization by the check) is sequenced before
+// the evaluation of the condition (which constitutes a use).
+void ifStmtSequencesDeclAndCondition() {
+  for (int i = 0; i < 10; ++i) {
+    if (A a = A()) {
+      std::move(a);
+    }
+  }
+}
+
+namespace PR33020 {
+class D {
+  ~D();
+};
+struct A {
+  D d;
+};
+class B {
+  A a;
+};
+template <typename T>
+class C : T, B {
+  void m_fn1() {
+    int a;
+    std::move(a);
+    C c;
+  }
+};
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-virtual-near-miss.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-virtual-near-miss.cpp
new file mode 100644
index 0000000..553d2f4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/bugprone-virtual-near-miss.cpp
@@ -0,0 +1,133 @@
+// RUN: %check_clang_tidy %s bugprone-virtual-near-miss %t
+
+class NoDefinedClass1;
+class NoDefinedClass2;
+
+struct Base {
+  virtual void func();
+  virtual void gunk();
+  virtual ~Base();
+  virtual Base &operator=(const Base &);
+  virtual NoDefinedClass1 *f();
+};
+
+struct Derived : Base {
+  // Should not warn "do you want to override 'gunk'?", because gunk is already
+  // overriden by this class.
+  virtual void funk();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Derived::funk' has a similar name and the same signature as virtual method 'Base::func'; did you mean to override it? [bugprone-virtual-near-miss]
+  // CHECK-FIXES: virtual void func();
+
+  void func2();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Derived::func2' has {{.*}} 'Base::func'
+  // CHECK-FIXES: void func();
+
+  void func22(); // Should not warn.
+
+  void gunk(); // Should not warn: gunk is override.
+
+  void fun();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Derived::fun' has {{.*}} 'Base::func'
+  // CHECK-FIXES: void func();
+
+  Derived &operator==(const Base &); // Should not warn: operators are ignored.
+
+  virtual NoDefinedClass2 *f1(); // Should not crash: non-defined class return type is ignored.
+};
+
+template <typename T>
+struct TBase {
+  virtual void tfunc(T t);
+};
+
+template <typename T>
+struct TDerived : TBase<T> {
+  virtual void tfunk(T t);
+  // Should not apply fix for template.
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: method 'TDerived<double>::tfunk' has {{.*}} 'TBase<double>::tfunc'
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: method 'TDerived<int>::tfunk' has {{.*}} 'TBase<int>::tfunc'
+  // CHECK-FIXES: virtual void tfunk(T t);
+};
+
+TDerived<int> T1;
+TDerived<double> T2;
+
+// Should not fix macro definition
+#define MACRO1 void funcM()
+// CHECK-FIXES: #define MACRO1 void funcM()
+#define MACRO2(m) void m()
+// CHECK-FIXES: #define MACRO2(m) void m()
+
+struct DerivedMacro : Base {
+  MACRO1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'DerivedMacro::funcM' has {{.*}} 'Base::func'
+  // CHECK-FIXES: MACRO1;
+
+  MACRO2(func3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'DerivedMacro::func3' has {{.*}} 'Base::func'
+  // CHECK-FIXES: MACRO2(func);
+};
+
+typedef Derived derived_type;
+
+class Father {
+public:
+  Father();
+  virtual void func();
+  virtual Father *create(int i);
+  virtual Base &&generate();
+  virtual Base *canonical(Derived D);
+};
+
+class Mother {
+public:
+  Mother();
+  static void method();
+  virtual int method(int argc, const char **argv);
+  virtual int method(int argc) const;
+  virtual int decay(const char *str);
+};
+
+class Child : private Father, private Mother {
+public:
+  Child();
+
+  virtual void func2();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::func2' has {{.*}} 'Father::func'
+  // CHECK-FIXES: virtual void func();
+
+  int methoe(int x, char **strs); // Should not warn: parameter types don't match.
+
+  int methoe(int x);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::methoe' has {{.*}} 'Mother::method'
+  // CHECK-FIXES: int method(int x);
+
+  void methof(int x, const char **strs); // Should not warn: return types don't match.
+
+  int methoh(int x, const char **strs);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::methoh' has {{.*}} 'Mother::method'
+  // CHECK-FIXES: int method(int x, const char **strs);
+
+  virtual Child *creat(int i);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::creat' has {{.*}} 'Father::create'
+  // CHECK-FIXES: virtual Child *create(int i);
+
+  virtual Derived &&generat();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::generat' has {{.*}} 'Father::generate'
+  // CHECK-FIXES: virtual Derived &&generate();
+
+  int decaz(const char str[]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::decaz' has {{.*}} 'Mother::decay'
+  // CHECK-FIXES: int decay(const char str[]);
+
+  operator bool();
+
+  derived_type *canonica(derived_type D);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::canonica' has {{.*}} 'Father::canonical'
+  // CHECK-FIXES: derived_type *canonical(derived_type D);
+
+private:
+  void funk();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::funk' has {{.*}} 'Father::func'
+  // CHECK-FIXES: void func();
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-dcl21-cpp.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-dcl21-cpp.cpp
new file mode 100644
index 0000000..c975f70
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-dcl21-cpp.cpp
@@ -0,0 +1,134 @@
+// RUN: %check_clang_tidy %s cert-dcl21-cpp %t
+
+class A {};
+
+A operator++(A &, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator++' returns a non-constant object instead of a constant object type [cert-dcl21-cpp]
+// CHECK-FIXES: {{^}}const A operator++(A &, int);
+
+A operator--(A &, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator--' returns a no
+// CHECK-FIXES: {{^}}const A operator--(A &, int);
+
+class B {};
+
+B &operator++(B &);
+const B operator++(B &, int);
+
+B &operator--(B &);
+const B operator--(B &, int);
+
+
+class D {
+D &operator++();
+const D operator++(int);
+
+D &operator--();
+const D operator--(int);
+};
+
+class C {
+C operator++(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator++' returns a no
+// CHECK-FIXES: {{^}}const C operator++(int);
+
+C operator--(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator--' returns a no
+// CHECK-FIXES: {{^}}const C operator--(int);
+};
+
+class E {};
+
+E &operator++(E &, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator++' returns a reference instead of a constant object type [cert-dcl21-cpp]
+// CHECK-FIXES: {{^}}const E operator++(E &, int);
+
+E &operator--(E &, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator--' returns a re
+// CHECK-FIXES: {{^}}const E operator--(E &, int);
+
+class G {
+G &operator++(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}}const G operator++(int);
+
+G &operator--(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator--' returns a re
+// CHECK-FIXES: {{^}}const G operator--(int);
+};
+
+class F {};
+
+const F &operator++(F &, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}}const F operator++(F &, int);
+
+const F &operator--(F &, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: overloaded 'operator--' returns a re
+// CHECK-FIXES: {{^}}const F operator--(F &, int);
+
+class H {
+const H &operator++(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}}const H operator++(int);
+
+const H &operator--(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: overloaded 'operator--' returns a re
+// CHECK-FIXES: {{^}}const H operator--(int);
+};
+
+
+#define FROM_MACRO P&
+class P {
+const FROM_MACRO operator++(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}}const FROM_MACRO operator++(int);
+};
+
+
+template<typename T>
+class Q {
+const Q &operator++(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}}const Q<T> operator++(int);
+
+const Q &operator--(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: overloaded 'operator--' returns a re
+// CHECK-FIXES: {{^}}const Q<T> operator--(int);
+};
+
+void foobar() {
+  Q<int> a;
+  Q<float> b;
+  (void)a;
+  (void)b;
+}
+
+struct S {};
+typedef S& SRef;
+
+SRef operator++(SRef, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}}SRef operator++(SRef, int);
+
+struct T {
+  typedef T& TRef;
+  
+  TRef operator++(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}}  TRef operator++(int);
+};
+
+struct U {
+  typedef const U& ConstURef;
+  
+  ConstURef& operator++(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: overloaded 'operator++' returns a re
+// CHECK-FIXES: {{^}}  ConstURef& operator++(int);
+};
+
+struct V {
+  V *operator++(int);
+  V *const operator--(int);
+};
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-dcl58-cpp.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-dcl58-cpp.cpp
new file mode 100644
index 0000000..34ee368
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-dcl58-cpp.cpp
@@ -0,0 +1,67 @@
+// RUN: %check_clang_tidy %s cert-dcl58-cpp %t -- -- -std=c++1z -I %S/Inputs/Headers
+
+#include "system-header-simulation.h"
+
+namespace A {
+  namespace B {
+    int b;
+  }
+}
+
+namespace A {
+  namespace B {
+    int c;
+  }
+}
+
+namespace posix {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: modification of 'posix' namespace can result in undefined behavior [cert-dcl58-cpp]
+  namespace vmi {
+  }
+}
+
+namespace std {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: modification of 'std' namespace can
+  int stdInt;
+}
+
+namespace foobar {
+  namespace std {
+    int bar;
+  }
+}
+
+namespace posix::a {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: modification of 'posix' namespace 
+}
+
+enum class MyError {
+  ErrorA,
+  ErrorB
+};
+
+namespace std {
+template <>
+struct is_error_code_enum<MyError> : std::true_type {};
+
+template<>
+void swap<MyError>(MyError &a, MyError &b);
+}
+
+enum class MyError2 {
+  Error2A,
+  Error2B
+};
+
+namespace std {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: modification of 'std' namespace 
+template <>
+struct is_error_code_enum<MyError2> : std::true_type {};
+
+int foobar;
+}
+
+using namespace std;
+
+int x;
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-env33-c.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-env33-c.c
new file mode 100644
index 0000000..5846b49
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-env33-c.c
@@ -0,0 +1,20 @@
+// RUN: %check_clang_tidy %s cert-env33-c %t
+
+typedef struct FILE {} FILE;
+
+extern int system(const char *);
+extern FILE *popen(const char *, const char *);
+extern FILE *_popen(const char *, const char *);
+
+void f(void) {
+  // It is permissible to check for the presence of a command processor.
+  system(0);
+
+  system("test");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling 'system' uses a command processor [cert-env33-c]
+
+  popen("test", "test");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling 'popen' uses a command processor
+  _popen("test", "test");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling '_popen' uses a command processor
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-err34-c.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-err34-c.c
new file mode 100644
index 0000000..e2cfc21
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-err34-c.c
@@ -0,0 +1,103 @@
+// RUN: %check_clang_tidy %s cert-err34-c %t -- -- -std=c11
+
+typedef __SIZE_TYPE__      size_t;
+typedef signed             ptrdiff_t;
+typedef long long          intmax_t;
+typedef unsigned long long uintmax_t;
+typedef void *             FILE;
+
+extern FILE *stdin;
+
+extern int fscanf(FILE * restrict stream, const char * restrict format, ...);
+extern int scanf(const char * restrict format, ...);
+extern int sscanf(const char * restrict s, const char * restrict format, ...);
+
+extern double atof(const char *nptr);
+extern int atoi(const char *nptr);
+extern long int atol(const char *nptr);
+extern long long int atoll(const char *nptr);
+
+void f1(const char *in) {
+  int i;
+  long long ll;
+  unsigned int ui;
+  unsigned long long ull;
+  intmax_t im;
+  uintmax_t uim;
+  float f;
+  double d;
+  long double ld;
+
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'sscanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead [cert-err34-c]
+  sscanf(in, "%d", &i);
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'fscanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtoll' instead [cert-err34-c]
+  fscanf(stdin, "%lld", &ll);
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'sscanf' used to convert a string to an unsigned integer value, but function will not report conversion errors; consider using 'strtoul' instead [cert-err34-c]
+  sscanf(in, "%u", &ui);
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'fscanf' used to convert a string to an unsigned integer value, but function will not report conversion errors; consider using 'strtoull' instead [cert-err34-c]
+  fscanf(stdin, "%llu", &ull);
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtoimax' instead [cert-err34-c]
+  scanf("%jd", &im);
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'fscanf' used to convert a string to an unsigned integer value, but function will not report conversion errors; consider using 'strtoumax' instead [cert-err34-c]
+  fscanf(stdin, "%ju", &uim);
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'sscanf' used to convert a string to a floating-point value, but function will not report conversion errors; consider using 'strtof' instead [cert-err34-c]
+  sscanf(in, "%f", &f); // to float
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'fscanf' used to convert a string to a floating-point value, but function will not report conversion errors; consider using 'strtod' instead [cert-err34-c]
+  fscanf(stdin, "%lg", &d);
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'sscanf' used to convert a string to a floating-point value, but function will not report conversion errors; consider using 'strtold' instead [cert-err34-c]
+  sscanf(in, "%Le", &ld);
+
+  // These are conversions with other modifiers
+  short s;
+  char c;
+  size_t st;
+  ptrdiff_t pt;
+
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+  scanf("%hhd", &c);
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+  scanf("%hd", &s);
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+  scanf("%zu", &st);
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+  scanf("%td", &pt);
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+  scanf("%o", ui);
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+  scanf("%X", ui);
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+  scanf("%x", ui);
+}
+
+void f2(const char *in) {
+  // CHECK-MESSAGES: :[[@LINE+1]]:11: warning: 'atoi' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead [cert-err34-c]
+  int i = atoi(in); // to int
+  // CHECK-MESSAGES: :[[@LINE+1]]:12: warning: 'atol' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead [cert-err34-c]
+  long l = atol(in); // to long
+  // CHECK-MESSAGES: :[[@LINE+1]]:18: warning: 'atoll' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtoll' instead [cert-err34-c]
+  long long ll = atoll(in); // to long long
+  // CHECK-MESSAGES: :[[@LINE+1]]:14: warning: 'atof' used to convert a string to a floating-point value, but function will not report conversion errors; consider using 'strtod' instead [cert-err34-c]
+  double d = atof(in); // to double
+}
+
+void f3(void) {
+  int i;
+  unsigned int u;
+  float f;
+  char str[32];
+
+  // Test that we don't report multiple infractions for a single call.
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+  scanf("%d%u%f", &i, &u, &f);
+
+  // Test that we still catch infractions that are not the first specifier.
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
+  scanf("%s%d", str, &i);
+}
+
+void do_not_diagnose(void) {
+  char str[32];
+
+  scanf("%s", str); // Not a numerical conversion
+  scanf("%*d"); // Assignment suppressed
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-err34-c.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-err34-c.cpp
new file mode 100644
index 0000000..dde7dc1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-err34-c.cpp
@@ -0,0 +1,43 @@
+// RUN: %check_clang_tidy %s cert-err34-c %t -- -- -std=c++11
+
+typedef void *             FILE;
+
+extern FILE *stdin;
+
+extern int fscanf(FILE * stream, const char * format, ...);
+extern int sscanf(const char * s, const char * format, ...);
+
+extern double atof(const char *nptr);
+extern int atoi(const char *nptr);
+extern long int atol(const char *nptr);
+extern long long int atoll(const char *nptr);
+
+namespace std {
+using ::FILE; using ::stdin;
+using ::fscanf; using ::sscanf;
+using ::atof; using ::atoi; using ::atol; using ::atoll;
+}
+
+void f1(const char *in) {
+  int i;
+  long long ll;
+
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'sscanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead [cert-err34-c]
+  std::sscanf(in, "%d", &i);
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'fscanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtoll' instead [cert-err34-c]
+  std::fscanf(std::stdin, "%lld", &ll);
+}
+
+void f2(const char *in) {
+  // CHECK-MESSAGES: :[[@LINE+1]]:11: warning: 'atoi' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead [cert-err34-c]
+  int i = std::atoi(in); // to int
+  // CHECK-MESSAGES: :[[@LINE+1]]:12: warning: 'atol' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead [cert-err34-c]
+  long l = std::atol(in); // to long
+
+  using namespace std;
+
+  // CHECK-MESSAGES: :[[@LINE+1]]:18: warning: 'atoll' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtoll' instead [cert-err34-c]
+  long long ll = atoll(in); // to long long
+  // CHECK-MESSAGES: :[[@LINE+1]]:14: warning: 'atof' used to convert a string to a floating-point value, but function will not report conversion errors; consider using 'strtod' instead [cert-err34-c]
+  double d = atof(in); // to double
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-flp30-c.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-flp30-c.c
new file mode 100644
index 0000000..eee16be
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-flp30-c.c
@@ -0,0 +1,19 @@
+// RUN: %check_clang_tidy %s cert-flp30-c %t
+
+float g(void);
+
+void func(void) {
+  for (float x = 0.1f; x <= 1.0f; x += 0.1f) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: loop induction expression should not have floating-point type [cert-flp30-c]
+
+  float f = 1.0f;
+  for (; f > 0; --f) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: loop induction expression
+
+  for (;;g()) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop induction expression
+
+  for (int i = 0; i < 10; i += 1.0f) {}
+
+  for (int i = 0; i < 10; ++i) {}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-limited-randomness.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-limited-randomness.c
new file mode 100644
index 0000000..c8009b5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-limited-randomness.c
@@ -0,0 +1,13 @@
+// RUN: %check_clang_tidy %s cert-msc30-c %t
+
+extern int rand(void);
+int nonrand();
+
+int cTest() {
+  int i = rand();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness [cert-msc30-c]
+
+  int k = nonrand();
+
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-limited-randomness.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-limited-randomness.cpp
new file mode 100644
index 0000000..845b735
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-limited-randomness.cpp
@@ -0,0 +1,28 @@
+// RUN: %check_clang_tidy %s cert-msc50-cpp %t
+
+int rand();
+int rand(int);
+
+namespace std {
+using ::rand;
+}
+
+namespace nonstd {
+  int rand();
+}
+
+void testFunction1() {
+  int i = std::rand();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness; use C++11 random library instead [cert-msc50-cpp]
+
+  int j = ::rand();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness; use C++11 random library instead [cert-msc50-cpp]
+
+  int k = rand(i);
+
+  int l = nonstd::rand();
+
+  int m = rand();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness; use C++11 random library instead [cert-msc50-cpp]
+}
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-msc32-c.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-msc32-c.c
new file mode 100644
index 0000000..6cc40fa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-msc32-c.c
@@ -0,0 +1,27 @@
+// RUN: %check_clang_tidy %s cert-msc32-c %t -- -config="{CheckOptions: [{key: cert-msc32-c.DisallowedSeedTypes, value: 'some_type,time_t'}]}" -- -std=c99
+
+void srand(int seed);
+typedef int time_t;
+time_t time(time_t *t);
+
+void f() {
+  srand(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc32-c]
+
+  const int a = 1;
+  srand(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc32-c]
+
+  time_t t;
+  srand(time(&t)); // Disallowed seed type
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc32-c]
+}
+
+void g() {
+  typedef int user_t;
+  user_t a = 1;
+  srand(a);
+
+  int b = 1;
+  srand(b); // Can not evaluate as int
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-msc51-cpp.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-msc51-cpp.cpp
new file mode 100644
index 0000000..8a8d778
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-msc51-cpp.cpp
@@ -0,0 +1,210 @@
+// RUN: %check_clang_tidy %s cert-msc51-cpp %t -- -config="{CheckOptions: [{key: cert-msc51-cpp.DisallowedSeedTypes, value: 'some_type,time_t'}]}" -- -std=c++11
+
+namespace std {
+
+void srand(int seed);
+
+template <class UIntType, UIntType a, UIntType c, UIntType m>
+struct linear_congruential_engine {
+  linear_congruential_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using default_random_engine = linear_congruential_engine<unsigned int, 1, 2, 3>;
+
+using size_t = int;
+template <class UIntType, size_t w, size_t n, size_t m, size_t r,
+          UIntType a, size_t u, UIntType d, size_t s,
+          UIntType b, size_t t,
+          UIntType c, size_t l, UIntType f>
+struct mersenne_twister_engine {
+  mersenne_twister_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using mt19937 = mersenne_twister_engine<unsigned int, 32, 624, 397, 21, 0x9908b0df, 11, 0xffffffff, 7, 0x9d2c5680, 15, 0xefc60000, 18, 1812433253>;
+
+template <class UIntType, size_t w, size_t s, size_t r>
+struct subtract_with_carry_engine {
+  subtract_with_carry_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using ranlux24_base = subtract_with_carry_engine<unsigned int, 24, 10, 24>;
+
+template <class Engine, size_t p, size_t r>
+struct discard_block_engine {
+  discard_block_engine();
+  discard_block_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using ranlux24 = discard_block_engine<ranlux24_base, 223, 23>;
+
+template <class Engine, size_t w, class UIntType>
+struct independent_bits_engine {
+  independent_bits_engine();
+  independent_bits_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using independent_bits = independent_bits_engine<ranlux24_base, 223, int>;
+
+template <class Engine, size_t k>
+struct shuffle_order_engine {
+  shuffle_order_engine();
+  shuffle_order_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using shuffle_order = shuffle_order_engine<ranlux24_base, 223>;
+
+struct random_device {
+  random_device();
+  int operator()();
+};
+} // namespace std
+
+using time_t = unsigned int;
+time_t time(time_t *t);
+
+void f() {
+  const int seed = 2;
+  time_t t;
+
+  std::srand(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::srand(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::srand(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  // One instantiation for every engine
+  std::default_random_engine engine1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine2(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine3(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine4(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  std::mt19937 engine5;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine6(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine7(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine8(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine5.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  engine5.seed(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine5.seed(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine5.seed(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  std::ranlux24_base engine9;
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::ranlux24_base engine10(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::ranlux24_base engine11(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::ranlux24_base engine12(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine9.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  engine9.seed(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine9.seed(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine9.seed(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  std::ranlux24 engine13;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::ranlux24 engine14(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::ranlux24 engine15(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::ranlux24 engine16(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine13.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  engine13.seed(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine13.seed(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine13.seed(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  std::independent_bits engine17;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::independent_bits engine18(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::independent_bits engine19(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::independent_bits engine20(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine17.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  engine17.seed(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine17.seed(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine17.seed(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  std::shuffle_order engine21;
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::shuffle_order engine22(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::shuffle_order engine23(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::shuffle_order engine24(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine21.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  engine21.seed(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine21.seed(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine21.seed(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+}
+
+struct A {
+  A(int _ = 0);
+  void seed(int _ = 0);
+};
+
+void g() {
+  int n = 1;
+  std::default_random_engine engine1(n);
+  std::mt19937 engine2(n);
+  std::ranlux24_base engine3(n);
+  std::ranlux24 engine4(n);
+  std::independent_bits engine5(n);
+  std::shuffle_order engine6(n);
+
+  std::random_device dev;
+  std::default_random_engine engine7(dev());
+  std::mt19937 engine8(dev());
+  std::ranlux24_base engine9(dev());
+  std::ranlux24 engine10(dev());
+  std::independent_bits engine11(dev());
+  std::shuffle_order engine12(dev());
+
+  A a1;
+  A a2(1);
+  a1.seed();
+  a1.seed(1);
+  a1.seed(n);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-oop11-cpp.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-oop11-cpp.cpp
new file mode 100644
index 0000000..650d6ec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-oop11-cpp.cpp
@@ -0,0 +1,21 @@
+// RUN: %check_clang_tidy %s cert-oop11-cpp %t -- -- -std=c++11
+
+struct B {
+  B(B&&) noexcept = default;
+
+  B(const B &) = default;
+  B& operator=(const B&) = default;
+  ~B() {}
+};
+
+struct D {
+  B b;
+
+  // CHECK-MESSAGES: :[[@LINE+1]]:14: warning: move constructor initializes class member by calling a copy constructor [cert-oop11-cpp]
+  D(D &&d) : b(d.b) {}
+
+  // This should not produce a diagnostic because it is not covered under
+  // the CERT guideline for OOP11-CPP. However, this will produce a diagnostic
+  // under performance-move-constructor-init.
+  D(B b) : b(b) {}
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-setlongjmp.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-setlongjmp.cpp
new file mode 100644
index 0000000..1bf5444
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-setlongjmp.cpp
@@ -0,0 +1,26 @@
+// RUN: %check_clang_tidy %s cert-err52-cpp %t -- -- -std=c++11
+
+typedef void *jmp_buf;
+extern int __setjmpimpl(jmp_buf);
+#define setjmp(x) __setjmpimpl(x)
+[[noreturn]] extern void longjmp(jmp_buf, int);
+
+namespace std {
+using ::jmp_buf;
+using ::longjmp;
+}
+
+static jmp_buf env;
+void g() {
+  std::longjmp(env, 1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not call 'longjmp'; consider using exception handling instead [cert-err52-cpp]
+  ::longjmp(env, 1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not call 'longjmp'; consider using exception handling instead
+  longjmp(env, 1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not call 'longjmp'; consider using exception handling instead
+}
+
+void f() {
+  (void)setjmp(env);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not call 'setjmp'; consider using exception handling instead
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-static-object-exception.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-static-object-exception.cpp
new file mode 100644
index 0000000..aa34bbd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-static-object-exception.cpp
@@ -0,0 +1,225 @@
+// RUN: clang-tidy %s -checks="-*,cert-err58-cpp" -- -std=c++11 -target x86_64-pc-linux-gnu \
+// RUN:   | FileCheck %s -check-prefix=CHECK-EXCEPTIONS \
+// RUN:   -implicit-check-not="{{warning|error}}:"
+// RUN: clang-tidy %s -checks="-*,cert-err58-cpp" -- -fno-exceptions -std=c++11 -target x86_64-pc-linux-gnu \
+// RUN:   | FileCheck %s -allow-empty -check-prefix=CHECK-NONEXCEPTIONS \
+// RUN:   -implicit-check-not="{{warning|error}}:"
+
+struct S {
+  S() noexcept(false);
+};
+
+struct T {
+  T() noexcept;
+};
+
+struct U {
+  U() {}
+};
+
+struct V {
+  explicit V(const char *) {} // Can throw
+};
+
+struct Cleanup {
+  ~Cleanup() {}
+};
+
+struct W {
+  W(Cleanup c = {}) noexcept(false);
+};
+
+struct X {
+  X(S = {}) noexcept;
+};
+
+struct Y {
+  S s;
+};
+
+struct Z {
+  T t;
+};
+
+int f();
+int g() noexcept(false);
+int h() noexcept(true);
+
+struct UserConv_Bad {
+  operator int() noexcept(false);
+};
+
+struct UserConv_Good {
+  operator int() noexcept;
+};
+
+UserConv_Bad some_bad_func() noexcept;
+UserConv_Good some_good_func() noexcept;
+
+S s;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 's' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
+// CHECK-EXCEPTIONS: 9:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+T t; // ok
+U u;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'u' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 17:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+V v("v");
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'v' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 21:12: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+W w;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'w' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 29:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+X x1(S{});
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'x1' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 9:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+X x2;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'x2' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 9:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+Y y;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'y' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 36:8: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+Z z;
+
+int i = f();
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:5: warning: initialization of 'i' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 44:5: note: possibly throwing function declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+int j = g();
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:5: warning: initialization of 'j' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 45:5: note: possibly throwing function declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+int k = h();
+int l = some_bad_func();
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:5: warning: initialization of 'l' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 49:3: note: possibly throwing function declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+int m = some_good_func();
+
+typedef decltype(sizeof(int)) size_t;
+inline void *operator new(size_t sz, void *here) noexcept { return here; }
+char n[sizeof(int)];
+int *o = new (n) int();
+int *p = new int();
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:6: warning: initialization of 'p' with static storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+
+thread_local S s3;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 's3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+thread_local T t3; // ok
+thread_local U u3;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'u3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+thread_local V v3("v");
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'v3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+thread_local W w3;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'w3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+
+void f(S s1, T t1, U u1, V v1, W w1) { // ok, ok, ok, ok, ok
+  S s2; // ok
+  T t2; // ok
+  U u2; // ok
+  V v2("v"); // ok
+  W w2; // ok
+
+  thread_local S s3; // ok
+  thread_local T t3; // ok
+  thread_local U u3; // ok
+  thread_local V v3("v"); // ok
+  thread_local W w3; // ok
+
+  static S s4; // ok
+  static T t4; // ok
+  static U u4; // ok
+  static V v4("v"); // ok
+  static W w4; // ok
+}
+
+namespace {
+S s;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 's' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
+// CHECK-EXCEPTIONS: 9:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+T t; // ok
+U u;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'u' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 17:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+V v("v");
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'v' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 21:12: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+W w;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'w' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 29:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+
+thread_local S s3;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 's3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+thread_local T t3; // ok
+thread_local U u3;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'u3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+thread_local V v3("v");
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'v3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+thread_local W w3;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'w3' with thread_local storage duration may throw an exception that cannot be caught
+// CHECK-NONEXCEPTIONS-NOT: warning:
+}; // namespace
+
+class Statics {
+  static S s; // warn when initialized
+  static T t; // ok
+  static U u; // warn when initialized
+  static V v; // warn when initialized
+  static W w; // warn when initialized
+
+  void f(S s, T t, U u, V v) {
+    S s2;      // ok
+    T t2;      // ok
+    U u2;      // ok
+    V v2("v"); // ok
+    W w2;      // ok
+
+    thread_local S s3;      // ok
+    thread_local T t3;      // ok
+    thread_local U u3;      // ok
+    thread_local V v3("v"); // ok
+    thread_local W w3;      // ok
+
+    static S s4;      // ok
+    static T t4;      // ok
+    static U u4;      // ok
+    static V v4("v"); // ok
+    static W w4;      // ok
+  }
+};
+
+S Statics::s;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:12: warning: initialization of 's' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
+// CHECK-EXCEPTIONS: 9:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+T Statics::t;
+U Statics::u;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:12: warning: initialization of 'u' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 17:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+V Statics::v("v");
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:12: warning: initialization of 'v' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 21:12: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
+W Statics::w;
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:12: warning: initialization of 'w' with static storage duration may throw an exception that cannot be caught
+// CHECK-EXCEPTIONS: 29:3: note: possibly throwing constructor declared here
+// CHECK-NONEXCEPTIONS-NOT: warning:
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-throw-exception-type.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-throw-exception-type.cpp
new file mode 100644
index 0000000..2ff9be5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-throw-exception-type.cpp
@@ -0,0 +1,127 @@
+// RUN: %check_clang_tidy %s cert-err60-cpp %t -- -- -std=c++11 -fcxx-exceptions
+
+struct S {};
+struct T : S {};
+struct U {
+  U() = default;
+  U(const U&) = default;
+};
+
+struct V {
+  V() = default;
+  V(const V&) noexcept;
+};
+
+struct W {
+  W() = default;
+  W(const W&) noexcept(false);
+};
+
+struct X {
+  X() = default;
+  X(const X&) {}
+};
+
+struct Y {
+  Y() = default;
+  Y(const Y&) throw();
+};
+
+struct Z {
+  Z() = default;
+  Z(const Z&) throw(int);
+};
+
+void g() noexcept(false);
+
+struct A {
+  A() = default;
+  A(const A&) noexcept(noexcept(g()));
+};
+
+struct B {
+  B() = default;
+  B(const B&) = default;
+  B(const A&) noexcept(false);
+};
+
+class C {
+  W M; // W is not no-throw copy constructible
+public:
+  C() = default;
+  C(const C&) = default;
+};
+
+struct D {
+  D() = default;
+  D(const D&) noexcept(false);
+  D(D&) noexcept(true);
+};
+
+struct E {
+  E() = default;
+  E(E&) noexcept(true);
+  E(const E&) noexcept(false);
+};
+
+struct Allocates {
+  int *x;
+  Allocates() : x(new int(0)) {}
+  Allocates(const Allocates &other) : x(new int(*other.x)) {}
+};
+
+struct OptionallyAllocates {
+  int *x;
+  OptionallyAllocates() : x(new int(0)) {}
+  OptionallyAllocates(const Allocates &other) noexcept(true) {
+    try {
+      x = new int(*other.x);
+    } catch (...) {
+      x = nullptr;
+    }
+  }
+};
+
+void f() {
+  throw 12; // ok
+  throw "test"; // ok
+  throw S(); // ok
+  throw T(); // ok
+  throw U(); // ok
+  throw V(); // ok
+  throw W(); // match, noexcept(false)
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible [cert-err60-cpp]
+  throw X(); // match, no noexcept clause, nontrivial
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible
+  throw Y(); // ok
+  throw Z(); // match, throw(int)
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible
+  throw A(); // match, noexcept(false)
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible
+  throw B(); // ok
+  throw C(); // match, C has a member variable that makes it throwing on copy
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible
+  throw D(); // match, has throwing copy constructor
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible
+  throw E(); // match, has throwing copy constructor
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible
+  throw Allocates(); // match, copy constructor throws
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible
+  throw OptionallyAllocates(); // ok
+}
+
+namespace PR25574 {
+struct B {
+  B(const B&) noexcept;
+};
+
+struct D : B {
+  D();
+  virtual ~D() noexcept;
+};
+
+template <typename T>
+void f() {
+  throw D();
+}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-variadic-function-def.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-variadic-function-def.cpp
new file mode 100644
index 0000000..6b2421b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cert-variadic-function-def.cpp
@@ -0,0 +1,24 @@
+// RUN: %check_clang_tidy %s cert-dcl50-cpp %t
+
+// Variadic function definitions are diagnosed.
+void f1(int, ...) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: do not define a C-style variadic function; consider using a function parameter pack or currying instead [cert-dcl50-cpp]
+
+// Variadic function *declarations* are not diagnosed.
+void f2(int, ...); // ok
+
+// Function parameter packs are good, however.
+template <typename Arg, typename... Ts>
+void f3(Arg F, Ts... Rest) {}
+
+struct S {
+  void f(int, ...); // ok
+  void f1(int, ...) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: do not define a C-style variadic function; consider using a function parameter pack or currying instead
+};
+
+// Function definitions that are extern "C" are good.
+extern "C" void f4(int, ...) {} // ok
+extern "C" {
+  void f5(int, ...) {} // ok
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/check_clang_tidy.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/check_clang_tidy.cpp
new file mode 100644
index 0000000..5c1bf92
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/check_clang_tidy.cpp
@@ -0,0 +1,21 @@
+// RUN: %check_clang_tidy -check-suffix=USING-A %s misc-unused-using-decls %t -- -- -DUSING_A
+// RUN: %check_clang_tidy -check-suffix=USING-B %s misc-unused-using-decls %t -- -- -DUSING_B
+// RUN: %check_clang_tidy %s misc-unused-using-decls %t
+
+namespace a {class A {}; class B {}; class C {}; }
+namespace b {
+#if defined(USING_A)
+using a::A;
+#elif  defined(USING_B)
+using a::B;
+#else
+using a::C;
+#endif
+}
+namespace c {}
+// CHECK-MESSAGES-USING-A: :[[@LINE-8]]:10: warning: using decl 'A' {{.*}}
+// CHECK-MESSAGES-USING-B: :[[@LINE-7]]:10: warning: using decl 'B' {{.*}}
+// CHECK-MESSAGES: :[[@LINE-6]]:10: warning: using decl 'C' {{.*}}
+// CHECK-FIXES-USING-A-NOT: using a::A;$
+// CHECK-FIXES-USING-B-NOT: using a::B;$
+// CHECK-FIXES-NOT: using a::C;$
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/check_clang_tidy.py b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/check_clang_tidy.py
new file mode 100755
index 0000000..bb2c5a2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/check_clang_tidy.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+#
+#===- check_clang_tidy.py - ClangTidy Test Helper ------------*- python -*--===#
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+r"""
+ClangTidy Test Helper
+=====================
+
+This script runs clang-tidy in fix mode and verify fixes, messages or both.
+
+Usage:
+  check_clang_tidy.py [-resource-dir=<resource-dir>] \
+    [-assume-filename=<file-with-source-extension>] \
+    [-check-suffix=<file-check-suffix>] \
+    <source-file> <check-name> <temp-file> \
+    -- [optional clang-tidy arguments]
+
+Example:
+  // RUN: %check_clang_tidy %s llvm-include-order %t -- -- -isystem %S/Inputs
+"""
+
+import argparse
+import os
+import re
+import subprocess
+import sys
+
+
+def write_file(file_name, text):
+  with open(file_name, 'w') as f:
+    f.write(text)
+    f.truncate()
+
+def main():
+  parser = argparse.ArgumentParser()
+  parser.add_argument('-expect-clang-tidy-error', action='store_true')
+  parser.add_argument('-resource-dir')
+  parser.add_argument('-assume-filename')
+  parser.add_argument('-check-suffix', default='')
+  parser.add_argument('input_file_name')
+  parser.add_argument('check_name')
+  parser.add_argument('temp_file_name')
+
+  args, extra_args = parser.parse_known_args()
+
+  resource_dir = args.resource_dir
+  assume_file_name = args.assume_filename
+  input_file_name = args.input_file_name
+  check_name = args.check_name
+  temp_file_name = args.temp_file_name
+  expect_clang_tidy_error = args.expect_clang_tidy_error
+
+  file_name_with_extension = assume_file_name or input_file_name
+  _, extension = os.path.splitext(file_name_with_extension)
+  if extension not in ['.c', '.hpp', '.m', '.mm']:
+    extension = '.cpp'
+  temp_file_name = temp_file_name + extension
+
+  clang_tidy_extra_args = extra_args
+  if len(clang_tidy_extra_args) == 0:
+    clang_tidy_extra_args = ['--']
+    if extension in ['.cpp', '.hpp', '.mm']:
+      clang_tidy_extra_args.append('--std=c++11')
+    if extension in ['.m', '.mm']:
+      clang_tidy_extra_args.extend(
+          ['-fobjc-abi-version=2', '-fobjc-arc'])
+
+  if args.check_suffix and not re.match('^[A-Z0-9\-]+$', args.check_suffix):
+    sys.exit('Only A..Z, 0..9 and "-" are allowed in check suffix, but "%s" was given' % (args.check_suffix))
+
+  file_check_suffix = ('-' + args.check_suffix) if args.check_suffix else ''
+  check_fixes_prefix = 'CHECK-FIXES' + file_check_suffix
+  check_messages_prefix = 'CHECK-MESSAGES' + file_check_suffix
+
+  # Tests should not rely on STL being available, and instead provide mock
+  # implementations of relevant APIs.
+  clang_tidy_extra_args.append('-nostdinc++')
+
+  if resource_dir is not None:
+    clang_tidy_extra_args.append('-resource-dir=%s' % resource_dir)
+
+  with open(input_file_name, 'r') as input_file:
+    input_text = input_file.read()
+
+  has_check_fixes = check_fixes_prefix in input_text
+  has_check_messages = check_messages_prefix in input_text
+
+  if not has_check_fixes and not has_check_messages:
+    sys.exit('Neither %s nor %s found in the input' % (check_fixes_prefix, check_messages_prefix) )
+
+  # Remove the contents of the CHECK lines to avoid CHECKs matching on
+  # themselves.  We need to keep the comments to preserve line numbers while
+  # avoiding empty lines which could potentially trigger formatting-related
+  # checks.
+  cleaned_test = re.sub('// *CHECK-[A-Z0-9\-]*:[^\r\n]*', '//', input_text)
+
+  write_file(temp_file_name, cleaned_test)
+
+  original_file_name = temp_file_name + ".orig"
+  write_file(original_file_name, cleaned_test)
+
+  args = ['clang-tidy', temp_file_name, '-fix', '--checks=-*,' + check_name] + \
+        clang_tidy_extra_args
+  if expect_clang_tidy_error:
+    args.insert(0, 'not')
+  print('Running ' + repr(args) + '...')
+  try:
+    clang_tidy_output = \
+        subprocess.check_output(args, stderr=subprocess.STDOUT).decode()
+  except subprocess.CalledProcessError as e:
+    print('clang-tidy failed:\n' + e.output.decode())
+    raise
+
+  print('------------------------ clang-tidy output -----------------------\n' +
+        clang_tidy_output +
+        '\n------------------------------------------------------------------')
+
+  try:
+    diff_output = subprocess.check_output(
+        ['diff', '-u', original_file_name, temp_file_name],
+        stderr=subprocess.STDOUT)
+  except subprocess.CalledProcessError as e:
+    diff_output = e.output
+
+  print('------------------------------ Fixes -----------------------------\n' +
+        diff_output.decode() +
+        '\n------------------------------------------------------------------')
+
+  if has_check_fixes:
+    try:
+      subprocess.check_output(
+          ['FileCheck', '-input-file=' + temp_file_name, input_file_name,
+           '-check-prefix=' + check_fixes_prefix, '-strict-whitespace'],
+          stderr=subprocess.STDOUT)
+    except subprocess.CalledProcessError as e:
+      print('FileCheck failed:\n' + e.output.decode())
+      raise
+
+  if has_check_messages:
+    messages_file = temp_file_name + '.msg'
+    write_file(messages_file, clang_tidy_output)
+    try:
+      subprocess.check_output(
+          ['FileCheck', '-input-file=' + messages_file, input_file_name,
+           '-check-prefix=' + check_messages_prefix,
+           '-implicit-check-not={{warning|error}}:'],
+          stderr=subprocess.STDOUT)
+    except subprocess.CalledProcessError as e:
+      print('FileCheck failed:\n' + e.output.decode())
+      raise
+
+if __name__ == '__main__':
+  main()
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-__clang_analyzer__macro.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-__clang_analyzer__macro.cpp
new file mode 100644
index 0000000..0fda1a3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-__clang_analyzer__macro.cpp
@@ -0,0 +1,5 @@
+// RUN: clang-tidy %s -checks=-*,modernize-use-nullptr -- | count 0
+
+#if !defined(__clang_analyzer__)
+#error __clang_analyzer__ is not defined
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-diff.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-diff.cpp
new file mode 100644
index 0000000..146287b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-diff.cpp
@@ -0,0 +1,27 @@
+// REQUIRES: shell
+// RUN: sed 's/placeholder_for_f/f/' %s > %t.cpp
+// RUN: clang-tidy -checks=-*,modernize-use-override %t.cpp -- -std=c++11 | FileCheck -check-prefix=CHECK-SANITY %s
+// RUN: not diff -U0 %s %t.cpp | %clang_tidy_diff -checks=-*,modernize-use-override -- -std=c++11 2>&1 | FileCheck %s
+// RUN: not diff -U0 %s %t.cpp | %clang_tidy_diff -checks=-*,modernize-use-override -quiet -- -std=c++11 2>&1 | FileCheck -check-prefix=CHECK-QUIET %s
+// RUN: mkdir -p %T/compilation-database-test/
+// RUN: echo '[{"directory": "%T", "command": "clang++ -o test.o -std=c++11 %t.cpp", "file": "%t.cpp"}]' > %T/compilation-database-test/compile_commands.json
+// RUN: not diff -U0 %s %t.cpp | %clang_tidy_diff -checks=-*,modernize-use-override -path %T/compilation-database-test 2>&1 | FileCheck -check-prefix=CHECK %s
+struct A {
+  virtual void f() {}
+  virtual void g() {}
+};
+// CHECK-NOT: warning:
+// CHECK-QUIET-NOT: warning:
+struct B : public A {
+  void placeholder_for_f() {}
+// CHECK-SANITY: [[@LINE-1]]:8: warning: annotate this
+// CHECK: [[@LINE-2]]:8: warning: annotate this
+// CHECK-QUIET: [[@LINE-3]]:8: warning: annotate this
+  void g() {}
+// CHECK-SANITY: [[@LINE-1]]:8: warning: annotate this
+// CHECK-NOT: warning:
+// CHECK-QUIET-NOT: warning:
+};
+// CHECK-SANITY-NOT: Suppressed
+// CHECK: Suppressed 1 warnings (1 due to line filter).
+// CHECK-QUIET-NOT: Suppressed
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-enable-check-profile-one-tu.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-enable-check-profile-one-tu.cpp
new file mode 100644
index 0000000..df4cb93
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-enable-check-profile-one-tu.cpp
@@ -0,0 +1,24 @@
+// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' %s -- 2>&1 | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' %s
+
+// CHECK: ===-------------------------------------------------------------------------===
+// CHECK-NEXT:                          clang-tidy checks profiling
+// CHECK-NEXT: ===-------------------------------------------------------------------------===
+// CHECK-NEXT: Total Execution Time: {{.*}} seconds ({{.*}} wall clock)
+
+// CHECK: {{.*}}  --- Name ---
+// CHECK-NEXT: {{.*}}  readability-function-size
+// CHECK-NEXT: {{.*}}  Total
+
+// CHECK-NOT: ===-------------------------------------------------------------------------===
+// CHECK-NOT:                          clang-tidy checks profiling
+// CHECK-NOT: ===-------------------------------------------------------------------------===
+// CHECK-NOT: Total Execution Time: {{.*}} seconds ({{.*}} wall clock)
+
+// CHECK-NOT: {{.*}}  --- Name ---
+// CHECK-NOT: {{.*}}  readability-function-size
+// CHECK-NOT: {{.*}}  Total
+
+class A {
+  A() {}
+  ~A() {}
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-enable-check-profile-two-tu.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-enable-check-profile-two-tu.cpp
new file mode 100644
index 0000000..30603a2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-enable-check-profile-two-tu.cpp
@@ -0,0 +1,33 @@
+// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' %s %s -- 2>&1 | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' %s
+
+// CHECK: ===-------------------------------------------------------------------------===
+// CHECK-NEXT:                          clang-tidy checks profiling
+// CHECK-NEXT: ===-------------------------------------------------------------------------===
+// CHECK-NEXT: Total Execution Time: {{.*}} seconds ({{.*}} wall clock)
+
+// CHECK: {{.*}}  --- Name ---
+// CHECK-NEXT: {{.*}}  readability-function-size
+// CHECK-NEXT: {{.*}}  Total
+
+// CHECK: ===-------------------------------------------------------------------------===
+// CHECK-NEXT:                          clang-tidy checks profiling
+// CHECK-NEXT: ===-------------------------------------------------------------------------===
+// CHECK-NEXT: Total Execution Time: {{.*}} seconds ({{.*}} wall clock)
+
+// CHECK: {{.*}}  --- Name ---
+// CHECK-NEXT: {{.*}}  readability-function-size
+// CHECK-NEXT: {{.*}}  Total
+
+// CHECK-NOT: ===-------------------------------------------------------------------------===
+// CHECK-NOT:                          clang-tidy checks profiling
+// CHECK-NOT: ===-------------------------------------------------------------------------===
+// CHECK-NOT: Total Execution Time: {{.*}} seconds ({{.*}} wall clock)
+
+// CHECK-NOT: {{.*}}  --- Name ---
+// CHECK-NOT: {{.*}}  readability-function-size
+// CHECK-NOT: {{.*}}  Total
+
+class A {
+  A() {}
+  ~A() {}
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-run-with-database.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-run-with-database.cpp
new file mode 100644
index 0000000..05bc14c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-run-with-database.cpp
@@ -0,0 +1,23 @@
+// RUN: mkdir -p %T/compilation-database-test/include
+// RUN: mkdir -p %T/compilation-database-test/a
+// RUN: mkdir -p %T/compilation-database-test/b
+// RUN: echo 'int *AA = 0;' > %T/compilation-database-test/a/a.cpp
+// RUN: echo 'int *AB = 0;' > %T/compilation-database-test/a/b.cpp
+// RUN: echo 'int *BB = 0;' > %T/compilation-database-test/b/b.cpp
+// RUN: echo 'int *BC = 0;' > %T/compilation-database-test/b/c.cpp
+// RUN: echo 'int *HP = 0;' > %T/compilation-database-test/include/header.h
+// RUN: echo '#include "header.h"' > %T/compilation-database-test/b/d.cpp
+// RUN: sed 's|test_dir|%/T/compilation-database-test|g' %S/Inputs/compilation-database/template.json > %T/compile_commands.json
+// RUN: clang-tidy --checks=-*,modernize-use-nullptr -p %T %T/compilation-database-test/b/not-exist -header-filter=.*
+// RUN: clang-tidy --checks=-*,modernize-use-nullptr -p %T %T/compilation-database-test/a/a.cpp %T/compilation-database-test/a/b.cpp %T/compilation-database-test/b/b.cpp %T/compilation-database-test/b/c.cpp %T/compilation-database-test/b/d.cpp -header-filter=.* -fix
+// RUN: FileCheck -input-file=%T/compilation-database-test/a/a.cpp %s -check-prefix=CHECK-FIX1
+// RUN: FileCheck -input-file=%T/compilation-database-test/a/b.cpp %s -check-prefix=CHECK-FIX2
+// RUN: FileCheck -input-file=%T/compilation-database-test/b/b.cpp %s -check-prefix=CHECK-FIX3
+// RUN: FileCheck -input-file=%T/compilation-database-test/b/c.cpp %s -check-prefix=CHECK-FIX4
+// RUN: FileCheck -input-file=%T/compilation-database-test/include/header.h %s -check-prefix=CHECK-FIX5
+
+// CHECK-FIX1: int *AA = nullptr;
+// CHECK-FIX2: int *AB = nullptr;
+// CHECK-FIX3: int *BB = nullptr;
+// CHECK-FIX4: int *BC = nullptr;
+// CHECK-FIX5: int *HP = nullptr;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-store-check-profile-one-tu.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-store-check-profile-one-tu.cpp
new file mode 100644
index 0000000..832723b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clang-tidy-store-check-profile-one-tu.cpp
@@ -0,0 +1,37 @@
+// RUN: rm -rf %T/out
+// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' -store-check-profile=%T/out %s -- 2>&1 | not FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK-CONSOLE %s
+// RUN: cat %T/out/*-clang-tidy-store-check-profile-one-tu.cpp.json | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK-FILE %s
+// RUN: rm -rf %T/out
+// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' -store-check-profile=%T/out %s -- 2>&1
+// RUN: cat %T/out/*-clang-tidy-store-check-profile-one-tu.cpp.json | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK-FILE %s
+
+// CHECK-CONSOLE-NOT: ===-------------------------------------------------------------------------===
+// CHECK-CONSOLE-NOT: {{.*}}  --- Name ---
+// CHECK-CONSOLE-NOT: {{.*}}  readability-function-size
+// CHECK-CONSOLE-NOT: {{.*}}  Total
+// CHECK-CONSOLE-NOT: ===-------------------------------------------------------------------------===
+
+// CHECK-FILE: {
+// CHECK-FILE-NEXT:"file": "{{.*}}clang-tidy-store-check-profile-one-tu.cpp",
+// CHECK-FILE-NEXT:"timestamp": "{{[0-9]+}}-{{[0-9]+}}-{{[0-9]+}} {{[0-9]+}}:{{[0-9]+}}:{{[0-9]+}}.{{[0-9]+}}",
+// CHECK-FILE-NEXT:"profile": {
+// CHECK-FILE-NEXT:	"time.clang-tidy.readability-function-size.wall": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}},
+// CHECK-FILE-NEXT:	"time.clang-tidy.readability-function-size.user": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}},
+// CHECK-FILE-NEXT:	"time.clang-tidy.readability-function-size.sys": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}}
+// CHECK-FILE-NEXT: }
+// CHECK-FILE-NEXT: }
+
+// CHECK-FILE-NOT: {
+// CHECK-FILE-NOT: "file": {{.*}}clang-tidy-store-check-profile-one-tu.cpp{{.*}},
+// CHECK-FILE-NOT: "timestamp": "{{[0-9]+}}-{{[0-9]+}}-{{[0-9]+}} {{[0-9]+}}:{{[0-9]+}}:{{[0-9]+}}.{{[0-9]+}}",
+// CHECK-FILE-NOT: "profile": {
+// CHECK-FILE-NOT:	"time.clang-tidy.readability-function-size.wall": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}},
+// CHECK-FILE-NOT:	"time.clang-tidy.readability-function-size.user": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}},
+// CHECK-FILE-NOT:	"time.clang-tidy.readability-function-size.sys": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}}
+// CHECK-FILE-NOT: }
+// CHECK-FILE-NOT: }
+
+class A {
+  A() {}
+  ~A() {}
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clean-up-code.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clean-up-code.cpp
new file mode 100644
index 0000000..15873ed
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/clean-up-code.cpp
@@ -0,0 +1,14 @@
+// RUN: %check_clang_tidy %s misc-unused-using-decls %t
+// RUN: %check_clang_tidy %s misc-unused-using-decls %t -- -format-style=none --
+// RUN: %check_clang_tidy %s misc-unused-using-decls %t -- -format-style=llvm --
+namespace a { class A {}; }
+namespace b {
+using a::A;
+}
+namespace c {}
+// CHECK-MESSAGES: :[[@LINE-3]]:10: warning: using decl 'A' is unused [misc-unused-using-decls]
+// CHECK-FIXES: {{^namespace a { class A {}; }$}}
+// CHECK-FIXES-NOT: namespace
+// CHECK-FIXES: {{^namespace c {}$}}
+// FIXME: cleanupAroundReplacements leaves whitespace. Otherwise we could just
+// check the next line.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/config-files.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/config-files.cpp
new file mode 100644
index 0000000..65ac54a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/config-files.cpp
@@ -0,0 +1,12 @@
+// RUN: clang-tidy -dump-config %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-BASE
+// CHECK-BASE: Checks: {{.*}}from-parent
+// CHECK-BASE: HeaderFilterRegex: parent
+// RUN: clang-tidy -dump-config %S/Inputs/config-files/1/- -- | FileCheck %s -check-prefix=CHECK-CHILD1
+// CHECK-CHILD1: Checks: {{.*}}from-child1
+// CHECK-CHILD1: HeaderFilterRegex: child1
+// RUN: clang-tidy -dump-config %S/Inputs/config-files/2/- -- | FileCheck %s -check-prefix=CHECK-CHILD2
+// CHECK-CHILD2: Checks: {{.*}}from-parent
+// CHECK-CHILD2: HeaderFilterRegex: parent
+// RUN: clang-tidy -dump-config -checks='from-command-line' -header-filter='from command line' %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-COMMAND-LINE
+// CHECK-COMMAND-LINE: Checks: {{.*}}from-parent,from-command-line
+// CHECK-COMMAND-LINE: HeaderFilterRegex: from command line
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-avoid-goto.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-avoid-goto.cpp
new file mode 100644
index 0000000..213947f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-avoid-goto.cpp
@@ -0,0 +1,139 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-goto %t
+
+void noop() {}
+
+int main() {
+  noop();
+  goto jump_to_me;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
+  // CHECK-MESSAGES: [[@LINE+3]]:1: note: label defined here
+  noop();
+
+jump_to_me:;
+
+jump_backwards:;
+  noop();
+  goto jump_backwards;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
+  // CHECK-MESSAGES: [[@LINE-4]]:1: note: label defined here
+
+  goto jump_in_line;
+  ;
+jump_in_line:;
+  // CHECK-MESSAGES: [[@LINE-3]]:3: warning: avoid using 'goto' for flow control
+  // CHECK-MESSAGES: [[@LINE-2]]:1: note: label defined here
+
+  // Test the GNU extension https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
+some_label:;
+  void *dynamic_label = &&some_label;
+
+  // FIXME: `IndirectGotoStmt` is not detected.
+  goto *dynamic_label;
+}
+
+void forward_jump_out_nested_loop() {
+  int array[] = {1, 2, 3, 4, 5};
+  for (int i = 0; i < 10; ++i) {
+    noop();
+    for (int j = 0; j < 10; ++j) {
+      noop();
+      if (i + j > 10)
+        goto early_exit1;
+    }
+    noop();
+  }
+
+  for (int i = 0; i < 10; ++i) {
+    noop();
+    while (true) {
+      noop();
+      if (i > 5)
+        goto early_exit1;
+    }
+    noop();
+  }
+
+  for (auto value : array) {
+    noop();
+    for (auto number : array) {
+      noop();
+      if (number == 5)
+        goto early_exit1;
+    }
+  }
+
+  do {
+    noop();
+    do {
+      noop();
+      goto early_exit1;
+    } while (true);
+  } while (true);
+
+  do {
+    for (auto number : array) {
+      noop();
+      if (number == 2)
+        goto early_exit1;
+    }
+  } while (true);
+
+  // Jumping further results in error, because the variable declaration would
+  // be skipped.
+early_exit1:;
+
+  int i = 0;
+  while (true) {
+    noop();
+    while (true) {
+      noop();
+      if (i > 5)
+        goto early_exit2;
+      i++;
+    }
+    noop();
+  }
+
+  while (true) {
+    noop();
+    for (int j = 0; j < 10; ++j) {
+      noop();
+      if (j > 5)
+        goto early_exit2;
+    }
+    noop();
+  }
+
+  while (true) {
+    noop();
+    for (auto number : array) {
+      if (number == 1)
+        goto early_exit2;
+      noop();
+    }
+  }
+
+  while (true) {
+    noop();
+    do {
+      noop();
+      goto early_exit2;
+    } while (true);
+  }
+early_exit2:;
+}
+
+void jump_out_backwards() {
+
+before_the_loop:
+  noop();
+
+  for (int i = 0; i < 10; ++i) {
+    for (int j = 0; j < 10; ++j) {
+      if (i * j > 80)
+        goto before_the_loop;
+      // CHECK-MESSAGES: [[@LINE-1]]:9: warning: avoid using 'goto' for flow control
+      // CHECK-MESSAGES: [[@LINE-8]]:1: note: label defined here
+    }
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-interfaces-global-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-interfaces-global-init.cpp
new file mode 100644
index 0000000..51f79e5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-interfaces-global-init.cpp
@@ -0,0 +1,84 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-interfaces-global-init %t
+
+constexpr int makesInt() { return 3; }
+constexpr int takesInt(int i) { return i + 1; }
+constexpr int takesIntPtr(int *i) { return *i; }
+
+extern int ExternGlobal;
+static int GlobalScopeBadInit1 = ExternGlobal;
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+static int GlobalScopeBadInit2 = takesInt(ExternGlobal);
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+static int GlobalScopeBadInit3 = takesIntPtr(&ExternGlobal);
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+static int GlobalScopeBadInit4 = 3 * (ExternGlobal + 2);
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+
+namespace ns {
+static int NamespaceScope = makesInt();
+static int NamespaceScopeBadInit = takesInt(ExternGlobal);
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+
+struct A {
+  static int ClassScope;
+  static int ClassScopeBadInit;
+};
+
+int A::ClassScopeBadInit = takesInt(ExternGlobal);
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+
+static int FromClassBadInit = takesInt(A::ClassScope);
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ClassScope'
+} // namespace ns
+
+// "const int B::I;" is fine, it just ODR-defines B::I. See [9.4.3] Static
+// members [class.static]. However the ODR-definitions are not in the right
+// order (C::I after C::J, see [3.6.2.3]).
+class B1 {
+  static const int I = 0;
+  static const int J = I;
+};
+const int B1::J;
+// CHECK-MESSAGES: [[@LINE-1]]:15: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'I'
+const int B1::I;
+
+void f() {
+  // This is fine, it's executed after dynamic initialization occurs.
+  static int G = takesInt(ExternGlobal);
+}
+
+// Declaration then definition then usage is fine.
+extern int ExternGlobal2;
+extern int ExternGlobal2;
+int ExternGlobal2 = 123;
+static int GlobalScopeGoodInit1 = ExternGlobal2;
+
+
+// Defined global variables are fine:
+static int GlobalScope = makesInt();
+static int GlobalScopeGoodInit2 = takesInt(GlobalScope);
+static int GlobalScope2 = takesInt(ns::NamespaceScope);
+// Enums are fine.
+enum Enum { kEnumValue = 1 };
+static int GlobalScopeFromEnum = takesInt(kEnumValue);
+
+// Leave constexprs alone.
+extern constexpr int GlobalScopeConstexpr = makesInt();
+static constexpr int GlobalScopeConstexprOk =
+    takesInt(GlobalScopeConstexpr);
+
+// This is a pretty common instance: People are usually not using constexpr, but
+// this is what they should write:
+static constexpr const char kValue[] = "value";
+constexpr int Fingerprint(const char *value) { return 0; }
+static int kFingerprint = Fingerprint(kValue);
+
+// This is fine because the ODR-definitions are in the right order (C::J after
+// C::I).
+class B2 {
+  static const int I = 0;
+  static const int J = I;
+};
+const int B2::I;
+const int B2::J;
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp
new file mode 100644
index 0000000..ecffba6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-narrowing-conversions.cpp
@@ -0,0 +1,103 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t
+
+float ceil(float);
+namespace std {
+double ceil(double);
+long double floor(long double);
+} // namespace std
+
+namespace floats {
+
+struct ConvertsToFloat {
+  operator float() const { return 0.5; }
+};
+
+float operator "" _Pa(unsigned long long);
+
+void not_ok(double d) {
+  int i = 0;
+  i = d;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions]
+  i = 0.5f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+  i = static_cast<float>(d);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+  i = ConvertsToFloat();
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+  i = 15_Pa;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+}
+
+void not_ok_binary_ops(double d) {
+  int i = 0;
+  i += 0.5;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions]
+  i += 0.5f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+  i += d;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions]
+  // We warn on the following even though it's not dangerous because there is no
+  // reason to use a double literal here.
+  // TODO(courbet): Provide an automatic fix.
+  i += 2.0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions]
+  i += 2.0f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+
+  i *= 0.5f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+  i /= 0.5f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'float' to 'int' [cppcoreguidelines-narrowing-conversions]
+  i += (double)0.5f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: narrowing conversion from 'double' to 'int' [cppcoreguidelines-narrowing-conversions]
+}
+
+void ok(double d) {
+  int i = 0;
+  i = 1;
+  i = static_cast<int>(0.5);
+  i = static_cast<int>(d);
+  i = std::ceil(0.5);
+  i = ::std::floor(0.5);
+  {
+    using std::ceil;
+    i = ceil(0.5f);
+  }
+  i = ceil(0.5f);
+}
+
+void ok_binary_ops(double d) {
+  int i = 0;
+  i += 1;
+  i += static_cast<int>(0.5);
+  i += static_cast<int>(d);
+  i += (int)d;
+  i += std::ceil(0.5);
+  i += ::std::floor(0.5);
+  {
+    using std::ceil;
+    i += ceil(0.5f);
+  }
+  i += ceil(0.5f);
+}
+
+// We're bailing out in templates and macros.
+template <typename T1, typename T2>
+void f(T1 one, T2 two) {
+  one += two;
+}
+
+void template_context() {
+  f(1, 2);
+  f(1, .5);
+}
+
+#define DERP(i, j) (i += j)
+
+void macro_context() {
+  int i = 0;
+  DERP(i, 2);
+  DERP(i, .5);
+}
+
+}  // namespace floats
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc-custom.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc-custom.cpp
new file mode 100644
index 0000000..89142fb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc-custom.cpp
@@ -0,0 +1,59 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-no-malloc %t \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: cppcoreguidelines-no-malloc.Allocations, value: "::malloc;::align_malloc;::calloc"},\
+// RUN:   {key: cppcoreguidelines-no-malloc.Reallocations, value: "::realloc;::align_realloc"},\
+// RUN:   {key: cppcoreguidelines-no-malloc.Deallocations, value: "::free;::align_free"}]}' \
+// RUN: --
+
+using size_t = __SIZE_TYPE__;
+
+void *malloc(size_t size);
+void *align_malloc(size_t size, unsigned short aligmnent);
+void *calloc(size_t num, size_t size);
+void *realloc(void *ptr, size_t size);
+void *align_realloc(void *ptr, size_t size, unsigned short alignment);
+void free(void *ptr);
+void *align_free(void *ptr);
+
+void malloced_array() {
+  int *array0 = (int *)malloc(sizeof(int) * 20);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+
+  int *zeroed = (int *)calloc(20, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+
+  int *aligned = (int *)align_malloc(20 * sizeof(int), 16);
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+
+  // reallocation memory, std::vector shall be used
+  char *realloced = (char *)realloc(array0, 50 * sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: do not manage memory manually; consider std::vector or std::string [cppcoreguidelines-no-malloc]
+
+  char *align_realloced = (char *)align_realloc(aligned, 50 * sizeof(int), 16);
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: do not manage memory manually; consider std::vector or std::string [cppcoreguidelines-no-malloc]
+
+  // freeing memory the bad way
+  free(realloced);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not manage memory manually; use RAII [cppcoreguidelines-no-malloc]
+
+  align_free(align_realloced);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not manage memory manually; use RAII [cppcoreguidelines-no-malloc]
+  
+  // check if a call to malloc as function argument is found as well
+  free(malloc(20));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not manage memory manually; use RAII [cppcoreguidelines-no-malloc]
+  // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+}
+
+/// newing an array is still not good, but not relevant to this checker
+void newed_array() {
+  int *new_array = new int[10]; // OK(1)
+}
+
+void arbitrary_call() {
+  // we dont want every function to raise the warning even if malloc is in the name
+  malloced_array(); // OK(2)
+
+  // completly unrelated function call to malloc
+  newed_array(); // OK(3)
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc-no-functions.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc-no-functions.cpp
new file mode 100644
index 0000000..8b4d464
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc-no-functions.cpp
@@ -0,0 +1,17 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-no-malloc %t \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: cppcoreguidelines-no-malloc.Allocations, value: "::malloc"},\
+// RUN:   {key: cppcoreguidelines-no-malloc.Reallocations, value: ""},\
+// RUN:   {key: cppcoreguidelines-no-malloc.Deallocations, value: ""}]}' \
+// RUN: --
+
+// Just ensure, the check will not crash, when no functions shall be checked.
+
+using size_t = __SIZE_TYPE__;
+
+void *malloc(size_t size);
+
+void malloced_array() {
+  int *array0 = (int *)malloc(sizeof(int) * 20);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc.cpp
new file mode 100644
index 0000000..7b7ccf3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-no-malloc.cpp
@@ -0,0 +1,42 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-no-malloc %t
+
+using size_t = __SIZE_TYPE__;
+
+void *malloc(size_t size);
+void *calloc(size_t num, size_t size);
+void *realloc(void *ptr, size_t size);
+void free(void *ptr);
+
+void malloced_array() {
+  int *array0 = (int *)malloc(sizeof(int) * 20);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+
+  int *zeroed = (int *)calloc(20, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+
+  // reallocation memory, std::vector shall be used
+  char *realloced = (char *)realloc(array0, 50 * sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: do not manage memory manually; consider std::vector or std::string [cppcoreguidelines-no-malloc]
+
+  // freeing memory the bad way
+  free(realloced);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not manage memory manually; use RAII [cppcoreguidelines-no-malloc]
+
+  // check if a call to malloc as function argument is found as well
+  free(malloc(20));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not manage memory manually; use RAII [cppcoreguidelines-no-malloc]
+  // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
+}
+
+/// newing an array is still not good, but not relevant to this checker
+void newed_array() {
+  int *new_array = new int[10]; // OK(1)
+}
+
+void arbitrary_call() {
+  // we dont want every function to raise the warning even if malloc is in the name
+  malloced_array(); // OK(2)
+
+  // completly unrelated function call to malloc
+  newed_array(); // OK(3)
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory-containers.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory-containers.cpp
new file mode 100644
index 0000000..929b33d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory-containers.cpp
@@ -0,0 +1,61 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-owning-memory %t
+
+namespace gsl {
+template <typename T>
+using owner = T;
+}
+
+namespace std {
+
+// Not actually a vector, but more a dynamic, fixed size array. Just to demonstrate
+// functionality or the lack of the same.
+template <typename T>
+class vector {
+public:
+  vector(unsigned long size, T val) : data{new T[size]}, size{size} {
+    for (unsigned long i = 0ul; i < size; ++i) {
+      data[i] = val;
+    }
+  }
+
+  T *begin() { return data; }
+  T *end() { return &data[size]; }
+  T &operator[](unsigned long index) { return data[index]; }
+
+private:
+  T *data;
+  unsigned long size;
+};
+
+} // namespace std
+
+// All of the following codesnippets should be valid with appropriate 'owner<>' anaylsis,
+// but currently the type information of 'gsl::owner<>' gets lost in typededuction.
+int main() {
+  std::vector<gsl::owner<int *>> OwnerStdVector(100, nullptr);
+
+  // Rangebased looping in resource vector.
+  for (auto *Element : OwnerStdVector) {
+    Element = new int(42);
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: assigning newly created 'gsl::owner<>' to non-owner 'int *'
+  }
+  for (auto *Element : OwnerStdVector) {
+    delete Element;
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead
+    // CHECK-MESSAGES: [[@LINE-3]]:8: note: variable declared here
+  }
+
+  // Indexbased looping in resource vector.
+  for (int i = 0; i < 100; ++i) {
+    OwnerStdVector[i] = new int(42);
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: assigning newly created 'gsl::owner<>' to non-owner 'int *'
+  }
+  for (int i = 0; i < 100; ++i) {
+    delete OwnerStdVector[i];
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead
+    // A note gets emitted here pointing to the return value of the operator[] from the
+    // vector implementation. Maybe this is considered misleading.
+  }
+
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory-legacy-functions.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory-legacy-functions.cpp
new file mode 100644
index 0000000..5785e9f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory-legacy-functions.cpp
@@ -0,0 +1,194 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-owning-memory %t \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: cppcoreguidelines-owning-memory.LegacyResourceProducers, value: "::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile"}, \
+// RUN:   {key: cppcoreguidelines-owning-memory.LegacyResourceConsumers, value: "::free;::realloc;::freopen;::fclose"}]}' \
+// RUN: -- -std=c++11 -nostdlib -nostdinc++
+
+namespace gsl {
+template <class T>
+using owner = T;
+} // namespace gsl
+
+extern "C" {
+using size_t = decltype(sizeof(void*));
+using FILE = int;
+
+void *malloc(size_t ByteCount);
+void *aligned_alloc(size_t Alignment, size_t Size);
+void *calloc(size_t Count, size_t SizeSingle);
+void *realloc(void *Resource, size_t NewByteCount);
+void free(void *Resource);
+
+FILE *tmpfile(void);
+FILE *fopen(const char *filename, const char *mode);
+FILE *freopen(const char *filename, const char *mode, FILE *stream);
+void fclose(FILE *Resource);
+}
+
+namespace std {
+using ::FILE;
+using ::size_t;
+
+using ::fclose;
+using ::fopen;
+using ::freopen;
+using ::tmpfile;
+
+using ::aligned_alloc;
+using ::calloc;
+using ::free;
+using ::malloc;
+using ::realloc;
+} // namespace std
+
+void nonOwningCall(int *Resource, size_t Size) {}
+void nonOwningCall(FILE *Resource) {}
+
+void consumesResource(gsl::owner<int *> Resource, size_t Size) {}
+void consumesResource(gsl::owner<FILE *> Resource) {}
+
+void testNonCasted(void *Resource) {}
+
+void testNonCastedOwner(gsl::owner<void *> Resource) {}
+
+FILE *fileFactory1() { return ::fopen("new_file.txt", "w"); }
+// CHECK-MESSAGES: [[@LINE-1]]:24: warning: returning a newly created resource of type 'FILE *' (aka 'int *') or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'
+gsl::owner<FILE *> fileFactory2() { return std::fopen("new_file.txt", "w"); } // Ok
+
+int *arrayFactory1() { return (int *)std::malloc(100); }
+// CHECK-MESSAGES: [[@LINE-1]]:24: warning: returning a newly created resource of type 'int *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'
+gsl::owner<int *> arrayFactory2() { return (int *)std::malloc(100); } // Ok
+void *dataFactory1() { return std::malloc(100); }
+// CHECK-MESSAGES: [[@LINE-1]]:24: warning: returning a newly created resource of type 'void *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'
+gsl::owner<void *> dataFactory2() { return std::malloc(100); } // Ok
+
+void test_resource_creators() {
+  const unsigned int ByteCount = 25 * sizeof(int);
+  int Bad = 42;
+
+  int *IntArray1 = (int *)std::malloc(ByteCount);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  int *IntArray2 = static_cast<int *>(std::malloc(ByteCount)); // Bad
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  void *IntArray3 = std::malloc(ByteCount);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'void *' with a newly created 'gsl::owner<>'
+
+  int *IntArray4 = (int *)::malloc(ByteCount);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  int *IntArray5 = static_cast<int *>(::malloc(ByteCount)); // Bad
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  void *IntArray6 = ::malloc(ByteCount);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'void *' with a newly created 'gsl::owner<>'
+
+  gsl::owner<int *> IntArray7 = (int *)malloc(ByteCount); // Ok
+  gsl::owner<void *> IntArray8 = malloc(ByteCount);       // Ok
+
+  gsl::owner<int *> IntArray9 = &Bad;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+
+  nonOwningCall((int *)malloc(ByteCount), 25);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: initializing non-owner argument of type 'int *' with a newly created 'gsl::owner<>'
+  nonOwningCall((int *)::malloc(ByteCount), 25);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: initializing non-owner argument of type 'int *' with a newly created 'gsl::owner<>'
+
+  consumesResource((int *)malloc(ByteCount), 25);   // Ok
+  consumesResource((int *)::malloc(ByteCount), 25); // Ok
+
+  testNonCasted(malloc(ByteCount));
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'void *' with a newly created 'gsl::owner<>'
+  testNonCastedOwner(gsl::owner<void *>(malloc(ByteCount))); // Ok
+  testNonCastedOwner(malloc(ByteCount));                     // Ok
+
+  FILE *File1 = std::fopen("test_name.txt", "w+");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+  FILE *File2 = ::fopen("test_name.txt", "w+");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+
+  gsl::owner<FILE *> File3 = ::fopen("test_name.txt", "w+"); // Ok
+
+  FILE *File4;
+  File4 = ::fopen("test_name.txt", "w+");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: assigning newly created 'gsl::owner<>' to non-owner 'FILE *' (aka 'int *')
+
+  gsl::owner<FILE *> File5;
+  File5 = ::fopen("test_name.txt", "w+"); // Ok
+  File5 = File1;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'FILE *' (aka 'int *')
+
+  gsl::owner<FILE *> File6 = File1;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'FILE *' (aka 'int *')
+
+  FILE *File7 = tmpfile();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+  gsl::owner<FILE *> File8 = tmpfile(); // Ok
+
+  nonOwningCall(::fopen("test_name.txt", "r"));
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+  nonOwningCall(std::fopen("test_name.txt", "r"));
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+
+  consumesResource(::fopen("test_name.txt", "r")); // Ok
+
+  int *HeapPointer3 = (int *)aligned_alloc(16ul, 4ul * 32ul);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  gsl::owner<int *> HeapPointer4 = static_cast<int *>(aligned_alloc(16ul, 4ul * 32ul)); // Ok
+
+  void *HeapPointer5 = calloc(10ul, 4ul);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'void *' with a newly created 'gsl::owner<>'
+  gsl::owner<void *> HeapPointer6 = calloc(10ul, 4ul); // Ok
+}
+
+void test_legacy_consumers() {
+  int StackInteger = 42;
+
+  int *StackPointer = &StackInteger;
+  int *HeapPointer1 = (int *)malloc(100);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  gsl::owner<int *> HeapPointer2 = (int *)malloc(100);
+
+  std::free(StackPointer);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+  std::free(HeapPointer1);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+  std::free(HeapPointer2); // Ok
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+
+  // FIXME: the check complains about initialization of 'void *' with new created owner.
+  // This happens, because the argument of `free` is not marked as 'owner<>' (and cannot be),
+  // and the check will not figure out could be meant as owner.
+  // This property will probably never be fixed, because it is probably a rather rare
+  // use-case and 'owner<>' should be wrapped in RAII classes anyway!
+  std::free(std::malloc(100)); // Ok but silly :)
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: initializing non-owner argument of type 'void *' with a newly created 'gsl::owner<>'
+
+  // Demonstrate, that multi-argument functions are diagnosed as well.
+  std::realloc(StackPointer, 200);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+  std::realloc(HeapPointer1, 200);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+  std::realloc(HeapPointer2, 200);     // Ok
+  std::realloc(std::malloc(100), 200); // Ok but silly
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: initializing non-owner argument of type 'void *' with a newly created 'gsl::owner<>'
+
+  fclose(fileFactory1());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+  fclose(fileFactory2()); // Ok, same as FIXME with `free(malloc(100))` applies here
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: initializing non-owner argument of type 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+
+  gsl::owner<FILE *> File1 = fopen("testfile.txt", "r"); // Ok
+  FILE *File2 = freopen("testfile.txt", "w", File1);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+  // CHECK-MESSAGES: [[@LINE-2]]:17: warning: calling legacy resource function without passing a 'gsl::owner<>'
+  // FIXME: The warning for not passing and owner<> is a false positive since both the filename and the
+  // mode are not supposed to be owners but still pointers. The check is to coarse for
+  // this function. Maybe `freopen` gets special treatment.
+
+  gsl::owner<FILE *> File3 = freopen("testfile.txt", "w", File2); // Bad, File2 no owner
+  // CHECK-MESSAGES: [[@LINE-1]]:30: warning: calling legacy resource function without passing a 'gsl::owner<>'
+
+  FILE *TmpFile = tmpfile();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+  FILE *File6 = freopen("testfile.txt", "w", TmpFile); // Bad, both return and argument
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+  // CHECK-MESSAGES: [[@LINE-2]]:17: warning: calling legacy resource function without passing a 'gsl::owner<>'
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory.cpp
new file mode 100644
index 0000000..47b12fb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-owning-memory.cpp
@@ -0,0 +1,391 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-owning-memory %t
+
+namespace gsl {
+template <class T>
+using owner = T;
+} // namespace gsl
+
+template <typename T>
+class unique_ptr {
+public:
+  unique_ptr(gsl::owner<T> resource) : memory(resource) {}
+  unique_ptr(const unique_ptr<T> &) = default;
+
+  ~unique_ptr() { delete memory; }
+
+private:
+  gsl::owner<T> memory;
+};
+
+void takes_owner(gsl::owner<int *> owned_int) {
+}
+
+void takes_pointer(int *unowned_int) {
+}
+
+void takes_owner_and_more(int some_int, gsl::owner<int *> owned_int, float f) {
+}
+
+template <typename T>
+void takes_templated_owner(gsl::owner<T> owned_T) {
+}
+
+gsl::owner<int *> returns_owner1() { return gsl::owner<int *>(new int(42)); } // Ok
+gsl::owner<int *> returns_owner2() { return new int(42); }                    // Ok
+
+int *returns_no_owner1() { return nullptr; }
+int *returns_no_owner2() {
+  return new int(42);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: returning a newly created resource of type 'int *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'
+}
+int *returns_no_owner3() {
+  int *should_be_owner = new int(42);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  return should_be_owner;
+}
+int *returns_no_owner4() {
+  gsl::owner<int *> owner = new int(42);
+  return owner;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: returning a newly created resource of type 'int *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'
+}
+
+unique_ptr<int *> returns_no_owner5() {
+  return unique_ptr<int *>(new int(42)); // Ok
+}
+
+/// FIXME: CSA finds it, but the report is misleading. Ownersemantics can catch this
+/// by flow analysis similar to bugprone-use-after-move.
+void csa_not_finding_leak() {
+  gsl::owner<int *> o1 = new int(42); // Ok
+
+  gsl::owner<int *> o2 = o1; // Ok
+  o2 = new int(45);          // conceptual leak, the memory from o1 is now leaked, since its considered moved in the guidelines
+
+  delete o2;
+  // actual leak occurs here, its found, but mixed
+  delete o1;
+}
+
+void test_assignment_and_initialization() {
+  int stack_int1 = 15;
+  int stack_int2;
+
+  gsl::owner<int *> owned_int1 = &stack_int1; // BAD
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+
+  gsl::owner<int *> owned_int2;
+  owned_int2 = &stack_int2; // BAD since no owner, bad since uninitialized
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'int *'
+
+  gsl::owner<int *> owned_int3 = new int(42); // Good
+  owned_int3 = nullptr;                       // Good
+
+  gsl::owner<int *> owned_int4(nullptr); // Ok
+  owned_int4 = new int(42);              // Good
+
+  gsl::owner<int *> owned_int5 = owned_int3; // Good
+
+  gsl::owner<int *> owned_int6{nullptr}; // Ok
+  owned_int6 = owned_int4;               // Good
+
+  // FIXME:, flow analysis for the case of reassignment. Value must be released before
+  owned_int6 = owned_int3; // BAD, because reassignment without resource release
+
+  auto owned_int7 = returns_owner1(); // Bad, since type deduction eliminates the owner wrapper
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  // CHECK-MESSAGES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+
+  const auto owned_int8 = returns_owner2(); // Bad, since type deduction eliminates the owner wrapper
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *const' with a newly created 'gsl::owner<>'
+  // CHECK-MESSAGES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+
+  gsl::owner<int *> owned_int9 = returns_owner1(); // Ok
+  int *unowned_int3 = returns_owner1();            // Bad
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+
+  gsl::owner<int *> owned_int10;
+  owned_int10 = returns_owner1(); // Ok
+
+  int *unowned_int4;
+  unowned_int4 = returns_owner1(); // Bad
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: assigning newly created 'gsl::owner<>' to non-owner 'int *'
+
+  gsl::owner<int *> owned_int11 = returns_no_owner1(); // Bad since no owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+
+  gsl::owner<int *> owned_int12;
+  owned_int12 = returns_no_owner1(); // Bad since no owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'int *'
+
+  int *unowned_int5 = returns_no_owner1(); // Ok
+  int *unowned_int6;
+  unowned_int6 = returns_no_owner1(); // Ok
+
+  int *unowned_int7 = new int(42); // Bad, since resource not assigned to an owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+
+  int *unowned_int8;
+  unowned_int8 = new int(42);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: assigning newly created 'gsl::owner<>' to non-owner 'int *'
+
+  gsl::owner<int *> owned_int13 = nullptr; // Ok
+}
+
+void test_deletion() {
+  gsl::owner<int *> owned_int1 = new int(42);
+  delete owned_int1; // Good
+
+  gsl::owner<int *> owned_int2 = new int[42];
+  delete[] owned_int2; // Good
+
+  int *unowned_int1 = new int(42); // BAD, since new creates and owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  delete unowned_int1; // BAD, since no owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead
+  // CHECK-MESSAGES: [[@LINE-4]]:3: note: variable declared here
+
+  int *unowned_int2 = new int[42]; // BAD, since new creates and owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  delete[] unowned_int2; // BAD since no owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead
+  // CHECK-MESSAGES: [[@LINE-4]]:3: note: variable declared here
+
+  delete new int(42);   // Technically ok, but stupid
+  delete[] new int[42]; // Technically ok, but stupid
+}
+
+void test_owner_function_calls() {
+  int stack_int = 42;
+  int *unowned_int1 = &stack_int;
+  takes_owner(&stack_int); // BAD
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+  takes_owner(unowned_int1); // BAD
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+
+  gsl::owner<int *> owned_int1 = new int(42);
+  takes_owner(owned_int1); // Ok
+
+  takes_owner_and_more(42, &stack_int, 42.0f); // BAD
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+  takes_owner_and_more(42, unowned_int1, 42.0f); // BAD
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+
+  takes_owner_and_more(42, new int(42), 42.0f); // Ok, since new is consumed by owner
+  takes_owner_and_more(42, owned_int1, 42.0f);  // Ok, since owner as argument
+
+  takes_templated_owner(owned_int1);   // Ok
+  takes_templated_owner(new int(42));  // Ok
+  takes_templated_owner(unowned_int1); // Bad
+  // CHECK-MESSAGES: [[@LINE-1]]:25: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+
+  takes_owner(returns_owner1());    // Ok
+  takes_owner(returns_no_owner1()); // BAD
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+}
+
+void test_unowned_function_calls() {
+  int stack_int = 42;
+  int *unowned_int1 = &stack_int;
+  gsl::owner<int *> owned_int1 = new int(42);
+
+  takes_pointer(&stack_int);   // Ok
+  takes_pointer(unowned_int1); // Ok
+  takes_pointer(owned_int1);   // Ok
+  takes_pointer(new int(42));  // Bad, since new creates and owner
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'int *' with a newly created 'gsl::owner<>'
+
+  takes_pointer(returns_owner1()); // Bad
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'int *' with a newly created 'gsl::owner<>'
+
+  takes_pointer(returns_no_owner1()); // Ok
+}
+
+// FIXME: Typedefing owner<> to something else does not work.
+// This might be necessary for code already having a similar typedef like owner<> and
+// replacing it with owner<>. This might be the same problem as with templates.
+// The canonical type will ignore the owner<> alias, since its a typedef as well.
+//
+// Check, if owners hidden by typedef are handled the same as 'obvious' owners.
+#if 0
+using heap_int = gsl::owner<int *>;
+typedef gsl::owner<float *> heap_float;
+
+// This tests only a subset, assuming that the check will either see through the
+// typedef or not (it doesn't!).
+void test_typedefed_values() {
+  // Modern typedef.
+  int StackInt1 = 42;
+  heap_int HeapInt1 = &StackInt1;
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'int *'
+
+  //FIXME: Typedef not considered correctly here.
+  // heap_int HeapInt2 = new int(42); // Ok
+  takes_pointer(HeapInt1); // Ok
+  takes_owner(HeapInt1);   // Ok
+
+  // Traditional typedef.
+  float StackFloat1 = 42.0f;
+  heap_float HeapFloat1 = &StackFloat1;
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'float *'
+
+  //FIXME: Typedef not considered correctly here.
+  // heap_float HeapFloat2 = new float(42.0f);
+  HeapFloat2 = HeapFloat1; // Ok
+}
+#endif
+
+struct ArbitraryClass {};
+struct ClassWithOwner {                    // Does not define destructor, necessary with owner
+  ClassWithOwner() : owner_var(nullptr) {} // Ok
+
+  ClassWithOwner(ArbitraryClass &other) : owner_var(&other) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:43: warning: expected initialization of owner member variable with value of type 'gsl::owner<>'; got 'ArbitraryClass *'
+
+  ClassWithOwner(gsl::owner<ArbitraryClass *> other) : owner_var(other) {} // Ok
+
+  ClassWithOwner(gsl::owner<ArbitraryClass *> data, int /* unused */) { // Ok
+    owner_var = data;                                                   // Ok
+  }
+
+  ClassWithOwner(ArbitraryClass *bad_data, int /* unused */, int /* unused */) {
+    owner_var = bad_data;
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: expected assignment source to be of type 'gsl::owner<>'; got 'ArbitraryClass *'
+  }
+
+  ClassWithOwner(ClassWithOwner &&other) : owner_var{other.owner_var} {} // Ok
+
+  ClassWithOwner &operator=(ClassWithOwner &&other) {
+    owner_var = other.owner_var; // Ok
+    return *this;
+  }
+
+  // Returning means, that the owner is "moved", so the class should not access this
+  // variable anymore after this method gets called.
+  gsl::owner<ArbitraryClass *> buggy_but_returns_owner() { return owner_var; }
+
+  gsl::owner<ArbitraryClass *> owner_var;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: member variable of type 'gsl::owner<>' requires the class 'ClassWithOwner' to implement a destructor to release the owned resource
+};
+
+class DefaultedDestructor {         // Bad since default constructor with owner
+  ~DefaultedDestructor() = default; // Bad, since will not destroy the owner
+  gsl::owner<int *> Owner;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: member variable of type 'gsl::owner<>' requires the class 'DefaultedDestructor' to implement a destructor to release the owned resource
+};
+
+struct DeletedDestructor {
+  ~DeletedDestructor() = delete;
+  gsl::owner<int *> Owner;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: member variable of type 'gsl::owner<>' requires the class 'DeletedDestructor' to implement a destructor to release the owned resource
+};
+
+void test_class_with_owner() {
+  ArbitraryClass A;
+  ClassWithOwner C1;                                                   // Ok
+  ClassWithOwner C2{A};                                                // Bad, since the owner would be initialized with an non-owner, but catched in the class
+  ClassWithOwner C3{gsl::owner<ArbitraryClass *>(new ArbitraryClass)}; // Ok
+
+  const auto Owner1 = C3.buggy_but_returns_owner(); // BAD, deduces Owner1 to ArbitraryClass *const
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'ArbitraryClass *const' with a newly created 'gsl::owner<>'
+  // CHECK-MESSAGES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+
+  auto Owner2 = C2.buggy_but_returns_owner(); // BAD, deduces Owner2 to ArbitraryClass *
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'ArbitraryClass *' with a newly created 'gsl::owner<>'
+  // CHECK-MESSAGES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+
+  Owner2 = &A; // Ok, since type deduction did NOT result in owner<int*>
+
+  gsl::owner<ArbitraryClass *> Owner3 = C1.buggy_but_returns_owner(); // Ok, still an owner
+  Owner3 = &A;                                                        // Bad, since assignment of non-owner to owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'ArbitraryClass *'
+}
+
+template <typename T>
+struct HeapArray {                                          // Ok, since destructor with owner
+  HeapArray() : _data(nullptr), size(0) {}                  // Ok
+  HeapArray(int size) : _data(new int[size]), size(size) {} // Ok
+  HeapArray(int size, T val) {
+    _data = new int[size]; // Ok
+    size = size;
+    for (auto i = 0u; i < size; ++i)
+      _data[i] = val; // Ok
+  }
+  HeapArray(int size, T val, int *problematic) : _data{problematic}, size(size) {} // Bad
+  // CHECK-MESSAGES: [[@LINE-1]]:50: warning: expected initialization of owner member variable with value of type 'gsl::owner<>'; got 'void'
+  // FIXME: void is incorrect type, probably wrong thing matched
+
+  HeapArray(HeapArray &&other) : _data(other._data), size(other.size) { // Ok
+    other._data = nullptr;                                              // Ok
+    other.size = 0;
+  }
+
+  HeapArray<T> &operator=(HeapArray<T> &&other) {
+    _data = other._data; // Ok, NOLINT warning here about bad types, why?
+    size = other.size;
+    return *this;
+  }
+
+  ~HeapArray() { delete[] _data; } // Ok
+
+  T *data() { return _data; } // Ok NOLINT, because it "looks" like a factory
+
+  gsl::owner<T *> _data;
+  unsigned int size;
+};
+
+void test_inner_template() {
+  HeapArray<int> Array1;
+  HeapArray<int> Array2(100);
+  HeapArray<int> Array3(100, 0);
+  HeapArray<int> Array4(100, 0, nullptr);
+
+  Array1 = static_cast<HeapArray<int> &&>(Array2);
+  HeapArray<int> Array5(static_cast<HeapArray<int> &&>(Array3));
+
+  int *NonOwningPtr = Array1.data();           // Ok
+  gsl::owner<int *> OwningPtr = Array1.data(); // Bad, since it does not return the owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+}
+
+// FIXME: Typededuction removes the owner - wrapper, therefore gsl::owner can not be used
+// with Template classes like this. Is there a walkaround?
+template <typename T>
+struct TemplateValue {
+  TemplateValue() = default;
+  TemplateValue(T t) : val{t} {}
+
+  void setVal(const T &t) { val = t; }
+  const T getVal() const { return val; }
+
+  T val;
+};
+
+// FIXME: Same typededcution problems
+template <typename T>
+void template_function(T t) {
+  gsl::owner<int *> owner_t = t; // Probably bad, since type deduction still wrong
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'T'
+  // CHECK-MESSAGES: [[@LINE-2]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+}
+
+// FIXME: Same typededcution problems
+void test_templates() {
+  int stack_int = 42;
+  int *stack_ptr1 = &stack_int;
+
+  TemplateValue<gsl::owner<int *>> Owner0; // Ok, T should be owner, but is int*
+
+  TemplateValue<gsl::owner<int *>> Owner1(new int(42)); // Ok, T should be owner, but is int*
+  Owner1.setVal(&stack_int);                            // Bad since non-owner assignment
+  Owner1.setVal(stack_ptr1);                            // Bad since non-owner assignment
+  //Owner1.setVal(new int(42)); // Ok, but since type deduction is wrong, this one is considered harmful
+
+  int *stack_ptr2 = Owner1.getVal(); // Bad, initializing non-owner with owner
+
+  TemplateValue<int *> NonOwner1(new int(42));      // Bad, T is int *, hence dynamic memory to non-owner
+  gsl::owner<int *> IntOwner1 = NonOwner1.getVal(); // Bad, since owner initialized with non-owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+
+  template_function(IntOwner1);  // Ok, but not actually ok, since type deduction removes owner
+  template_function(stack_ptr1); // Bad, but type deduction gets it wrong
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-array-to-pointer-decay.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-array-to-pointer-decay.cpp
new file mode 100644
index 0000000..ce19280
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-array-to-pointer-decay.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-array-to-pointer-decay %t
+#include <stddef.h>
+
+namespace gsl {
+template <class T>
+class array_view {
+public:
+  template <class U, size_t N>
+  array_view(U (&arr)[N]);
+};
+}
+
+void pointerfun(int *p);
+void arrayfun(int p[]);
+void arrayviewfun(gsl::array_view<int> &p);
+size_t s();
+
+void f() {
+  int a[5];
+  pointerfun(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay]
+  pointerfun((int *)a); // OK, explicit cast
+  arrayfun(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not implicitly decay an array into a pointer
+
+  pointerfun(a + s() - 10); // Convert to &a[g() - 10];
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not implicitly decay an array into a pointer
+
+  gsl::array_view<int> av(a);
+  arrayviewfun(av); // OK
+
+  int i = a[0];      // OK
+  pointerfun(&a[0]); // OK
+
+  for (auto &e : a) // OK, iteration internally decays array to pointer
+    e = 1;
+}
+
+const char *g() {
+  return "clang"; // OK, decay string literal to pointer
+}
+
+void f2(void *const *);
+void bug25362() {
+  void *a[2];
+  f2(static_cast<void *const*>(a)); // OK, explicit cast
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index-c++03.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index-c++03.cpp
new file mode 100644
index 0000000..ad9fcd9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index-c++03.cpp
@@ -0,0 +1,11 @@
+// RUN: clang-tidy %s -checks=-*,cppcoreguidelines-pro-bounds-constant-array-index -- -std=c++03 | count 0
+
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+template <int index> struct B {
+  int get() {
+    // The next line used to crash the check (in C++03 mode only).
+    return x[index];
+  }
+  int x[3];
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index-gslheader.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index-gslheader.cpp
new file mode 100644
index 0000000..a88a2d9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index-gslheader.cpp
@@ -0,0 +1,79 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-constant-array-index %t -- -config='{CheckOptions: [{key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader, value: "dir1/gslheader.h"}]}' -- -std=c++11
+// CHECK-FIXES: #include "dir1/gslheader.h"
+
+typedef __SIZE_TYPE__ size_t;
+
+namespace std {
+  template<typename T, size_t N>
+  struct array {
+    T& operator[](size_t n);
+    T& at(size_t n);
+  };
+}
+
+
+namespace gsl {
+  template<class T, size_t N>
+  T& at( T(&a)[N], size_t index );
+
+  template<class T, size_t N>
+  T& at( std::array<T, N> &a, size_t index );
+}
+
+constexpr int const_index(int base) {
+  return base + 3;
+}
+
+void f(std::array<int, 10> a, int pos) {
+  a [ pos / 2 /*comment*/] = 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use array subscript when the index is not an integer constant expression; use gsl::at() instead [cppcoreguidelines-pro-bounds-constant-array-index]
+  // CHECK-FIXES: gsl::at(a,  pos / 2 /*comment*/) = 1;
+  int j = a[pos - 1];
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use array subscript when the index is not an integer constant expression; use gsl::at() instead
+  // CHECK-FIXES: int j = gsl::at(a, pos - 1);
+
+  a.at(pos-1) = 2; // OK, at() instead of []
+  gsl::at(a, pos-1) = 2; // OK, gsl::at() instead of []
+
+  a[-1] = 3;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index -1 is negative [cppcoreguidelines-pro-bounds-constant-array-index]
+  a[10] = 4;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements) [cppcoreguidelines-pro-bounds-constant-array-index]
+
+  a[const_index(7)] = 3;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements)
+
+  a[0] = 3; // OK, constant index and inside bounds
+  a[1] = 3; // OK, constant index and inside bounds
+  a[9] = 3; // OK, constant index and inside bounds
+  a[const_index(6)] = 3; // OK, constant index and inside bounds
+}
+
+void g() {
+  int a[10];
+  for (int i = 0; i < 10; ++i) {
+    a[i] = i;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use array subscript when the index is not an integer constant expression; use gsl::at() instead
+    // CHECK-FIXES: gsl::at(a, i) = i;
+    gsl::at(a, i) = i; // OK, gsl::at() instead of []
+  }
+
+  a[-1] = 3; // flagged by clang-diagnostic-array-bounds
+  a[10] = 4; // flagged by clang-diagnostic-array-bounds
+  a[const_index(7)] = 3; // flagged by clang-diagnostic-array-bounds
+
+  a[0] = 3; // OK, constant index and inside bounds
+  a[1] = 3; // OK, constant index and inside bounds
+  a[9] = 3; // OK, constant index and inside bounds
+  a[const_index(6)] = 3; // OK, constant index and inside bounds
+}
+
+struct S {
+  int& operator[](int i);
+};
+
+void customOperator() {
+  S s;
+  int i = 0;
+  s[i] = 3; // OK, custom operator
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index.cpp
new file mode 100644
index 0000000..3519410
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index.cpp
@@ -0,0 +1,87 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-constant-array-index %t
+
+typedef __SIZE_TYPE__ size_t;
+
+namespace std {
+  template<typename T, size_t N>
+  struct array {
+    T& operator[](size_t n);
+    T& at(size_t n);
+  };
+}
+
+
+namespace gsl {
+  template<class T, size_t N>
+  T& at( T(&a)[N], size_t index );
+
+  template<class T, size_t N>
+  T& at( std::array<T, N> &a, size_t index );
+}
+
+constexpr int const_index(int base) {
+  return base + 3;
+}
+
+void f(std::array<int, 10> a, int pos) {
+  a [ pos / 2 /*comment*/] = 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use array subscript when the index is not an integer constant expression; use gsl::at() instead [cppcoreguidelines-pro-bounds-constant-array-index]
+  int j = a[pos - 1];
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use array subscript when the index is not an integer constant expression; use gsl::at() instead
+
+  a.at(pos-1) = 2; // OK, at() instead of []
+  gsl::at(a, pos-1) = 2; // OK, gsl::at() instead of []
+
+  a[-1] = 3;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index -1 is negative [cppcoreguidelines-pro-bounds-constant-array-index]
+  a[10] = 4;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements) [cppcoreguidelines-pro-bounds-constant-array-index]
+
+  a[const_index(7)] = 3;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements)
+
+  a[0] = 3; // OK, constant index and inside bounds
+  a[1] = 3; // OK, constant index and inside bounds
+  a[9] = 3; // OK, constant index and inside bounds
+  a[const_index(6)] = 3; // OK, constant index and inside bounds
+}
+
+void g() {
+  int a[10];
+  for (int i = 0; i < 10; ++i) {
+    a[i] = i;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use array subscript when the index is not an integer constant expression; use gsl::at() instead
+    // CHECK-FIXES: gsl::at(a, i) = i;
+    gsl::at(a, i) = i; // OK, gsl::at() instead of []
+  }
+
+  a[-1] = 3; // flagged by clang-diagnostic-array-bounds
+  a[10] = 4; // flagged by clang-diagnostic-array-bounds
+  a[const_index(7)] = 3; // flagged by clang-diagnostic-array-bounds
+
+  a[0] = 3; // OK, constant index and inside bounds
+  a[1] = 3; // OK, constant index and inside bounds
+  a[9] = 3; // OK, constant index and inside bounds
+  a[const_index(6)] = 3; // OK, constant index and inside bounds
+}
+
+struct S {
+  int& operator[](int i);
+};
+
+void customOperator() {
+  S s;
+  int i = 0;
+  s[i] = 3; // OK, custom operator
+}
+
+struct A {
+  // The compiler-generated copy constructor uses an ArraySubscriptExpr. Don't warn.
+  int x[3];
+};
+
+void use_A() {
+  // Force the compiler to generate a copy constructor.
+  A a;
+  A a2(a);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic-pr36489.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic-pr36489.cpp
new file mode 100644
index 0000000..4710952
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic-pr36489.cpp
@@ -0,0 +1,53 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-pointer-arithmetic %t -- -- -std=c++14
+
+// Fix PR36489 and detect auto-deduced value correctly.
+char *getPtr();
+auto getPtrAuto() { return getPtr(); }
+decltype(getPtr()) getPtrDeclType();
+decltype(auto) getPtrDeclTypeAuto() { return getPtr(); }
+auto getPtrWithTrailingReturnType() -> char *;
+
+void auto_deduction_binary() {
+  auto p1 = getPtr() + 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: do not use pointer arithmetic
+  auto p2 = getPtrAuto() + 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: do not use pointer arithmetic
+  auto p3 = getPtrWithTrailingReturnType() + 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: do not use pointer arithmetic
+  auto p4 = getPtr();
+  auto *p5 = getPtr();
+  p4 = p4 + 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use pointer arithmetic
+  p5 = p5 + 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use pointer arithmetic
+  auto p6 = getPtrDeclType() + 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: do not use pointer arithmetic
+  auto p7 = getPtrDeclTypeAuto() + 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: do not use pointer arithmetic
+  auto *p8 = getPtrDeclType() + 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: do not use pointer arithmetic
+  auto *p9 = getPtrDeclTypeAuto() + 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: do not use pointer arithmetic
+}
+
+void auto_deduction_subscript() {
+  char p1 = getPtr()[2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+  auto p2 = getPtr()[3];
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+
+  char p3 = getPtrAuto()[4];
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+  auto p4 = getPtrAuto()[5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+
+  char p5 = getPtrWithTrailingReturnType()[6];
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+  auto p6 = getPtrWithTrailingReturnType()[7];
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+
+  auto p7 = getPtrDeclType()[8];
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+  auto p8 = getPtrDeclTypeAuto()[9];
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use pointer arithmetic
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic.cpp
new file mode 100644
index 0000000..7cbc6dd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic.cpp
@@ -0,0 +1,89 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-pointer-arithmetic %t
+
+enum E {
+  ENUM_LITERAL = 1
+};
+
+int i = 4;
+int j = 1;
+int *p = 0;
+int *q = 0;
+
+void fail() {
+  q = p + 4;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic [cppcoreguidelines-pro-bounds-pointer-arithmetic]
+  p = q + i;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic
+  p = q + ENUM_LITERAL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic
+
+  q = p - 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic
+  p = q - i;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic
+  p = q - ENUM_LITERAL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic
+
+  p += 4;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic
+  p += i;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic
+  p += ENUM_LITERAL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic
+
+  q -= 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic
+  q -= i;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic
+  q -= ENUM_LITERAL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic
+
+  p++;
+  // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: do not use pointer arithmetic
+  ++p;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use pointer arithmetic
+
+  p--;
+  // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: do not use pointer arithmetic
+  --p;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use pointer arithmetic
+
+  i = p[1];
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use pointer arithmetic
+}
+
+struct S {
+  operator int() const;
+};
+
+void f(S &s) {
+  int *i;
+  i = i + s;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic
+}
+
+void f2(int i[]) {
+  i[1] = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use pointer arithmetic
+}
+
+void okay() {
+  int a[3];
+  i = a[2]; // OK, access to array
+
+  p = q;
+  p = &i;
+
+  i++;
+  ++i;
+  i--;
+  --i;
+  i += 1;
+  i -= 1;
+  i = j + 1;
+  i = j - 1;
+
+  auto diff = p - q; // OK, result is arithmetic
+
+  for(int ii : a) ; // OK, pointer arithmetic generated by compiler
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-const-cast.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-const-cast.cpp
new file mode 100644
index 0000000..2d32e13
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-const-cast.cpp
@@ -0,0 +1,6 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-const-cast %t
+
+const int *i;
+int *j;
+void f() { j = const_cast<int *>(i); }
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use const_cast [cppcoreguidelines-pro-type-const-cast]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-cstyle-cast.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-cstyle-cast.cpp
new file mode 100644
index 0000000..31f59e3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-cstyle-cast.cpp
@@ -0,0 +1,141 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-cstyle-cast %t
+
+void reinterpretcast() {
+  int i = 0;
+  void *j;
+  j = (int*)j;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use C-style cast to convert between unrelated types [cppcoreguidelines-pro-type-cstyle-cast]
+}
+
+void constcast() {
+  int* i;
+  const int* j;
+  i = (int*)j;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use C-style cast to cast away constness
+  j = (const int*)i; // OK, const added
+  (void)j; // OK, not a const_cast
+}
+
+void const_and_reinterpret() {
+  int* i;
+  const void* j;
+  i = (int*)j;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use C-style cast to convert between unrelated types
+}
+
+class Base {
+};
+
+class Derived : public Base {
+};
+
+class Base2 {
+};
+
+class MultiDerived : public Base, public Base2 {
+};
+
+class PolymorphicBase {
+public:
+  virtual ~PolymorphicBase();
+};
+
+class PolymorphicDerived : public PolymorphicBase {
+};
+
+class PolymorphicMultiDerived : public Base, public PolymorphicBase {
+};
+
+void pointers() {
+
+  auto P0 = (Derived*)new Base();
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use C-style cast to downcast from a base to a derived class
+
+  const Base* B0;
+  auto PC0 = (const Derived*)(B0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use C-style cast to downcast from a base to a derived class
+
+  auto P1 = (Base*)new Derived(); // OK, upcast to a public base
+  auto P2 = (Base*)new MultiDerived(); // OK, upcast to a public base
+  auto P3 = (Base2*)new MultiDerived(); // OK, upcast to a public base
+}
+
+void pointers_polymorphic() {
+
+  auto PP0 = (PolymorphicDerived*)new PolymorphicBase();
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use C-style cast to downcast from a base to a derived class; use dynamic_cast instead
+  // CHECK-FIXES: auto PP0 = dynamic_cast<PolymorphicDerived*>(new PolymorphicBase());
+
+  const PolymorphicBase* B0;
+  auto PPC0 = (const PolymorphicDerived*)B0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: do not use C-style cast to downcast from a base to a derived class; use dynamic_cast instead
+  // CHECK-FIXES: auto PPC0 = dynamic_cast<const PolymorphicDerived*>(B0);
+
+
+  auto B1 = (PolymorphicBase*)new PolymorphicDerived(); // OK, upcast to a public base
+  auto B2 = (PolymorphicBase*)new PolymorphicMultiDerived(); // OK, upcast to a public base
+  auto B3 = (Base*)new PolymorphicMultiDerived(); // OK, upcast to a public base
+}
+
+void arrays() {
+  Base ArrayOfBase[10];
+  auto A0 = (Derived*)ArrayOfBase;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use C-style cast to downcast from a base to a derived class
+}
+
+void arrays_polymorphic() {
+  PolymorphicBase ArrayOfPolymorphicBase[10];
+  auto AP0 = (PolymorphicDerived*)ArrayOfPolymorphicBase;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use C-style cast to downcast from a base to a derived class; use dynamic_cast instead
+  // CHECK-FIXES: auto AP0 = dynamic_cast<PolymorphicDerived*>(ArrayOfPolymorphicBase);
+}
+
+void references() {
+  Base B0;
+  auto R0 = (Derived&)B0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use C-style cast to downcast from a base to a derived class
+  Base& RefToBase = B0;
+  auto R1 = (Derived&)RefToBase;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use C-style cast to downcast from a base to a derived class
+
+  const Base& ConstRefToBase = B0;
+  auto RC1 = (const Derived&)ConstRefToBase;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use C-style cast to downcast from a base to a derived class
+
+
+  Derived RD1;
+  auto R2 = (Base&)RD1; // OK, upcast to a public base
+}
+
+void references_polymorphic() {
+  PolymorphicBase B0;
+  auto RP0 = (PolymorphicDerived&)B0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use C-style cast to downcast from a base to a derived class; use dynamic_cast instead
+  // CHECK-FIXES: auto RP0 = dynamic_cast<PolymorphicDerived&>(B0);
+
+  PolymorphicBase& RefToPolymorphicBase = B0;
+  auto RP1 = (PolymorphicDerived&)RefToPolymorphicBase;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use C-style cast to downcast from a base to a derived class; use dynamic_cast instead
+  // CHECK-FIXES: auto RP1 = dynamic_cast<PolymorphicDerived&>(RefToPolymorphicBase);
+
+  const PolymorphicBase& ConstRefToPolymorphicBase = B0;
+  auto RPC2 = (const PolymorphicDerived&)(ConstRefToPolymorphicBase);
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: do not use C-style cast to downcast from a base to a derived class; use dynamic_cast instead
+  // CHECK-FIXES: auto RPC2 = dynamic_cast<const PolymorphicDerived&>(ConstRefToPolymorphicBase);
+
+  PolymorphicDerived d1;
+  auto RP2 = (PolymorphicBase&)d1; // OK, upcast to a public base
+}
+
+template<class B, class D>
+void templ() {
+  auto B0 = (B*)new D();
+}
+
+void templ_bad_call() {
+  templ<Derived, Base>(); //FIXME: this should trigger a warning
+}
+
+void templ_good_call() {
+  templ<Base, Derived>(); // OK, upcast to a public base
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx2a.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx2a.cpp
new file mode 100644
index 0000000..d3e3ade
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx2a.cpp
@@ -0,0 +1,19 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -- -std=c++2a -fno-delayed-template-parsing
+
+struct PositiveBitfieldMember {
+  PositiveBitfieldMember() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
+  unsigned F : 5;
+  // CHECK-FIXES: unsigned F : 5{};
+};
+
+struct NegativeUnnamedBitfieldMember {
+  NegativeUnnamedBitfieldMember() {}
+  unsigned : 5;
+};
+
+struct NegativeInitializedBitfieldMembers {
+  NegativeInitializedBitfieldMembers() : F(3) { G = 2; }
+  unsigned F : 5;
+  unsigned G : 5;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
new file mode 100644
index 0000000..db97bb4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
@@ -0,0 +1,116 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -- -std=c++98 -fno-delayed-template-parsing
+
+struct PositiveFieldBeforeConstructor {
+  int F;
+  PositiveFieldBeforeConstructor() /* some comment */ {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
+  // CHECK-FIXES: PositiveFieldBeforeConstructor() : F() /* some comment */ {}
+};
+
+struct PositiveFieldAfterConstructor {
+  PositiveFieldAfterConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F, G, H
+  // CHECK-FIXES: PositiveFieldAfterConstructor() : F(), G(), H() {}
+  int F;
+  bool G /* with comment */;
+  int *H;
+  PositiveFieldBeforeConstructor IgnoredField;
+};
+
+struct PositiveSeparateDefinition {
+  PositiveSeparateDefinition();
+  int F;
+};
+
+PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: F
+// CHECK-FIXES: PositiveSeparateDefinition::PositiveSeparateDefinition() : F() {}
+
+struct PositiveMixedFieldOrder {
+  PositiveMixedFieldOrder() : /* some comment */ J(0), L(0), M(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: I, K, N
+  // CHECK-FIXES: PositiveMixedFieldOrder() : I(), /* some comment */ J(0), K(), L(0), M(0), N() {}
+  int I;
+  int J;
+  int K;
+  int L;
+  int M;
+  int N;
+};
+
+struct PositiveAfterBaseInitializer : public PositiveMixedFieldOrder {
+  PositiveAfterBaseInitializer() : PositiveMixedFieldOrder() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
+  // CHECK-FIXES: PositiveAfterBaseInitializer() : PositiveMixedFieldOrder(), F() {}
+  int F;
+};
+
+struct NegativeFieldInitialized {
+  int F;
+
+  NegativeFieldInitialized() : F() {}
+};
+
+struct NegativeFieldInitializedInDefinition {
+  int F;
+
+  NegativeFieldInitializedInDefinition();
+};
+
+NegativeFieldInitializedInDefinition::NegativeFieldInitializedInDefinition() : F() {}
+
+struct NegativeInitializedInBody {
+  NegativeInitializedInBody() { I = 0; }
+  int I;
+};
+
+struct NegativeAggregateType {
+  int X;
+  int Y;
+  int Z;
+};
+
+struct TrivialType {
+  int X;
+  int Y;
+};
+
+struct PositiveUninitializedBaseOrdering : public NegativeAggregateType,
+                                           public TrivialType {
+  PositiveUninitializedBaseOrdering() : NegativeAggregateType(), TrivialType(), B() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A
+  // CHECK-FIXES: PositiveUninitializedBaseOrdering() : NegativeAggregateType(), TrivialType(), A(), B() {}
+
+  // This is somewhat pathological with the base class initializer at the end...
+  PositiveUninitializedBaseOrdering(int) : B(), TrivialType(), A() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType
+  // CHECK-FIXES: PositiveUninitializedBaseOrdering(int) : B(), NegativeAggregateType(), TrivialType(), A() {}
+
+  PositiveUninitializedBaseOrdering(float) : NegativeAggregateType(), A() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: TrivialType
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: constructor does not initialize these fields: B
+  // CHECK-FIXES: PositiveUninitializedBaseOrdering(float) : NegativeAggregateType(), TrivialType(), A(), B() {}
+
+  int A, B;
+};
+
+template <class T>
+class PositiveTemplateBase : T {
+public:
+  PositiveTemplateBase() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: X
+  // CHECK-FIXES: PositiveTemplateBase() : X() {}
+
+  int X;
+};
+
+class PositiveIndirectMember {
+  struct {
+    int *A;
+  };
+
+  PositiveIndirectMember() : A() {}
+  PositiveIndirectMember(int) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A
+  // CHECK-FIXES: PositiveIndirectMember(int) : A() {}
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-delayed.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-delayed.cpp
new file mode 100644
index 0000000..d3436ba
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-delayed.cpp
@@ -0,0 +1,32 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -- -fdelayed-template-parsing
+
+template <class T>
+struct PositiveFieldBeforeConstructor {
+  int F;
+  bool G /* with comment */;
+  int *H;
+  PositiveFieldBeforeConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F, G, H
+};
+// Explicit instantiation.
+template class PositiveFieldBeforeConstructor<int>;
+
+template <class T>
+struct PositiveFieldAfterConstructor {
+  PositiveFieldAfterConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F, G, H
+  int F;
+  bool G /* with comment */;
+  int *H;
+};
+// Explicit instantiation.
+template class PositiveFieldAfterConstructor<int>;
+
+// This declaration isn't used and won't be parsed 'delayed-template-parsing'.
+// The body of the declaration is 'null' and may cause crash if not handled
+// properly by checkers.
+template <class T>
+struct UnusedDelayedConstructor {
+  UnusedDelayedConstructor() {}
+  int F;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
new file mode 100644
index 0000000..86f094d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
@@ -0,0 +1,502 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -- -std=c++11 -fno-delayed-template-parsing
+
+struct PositiveFieldBeforeConstructor {
+  int F;
+  // CHECK-FIXES: int F{};
+  PositiveFieldBeforeConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
+  // CHECK-FIXES: PositiveFieldBeforeConstructor() {}
+};
+
+struct PositiveFieldAfterConstructor {
+  PositiveFieldAfterConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F, G
+  // CHECK-FIXES: PositiveFieldAfterConstructor() {}
+  int F;
+  // CHECK-FIXES: int F{};
+  bool G /* with comment */;
+  // CHECK-FIXES: bool G{} /* with comment */;
+  PositiveFieldBeforeConstructor IgnoredField;
+};
+
+struct PositiveSeparateDefinition {
+  PositiveSeparateDefinition();
+  int F;
+  // CHECK-FIXES: int F{};
+};
+
+PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: F
+// CHECK-FIXES: PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+
+struct PositiveMixedFieldOrder {
+  PositiveMixedFieldOrder() : J(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: I, K
+  // CHECK-FIXES: PositiveMixedFieldOrder() : J(0) {}
+  int I;
+  // CHECK-FIXES: int I{};
+  int J;
+  int K;
+  // CHECK-FIXES: int K{};
+};
+
+template <typename T>
+struct Template {
+  Template() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
+  int F;
+  // CHECK-FIXES: int F{};
+  T T1;
+  // CHECK-FIXES: T T1;
+};
+
+void instantiate() {
+  Template<int> TInt;
+}
+
+struct NegativeFieldInitialized {
+  int F;
+
+  NegativeFieldInitialized() : F() {}
+};
+
+struct NegativeFieldInitializedInDefinition {
+  int F;
+
+  NegativeFieldInitializedInDefinition();
+};
+NegativeFieldInitializedInDefinition::NegativeFieldInitializedInDefinition() : F() {}
+
+struct NegativeInClassInitialized {
+  int F = 0;
+
+  NegativeInClassInitialized() {}
+};
+
+struct NegativeInClassInitializedDefaulted {
+  int F = 0;
+  NegativeInClassInitializedDefaulted() = default;
+};
+
+struct NegativeConstructorDelegated {
+  int F;
+
+  NegativeConstructorDelegated(int F) : F(F) {}
+  NegativeConstructorDelegated() : NegativeConstructorDelegated(0) {}
+};
+
+struct NegativeInitializedInBody {
+  NegativeInitializedInBody() { I = 0; }
+  int I;
+};
+
+struct A {};
+template <class> class AA;
+template <class T> class NegativeTemplateConstructor {
+  NegativeTemplateConstructor(const AA<T> &, A) {}
+  bool Bool{false};
+  // CHECK-FIXES: bool Bool{false};
+};
+
+#define UNINITIALIZED_FIELD_IN_MACRO_BODY(FIELD) \
+  struct UninitializedField##FIELD {             \
+    UninitializedField##FIELD() {}               \
+    int FIELD;                                   \
+  };                                             \
+// Ensure FIELD is not initialized since fixes inside of macros are disabled.
+// CHECK-FIXES: int FIELD;
+
+UNINITIALIZED_FIELD_IN_MACRO_BODY(F);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: F
+UNINITIALIZED_FIELD_IN_MACRO_BODY(G);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: G
+
+#define UNINITIALIZED_FIELD_IN_MACRO_ARGUMENT(ARGUMENT) \
+  ARGUMENT
+
+UNINITIALIZED_FIELD_IN_MACRO_ARGUMENT(struct UninitializedFieldInMacroArg {
+  UninitializedFieldInMacroArg() {}
+  int Field;
+});
+// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: constructor does not initialize these fields: Field
+// Ensure FIELD is not initialized since fixes inside of macros are disabled.
+// CHECK-FIXES: int Field;
+
+struct NegativeAggregateType {
+  int X;
+  int Y;
+  int Z;
+};
+
+struct PositiveTrivialType {
+  PositiveTrivialType() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
+
+  NegativeAggregateType F;
+  // CHECK-FIXES: NegativeAggregateType F{};
+};
+
+struct NegativeNonTrivialType {
+  PositiveTrivialType F;
+};
+
+static void PositiveUninitializedTrivialType() {
+  NegativeAggregateType X;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: uninitialized record type: 'X'
+  // CHECK-FIXES: NegativeAggregateType X{};
+
+  NegativeAggregateType A[10]; // Don't warn because this isn't an object type.
+}
+
+static void NegativeInitializedTrivialType() {
+  NegativeAggregateType X{};
+  NegativeAggregateType Y = {};
+  NegativeAggregateType Z = NegativeAggregateType();
+  NegativeAggregateType A[10]{};
+  NegativeAggregateType B[10] = {};
+  int C; // No need to initialize this because we don't have a constructor.
+  int D[8];
+  NegativeAggregateType E = {0, 1, 2};
+  NegativeAggregateType F({});
+}
+
+struct NonTrivialType {
+  NonTrivialType() = default;
+  NonTrivialType(const NonTrivialType &RHS) : X(RHS.X), Y(RHS.Y) {}
+
+  int X;
+  int Y;
+};
+
+static void PositiveNonTrivialTypeWithCopyConstructor() {
+  NonTrivialType T;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: uninitialized record type: 'T'
+  // CHECK-FIXES: NonTrivialType T{};
+
+  NonTrivialType A[8];
+  // Don't warn because this isn't an object type
+}
+
+struct ComplexNonTrivialType {
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: Y
+  NegativeFieldInitialized X;
+  int Y;
+  // CHECK-FIXES: int Y{};
+};
+
+static void PositiveComplexNonTrivialType() {
+  ComplexNonTrivialType T;
+}
+
+struct NegativeStaticMember {
+  static NonTrivialType X;
+  static NonTrivialType Y;
+  static constexpr NonTrivialType Z{};
+};
+
+NonTrivialType NegativeStaticMember::X;
+NonTrivialType NegativeStaticMember::Y{};
+
+struct PositiveMultipleConstructors {
+  PositiveMultipleConstructors() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B
+
+  PositiveMultipleConstructors(int) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B
+
+  PositiveMultipleConstructors(const PositiveMultipleConstructors &) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B
+
+  // FIXME: The fix-its here collide providing an erroneous fix
+  int A, B;
+  // CHECK-FIXES: int A{}{}{}, B{}{}{};
+};
+
+typedef struct {
+  int Member;
+} CStyleStruct;
+
+struct PositiveUninitializedBase : public NegativeAggregateType, CStyleStruct {
+  PositiveUninitializedBase() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType, CStyleStruct
+  // CHECK-FIXES: PositiveUninitializedBase() : NegativeAggregateType(), CStyleStruct() {}
+};
+
+struct PositiveUninitializedBaseOrdering : public NegativeAggregateType,
+                                           public NonTrivialType {
+  PositiveUninitializedBaseOrdering() : B() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType, NonTrivialType
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: constructor does not initialize these fields: A
+  // CHECK-FIXES: PositiveUninitializedBaseOrdering() : NegativeAggregateType(), NonTrivialType(), B() {}
+
+  // This is somewhat pathological with the base class initializer at the end...
+  PositiveUninitializedBaseOrdering(int) : B(), NonTrivialType(), A() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType
+  // CHECK-FIXES: PositiveUninitializedBaseOrdering(int) : B(), NegativeAggregateType(), NonTrivialType(), A() {}
+
+  PositiveUninitializedBaseOrdering(float) : B(), NegativeAggregateType(), A() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NonTrivialType
+  // CHECK-FIXES: PositiveUninitializedBaseOrdering(float) : B(), NegativeAggregateType(), NonTrivialType(), A() {}
+
+  int A, B;
+  // CHECK-FIXES: int A{}, B;
+};
+
+// We shouldn't need to initialize anything because PositiveUninitializedBase
+// has a user-defined constructor.
+struct NegativeUninitializedBase : public PositiveUninitializedBase {
+  NegativeUninitializedBase() {}
+};
+
+struct InheritedAggregate : public NegativeAggregateType {
+  int F;
+};
+
+static InheritedAggregate NegativeGlobal;
+
+enum TestEnum {
+  A,
+  B,
+  C
+};
+
+enum class TestScopedEnum {
+  A,
+  B,
+  C
+};
+
+struct PositiveEnumType {
+  PositiveEnumType() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: X, Y
+  // No proposed fixes, as we don't know whether value initialization for these
+  // enums really makes sense.
+
+  TestEnum X;
+  TestScopedEnum Y;
+};
+
+extern "C" {
+struct NegativeCStruct {
+  int X, Y, Z;
+};
+
+static void PositiveCStructVariable() {
+  NegativeCStruct X;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: uninitialized record type: 'X'
+  // CHECK-FIXES: NegativeCStruct X{};
+}
+}
+
+static void NegativeStaticVariable() {
+  static NegativeCStruct S;
+  (void)S;
+}
+
+union NegativeUnionInClass {
+  NegativeUnionInClass() {} // No message as a union can only initialize one member.
+  int X = 0;
+  float Y;
+};
+
+union PositiveUnion {
+  PositiveUnion() : X() {} // No message as a union can only initialize one member.
+  PositiveUnion(int) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: union constructor should initialize one of these fields: X, Y
+
+  int X;
+  // CHECK-FIXES: int X{};
+
+  // Make sure we don't give Y an initializer.
+  float Y;
+  // CHECK-FIXES-NOT: float Y{};
+};
+
+union PositiveUnionReversed {
+  PositiveUnionReversed() : X() {} // No message as a union can only initialize one member.
+  PositiveUnionReversed(int) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: union constructor should initialize one of these fields: Y, X
+
+  // Make sure we don't give Y an initializer.
+  TestEnum Y;
+  // CHECK-FIXES-NOT: TestEnum Y{};
+
+  int X;
+  // CHECK-FIXES: int X{};
+};
+
+struct PositiveAnonymousUnionAndStruct {
+  PositiveAnonymousUnionAndStruct() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B, Y, Z, C, D, E, F, X
+
+  union {
+    int A;
+    // CHECK-FIXES: int A{};
+    short B;
+  };
+
+  struct {
+    int Y;
+    // CHECK-FIXES: int Y{};
+    char *Z;
+    // CHECK-FIXES: char *Z{};
+
+    struct {
+      short C;
+      // CHECK-FIXES: short C{};
+      double D;
+      // CHECK-FIXES: double D{};
+    };
+
+    union {
+      long E;
+      // CHECK-FIXES: long E{};
+      float F;
+    };
+  };
+  int X;
+  // CHECK-FIXES: int X{};
+};
+
+// This check results in a CXXConstructorDecl with no body.
+struct NegativeDeletedConstructor : NegativeAggregateType {
+  NegativeDeletedConstructor() = delete;
+
+  Template<int> F;
+};
+
+// This pathological template fails to compile if actually instantiated. It
+// results in the check seeing a null RecordDecl when examining the base class
+// initializer list.
+template <typename T>
+class PositiveSelfInitialization : NegativeAggregateType
+{
+  PositiveSelfInitialization() : PositiveSelfInitialization() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType
+  // CHECK-FIXES: PositiveSelfInitialization() : NegativeAggregateType(), PositiveSelfInitialization() {}
+};
+
+class PositiveIndirectMember {
+  struct {
+    int *A;
+    // CHECK-FIXES: int *A{};
+  };
+
+  PositiveIndirectMember() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A
+};
+
+void Bug30487()
+{
+  NegativeInClassInitializedDefaulted s;
+}
+
+struct PositiveVirtualMethod {
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: F
+  int F;
+  // CHECK-FIXES: int F{};
+  virtual int f() = 0;
+};
+
+struct PositiveVirtualDestructor {
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: F
+  PositiveVirtualDestructor() = default;
+  int F;
+  // CHECK-FIXES: int F{};
+  virtual ~PositiveVirtualDestructor() {}
+};
+
+struct PositiveVirtualBase : public virtual NegativeAggregateType {
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these bases: NegativeAggregateType
+  // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: constructor does not initialize these fields: F
+  int F;
+  // CHECK-FIXES: int F{};
+};
+
+template <typename T>
+struct PositiveTemplateVirtualDestructor {
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: F
+  T Val;
+  int F;
+  // CHECK-FIXES: int F{};
+  virtual ~PositiveTemplateVirtualDestructor() = default;
+};
+
+template struct PositiveTemplateVirtualDestructor<int>;
+
+#define UNINITIALIZED_FIELD_IN_MACRO_BODY_VIRTUAL(FIELD) \
+  struct UninitializedFieldVirtual##FIELD {              \
+    int FIELD;                                           \
+    virtual ~UninitializedFieldVirtual##FIELD() {}       \
+  };                                                     \
+// Ensure FIELD is not initialized since fixes inside of macros are disabled.
+// CHECK-FIXES: int FIELD;
+
+UNINITIALIZED_FIELD_IN_MACRO_BODY_VIRTUAL(F);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: F
+UNINITIALIZED_FIELD_IN_MACRO_BODY_VIRTUAL(G);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: G
+
+struct NegativeEmpty {
+};
+
+static void NegativeEmptyVar() {
+  NegativeEmpty e;
+  (void)e;
+}
+
+struct NegativeEmptyMember {
+  NegativeEmptyMember() {}
+  NegativeEmpty e;
+};
+
+struct NegativeEmptyBase : NegativeEmpty {
+  NegativeEmptyBase() {}
+};
+
+struct NegativeEmptyArrayMember {
+  NegativeEmptyArrayMember() {}
+  char e[0];
+};
+
+struct NegativeIncompleteArrayMember {
+  NegativeIncompleteArrayMember() {}
+  char e[];
+};
+
+template <typename T> class NoCrash {
+  class B : public NoCrash {
+    template <typename U> B(U u) {}
+  };
+};
+
+struct PositiveBitfieldMember {
+  PositiveBitfieldMember() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
+  unsigned F : 5;
+  // CHECK-FIXES-NOT: unsigned F : 5{};
+};
+
+struct NegativeUnnamedBitfieldMember {
+  NegativeUnnamedBitfieldMember() {}
+  unsigned : 5;
+};
+
+struct NegativeInitializedBitfieldMembers {
+  NegativeInitializedBitfieldMembers() : F(3) { G = 2; }
+  unsigned F : 5;
+  unsigned G : 5;
+};
+
+struct NegativeImplicitInheritedCtorBase {
+  NegativeImplicitInheritedCtorBase(unsigned F) : F(F) {}
+  unsigned F;
+};
+
+struct NegativeImplicitInheritedCtor : NegativeImplicitInheritedCtorBase {
+  using NegativeImplicitInheritedCtorBase::NegativeImplicitInheritedCtorBase;
+};
+
+void Bug33557() {
+  NegativeImplicitInheritedCtor I(5);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-reinterpret-cast.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-reinterpret-cast.cpp
new file mode 100644
index 0000000..5420810
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-reinterpret-cast.cpp
@@ -0,0 +1,6 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-reinterpret-cast %t
+
+int i = 0;
+void *j;
+void f() { j = reinterpret_cast<void *>(i); }
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use reinterpret_cast [cppcoreguidelines-pro-type-reinterpret-cast]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-static-cast-downcast.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-static-cast-downcast.cpp
new file mode 100644
index 0000000..7a6c027
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-static-cast-downcast.cpp
@@ -0,0 +1,118 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-static-cast-downcast %t
+
+class Base {
+};
+
+class Derived : public Base {
+};
+
+class Base2 {
+};
+
+class MultiDerived : public Base, public Base2 {
+};
+
+class PolymorphicBase {
+public:
+  virtual ~PolymorphicBase();
+};
+
+class PolymorphicDerived : public PolymorphicBase {
+};
+
+class PolymorphicMultiDerived : public Base, public PolymorphicBase {
+};
+
+void pointers() {
+
+  auto P0 = static_cast<Derived*>(new Base());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
+
+  const Base* B0;
+  auto PC0 = static_cast<const Derived*>(B0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
+
+  auto P1 = static_cast<Base*>(new Derived()); // OK, upcast to a public base
+  auto P2 = static_cast<Base*>(new MultiDerived()); // OK, upcast to a public base
+  auto P3 = static_cast<Base2*>(new MultiDerived()); // OK, upcast to a public base
+}
+
+void pointers_polymorphic() {
+
+  auto PP0 = static_cast<PolymorphicDerived*>(new PolymorphicBase());
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead [cppcoreguidelines-pro-type-static-cast-downcast]
+  // CHECK-FIXES: auto PP0 = dynamic_cast<PolymorphicDerived*>(new PolymorphicBase());
+
+  const PolymorphicBase* B0;
+  auto PPC0 = static_cast<const PolymorphicDerived*>(B0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead [cppcoreguidelines-pro-type-static-cast-downcast]
+  // CHECK-FIXES: auto PPC0 = dynamic_cast<const PolymorphicDerived*>(B0);
+
+
+  auto B1 = static_cast<PolymorphicBase*>(new PolymorphicDerived()); // OK, upcast to a public base
+  auto B2 = static_cast<PolymorphicBase*>(new PolymorphicMultiDerived()); // OK, upcast to a public base
+  auto B3 = static_cast<Base*>(new PolymorphicMultiDerived()); // OK, upcast to a public base
+}
+
+void arrays() {
+  Base ArrayOfBase[10];
+  auto A0 = static_cast<Derived*>(ArrayOfBase);
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
+}
+
+void arrays_polymorphic() {
+  PolymorphicBase ArrayOfPolymorphicBase[10];
+  auto AP0 = static_cast<PolymorphicDerived*>(ArrayOfPolymorphicBase);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead
+  // CHECK-FIXES: auto AP0 = dynamic_cast<PolymorphicDerived*>(ArrayOfPolymorphicBase);
+}
+
+void references() {
+  Base B0;
+  auto R0 = static_cast<Derived&>(B0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
+  Base& RefToBase = B0;
+  auto R1 = static_cast<Derived&>(RefToBase);
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
+
+  const Base& ConstRefToBase = B0;
+  auto RC1 = static_cast<const Derived&>(ConstRefToBase);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
+
+
+  Derived RD1;
+  auto R2 = static_cast<Base&>(RD1); // OK, upcast to a public base
+}
+
+void references_polymorphic() {
+  PolymorphicBase B0;
+  auto RP0 = static_cast<PolymorphicDerived&>(B0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead
+  // CHECK-FIXES: auto RP0 = dynamic_cast<PolymorphicDerived&>(B0);
+
+  PolymorphicBase& RefToPolymorphicBase = B0;
+  auto RP1 = static_cast<PolymorphicDerived&>(RefToPolymorphicBase);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead [cppcoreguidelines-pro-type-static-cast-downcast]
+  // CHECK-FIXES: auto RP1 = dynamic_cast<PolymorphicDerived&>(RefToPolymorphicBase);
+
+  const PolymorphicBase& ConstRefToPolymorphicBase = B0;
+  auto RPC2 = static_cast<const PolymorphicDerived&>(ConstRefToPolymorphicBase);
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead [cppcoreguidelines-pro-type-static-cast-downcast]
+  // CHECK-FIXES: auto RPC2 = dynamic_cast<const PolymorphicDerived&>(ConstRefToPolymorphicBase);
+
+  PolymorphicDerived d1;
+  auto RP2 = static_cast<PolymorphicBase&>(d1); // OK, upcast to a public base
+}
+
+template<class B, class D>
+void templ() {
+  auto B0 = static_cast<B*>(new D());
+}
+
+void templ_bad_call() {
+  templ<Derived, Base>(); //FIXME: this should trigger a warning
+}
+
+void templ_good_call() {
+  templ<Base, Derived>(); // OK, upcast to a public base
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-union-access.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-union-access.cpp
new file mode 100644
index 0000000..6abc22b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-union-access.cpp
@@ -0,0 +1,41 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-union-access %t
+
+union U {
+  bool union_member1;
+  char union_member2;
+} u;
+
+struct S {
+  int non_union_member;
+  union {
+    bool union_member;
+  };
+  union {
+    char union_member2;
+  } u;
+} s;
+
+
+void f(char);
+void f2(U);
+void f3(U&);
+void f4(U*);
+
+void check()
+{
+  u.union_member1 = true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not access members of unions; use (boost::)variant instead [cppcoreguidelines-pro-type-union-access]
+  auto b = u.union_member2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not access members of unions; use (boost::)variant instead
+  auto a = &s.union_member;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: do not access members of unions; use (boost::)variant instead
+  f(s.u.union_member2);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not access members of unions; use (boost::)variant instead
+
+  s.non_union_member = 2; // OK
+
+  U u2 = u; // OK
+  f2(u); // OK
+  f3(u); // OK
+  f4(&u); // OK
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-vararg.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-vararg.cpp
new file mode 100644
index 0000000..021322a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-vararg.cpp
@@ -0,0 +1,51 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-vararg %t
+
+void f(int i);
+void f_vararg(int i, ...);
+
+struct C {
+  void g_vararg(...);
+  void g(const char*);
+} c;
+
+template<typename... P>
+void cpp_vararg(P... p);
+
+void check() {
+  f_vararg(1, 7, 9);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not call c-style vararg functions [cppcoreguidelines-pro-type-vararg]
+  c.g_vararg("foo");
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not call c-style vararg functions
+
+  f(3); // OK
+  c.g("foo"); // OK
+  cpp_vararg(1, 7, 9); // OK
+}
+
+// ... as a parameter is allowed (e.g. for SFINAE)
+template <typename T>
+void CallFooIfAvailableImpl(T& t, ...) {
+  // nothing
+}
+template <typename T>
+void CallFooIfAvailableImpl(T& t, decltype(t.foo())*) {
+  t.foo();
+}
+template <typename T>
+void CallFooIfAvailable(T& t) {
+  CallFooIfAvailableImpl(t, 0); // OK to call variadic function when the argument is a literal 0
+}
+
+#include <stdarg.h>
+void my_printf(const char* format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not call c-style vararg functions
+  va_list n;
+  va_copy(n, ap); // Don't warn, va_copy is anyway useless without va_start
+  int i = va_arg(ap, int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use va_start/va_arg to define c-style vararg functions; use variadic templates instead
+  va_end(ap); // Don't warn, va_end is anyway useless without va_start
+}
+
+int my_vprintf(const char* format, va_list arg ); // OK to declare function taking va_list
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-slicing.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-slicing.cpp
new file mode 100644
index 0000000..6856f52
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-slicing.cpp
@@ -0,0 +1,100 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-slicing %t
+
+class Base {
+  int i;
+  void f() {}
+  virtual void g() {}
+};
+
+class DerivedWithMemberVariables : public Base {
+  void f();
+  int j;
+};
+
+class TwiceDerivedWithNoMemberVariables : public DerivedWithMemberVariables {
+  void f();
+};
+
+class DerivedWithOverride : public Base {
+  void f();
+  void g() override {}
+};
+
+class TwiceDerivedWithNoOverride : public DerivedWithOverride {
+  void f();
+};
+
+void TakesBaseByValue(Base base);
+
+DerivedWithMemberVariables ReturnsDerived();
+
+void positivesWithMemberVariables() {
+  DerivedWithMemberVariables b;
+  Base a{b};
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state [cppcoreguidelines-slicing]
+  a = b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
+  TakesBaseByValue(b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
+
+  TwiceDerivedWithNoMemberVariables c;
+  a = c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'TwiceDerivedWithNoMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
+
+  a = ReturnsDerived();
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
+}
+
+void positivesWithOverride() {
+  DerivedWithOverride b;
+  Base a{b};
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+  a = b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+  TakesBaseByValue(b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+
+  TwiceDerivedWithNoOverride c;
+  a = c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+}
+
+void TakesBaseByReference(Base &base);
+
+class DerivedThatAddsVirtualH : public Base {
+  virtual void h();
+};
+
+class DerivedThatOverridesH : public DerivedThatAddsVirtualH {
+  void h() override;
+};
+
+void negatives() {
+  // OK, simple copying from the same type.
+  Base a;
+  TakesBaseByValue(a);
+  DerivedWithMemberVariables b;
+  DerivedWithMemberVariables c{b};
+  b = c;
+
+  // OK, derived type does not have extra state.
+  TwiceDerivedWithNoMemberVariables d;
+  DerivedWithMemberVariables e{d};
+  e = d;
+
+  // OK, derived does not override any method.
+  TwiceDerivedWithNoOverride f;
+  DerivedWithOverride g{f};
+  g = f;
+
+  // OK, no copying.
+  TakesBaseByReference(d);
+  TakesBaseByReference(f);
+
+  // Derived type overrides methods, but these methods are not in the base type,
+  // so cannot be called accidentally. Right now this triggers, but we might
+  // want to allow it.
+  DerivedThatOverridesH h;
+  a = h;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedThatOverridesH' to 'Base' discards override 'h'
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions-cxx-03.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions-cxx-03.cpp
new file mode 100644
index 0000000..8fe5e42
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions-cxx-03.cpp
@@ -0,0 +1,26 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-special-member-functions %t -- -- -std=c++03
+
+class DefinesDestructor {
+  ~DefinesDestructor();
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesDestructor' defines a non-default destructor but does not define a copy constructor or a copy assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesCopyConstructor {
+  DefinesCopyConstructor(const DefinesCopyConstructor &);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesCopyConstructor' defines a copy constructor but does not define a destructor or a copy assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesCopyAssignment {
+  DefinesCopyAssignment &operator=(const DefinesCopyAssignment &);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesCopyAssignment' defines a copy assignment operator but does not define a destructor or a copy constructor [cppcoreguidelines-special-member-functions]
+
+class DefinesNothing {
+};
+
+class DefinesEverything {
+  DefinesEverything(const DefinesEverything &);
+  DefinesEverything &operator=(const DefinesEverything &);
+  ~DefinesEverything();
+};
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions-relaxed.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions-relaxed.cpp
new file mode 100644
index 0000000..4fff02d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions-relaxed.cpp
@@ -0,0 +1,71 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-special-member-functions %t -- -config="{CheckOptions: [{key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions, value: 1}, {key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor, value: 1}]}" --
+
+class DefinesDestructor {
+  ~DefinesDestructor();
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesDestructor' defines a non-default destructor but does not define a copy constructor or a copy assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesDefaultedDestructor {
+  ~DefinesDefaultedDestructor() = default;
+};
+
+class DefinesCopyConstructor {
+  DefinesCopyConstructor(const DefinesCopyConstructor &);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesCopyConstructor' defines a copy constructor but does not define a destructor or a copy assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesCopyAssignment {
+  DefinesCopyAssignment &operator=(const DefinesCopyAssignment &);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesCopyAssignment' defines a copy assignment operator but does not define a destructor or a copy constructor [cppcoreguidelines-special-member-functions]
+
+class DefinesMoveConstructor {
+  DefinesMoveConstructor(DefinesMoveConstructor &&);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesMoveConstructor' defines a move constructor but does not define a destructor, a copy constructor, a copy assignment operator or a move assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesMoveAssignment {
+  DefinesMoveAssignment &operator=(DefinesMoveAssignment &&);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesMoveAssignment' defines a move assignment operator but does not define a destructor, a copy constructor, a copy assignment operator or a move constructor [cppcoreguidelines-special-member-functions]
+class DefinesNothing {
+};
+
+class DefinesEverything {
+  DefinesEverything(const DefinesEverything &);
+  DefinesEverything &operator=(const DefinesEverything &);
+  DefinesEverything(DefinesEverything &&);
+  DefinesEverything &operator=(DefinesEverything &&);
+  ~DefinesEverything();
+};
+
+class DeletesEverything {
+  DeletesEverything(const DeletesEverything &) = delete;
+  DeletesEverything &operator=(const DeletesEverything &) = delete;
+  DeletesEverything(DeletesEverything &&) = delete;
+  DeletesEverything &operator=(DeletesEverything &&) = delete;
+  ~DeletesEverything() = delete;
+};
+
+class DeletesCopyDefaultsMove {
+  DeletesCopyDefaultsMove(const DeletesCopyDefaultsMove &) = delete;
+  DeletesCopyDefaultsMove &operator=(const DeletesCopyDefaultsMove &) = delete;
+  DeletesCopyDefaultsMove(DeletesCopyDefaultsMove &&) = default;
+  DeletesCopyDefaultsMove &operator=(DeletesCopyDefaultsMove &&) = default;
+  ~DeletesCopyDefaultsMove() = default;
+};
+
+template <typename T>
+struct TemplateClass {
+  TemplateClass() = default;
+  TemplateClass(const TemplateClass &);
+  TemplateClass &operator=(const TemplateClass &);
+  TemplateClass(TemplateClass &&);
+  TemplateClass &operator=(TemplateClass &&);
+  ~TemplateClass();
+};
+
+// Multiple instantiations of a class template will trigger multiple matches for defined special members.
+// This should not cause problems.
+TemplateClass<int> InstantiationWithInt;
+TemplateClass<double> InstantiationWithDouble;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions.cpp
new file mode 100644
index 0000000..013ba86
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/cppcoreguidelines-special-member-functions.cpp
@@ -0,0 +1,72 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-special-member-functions %t
+
+class DefinesDestructor {
+  ~DefinesDestructor();
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesDestructor' defines a non-default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesDefaultedDestructor {
+  ~DefinesDefaultedDestructor() = default;
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesDefaultedDestructor' defines a default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesCopyConstructor {
+  DefinesCopyConstructor(const DefinesCopyConstructor &);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesCopyConstructor' defines a copy constructor but does not define a destructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesCopyAssignment {
+  DefinesCopyAssignment &operator=(const DefinesCopyAssignment &);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesCopyAssignment' defines a copy assignment operator but does not define a destructor, a copy constructor, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesMoveConstructor {
+  DefinesMoveConstructor(DefinesMoveConstructor &&);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesMoveConstructor' defines a move constructor but does not define a destructor, a copy constructor, a copy assignment operator or a move assignment operator [cppcoreguidelines-special-member-functions]
+
+class DefinesMoveAssignment {
+  DefinesMoveAssignment &operator=(DefinesMoveAssignment &&);
+};
+// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesMoveAssignment' defines a move assignment operator but does not define a destructor, a copy constructor, a copy assignment operator or a move constructor [cppcoreguidelines-special-member-functions]
+class DefinesNothing {
+};
+
+class DefinesEverything {
+  DefinesEverything(const DefinesEverything &);
+  DefinesEverything &operator=(const DefinesEverything &);
+  DefinesEverything(DefinesEverything &&);
+  DefinesEverything &operator=(DefinesEverything &&);
+  ~DefinesEverything();
+};
+
+class DeletesEverything {
+  DeletesEverything(const DeletesEverything &) = delete;
+  DeletesEverything &operator=(const DeletesEverything &) = delete;
+  DeletesEverything(DeletesEverything &&) = delete;
+  DeletesEverything &operator=(DeletesEverything &&) = delete;
+  ~DeletesEverything() = delete;
+};
+
+class DeletesCopyDefaultsMove {
+  DeletesCopyDefaultsMove(const DeletesCopyDefaultsMove &) = delete;
+  DeletesCopyDefaultsMove &operator=(const DeletesCopyDefaultsMove &) = delete;
+  DeletesCopyDefaultsMove(DeletesCopyDefaultsMove &&) = default;
+  DeletesCopyDefaultsMove &operator=(DeletesCopyDefaultsMove &&) = default;
+  ~DeletesCopyDefaultsMove() = default;
+};
+
+template <typename T>
+struct TemplateClass {
+  TemplateClass() = default;
+  TemplateClass(const TemplateClass &);
+  TemplateClass &operator=(const TemplateClass &);
+  TemplateClass(TemplateClass &&);
+  TemplateClass &operator=(TemplateClass &&);
+  ~TemplateClass();
+};
+
+// Multiple instantiations of a class template will trigger multiple matches for defined special members.
+// This should not cause problems.
+TemplateClass<int> InstantiationWithInt;
+TemplateClass<double> InstantiationWithDouble;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/custom-diagnostics.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/custom-diagnostics.cpp
new file mode 100644
index 0000000..8183770
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/custom-diagnostics.cpp
@@ -0,0 +1,27 @@
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-shadow,clang-diagnostic-float-conversion' %s -- | count 0
+//
+// Enable warnings using -config:
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-shadow,clang-diagnostic-float-conversion' \
+// RUN:   -config='{ExtraArgs: ["-Wshadow","-Wno-unused-variable"], ExtraArgsBefore: ["-Wno-shadow","-Wfloat-conversion","-Wunused-variable"]}' %s -- \
+// RUN:   | FileCheck -implicit-check-not='{{warning:|error:}}' %s
+//
+// ... -extra-arg:
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-shadow,clang-diagnostic-float-conversion' \
+// RUN:   -extra-arg=-Wshadow -extra-arg=-Wno-unused-variable \
+// RUN:   -extra-arg-before=-Wno-shadow -extra-arg-before=-Wfloat-conversion \
+// RUN:   -extra-arg-before=-Wunused-variable %s -- \
+// RUN:   | FileCheck -implicit-check-not='{{warning:|error:}}' %s
+//
+// ... a combination of -config and -extra-arg(-before):
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-shadow,clang-diagnostic-float-conversion' \
+// RUN:   -config='{ExtraArgs: ["-Wno-unused-variable"], ExtraArgsBefore: ["-Wno-shadow","-Wfloat-conversion"]}' \
+// RUN:   -extra-arg=-Wshadow -extra-arg-before=-Wunused-variable %s -- \
+// RUN:   | FileCheck -implicit-check-not='{{warning:|error:}}' %s
+
+void f(float x) {
+  int a;
+  { int a; }
+  // CHECK: :[[@LINE-1]]:9: warning: declaration shadows a local variable [clang-diagnostic-shadow]
+  int b = x;
+  // CHECK: :[[@LINE-1]]:11: warning: implicit conversion turns floating-point number into integer: 'float' to 'int' [clang-diagnostic-float-conversion]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/deduplication.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/deduplication.cpp
new file mode 100644
index 0000000..056fe4e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/deduplication.cpp
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s google-explicit-constructor %t
+
+template<typename T>
+struct A { A(T); };
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: single-argument constructors must be marked explicit
+
+void f() {
+  A<int> a(0);
+  A<double> b(0);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/diagnostic.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/diagnostic.cpp
new file mode 100644
index 0000000..d12fc7b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/diagnostic.cpp
@@ -0,0 +1,50 @@
+// RUN: not clang-tidy -checks='-*,modernize-use-override' %s.nonexistent.cpp -- | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %s -- -fan-unknown-option | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %s -- -fan-unknown-option | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,modernize-use-override' %s -- -DCOMPILATION_ERROR | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s
+//
+// Now repeat the tests and ensure no other errors appear on stderr:
+// RUN: not clang-tidy -checks='-*,modernize-use-override' %s.nonexistent.cpp -- 2>&1 | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %s -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %s -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE 2>&1 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,modernize-use-override' %s -- -DCOMPILATION_ERROR 2>&1 | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s
+//
+// Now create a directory with a compilation database file and ensure we don't
+// use it after failing to parse commands from the command line:
+//
+// RUN: mkdir -p %T/diagnostics/
+// RUN: echo '[{"directory": "%/T/diagnostics/","command": "clang++ -fan-option-from-compilation-database -c %/T/diagnostics/input.cpp", "file": "%/T/diagnostics/input.cpp"}]' > %T/diagnostics/compile_commands.json
+// RUN: cat %s > %T/diagnostics/input.cpp
+// RUN: not clang-tidy -checks='-*,modernize-use-override' %T/diagnostics/nonexistent.cpp -- 2>&1 | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %T/diagnostics/input.cpp -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %T/diagnostics/input.cpp -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %T/diagnostics/input.cpp -- -DMACRO_FROM_COMMAND_LINE 2>&1 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %T/diagnostics/input.cpp 2>&1 | FileCheck -check-prefix=CHECK5 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,modernize-use-override' %T/diagnostics/input.cpp -- -DCOMPILATION_ERROR 2>&1 | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s
+
+// CHECK1: error: error reading '{{.*}}nonexistent.cpp' [clang-diagnostic-error]
+// CHECK2: error: unknown argument: '-fan-unknown-option' [clang-diagnostic-error]
+// CHECK3: error: unknown argument: '-fan-unknown-option' [clang-diagnostic-error]
+// CHECK5: error: unknown argument: '-fan-option-from-compilation-database' [clang-diagnostic-error]
+
+// CHECK2: :[[@LINE+3]]:9: warning: implicit conversion from 'double' to 'int' changes value from 1.5 to 1 [clang-diagnostic-literal-conversion]
+// CHECK3: :[[@LINE+2]]:9: warning: implicit conversion from 'double' to 'int' changes value
+// CHECK5: :[[@LINE+1]]:9: warning: implicit conversion from 'double' to 'int' changes value
+int a = 1.5;
+
+// CHECK2: :[[@LINE+3]]:11: warning: single-argument constructors must be marked explicit
+// CHECK3: :[[@LINE+2]]:11: warning: single-argument constructors must be marked explicit
+// CHECK5: :[[@LINE+1]]:11: warning: single-argument constructors must be marked explicit
+class A { A(int) {} };
+
+#define MACRO_FROM_COMMAND_LINE
+// CHECK4: :[[@LINE-1]]:9: warning: 'MACRO_FROM_COMMAND_LINE' macro redefined
+
+#ifdef COMPILATION_ERROR
+void f(int a) {
+  &(a + 1);
+  // CHECK6: :[[@LINE-1]]:3: error: cannot take the address of an rvalue of type 'int' [clang-diagnostic-error]
+}
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/enable-alpha-checks.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/enable-alpha-checks.cpp
new file mode 100644
index 0000000..b1e5130
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/enable-alpha-checks.cpp
@@ -0,0 +1,6 @@
+// Check if '-allow-enabling-analyzer-alpha-checkers' is visible for users.
+// RUN: clang-tidy -help | not grep 'allow-enabling-analyzer-alpha-checkers'
+
+// Check if '-allow-enabling-analyzer-alpha-checkers' enables alpha checks.
+// RUN: clang-tidy -checks=* -list-checks | not grep 'clang-analyzer-alpha'
+// RUN: clang-tidy -checks=* -list-checks -allow-enabling-analyzer-alpha-checkers | grep 'clang-analyzer-alpha'
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/explain-checks.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/explain-checks.cpp
new file mode 100644
index 0000000..9bff30c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/explain-checks.cpp
@@ -0,0 +1,12 @@
+// RUN: clang-tidy -checks=-*,modernize-use-nullptr -explain-config | FileCheck --check-prefix=CHECK-MESSAGE1 %s
+// RUN: clang-tidy -config="{Checks: '-*,modernize-use-nullptr'}" -explain-config | FileCheck --check-prefix=CHECK-MESSAGE2 %s
+// RUN: clang-tidy -checks=modernize-use-nullptr -config="{Checks: '-*,modernize-use-nullptr'}" -explain-config | FileCheck --check-prefix=CHECK-MESSAGE3 %s
+// RUN: clang-tidy -checks=modernize-use-nullptr -config="{Checks: '-*,-modernize-use-nullptr'}" %S/Inputs/explain-config/a.cc -explain-config -- | FileCheck --check-prefix=CHECK-MESSAGE4 %s
+// RUN: clang-tidy -checks=modernize-use-nullptr -config="{Checks: '-*,modernize-*'}" -explain-config | FileCheck --check-prefix=CHECK-MESSAGE5 %s
+// RUN: clang-tidy -explain-config %S/Inputs/explain-config/a.cc -- | grep "'modernize-use-nullptr' is enabled in the .*[/\\]Inputs[/\\]explain-config[/\\].clang-tidy."
+
+// CHECK-MESSAGE1: 'modernize-use-nullptr' is enabled in the command-line option '-checks'.
+// CHECK-MESSAGE2: 'modernize-use-nullptr' is enabled in the command-line option '-config'.
+// CHECK-MESSAGE3: 'modernize-use-nullptr' is enabled in the command-line option '-checks'.
+// CHECK-MESSAGE4: 'modernize-use-nullptr' is enabled in the command-line option '-checks'.
+// CHECK-MESSAGE5: 'modernize-use-nullptr' is enabled in the command-line option '-checks'.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/extra-args.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/extra-args.cpp
new file mode 100644
index 0000000..d65aacc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/extra-args.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-tidy -checks='-*,modernize-use-override' \
+// RUN:   -config='{ExtraArgs: ["-DTEST4"], ExtraArgsBefore: ["-DTEST1"]}' \
+// RUN:   -extra-arg=-DTEST3 -extra-arg-before=-DTEST2 %s -- -v 2>&1 \
+// RUN:   | FileCheck -implicit-check-not='{{warning:|error:}}' %s
+
+// CHECK: {{^}}clang Invocation:{{$}}
+// CHECK-NEXT: {{"-D" "TEST1" .*"-D" "TEST2" .*"-D" "TEST3" .*"-D" "TEST4"}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/file-filter.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/file-filter.cpp
new file mode 100644
index 0000000..9ee5cad
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/file-filter.cpp
@@ -0,0 +1,73 @@
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='' %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='' -quiet %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK-QUIET %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK2 %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -quiet %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK2-QUIET %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='header2\.h' %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK3 %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='header2\.h' -quiet %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK3-QUIET %s
+// FIXME: "-I %S/Inputs/file-filter/system/.." must be redundant.
+//       On Win32, file-filter/system\system-header1.h precedes
+//       file-filter\header*.h due to code order between '/' and '\\'.
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK4 %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers -quiet %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK4-QUIET %s
+
+#include "header1.h"
+// CHECK-NOT: warning:
+// CHECK-QUIET-NOT: warning:
+// CHECK2: header1.h:1:12: warning: single-argument constructors must be marked explicit
+// CHECK2-QUIET: header1.h:1:12: warning: single-argument constructors must be marked explicit
+// CHECK3-NOT: warning:
+// CHECK3-QUIET-NOT: warning:
+// CHECK4: header1.h:1:12: warning: single-argument constructors
+// CHECK4-QUIET: header1.h:1:12: warning: single-argument constructors
+
+#include "header2.h"
+// CHECK-NOT: warning:
+// CHECK-QUIET-NOT: warning:
+// CHECK2: header2.h:1:12: warning: single-argument constructors
+// CHECK2-QUIET: header2.h:1:12: warning: single-argument constructors
+// CHECK3: header2.h:1:12: warning: single-argument constructors
+// CHECK3-QUIET: header2.h:1:12: warning: single-argument constructors
+// CHECK4: header2.h:1:12: warning: single-argument constructors
+// CHECK4-QUIET: header2.h:1:12: warning: single-argument constructors
+
+#include <system-header.h>
+// CHECK-NOT: warning:
+// CHECK-QUIET-NOT: warning:
+// CHECK2-NOT: warning:
+// CHECK2-QUIET-NOT: warning:
+// CHECK3-NOT: warning:
+// CHECK3-QUIET-NOT: warning:
+// CHECK4: system-header.h:1:12: warning: single-argument constructors
+// CHECK4-QUIET: system-header.h:1:12: warning: single-argument constructors
+
+class A { A(int); };
+// CHECK: :[[@LINE-1]]:11: warning: single-argument constructors
+// CHECK-QUIET: :[[@LINE-2]]:11: warning: single-argument constructors
+// CHECK2: :[[@LINE-3]]:11: warning: single-argument constructors
+// CHECK2-QUIET: :[[@LINE-4]]:11: warning: single-argument constructors
+// CHECK3: :[[@LINE-5]]:11: warning: single-argument constructors
+// CHECK3-QUIET: :[[@LINE-6]]:11: warning: single-argument constructors
+// CHECK4: :[[@LINE-7]]:11: warning: single-argument constructors
+// CHECK4-QUIET: :[[@LINE-8]]:11: warning: single-argument constructors
+
+// CHECK-NOT: warning:
+// CHECK-QUIET-NOT: warning:
+// CHECK2-NOT: warning:
+// CHECK2-QUIET-NOT: warning:
+// CHECK3-NOT: warning:
+// CHECK3-QUIET-NOT: warning:
+// CHECK4-NOT: warning:
+// CHECK4-QUIET-NOT: warning:
+
+// CHECK: Suppressed 3 warnings (3 in non-user code)
+// CHECK: Use -header-filter=.* to display errors from all non-system headers.
+// CHECK-QUIET-NOT: Suppressed
+// CHECK2: Suppressed 1 warnings (1 in non-user code)
+// CHECK2: Use -header-filter=.* {{.*}}
+// CHECK2-QUIET-NOT: Suppressed
+// CHECK3: Suppressed 2 warnings (2 in non-user code)
+// CHECK3: Use -header-filter=.* {{.*}}
+// CHECK3-QUIET-NOT: Suppressed
+// CHECK4-NOT: Suppressed {{.*}} warnings
+// CHECK4-NOT: Use -header-filter=.* {{.*}}
+// CHECK4-QUIET-NOT: Suppressed
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fix-errors.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fix-errors.cpp
new file mode 100644
index 0000000..0c02616
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fix-errors.cpp
@@ -0,0 +1,15 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: not clang-tidy %t.cpp -checks='-*,google-explicit-constructor' -fix -- > %t.msg 2>&1
+// RUN: FileCheck -input-file=%t.cpp -check-prefix=CHECK-FIX %s
+// RUN: FileCheck -input-file=%t.msg -check-prefix=CHECK-MESSAGES %s
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: clang-tidy %t.cpp -checks='-*,google-explicit-constructor' -fix-errors -- > %t.msg 2>&1
+// RUN: FileCheck -input-file=%t.cpp -check-prefix=CHECK-FIX2 %s
+// RUN: FileCheck -input-file=%t.msg -check-prefix=CHECK-MESSAGES2 %s
+
+class A { A(int i); }
+// CHECK-FIX: class A { A(int i); }{{$}}
+// CHECK-MESSAGES: Fixes have NOT been applied.
+// CHECK-FIX2: class A { explicit A(int i); };
+// CHECK-MESSAGES2: note: FIX-IT applied suggested code changes
+// CHECK-MESSAGES2: clang-tidy applied 2 of 2 suggested fixes.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fix.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fix.cpp
new file mode 100644
index 0000000..db6bc22
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fix.cpp
@@ -0,0 +1,18 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: clang-tidy %t.cpp -checks='-*,google-explicit-constructor,llvm-namespace-comment' -fix -export-fixes=%t.yaml -- > %t.msg 2>&1
+// RUN: FileCheck -input-file=%t.cpp %s
+// RUN: FileCheck -input-file=%t.msg -check-prefix=CHECK-MESSAGES %s
+// RUN: FileCheck -input-file=%t.yaml -check-prefix=CHECK-YAML %s
+
+namespace i {
+void f(); // So that the namespace isn't empty.
+}
+// CHECK: } // namespace i
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-YAML: ReplacementText: ' // namespace i'
+
+class A { A(int i); };
+// CHECK: class A { explicit A(int i); };
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-MESSAGES: clang-tidy applied 2 of 2 suggested fixes.
+// CHECK-YAML: ReplacementText: 'explicit '
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-default-arguments.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-default-arguments.cpp
new file mode 100644
index 0000000..f7b1ae6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-default-arguments.cpp
@@ -0,0 +1,81 @@
+// RUN: %check_clang_tidy %s fuchsia-default-arguments %t
+
+int foo(int value = 5) { return value; }
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments]
+// CHECK-FIXES: int foo(int value) { return value; }
+
+int f() {
+  foo();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling a function that uses a default argument is disallowed [fuchsia-default-arguments]
+  // CHECK-NEXT: note: default parameter was declared here:
+  // CHECK-NEXT: int foo(int value = 5) { return value; }
+}
+
+int bar(int value) { return value; }
+
+int n() {
+  foo(0);
+  bar(0);
+}
+
+class Baz {
+public:
+  int a(int value = 5) { return value; }
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments]
+  // CHECK-FIXES: int a(int value) { return value; }
+
+  int b(int value) { return value; }
+};
+
+class Foo {
+  // Fix should be suggested in declaration
+  int a(int value = 53);
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments]
+  // CHECK-FIXES: int a(int value);
+};
+
+// Fix shouldn't be suggested in implementation
+int Foo::a(int value) {
+  return value;
+}
+
+// Elided functions
+void f(int = 5) {};
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments]
+// CHECK-FIXES: void f(int) {};
+
+void g(int) {};
+
+// Should not suggest fix for macro-defined parameters
+#define D(val) = val
+
+void h(int i D(5));
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments]
+// CHECK-FIXES-NOT: void h(int i);
+
+void x(int i);
+void x(int i = 12);
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments]
+// CHECK-FIXES: void x(int i);
+
+void x(int i) {}
+
+struct S {
+  void x(int i);
+};
+
+void S::x(int i = 12) {}
+// CHECK-MESSAGES: [[@LINE-1]]:11: warning: declaring a parameter with a default argument is disallowed [fuchsia-default-arguments]
+// CHECK-FIXES: void S::x(int i) {}
+
+int main() {
+  S s;
+  s.x();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling a function that uses a default argument is disallowed [fuchsia-default-arguments]
+  // CHECK-NEXT: note: default parameter was declared here:
+  // CHECK-NEXT: void S::x(int i = 12) {}
+  x();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling a function that uses a default argument is disallowed [fuchsia-default-arguments]
+  // CHECK-NEXT: note: default parameter was declared here:
+  // CHECK-NEXT: void x(int i = 12);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-multiple-inheritance.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-multiple-inheritance.cpp
new file mode 100644
index 0000000..fd2ed14
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-multiple-inheritance.cpp
@@ -0,0 +1,147 @@
+// RUN: %check_clang_tidy %s fuchsia-multiple-inheritance %t
+
+class Base_A {
+public:
+  virtual int foo() { return 0; }
+};
+
+class Base_B {
+public:
+  virtual int bar() { return 0; }
+};
+
+class Base_A_child : public Base_A {
+public:
+  virtual int baz() { return 0; }
+};
+
+class Interface_A {
+public:
+  virtual int foo() = 0;
+};
+
+class Interface_B {
+public:
+  virtual int bar() = 0;
+};
+
+class Interface_C {
+public:
+  virtual int blat() = 0;
+};
+
+class Interface_A_with_member {
+public:
+  virtual int foo() = 0;
+  int val = 0;
+};
+
+class Interface_with_A_Parent : public Base_A {
+public:
+  virtual int baz() = 0;
+};
+
+// Inherits from multiple concrete classes.
+// CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting mulitple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance]
+// CHECK-NEXT: class Bad_Child1 : public Base_A, Base_B {};
+class Bad_Child1 : public Base_A, Base_B {};
+
+// CHECK-MESSAGES: [[@LINE+1]]:1: warning: inheriting mulitple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance]
+class Bad_Child2 : public Base_A, Interface_A_with_member {
+  virtual int foo() override { return 0; }
+};
+
+// CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting mulitple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance]
+// CHECK-NEXT: class Bad_Child3 : public Interface_with_A_Parent, Base_B {
+class Bad_Child3 : public Interface_with_A_Parent, Base_B {
+  virtual int baz() override { return 0; }
+};
+
+// Easy cases of single inheritance
+class Simple_Child1 : public Base_A {};
+class Simple_Child2 : public Interface_A {
+  virtual int foo() override { return 0; }
+};
+
+// Valid uses of multiple inheritance
+class Good_Child1 : public Interface_A, Interface_B {
+  virtual int foo() override { return 0; }
+  virtual int bar() override { return 0; }
+};
+
+class Good_Child2 : public Base_A, Interface_B {
+  virtual int bar() override { return 0; }
+};
+
+class Good_Child3 : public Base_A_child, Interface_C, Interface_B {
+  virtual int bar() override { return 0; }
+  virtual int blat() override { return 0; }
+};
+
+struct B1 { int x; };
+struct B2 { int x;};
+// CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting mulitple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance]
+// CHECK-NEXT: struct D : B1, B2 {};
+struct D1 : B1, B2 {};
+
+struct Base1 { virtual void foo() = 0; };
+struct V1 : virtual Base1 {};
+struct V2 : virtual Base1 {};
+struct D2 : V1, V2 {};
+
+struct Base2 { virtual void foo(); };
+struct V3 : virtual Base2 {};
+struct V4 : virtual Base2 {};
+struct D3 : V3, V4 {};
+
+struct Base3 {};
+struct V5 : virtual Base3 { virtual void f(); };
+struct V6 : virtual Base3 { virtual void g(); };
+// CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting mulitple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance]
+// CHECK-NEXT: struct D4 : V5, V6 {};
+struct D4 : V5, V6 {};
+
+struct Base4 {};
+struct V7 : virtual Base4 { virtual void f() = 0; };
+struct V8 : virtual Base4 { virtual void g() = 0; };
+struct D5 : V7, V8 {};
+
+struct Base5 { virtual void f() = 0; };
+struct V9 : virtual Base5 { virtual void f(); };
+struct V10 : virtual Base5 { virtual void g() = 0; };
+struct D6 : V9, V10 {};
+
+struct Base6 { virtual void f(); };
+struct Base7 { virtual void g(); };
+struct V15 : virtual Base6 { virtual void f() = 0; };
+struct V16 : virtual Base7 { virtual void g() = 0; };
+// CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting mulitple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance]
+// CHECK-NEXT: struct D9 : V15, V16 {};
+struct D9 : V15, V16 {};
+
+struct Static_Base { static void foo(); };
+struct V11 : virtual Static_Base {};
+struct V12 : virtual Static_Base {};
+struct D7 : V11, V12 {};
+
+struct Static_Base_2 {};
+struct V13 : virtual Static_Base_2 { static void f(); };
+struct V14 : virtual Static_Base_2 { static void g(); };
+struct D8 : V13, V14 {};
+
+template<typename T> struct A : T {};
+template<typename T> struct B : virtual T {};
+
+template<typename> struct C {};
+template<typename T> struct D : C<T> {};
+
+// Check clang_tidy does not crash on this code.
+template <class T>
+struct WithTemplBase : T {
+  WithTemplBase();
+};
+
+int test_no_crash() {
+  auto foo = []() {};
+  WithTemplBase<decltype(foo)>();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-overloaded-operator.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-overloaded-operator.cpp
new file mode 100644
index 0000000..be65a32
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-overloaded-operator.cpp
@@ -0,0 +1,21 @@
+// RUN: %check_clang_tidy %s fuchsia-overloaded-operator %t
+
+class A {
+public:
+  int operator+(int);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: overloading 'operator+' is disallowed
+};
+
+class B {
+public:
+  B &operator=(const B &Other);
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:3: warning: overloading 'operator=' is disallowed
+  B &operator=(B &&Other);
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:3: warning: overloading 'operator=' is disallowed
+};
+
+A operator-(const A &A1, const A &A2);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: overloading 'operator-' is disallowed
+
+void operator delete(void*, void*) throw();
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: overloading 'operator delete' is disallowed
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-all.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-all.cpp
new file mode 100644
index 0000000..21f4b68
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-all.cpp
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s fuchsia-restrict-system-includes %t \
+// RUN:		-- -config="{CheckOptions: [{key: fuchsia-restrict-system-includes.Includes, value: ''}]}" \
+// RUN:   -- -std=c++11 -I %S/Inputs/fuchsia-restrict-system-includes -isystem %S/Inputs/fuchsia-restrict-system-includes/system
+
+#include <cstdlib.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include cstdlib.h not allowed
+#include <cstdarg.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include cstdarg.h not allowed
+#include <t.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include t.h not allowed
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-glob.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-glob.cpp
new file mode 100644
index 0000000..334990d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-glob.cpp
@@ -0,0 +1,9 @@
+// RUN: %check_clang_tidy %s fuchsia-restrict-system-includes %t \
+// RUN:		-- -config="{CheckOptions: [{key: fuchsia-restrict-system-includes.Includes, value: 'cstd*'}]}" \
+// RUN:   -- -std=c++11 -I %S/Inputs/fuchsia-restrict-system-includes -isystem %S/Inputs/fuchsia-restrict-system-includes/system
+
+#include <cstdlib.h>
+#include <cstdarg.h>
+#include <t.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include t.h not allowed
+// CHECK-FIXES-NOT: #include <t.h>
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-headers.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-headers.cpp
new file mode 100644
index 0000000..f392eac
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes-headers.cpp
@@ -0,0 +1,23 @@
+// RUN: rm -rf %T/Headers
+// RUN: mkdir %T/Headers
+// RUN: cp -r %S/Inputs/fuchsia-restrict-system-includes %T/Headers/fuchsia-restrict-system-includes
+// RUN: %check_clang_tidy %s fuchsia-restrict-system-includes %t \
+// RUN:		-- -config="{CheckOptions: [{key: fuchsia-restrict-system-includes.Includes, value: 'transitive.h,s.h'}]}" \
+// RUN:   -system-headers -header-filter=.* \
+// RUN:   -- -std=c++11 -I %T/Headers/fuchsia-restrict-system-includes -isystem %T/Headers/fuchsia-restrict-system-includes/system
+// RUN: FileCheck -input-file=%T/Headers/fuchsia-restrict-system-includes/transitive2.h %s -check-prefix=CHECK-FIXES
+// RUN: rm -rf %T/Headers
+
+// transitive.h includes <r.h> and <t.h>
+#include <transitive.h>
+// CHECK-MESSAGES: :1:1: warning: system include r.h not allowed, transitively included from {{.*}}
+// CHECK-MESSAGES: :2:1: warning: system include t.h not allowed, transitively included from {{.*}}
+
+// transitive.h includes <s.h> and <t.h>
+#include "transitive2.h"
+// CHECK-MESSAGES: :2:1: warning: system include t.h not allowed, transitively included from {{.*}}
+// CHECK-FIXES-NOT: #include <t.h>
+
+int main() {
+  // f() is declared in r.h
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes.cpp
new file mode 100644
index 0000000..e2ba710
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-restrict-system-includes.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s fuchsia-restrict-system-includes %t \
+// RUN:		-- -config="{CheckOptions: [{key: fuchsia-restrict-system-includes.Includes, value: 's.h'}]}" \
+// RUN:   -- -std=c++11 -I %S/Inputs/fuchsia-restrict-system-includes -isystem %S/Inputs/fuchsia-restrict-system-includes/system
+
+#include "a.h"
+
+#include <s.h>
+#include <t.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include t.h not allowed
+// CHECK-FIXES-NOT: #include <t.h>
+
+#include "s.h"
+#include "t.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include t.h not allowed
+// CHECK-FIXES-NOT: #include "t.h"
+
+#define foo <j.h>
+
+#include foo
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include j.h not allowed
+// CHECK-FIXES-NOT: #include foo
+
+#/* comment */ include /* comment */ foo
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include j.h not allowed
+// CHECK-FIXES-NOT: # /* comment */ include /* comment */ foo
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-statically-constructed-objects.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-statically-constructed-objects.cpp
new file mode 100644
index 0000000..006494e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-statically-constructed-objects.cpp
@@ -0,0 +1,91 @@
+// RUN: %check_clang_tidy %s fuchsia-statically-constructed-objects %t
+
+// Trivial static is fine
+static int i;
+
+class ClassWithNoCtor {};
+
+class ClassWithCtor {
+public:
+  ClassWithCtor(int Val) : Val(Val) {}
+private:
+  int Val;
+};
+
+class ClassWithConstexpr {
+public:
+  ClassWithConstexpr(int Val1, int Val2) : Val(Val1) {}
+  constexpr ClassWithConstexpr(int Val) : Val(Val) {}
+
+private:
+  int Val;
+};
+
+ClassWithNoCtor A;
+ClassWithConstexpr C(0);
+ClassWithConstexpr E(0, 1);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT:  ClassWithConstexpr E(0, 1);
+ClassWithCtor G(0);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT:  ClassWithCtor G(0);
+
+static ClassWithNoCtor A2;
+static ClassWithConstexpr C2(0);
+static ClassWithConstexpr E2(0, 1);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT:  static ClassWithConstexpr E2(0, 1);
+static ClassWithCtor G2(0);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT:  static ClassWithCtor G2(0);
+
+struct StructWithConstexpr { constexpr StructWithConstexpr(int Val) {} };
+struct StructWithNoCtor {};
+struct StructWithCtor { StructWithCtor(); };
+
+StructWithNoCtor SNoCtor;
+StructWithConstexpr SConstexpr(0);
+StructWithCtor SCtor;
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT:  StructWithCtor SCtor;
+
+static StructWithConstexpr SConstexpr2(0);
+static StructWithNoCtor SNoCtor2;
+static StructWithCtor SCtor2;
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT:  static StructWithCtor SCtor2;
+
+extern StructWithCtor SCtor3;
+
+class ClassWithStaticMember {
+private:
+  static StructWithNoCtor S;
+};
+
+ClassWithStaticMember Z();
+
+class S {
+  int Val;
+public:
+  constexpr S(int i) : Val(100 / i) {}
+  int getVal() const { return Val; }
+};
+
+static S s1(1);
+static S s2(0); 
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT: static S s2(0);
+
+extern int get_i();
+static S s3(get_i());
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: static objects are disallowed; if possible, use a constexpr constructor instead [fuchsia-statically-constructed-objects]
+// CHECK-MESSAGES-NEXT:  static S s3(get_i());
+
+void f() {
+  // Locally static is fine
+  static int i;
+  static ClassWithNoCtor A2;
+  static ClassWithConstexpr C2(0);
+  static ClassWithConstexpr E2(0, 1);
+  static ClassWithCtor G2(0);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-trailing-return.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-trailing-return.cpp
new file mode 100644
index 0000000..f6c943a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-trailing-return.cpp
@@ -0,0 +1,23 @@
+// RUN: %check_clang_tidy %s fuchsia-trailing-return %t
+
+int add_one(const int arg) { return arg; }
+
+auto get_add_one() -> int (*)(const int) {
+  // CHECK-MESSAGES: [[@LINE-1]]:1: warning: a trailing return type is disallowed for this type of declaration
+  // CHECK-NEXT: auto get_add_one() -> int (*)(const int) {
+  return add_one;
+}
+
+auto lambda = [](double x, double y) {return x + y;};
+
+auto lambda2 = [](double x, double y) -> double {return x + y;};
+
+int main() {
+  get_add_one()(5);
+  return 0;
+}
+
+template <typename T1, typename T2>
+auto fn(const T1 &lhs, const T2 &rhs) -> decltype(lhs + rhs) {
+  return lhs + rhs;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-virtual-inheritance.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-virtual-inheritance.cpp
new file mode 100644
index 0000000..0c3311a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/fuchsia-virtual-inheritance.cpp
@@ -0,0 +1,42 @@
+// RUN: %check_clang_tidy %s fuchsia-virtual-inheritance %t
+
+class A {
+public:
+  A(int value) : val(value) {}
+
+  int do_A() { return val; }
+
+private:
+  int val;
+};
+
+class B : public virtual A {
+  // CHECK-MESSAGES: [[@LINE-1]]:1: warning: direct virtual inheritance is disallowed [fuchsia-virtual-inheritance]
+  // CHECK-NEXT: class B : public virtual A {
+public:
+  B() : A(0) {}
+  int do_B() { return 1 + do_A(); }
+};
+
+class C : public virtual A {
+  // CHECK-MESSAGES: [[@LINE-1]]:1: warning: direct virtual inheritance is disallowed [fuchsia-virtual-inheritance]
+  // CHECK-NEXT: class C : public virtual A {
+public:
+  C() : A(0) {}
+  int do_C() { return 2 + do_A(); }
+};
+
+class D : public B, public C {
+public:
+  D(int value) : A(value), B(), C() {}
+
+  int do_D() { return do_A() + do_B() + do_C(); }
+};
+
+int main() {
+  A *a = new A(0);
+  B *b = new B();
+  C *c = new C();
+  D *d = new D(0);
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-build-explicit-make-pair.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-build-explicit-make-pair.cpp
new file mode 100644
index 0000000..6dcd357
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-build-explicit-make-pair.cpp
@@ -0,0 +1,51 @@
+// RUN: %check_clang_tidy %s google-build-explicit-make-pair %t
+
+namespace std {
+template <class T1, class T2>
+struct pair {
+  pair(T1 x, T2 y) {}
+};
+
+template <class T1, class T2>
+pair<T1, T2> make_pair(T1 x, T2 y) {
+  return pair<T1, T2>(x, y);
+}
+}
+
+template <typename T>
+void templ(T a, T b) {
+  std::make_pair<T, unsigned>(a, b);
+  std::make_pair<int, int>(1, 2);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: for C++11-compatibility, omit template arguments from make_pair
+// CHECK-FIXES: std::make_pair(1, 2)
+}
+
+template <typename T>
+int t();
+
+void test(int i) {
+  std::make_pair<int, int>(i, i);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: for C++11-compatibility, omit template arguments from make_pair
+// CHECK-FIXES: std::make_pair(i, i)
+
+  std::make_pair<unsigned, int>(i, i);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: for C++11-compatibility, use pair directly
+// CHECK-FIXES: std::pair<unsigned, int>(i, i)
+
+  std::make_pair<int, unsigned>(i, i);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: for C++11-compatibility, use pair directly
+// CHECK-FIXES: std::pair<int, unsigned>(i, i)
+
+#define M std::make_pair<int, unsigned>(i, i);
+M
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: for C++11-compatibility, use pair directly
+// Can't fix in macros.
+// CHECK-FIXES: #define M std::make_pair<int, unsigned>(i, i);
+// CHECK-FIXES-NEXT: M
+
+  templ(i, i);
+  templ(1U, 2U);
+
+  std::make_pair(i, 1); // no-warning
+  std::make_pair(t<int>, 1);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-default-arguments.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-default-arguments.cpp
new file mode 100644
index 0000000..48d3f2d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-default-arguments.cpp
@@ -0,0 +1,29 @@
+// RUN: %check_clang_tidy %s google-default-arguments %t
+
+struct A {
+  virtual void f(int I, int J = 3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: default arguments on virtual or override methods are prohibited [google-default-arguments]
+};
+
+struct B : public A {
+  void f(int I, int J = 5);
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: default arguments on virtual or override methods are prohibited
+};
+
+struct C : public B {
+  void f(int I, int J = 5) override;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: default arguments on virtual or override methods are prohibited
+};
+
+// Negatives.
+struct D : public B {
+  void f(int I, int J) override;
+};
+
+struct X {
+  void f(int I, int J = 3);
+};
+
+struct Y : public X {
+  void f(int I, int J = 5);
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-explicit-constructor.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-explicit-constructor.cpp
new file mode 100644
index 0000000..921237a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-explicit-constructor.cpp
@@ -0,0 +1,188 @@
+// RUN: %check_clang_tidy %s google-explicit-constructor %t
+
+namespace std {
+  typedef decltype(sizeof(int)) size_t;
+
+  // libc++'s implementation
+  template <class _E>
+  class initializer_list
+  {
+    const _E* __begin_;
+    size_t    __size_;
+
+    initializer_list(const _E* __b, size_t __s)
+      : __begin_(__b),
+        __size_(__s)
+    {}
+
+  public:
+    typedef _E        value_type;
+    typedef const _E& reference;
+    typedef const _E& const_reference;
+    typedef size_t    size_type;
+
+    typedef const _E* iterator;
+    typedef const _E* const_iterator;
+
+    initializer_list() : __begin_(nullptr), __size_(0) {}
+
+    size_t    size()  const {return __size_;}
+    const _E* begin() const {return __begin_;}
+    const _E* end()   const {return __begin_ + __size_;}
+  };
+}
+
+struct A {
+  A() {}
+  A(int x, int y) {}
+
+  explicit A(void *x) {}
+  explicit A(void *x, void *y) {}
+  explicit operator bool() const { return true; }
+
+  operator double() const = delete;
+
+  explicit A(const A& a) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: copy constructor should not be declared explicit [google-explicit-constructor]
+  // CHECK-FIXES: {{^  }}A(const A& a) {}
+
+  A(int x1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor]
+  // CHECK-FIXES: {{^  }}explicit A(int x1);
+
+  A(double x2, double y = 3.14) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructors that are callable with a single argument must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor]
+  // CHECK-FIXES: {{^  }}explicit A(double x2, double y = 3.14) {}
+
+  template <typename... T>
+  A(T&&... args);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructors that are callable with a single argument
+  // CHECK-FIXES: {{^  }}explicit A(T&&... args);
+};
+
+inline A::A(int x1) {}
+
+struct B {
+  B(std::initializer_list<int> list1) {}
+  B(const std::initializer_list<unsigned> &list2) {}
+  B(std::initializer_list<unsigned> &&list3) {}
+
+  operator bool() const { return true; }
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor]
+  // CHECK-FIXES: {{^  }}explicit operator bool() const { return true; }
+
+  operator double() const;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor]
+  // CHECK-FIXES: {{^  }}explicit operator double() const;
+
+  explicit B(::std::initializer_list<double> list4) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: initializer-list constructor should not be declared explicit [google-explicit-constructor]
+  // CHECK-FIXES: {{^  }}B(::std::initializer_list<double> list4) {}
+
+  explicit B(const ::std::initializer_list<char> &list5) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: initializer-list constructor
+  // CHECK-FIXES: {{^  }}B(const ::std::initializer_list<char> &list5) {}
+
+  explicit B(::std::initializer_list<char> &&list6) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: initializer-list constructor
+  // CHECK-FIXES: {{^  }}B(::std::initializer_list<char> &&list6) {}
+};
+
+inline B::operator double() const { return 0.0; }
+
+struct StructWithFnPointer {
+  void (*f)();
+} struct_with_fn_pointer = {[] {}};
+
+using namespace std;
+
+struct C {
+  C(initializer_list<int> list1) {}
+  C(const initializer_list<unsigned> &list2) {}
+  C(initializer_list<unsigned> &&list3) {}
+};
+
+template <typename T>
+struct C2 {
+  C2(initializer_list<int> list1) {}
+  C2(const initializer_list<unsigned> &list2) {}
+  C2(initializer_list<unsigned> &&list3) {}
+
+  explicit C2(initializer_list<double> list4) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: initializer-list constructor
+  // CHECK-FIXES: {{^  }}C2(initializer_list<double> list4) {}
+};
+
+template <typename T>
+struct C3 {
+  C3(initializer_list<T> list1) {}
+  C3(const std::initializer_list<T*> &list2) {}
+  C3(::std::initializer_list<T**> &&list3) {}
+
+  template <typename U>
+  C3(initializer_list<U> list3) {}
+};
+
+struct D {
+  template <typename T>
+  explicit D(T t) {}
+};
+
+template <typename T>
+struct E {
+  E(T *pt) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: single-argument constructors
+  // CHECK-FIXES: {{^  }}explicit E(T *pt) {}
+  template <typename U>
+  E(U *pu) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: single-argument constructors
+  // CHECK-FIXES: {{^  }}explicit E(U *pu) {}
+
+  explicit E(T t) {}
+  template <typename U>
+  explicit E(U u) {}
+};
+
+void f(std::initializer_list<int> list) {
+  D d(list);
+  E<decltype(list)> e(list);
+  E<int> e2(list);
+}
+
+template <typename T>
+struct F {};
+
+template<typename T>
+struct G {
+  operator bool() const;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator bool' must be marked
+  // CHECK-FIXES: {{^}}  explicit operator bool() const;
+  operator F<T>() const;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator F<type-parameter-0-0>' must be marked
+  // CHECK-FIXES: {{^}}  explicit operator F<T>() const;
+  template<typename U>
+  operator F<U>*() const;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator F<type-parameter-1-0> *' must be marked
+  // CHECK-FIXES: {{^}}  explicit operator F<U>*() const;
+};
+
+void f2() {
+  G<int> a;
+  (void)(F<int>)a;
+  if (a) {}
+  (void)(F<int>*)a;
+  (void)(F<int*>*)a;
+
+  G<double> b;
+  (void)(F<double>)b;
+  if (b) {}
+  (void)(F<double>*)b;
+  (void)(F<double*>*)b;
+}
+
+#define DEFINE_STRUCT_WITH_OPERATOR_BOOL(name) \
+  struct name {                                \
+    operator bool() const;                     \
+  }
+
+DEFINE_STRUCT_WITH_OPERATOR_BOOL(H);
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-module.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-module.cpp
new file mode 100644
index 0000000..494ac48
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-module.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-tidy -checks='-*,google*' -config='{}' -dump-config - -- | FileCheck %s
+// CHECK: CheckOptions:
+// CHECK: {{- key: *google-readability-braces-around-statements.ShortStatementLines}}
+// CHECK-NEXT: {{value: *'1'}}
+// CHECK: {{- key: *google-readability-function-size.StatementThreshold}}
+// CHECK-NEXT: {{value: *'800'}}
+// CHECK: {{- key: *google-readability-namespace-comments.ShortNamespaceLines}}
+// CHECK-NEXT: {{value: *'10'}}
+// CHECK: {{- key: *google-readability-namespace-comments.SpacesBeforeComments}}
+// CHECK-NEXT: {{value: *'2'}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-namespaces.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-namespaces.cpp
new file mode 100644
index 0000000..9bda3c0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-namespaces.cpp
@@ -0,0 +1,52 @@
+// RUN: clang-tidy %s -checks='-*,google-build-namespaces,google-build-using-namespace' -header-filter='.*' -- | FileCheck %s -implicit-check-not="{{warning|error}}:"
+#include "Inputs/google-namespaces.h"
+// CHECK: warning: do not use unnamed namespaces in header files [google-build-namespaces]
+
+using namespace spaaaace;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
+
+using spaaaace::core; // no-warning
+
+namespace std {
+inline namespace literals {
+inline namespace chrono_literals {
+}
+inline namespace complex_literals {
+}
+inline namespace string_literals {
+}
+}
+}
+
+using namespace std::chrono_literals;            // no-warning
+using namespace std::complex_literals;           // no-warning
+using namespace std::literals;                   // no-warning
+using namespace std::literals::chrono_literals;  // no-warning
+using namespace std::literals::complex_literals; // no-warning
+using namespace std::literals::string_literals;  // no-warning
+using namespace std::string_literals;            // no-warning
+
+namespace literals {}
+
+using namespace literals;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
+
+namespace foo {
+inline namespace literals {
+inline namespace bar_literals {}
+}
+}
+
+using namespace foo::literals;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
+
+using namespace foo::bar_literals;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
+
+using namespace foo::literals::bar_literals;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
+
+namespace foo_literals {}
+
+using namespace foo_literals;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-objc-avoid-throwing-exception.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-objc-avoid-throwing-exception.m
new file mode 100644
index 0000000..7fa32e7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-objc-avoid-throwing-exception.m
@@ -0,0 +1,32 @@
+// RUN: %check_clang_tidy %s google-objc-avoid-throwing-exception %t
+@class NSString;
+
+@interface NSException
+
++ (void)raise:(NSString *)name format:(NSString *)format;
++ (void)raise:(NSString *)name format:(NSString *)format arguments:(NSString *)args; // using NSString type since va_list cannot be recognized here
+
+@end
+
+@interface NotException
+
++ (void)raise:(NSString *)name format:(NSString *)format;
+
+@end
+
+@implementation Foo
+- (void)f {
+    NSString *foo = @"foo";
+    @throw foo;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass in NSError ** instead of throwing exception to indicate Objective-C errors [google-objc-avoid-throwing-exception]
+}
+
+- (void)f2 {
+    [NSException raise:@"TestException" format:@"Test"];
+    // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: pass in NSError ** instead of throwing exception to indicate Objective-C errors [google-objc-avoid-throwing-exception]
+    [NSException raise:@"TestException" format:@"Test %@" arguments:@"bar"];
+    // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: pass in NSError ** instead of throwing exception to indicate Objective-C errors [google-objc-avoid-throwing-exception]
+    [NotException raise:@"NotException" format:@"Test"];
+}
+@end
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-objc-global-variable-declaration.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-objc-global-variable-declaration.m
new file mode 100644
index 0000000..346ddec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-objc-global-variable-declaration.m
@@ -0,0 +1,49 @@
+// RUN: %check_clang_tidy %s google-objc-global-variable-declaration %t
+
+@class NSString;
+static NSString* const myConstString = @"hello";
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: const global variable 'myConstString' must have a name which starts with an appropriate prefix [google-objc-global-variable-declaration]
+// CHECK-FIXES: static NSString* const kMyConstString = @"hello";
+
+static NSString* MyString = @"hi";
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: non-const global variable 'MyString' must have a name which starts with 'g[A-Z]' [google-objc-global-variable-declaration]
+// CHECK-FIXES: static NSString* gMyString = @"hi";
+
+NSString* globalString = @"test";
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: non-const global variable 'globalString' must have a name which starts with 'g[A-Z]' [google-objc-global-variable-declaration]
+// CHECK-FIXES: NSString* gGlobalString = @"test";
+
+static NSString* a = @"too simple";
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: non-const global variable 'a' must have a name which starts with 'g[A-Z]' [google-objc-global-variable-declaration]
+// CHECK-FIXES: static NSString* a = @"too simple";
+
+static NSString* noDef;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: non-const global variable 'noDef' must have a name which starts with 'g[A-Z]' [google-objc-global-variable-declaration]
+// CHECK-FIXES: static NSString* gNoDef;
+
+static NSString* const _notAlpha = @"NotBeginWithAlpha";
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: const global variable '_notAlpha' must have a name which starts with an appropriate prefix [google-objc-global-variable-declaration]
+// CHECK-FIXES: static NSString* const _notAlpha = @"NotBeginWithAlpha";
+
+static NSString* const k_Alpha = @"SecondNotAlpha";
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: const global variable 'k_Alpha' must have a name which starts with an appropriate prefix [google-objc-global-variable-declaration]
+// CHECK-FIXES: static NSString* const k_Alpha = @"SecondNotAlpha";
+
+static NSString* const kGood = @"hello";
+static NSString* const XYGood = @"hello";
+static NSString* gMyIntGood = 0;
+
+extern NSString* const GTLServiceErrorDomain;
+
+enum GTLServiceError {
+  GTLServiceErrorQueryResultMissing = -3000,
+  GTLServiceErrorWaitTimedOut       = -3001,
+};
+
+@implementation Foo
+- (void)f {
+    int x = 0;
+    static int bar;
+    static const int baz = 42;
+}
+@end
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-overloaded-unary-and.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-overloaded-unary-and.cpp
new file mode 100644
index 0000000..16893d2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-overloaded-unary-and.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s google-runtime-operator %t
+
+struct Foo {
+  void *operator&();
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not overload unary operator&, it is dangerous. [google-runtime-operator]
+};
+
+template <typename T>
+struct TFoo {
+  T *operator&();
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not overload unary operator&
+};
+
+TFoo<int> tfoo;
+
+struct Bar;
+void *operator&(Bar &b);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not overload unary operator&
+
+// No warnings on binary operators.
+struct Qux {
+  void *operator&(Qux &q);
+};
+
+void *operator&(Qux &q, Qux &r);
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.c
new file mode 100644
index 0000000..488bcd7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.c
@@ -0,0 +1,24 @@
+// RUN: %check_clang_tidy %s google-readability-casting %t -- -- -x c
+// The testing script always adds .cpp extension to the input file name, so we
+// need to run clang-tidy directly in order to verify handling of .c files:
+// RUN: clang-tidy --checks=-*,google-readability-casting %s -- -x c++ | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not='{{warning|error}}:'
+// RUN: cp %s %t.main_file.cpp
+// RUN: clang-tidy --checks=-*,google-readability-casting -header-filter='.*' %t.main_file.cpp -- -I%S -DTEST_INCLUDE -x c++ | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not='{{warning|error}}:'
+
+#ifdef TEST_INCLUDE
+
+#undef TEST_INCLUDE
+#include "google-readability-casting.c"
+
+#else
+
+void f(const char *cpc) {
+  const char *cpc2 = (const char*)cpc;
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant cast to the same type [google-readability-casting]
+  // CHECK-FIXES: const char *cpc2 = cpc;
+  char *pc = (char*)cpc;
+  typedef const char *Typedef1;
+  (Typedef1)cpc;
+}
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.cpp
new file mode 100644
index 0000000..d36fef6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.cpp
@@ -0,0 +1,323 @@
+// RUN: %check_clang_tidy %s google-readability-casting %t
+
+bool g() { return false; }
+
+enum Enum { Enum1 };
+struct X {};
+struct Y : public X {};
+
+void f(int a, double b, const char *cpc, const void *cpv, X *pX) {
+  const char *cpc2 = (const char*)cpc;
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant cast to the same type [google-readability-casting]
+  // CHECK-FIXES: const char *cpc2 = cpc;
+
+  typedef const char *Typedef1;
+  typedef const char *Typedef2;
+  Typedef1 t1;
+  (Typedef2)t1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: C-style casts are discouraged; use static_cast (if needed, the cast may be redundant) [google-readability-casting]
+  // CHECK-FIXES: {{^}}  static_cast<Typedef2>(t1);
+  (const char*)t1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed
+  // CHECK-FIXES: {{^}}  static_cast<const char*>(t1);
+  (Typedef1)cpc;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed
+  // CHECK-FIXES: {{^}}  static_cast<Typedef1>(cpc);
+  (Typedef1)t1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant cast to the same type
+  // CHECK-FIXES: {{^}}  t1;
+
+  char *pc = (char*)cpc;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use const_cast [google-readability-casting]
+  // CHECK-FIXES: char *pc = const_cast<char*>(cpc);
+  typedef char Char;
+  Char *pChar = (Char*)pc;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}}; use static_cast (if needed
+  // CHECK-FIXES: {{^}}  Char *pChar = static_cast<Char*>(pc);
+
+  (Char)*cpc;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed
+  // CHECK-FIXES: {{^}}  static_cast<Char>(*cpc);
+
+  (char)*pChar;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed
+  // CHECK-FIXES: {{^}}  static_cast<char>(*pChar);
+
+  (const char*)cpv;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast [
+  // CHECK-FIXES: static_cast<const char*>(cpv);
+
+  char *pc2 = (char*)(cpc + 33);
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}}; use const_cast [
+  // CHECK-FIXES: char *pc2 = const_cast<char*>(cpc + 33);
+
+  const char &crc = *cpc;
+  char &rc = (char&)crc;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}}; use const_cast [
+  // CHECK-FIXES: char &rc = const_cast<char&>(crc);
+
+  char &rc2 = (char&)*cpc;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}}; use const_cast [
+  // CHECK-FIXES: char &rc2 = const_cast<char&>(*cpc);
+
+  char ** const* const* ppcpcpc;
+  char ****ppppc = (char****)ppcpcpc;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: {{.*}}; use const_cast [
+  // CHECK-FIXES: char ****ppppc = const_cast<char****>(ppcpcpc);
+
+  char ***pppc = (char***)*(ppcpcpc);
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: {{.*}}; use const_cast [
+  // CHECK-FIXES: char ***pppc = const_cast<char***>(*(ppcpcpc));
+
+  char ***pppc2 = (char***)(*ppcpcpc);
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: {{.*}}; use const_cast [
+  // CHECK-FIXES: char ***pppc2 = const_cast<char***>(*ppcpcpc);
+
+  char *pc5 = (char*)(const char*)(cpv);
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}}; use const_cast [
+  // CHECK-MESSAGES: :[[@LINE-2]]:22: warning: {{.*}}; use static_cast [
+  // CHECK-FIXES: char *pc5 = const_cast<char*>(static_cast<const char*>(cpv));
+
+  int b1 = (int)b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}}; use static_cast [
+  // CHECK-FIXES: int b1 = static_cast<int>(b);
+  b1 = (const int&)b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [
+  // CHECK-FIXES: b1 = (const int&)b;
+
+  b1 = (int) b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}}
+  // CHECK-FIXES: b1 = static_cast<int>(b);
+
+  b1 = (int)         b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}}
+  // CHECK-FIXES: b1 = static_cast<int>(b);
+
+  b1 = (int) (b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}}
+  // CHECK-FIXES: b1 = static_cast<int>(b);
+
+  b1 = (int)         (b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}}
+  // CHECK-FIXES: b1 = static_cast<int>(b);
+
+  Y *pB = (Y*)pX;
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [
+  Y &rB = (Y&)*pX;
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [
+
+  const char *pc3 = (const char*)cpv;
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}}; use static_cast [
+  // CHECK-FIXES: const char *pc3 = static_cast<const char*>(cpv);
+
+  char *pc4 = (char*)cpv;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [
+  // CHECK-FIXES: char *pc4 = (char*)cpv;
+
+  b1 = (int)Enum1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast [
+  // CHECK-FIXES: b1 = static_cast<int>(Enum1);
+
+  Enum e = (Enum)b1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}}; use static_cast [
+  // CHECK-FIXES: Enum e = static_cast<Enum>(b1);
+
+  e = (Enum)Enum1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type
+  // CHECK-FIXES: {{^}}  e = Enum1;
+
+  e = (Enum)e;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type
+  // CHECK-FIXES: {{^}}  e = e;
+
+  e = (Enum)           e;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type
+  // CHECK-FIXES: {{^}}  e = e;
+
+  e = (Enum)           (e);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type
+  // CHECK-FIXES: {{^}}  e = (e);
+
+  static const int kZero = 0;
+  (int)kZero;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant cast to the same type
+  // CHECK-FIXES: {{^}}  kZero;
+
+  int b2 = int(b);
+  int b3 = static_cast<double>(b);
+  int b4 = b;
+  double aa = a;
+  (void)b2;
+  return (void)g();
+}
+
+template <typename T>
+void template_function(T t, int n) {
+  int i = (int)t;
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [
+  // CHECK-FIXES: int i = (int)t;
+  int j = (int)n;
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant cast to the same type
+  // CHECK-FIXES: int j = n;
+}
+
+template <typename T>
+struct TemplateStruct {
+  void f(T t, int n) {
+    int k = (int)t;
+    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast
+    // CHECK-FIXES: int k = (int)t;
+    int l = (int)n;
+    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant cast to the same type
+    // CHECK-FIXES: int l = n;
+  }
+};
+
+void test_templates() {
+  template_function(1, 42);
+  template_function(1.0, 42);
+  TemplateStruct<int>().f(1, 42);
+  TemplateStruct<double>().f(1.0, 42);
+}
+
+extern "C" {
+void extern_c_code(const char *cpc) {
+  const char *cpc2 = (const char*)cpc;
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant cast to the same type
+  // CHECK-FIXES: const char *cpc2 = cpc;
+  char *pc = (char*)cpc;
+}
+}
+
+#define CAST(type, value) (type)(value)
+void macros(double d) {
+  int i = CAST(int, d);
+}
+
+enum E { E1 = 1 };
+template <E e>
+struct A {
+  // Usage of template argument e = E1 is represented as (E)1 in the AST for
+  // some reason. We have a special treatment of this case to avoid warnings
+  // here.
+  static const E ee = e;
+};
+struct B : public A<E1> {};
+
+
+void overloaded_function();
+void overloaded_function(int);
+
+template<typename Fn>
+void g(Fn fn) {
+  fn();
+}
+
+void function_casts() {
+  typedef void (*FnPtrVoid)();
+  typedef void (&FnRefVoid)();
+  typedef void (&FnRefInt)(int);
+
+  g((void (*)())overloaded_function);
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: g(static_cast<void (*)()>(overloaded_function));
+  g((void (*)())&overloaded_function);
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: g(static_cast<void (*)()>(&overloaded_function));
+  g((void (&)())overloaded_function);
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: g(static_cast<void (&)()>(overloaded_function));
+
+  g((FnPtrVoid)overloaded_function);
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: g(static_cast<FnPtrVoid>(overloaded_function));
+  g((FnPtrVoid)&overloaded_function);
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: g(static_cast<FnPtrVoid>(&overloaded_function));
+  g((FnRefVoid)overloaded_function);
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: g(static_cast<FnRefVoid>(overloaded_function));
+
+  FnPtrVoid fn0 = (void (*)())&overloaded_function;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: FnPtrVoid fn0 = static_cast<void (*)()>(&overloaded_function);
+  FnPtrVoid fn1 = (void (*)())overloaded_function;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: FnPtrVoid fn1 = static_cast<void (*)()>(overloaded_function);
+  FnPtrVoid fn1a = (FnPtrVoid)overloaded_function;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: FnPtrVoid fn1a = static_cast<FnPtrVoid>(overloaded_function);
+  FnRefInt fn2 = (void (&)(int))overloaded_function;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: FnRefInt fn2 = static_cast<void (&)(int)>(overloaded_function);
+  auto fn3 = (void (*)())&overloaded_function;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: auto fn3 = static_cast<void (*)()>(&overloaded_function);
+  auto fn4 = (void (*)())overloaded_function;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: auto fn4 = static_cast<void (*)()>(overloaded_function);
+  auto fn5 = (void (&)(int))overloaded_function;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: auto fn5 = static_cast<void (&)(int)>(overloaded_function);
+
+  void (*fn6)() = (void (*)())&overloaded_function;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: void (*fn6)() = static_cast<void (*)()>(&overloaded_function);
+  void (*fn7)() = (void (*)())overloaded_function;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: void (*fn7)() = static_cast<void (*)()>(overloaded_function);
+  void (*fn8)() = (FnPtrVoid)overloaded_function;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: void (*fn8)() = static_cast<FnPtrVoid>(overloaded_function);
+  void (&fn9)(int) = (void (&)(int))overloaded_function;
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: void (&fn9)(int) = static_cast<void (&)(int)>(overloaded_function);
+
+  void (*correct1)() = static_cast<void (*)()>(overloaded_function);
+  FnPtrVoid correct2 = static_cast<void (*)()>(&overloaded_function);
+  FnRefInt correct3 = static_cast<void (&)(int)>(overloaded_function);
+}
+
+struct S {
+    S(const char *);
+};
+struct ConvertibleToS {
+  operator S() const;
+};
+struct ConvertibleToSRef {
+  operator const S&() const;
+};
+
+void conversions() {
+  //auto s1 = (const S&)"";
+  // C HECK-MESSAGES: :[[@LINE-1]]:10: warning: C-style casts are discouraged; use static_cast [
+  // C HECK-FIXES: S s1 = static_cast<const S&>("");
+  auto s2 = (S)"";
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use constructor call syntax [
+  // CHECK-FIXES: auto s2 = S("");
+  auto s2a = (struct S)"";
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [
+  // CHECK-FIXES: auto s2a = static_cast<struct S>("");
+  auto s2b = (const S)"";
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [
+  // FIXME: This should be constructor call syntax: S("").
+  // CHECK-FIXES: auto s2b = static_cast<const S>("");
+  ConvertibleToS c;
+  auto s3 = (const S&)c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use static_cast/const_cast/reinterpret_cast [
+  // CHECK-FIXES: auto s3 = (const S&)c;
+  // FIXME: This should be a static_cast.
+  // C HECK-FIXES: auto s3 = static_cast<const S&>(c);
+  auto s4 = (S)c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use constructor call syntax [
+  // CHECK-FIXES: auto s4 = S(c);
+  ConvertibleToSRef cr;
+  auto s5 = (const S&)cr;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use static_cast/const_cast/reinterpret_cast [
+  // CHECK-FIXES: auto s5 = (const S&)cr;
+  // FIXME: This should be a static_cast.
+  // C HECK-FIXES: auto s5 = static_cast<const S&>(cr);
+  auto s6 = (S)cr;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use constructor call syntax [
+  // CHECK-FIXES: auto s6 = S(cr);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.mm b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.mm
new file mode 100644
index 0000000..b987dc2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-casting.mm
@@ -0,0 +1,179 @@
+// RUN: clang-tidy %s -checks=-*,google-readability-casting -- \
+// RUN:   -xobjective-c++ -fobjc-abi-version=2 -fobjc-arc | count 0
+
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+
+bool g() { return false; }
+
+enum Enum { Enum1 };
+struct X {};
+struct Y : public X {};
+
+void f(int a, double b, const char *cpc, const void *cpv, X *pX) {
+
+  typedef const char *Typedef1;
+  typedef const char *Typedef2;
+  Typedef1 t1;
+  (Typedef2)t1;
+  (const char*)t1;
+  (Typedef1)cpc;
+
+  typedef char Char;
+  char *pc;
+  Char *pChar = (Char*)pc;
+
+  (Char)*cpc;
+
+  (char)*pChar;
+
+  (const char*)cpv;
+
+  char *pc2 = (char*)(cpc + 33);
+
+  const char &crc = *cpc;
+  char &rc = (char&)crc;
+
+  char &rc2 = (char&)*cpc;
+
+  char ** const* const* ppcpcpc;
+  char ****ppppc = (char****)ppcpcpc;
+
+  char ***pppc = (char***)*(ppcpcpc);
+
+  char ***pppc2 = (char***)(*ppcpcpc);
+
+  char *pc5 = (char*)(const char*)(cpv);
+
+  int b1 = (int)b;
+  b1 = (const int&)b;
+
+  b1 = (int) b;
+
+  b1 = (int)         b;
+
+  b1 = (int) (b);
+
+  b1 = (int)         (b);
+
+  Y *pB = (Y*)pX;
+  Y &rB = (Y&)*pX;
+
+  const char *pc3 = (const char*)cpv;
+
+  char *pc4 = (char*)cpv;
+
+  b1 = (int)Enum1;
+
+  Enum e = (Enum)b1;
+
+  int b2 = int(b);
+  int b3 = static_cast<double>(b);
+  int b4 = b;
+  double aa = a;
+  (void)b2;
+  return (void)g();
+}
+
+template <typename T>
+void template_function(T t, int n) {
+  int i = (int)t;
+}
+
+template <typename T>
+struct TemplateStruct {
+  void f(T t, int n) {
+    int k = (int)t;
+  }
+};
+
+void test_templates() {
+  template_function(1, 42);
+  template_function(1.0, 42);
+  TemplateStruct<int>().f(1, 42);
+  TemplateStruct<double>().f(1.0, 42);
+}
+
+extern "C" {
+void extern_c_code(const char *cpc) {
+  char *pc = (char*)cpc;
+}
+}
+
+#define CAST(type, value) (type)(value)
+void macros(double d) {
+  int i = CAST(int, d);
+}
+
+enum E { E1 = 1 };
+template <E e>
+struct A {
+  // Usage of template argument e = E1 is represented as (E)1 in the AST for
+  // some reason. We have a special treatment of this case to avoid warnings
+  // here.
+  static const E ee = e;
+};
+struct B : public A<E1> {};
+
+
+void overloaded_function();
+void overloaded_function(int);
+
+template<typename Fn>
+void g(Fn fn) {
+  fn();
+}
+
+void function_casts() {
+  typedef void (*FnPtrVoid)();
+  typedef void (&FnRefVoid)();
+  typedef void (&FnRefInt)(int);
+
+  g((void (*)())overloaded_function);
+  g((void (*)())&overloaded_function);
+  g((void (&)())overloaded_function);
+
+  g((FnPtrVoid)overloaded_function);
+  g((FnPtrVoid)&overloaded_function);
+  g((FnRefVoid)overloaded_function);
+
+  FnPtrVoid fn0 = (void (*)())&overloaded_function;
+  FnPtrVoid fn1 = (void (*)())overloaded_function;
+  FnPtrVoid fn1a = (FnPtrVoid)overloaded_function;
+  FnRefInt fn2 = (void (&)(int))overloaded_function;
+  auto fn3 = (void (*)())&overloaded_function;
+  auto fn4 = (void (*)())overloaded_function;
+  auto fn5 = (void (&)(int))overloaded_function;
+
+  void (*fn6)() = (void (*)())&overloaded_function;
+  void (*fn7)() = (void (*)())overloaded_function;
+  void (*fn8)() = (FnPtrVoid)overloaded_function;
+  void (&fn9)(int) = (void (&)(int))overloaded_function;
+
+  void (*correct1)() = static_cast<void (*)()>(overloaded_function);
+  FnPtrVoid correct2 = static_cast<void (*)()>(&overloaded_function);
+  FnRefInt correct3 = static_cast<void (&)(int)>(overloaded_function);
+}
+
+struct S {
+    S(const char *);
+};
+struct ConvertibleToS {
+  operator S() const;
+};
+struct ConvertibleToSRef {
+  operator const S&() const;
+};
+
+void conversions() {
+  //auto s1 = (const S&)"";
+  auto s2 = (S)"";
+  auto s2a = (struct S)"";
+  auto s2b = (const S)"";
+  ConvertibleToS c;
+  auto s3 = (const S&)c;
+  auto s4 = (S)c;
+  ConvertibleToSRef cr;
+  auto s5 = (const S&)cr;
+  auto s6 = (S)cr;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-namespace-comments.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-namespace-comments.cpp
new file mode 100644
index 0000000..9abb984
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-namespace-comments.cpp
@@ -0,0 +1,54 @@
+// RUN: %check_clang_tidy %s google-readability-namespace-comments %t
+
+namespace n1 {
+namespace n2 {
+
+
+void f(); // So that the namespace isn't empty.
+
+
+// CHECK-MESSAGES: :[[@LINE+4]]:2: warning: namespace 'n2' not terminated with a closing comment [google-readability-namespace-comments]
+// CHECK-MESSAGES: :[[@LINE-7]]:11: note: namespace 'n2' starts here
+// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: namespace 'n1' not terminated with
+// CHECK-MESSAGES: :[[@LINE-10]]:11: note: namespace 'n1' starts here
+}}
+// CHECK-FIXES: }  // namespace n2
+// CHECK-FIXES: }  // namespace n1
+
+#define MACRO macro_expansion
+namespace MACRO {
+void f(); // So that the namespace isn't empty.
+// 1
+// 2
+// 3
+// 4
+// 5
+// 6
+// 7
+// CHECK-MESSAGES: :[[@LINE+2]]:2: warning: namespace 'macro_expansion' not terminated with
+// CHECK-MESSAGES: :[[@LINE-10]]:11: note: namespace 'macro_expansion' starts here
+}
+// CHECK-FIXES: }  // namespace macro_expansion
+
+namespace short1 {
+namespace short2 {
+// Namespaces covering 10 lines or fewer are exempt from this rule.
+
+
+
+
+
+}
+}
+
+namespace n3 {
+
+
+
+
+
+
+
+
+
+}; // namespace n3
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-nested-namespace-comments.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-nested-namespace-comments.cpp
new file mode 100644
index 0000000..d7765c6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-nested-namespace-comments.cpp
@@ -0,0 +1,17 @@
+// RUN: %check_clang_tidy %s google-readability-namespace-comments %t
+
+namespace n1::n2 {
+namespace n3 {
+
+// So that namespace is not empty.
+void f();
+
+
+// CHECK-MESSAGES: :[[@LINE+4]]:2: warning: namespace 'n3' not terminated with
+// CHECK-MESSAGES: :[[@LINE-7]]:11: note: namespace 'n3' starts here
+// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: namespace 'n1::n2' not terminated with a closing comment [google-readability-namespace-comments]
+// CHECK-MESSAGES: :[[@LINE-10]]:11: note: namespace 'n1::n2' starts here
+}}
+// CHECK-FIXES: }  // namespace n3
+// CHECK-FIXES: }  // namespace n1::n2
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-todo.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-todo.cpp
new file mode 100644
index 0000000..6b900aa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-readability-todo.cpp
@@ -0,0 +1,26 @@
+// RUN: %check_clang_tidy %s google-readability-todo %t -- -config="{User: 'some user'}" --
+
+//   TODOfix this1
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO
+// CHECK-FIXES: // TODO(some user): fix this1
+
+//   TODO fix this2
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO
+// CHECK-FIXES: // TODO(some user): fix this2
+
+// TODO fix this3
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO
+// CHECK-FIXES: // TODO(some user): fix this3
+
+// TODO: fix this4
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO
+// CHECK-FIXES: // TODO(some user): fix this4
+
+//   TODO(clang)fix this5
+
+// TODO(foo):shave yaks
+// TODO(bar):
+// TODO(foo): paint bikeshed
+// TODO(b/12345): find the holy grail
+// TODO (b/12345): allow spaces before parentheses
+// TODO(asdf) allow missing semicolon
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int-std.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int-std.cpp
new file mode 100644
index 0000000..c5d3112
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int-std.cpp
@@ -0,0 +1,57 @@
+// RUN: %check_clang_tidy %s google-runtime-int %t -- \
+// RUN:   -config='{CheckOptions: [ \
+// RUN:     {key: google-runtime-int.UnsignedTypePrefix, value: "std::uint"}, \
+// RUN:     {key: google-runtime-int.SignedTypePrefix, value: "std::int"}, \
+// RUN:     {key: google-runtime-int.TypeSuffix, value: "_t"}, \
+// RUN:   ]}' -- -std=c++11
+
+long a();
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: consider replacing 'long' with 'std::int{{..}}_t'
+
+typedef unsigned long long uint64; // NOLINT
+
+long b(long = 1);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: consider replacing 'long' with 'std::int{{..}}_t'
+// CHECK-MESSAGES: [[@LINE-2]]:8: warning: consider replacing 'long' with 'std::int{{..}}_t'
+
+template <typename T>
+void tmpl() {
+  T i;
+}
+
+short bar(const short, unsigned short) {
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: consider replacing 'short' with 'std::int16_t'
+// CHECK-MESSAGES: [[@LINE-2]]:17: warning: consider replacing 'short' with 'std::int16_t'
+// CHECK-MESSAGES: [[@LINE-3]]:24: warning: consider replacing 'unsigned short' with 'std::uint16_t'
+  long double foo = 42;
+  uint64 qux = 42;
+  unsigned short port;
+
+  const unsigned short bar = 0;
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: consider replacing 'unsigned short' with 'std::uint16_t'
+  long long *baar;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'long long' with 'std::int64_t'
+  const unsigned short &bara = bar;
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: consider replacing 'unsigned short' with 'std::uint16_t'
+  long const long moo = 1;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'long long' with 'std::int64_t'
+  long volatile long wat = 42;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'long long' with 'std::int64_t'
+  unsigned long y;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned long' with 'std::uint{{..}}_t'
+  unsigned long long **const *tmp;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned long long' with 'std::uint64_t'
+  unsigned long long **const *&z = tmp;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned long long' with 'std::uint64_t'
+  unsigned short porthole;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned short' with 'std::uint16_t'
+
+  uint64 cast = (short)42;
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: consider replacing 'short' with 'std::int16_t'
+
+#define l long
+  l x;
+
+  tmpl<short>();
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: consider replacing 'short' with 'std::int16_t'
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int.c
new file mode 100644
index 0000000..8657e2d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int.c
@@ -0,0 +1,27 @@
+// RUN: clang-tidy -checks=-*,google-runtime-int %s -- -x c 2>&1 | not grep 'warning:\|error:'
+
+long a();
+
+long b(long x);
+
+short bar(const short q, unsigned short w) {
+  long double foo;
+  unsigned short port;
+
+  const unsigned short bar;
+  long long *baar;
+  const unsigned short bara;
+  long const long moo;
+  long volatile long wat;
+  unsigned long y;
+  unsigned long long **const *tmp;
+  unsigned short porthole;
+
+  unsigned cast;
+  cast = (short)42;
+  return q;
+}
+
+void qux() {
+  short port;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int.cpp
new file mode 100644
index 0000000..4bb7398
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-int.cpp
@@ -0,0 +1,91 @@
+// RUN: %check_clang_tidy %s google-runtime-int %t
+
+long a();
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: consider replacing 'long' with 'int{{..}}'
+
+typedef unsigned long long uint64; // NOLINT
+
+long b(long = 1);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: consider replacing 'long' with 'int{{..}}'
+// CHECK-MESSAGES: [[@LINE-2]]:8: warning: consider replacing 'long' with 'int{{..}}'
+
+template <typename T>
+void tmpl() {
+  T i;
+}
+
+short bar(const short, unsigned short) {
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: consider replacing 'short' with 'int16'
+// CHECK-MESSAGES: [[@LINE-2]]:17: warning: consider replacing 'short' with 'int16'
+// CHECK-MESSAGES: [[@LINE-3]]:24: warning: consider replacing 'unsigned short' with 'uint16'
+  long double foo = 42;
+  uint64 qux = 42;
+  unsigned short port;
+
+  const unsigned short bar = 0;
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: consider replacing 'unsigned short' with 'uint16'
+  long long *baar;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'long long' with 'int64'
+  const unsigned short &bara = bar;
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: consider replacing 'unsigned short' with 'uint16'
+  long const long moo = 1;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'long long' with 'int64'
+  long volatile long wat = 42;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'long long' with 'int64'
+  unsigned long y;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned long' with 'uint{{..}}'
+  unsigned long long **const *tmp;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned long long' with 'uint64'
+  unsigned long long **const *&z = tmp;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned long long' with 'uint64'
+  unsigned short porthole;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'unsigned short' with 'uint16'
+
+  uint64 cast = (short)42;
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: consider replacing 'short' with 'int16'
+
+#define l long
+  l x;
+
+  tmpl<short>();
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: consider replacing 'short' with 'int16'
+  return 0;
+}
+
+void p(unsigned short port);
+
+void qux() {
+  short port;
+// CHECK-MESSAGES: [[@LINE-1]]:3: warning: consider replacing 'short' with 'int16'
+}
+
+// FIXME: This shouldn't warn, as UD-literal operators require one of a handful
+// of types as an argument.
+struct some_value {};
+constexpr some_value operator"" _some_literal(unsigned long long int i);
+// CHECK-MESSAGES: [[@LINE-1]]:47: warning: consider replacing 'unsigned long long'
+
+struct A { A& operator=(const A&); };
+class B { A a[0]; };
+
+void fff() {
+  B a, b;
+  a = b;
+}
+
+__attribute__((__format__ (__printf__, 1, 2)))
+void myprintf(const char* s, ...);
+
+void doprint_no_warning() {
+  uint64 foo = 23;
+  myprintf("foo %lu %lu", (unsigned long)42, (unsigned long)foo);
+}
+
+void myprintf_no_attribute(const char* s, ...);
+
+void doprint_warning() {
+  uint64 foo = 23;
+  myprintf_no_attribute("foo %lu %lu", (unsigned long)42, (unsigned long)foo);
+// CHECK-MESSAGES: [[@LINE-1]]:41: warning: consider replacing 'unsigned long'
+// CHECK-MESSAGES: [[@LINE-2]]:60: warning: consider replacing 'unsigned long'
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-references.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-references.cpp
new file mode 100644
index 0000000..b9f84b6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/google-runtime-references.cpp
@@ -0,0 +1,152 @@
+// RUN: %check_clang_tidy %s google-runtime-references %t -- \
+// RUN:   -extra-arg="-std=c++11" \
+// RUN:   -config="{CheckOptions: \
+// RUN:             [{key: google-runtime-references.WhiteListTypes, \
+// RUN:               value: 'whitelist::A; whitelist::B'}]}" --
+
+int a;
+int &b = a;
+int *c;
+void f1(int a);
+void f2(int *b);
+void f3(const int &c);
+void f4(int const &d);
+
+// Don't warn on implicit operator= in c++11 mode.
+class A {
+  virtual void f() {}
+};
+// Don't warn on rvalue-references.
+struct A2 {
+  A2(A2&&) = default;
+  void f(A2&&) {}
+};
+
+// Don't warn on iostream parameters.
+namespace xxx {
+class istream { };
+class ostringstream { };
+}
+void g1(xxx::istream &istr);
+void g1(xxx::ostringstream &istr);
+
+void g1(int &a);
+// CHECK-MESSAGES: [[@LINE-1]]:14: warning: non-const reference parameter 'a', make it const or use a pointer [google-runtime-references]
+
+struct s {};
+void g2(int a, int b, s c, s &d);
+// CHECK-MESSAGES: [[@LINE-1]]:31: warning: non-const reference parameter 'd', {{.*}}
+
+typedef int &ref;
+void g3(ref a);
+// CHECK-MESSAGES: [[@LINE-1]]:13: warning: non-const reference {{.*}}
+
+void g4(int &a, int &b, int &);
+// CHECK-MESSAGES: [[@LINE-1]]:14: warning: non-const reference parameter 'a', {{.*}}
+// CHECK-MESSAGES: [[@LINE-2]]:22: warning: non-const reference parameter 'b', {{.*}}
+// CHECK-MESSAGES: [[@LINE-3]]:30: warning: non-const reference parameter at index 2, {{.*}}
+
+class B {
+  B(B& a) {}
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: non-const reference {{.*}}
+  virtual void f(int &a) {}
+// CHECK-MESSAGES: [[@LINE-1]]:23: warning: non-const reference {{.*}}
+  void g(int &b);
+// CHECK-MESSAGES: [[@LINE-1]]:15: warning: non-const reference {{.*}}
+
+  // Don't warn on the parameter of stream extractors defined as members.
+  B& operator>>(int& val) { return *this; }
+};
+
+// Only warn on the first declaration of each function to reduce duplicate
+// warnings.
+void B::g(int &b) {}
+
+// Don't warn on the first parameter of stream inserters.
+A& operator<<(A& s, int&) { return s; }
+// CHECK-MESSAGES: [[@LINE-1]]:25: warning: non-const reference parameter at index 1, {{.*}}
+
+// Don't warn on either parameter of stream extractors. Both need to be
+// non-const references by convention.
+A& operator>>(A& input, int& val) { return input; }
+
+// Don't warn on lambdas.
+auto lambda = [] (int&) {};
+
+// Don't warn on typedefs, as we'll warn on the function itself.
+typedef int (*fp)(int &);
+
+// Don't warn on function references.
+typedef void F();
+void g5(const F& func) {}
+void g6(F& func) {}
+
+template<typename T>
+void g7(const T& t) {}
+
+template<typename T>
+void g8(T t) {}
+
+void f5() {
+  g5(f5);
+  g6(f5);
+  g7(f5);
+  g7<F&>(f5);
+  g8(f5);
+  g8<F&>(f5);
+}
+
+// Don't warn on dependent types.
+template<typename T>
+void g9(T& t) {}
+template<typename T>
+void g10(T t) {}
+
+void f6() {
+  int i;
+  float f;
+  g9<int>(i);
+  g9<const int>(i);
+  g9<int&>(i);
+  g10<int&>(i);
+  g10<float&>(f);
+}
+
+// Warn only on the overridden methods from the base class, as the child class
+// only implements the interface.
+class C : public B {
+  C();
+  virtual void f(int &a) {}
+};
+
+// Don't warn on operator<< with streams-like interface.
+A& operator<<(A& s, int) { return s; }
+
+// Don't warn on swap().
+void swap(C& c1, C& c2) {}
+
+// Don't warn on standalone operator++, operator--, operator+=, operator-=,
+// operator*=, etc. that all need non-const references to be functional.
+A& operator++(A& a) { return a; }
+A operator++(A& a, int) { return a; }
+A& operator--(A& a) { return a; }
+A operator--(A& a, int) { return a; }
+A& operator+=(A& a, const A& b) { return a; }
+A& operator-=(A& a, const A& b) { return a; }
+A& operator*=(A& a, const A& b) { return a; }
+A& operator/=(A& a, const A& b) { return a; }
+A& operator%=(A& a, const A& b) { return a; }
+A& operator<<=(A& a, const A& b) { return a; }
+A& operator>>=(A& a, const A& b) { return a; }
+A& operator|=(A& a, const A& b) { return a; }
+A& operator^=(A& a, const A& b) { return a; }
+A& operator&=(A& a, const A& b) { return a; }
+
+namespace whitelist {
+class A {};
+class B {};
+void f7(A &);
+void f8(B &);
+}
+void f9(whitelist::A &);
+void f10(whitelist::B &);
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-exception-baseclass.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-exception-baseclass.cpp
new file mode 100644
index 0000000..9a0638b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-exception-baseclass.cpp
@@ -0,0 +1,179 @@
+// RUN: %check_clang_tidy %s hicpp-exception-baseclass %t -- -- -fcxx-exceptions
+
+namespace std {
+class exception {};
+} // namespace std
+
+class derived_exception : public std::exception {};
+class deep_hierarchy : public derived_exception {};
+class non_derived_exception {};
+class terrible_idea : public non_derived_exception, public derived_exception {};
+
+// FIXME: More complicated kinds of inheritance should be checked later, but there is
+// currently no way use ASTMatchers for this kind of task.
+#if 0
+class bad_inheritance : private std::exception {};
+class no_good_inheritance : protected std::exception {};
+class really_creative : public non_derived_exception, private std::exception {};
+#endif
+
+void problematic() {
+  try {
+    throw int(42);
+    // CHECK-MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+  } catch (int e) {
+  }
+  throw int(42);
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+
+  try {
+    throw 12;
+    // CHECK-MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+  } catch (...) {
+    throw; // Ok, even if the type is not known, conforming code can never rethrow a non-std::exception object.
+  }
+
+  try {
+    throw non_derived_exception();
+    // CHECK-MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
+    // CHECK-MESSAGES: 9:1: note: type defined here
+  } catch (non_derived_exception &e) {
+  }
+  throw non_derived_exception();
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
+  // CHECK-MESSAGES: 9:1: note: type defined here
+
+// FIXME: More complicated kinds of inheritance should be checked later, but there is
+// currently no way use ASTMatchers for this kind of task.
+#if 0
+  // Handle private inheritance cases correctly.
+  try {
+    throw bad_inheritance();
+    // CHECK MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'bad_inheritance' is not derived from 'std::exception'
+    // CHECK MESSAGES: 10:1: note: type defined here
+    throw no_good_inheritance();
+    // CHECK MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'no_good_inheritance' is not derived from 'std::exception'
+    // CHECK MESSAGES: 11:1: note: type defined here
+    throw really_creative();
+    // CHECK MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'really_creative' is not derived from 'std::exception'
+    // CHECK MESSAGES: 12:1: note: type defined here
+  } catch (...) {
+  }
+  throw bad_inheritance();
+  // CHECK MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_inheritance' is not derived from 'std::exception'
+  // CHECK MESSAGES: 10:1: note: type defined here
+  throw no_good_inheritance();
+  // CHECK MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'no_good_inheritance' is not derived from 'std::exception'
+  // CHECK MESSAGES: 11:1: note: type defined here
+  throw really_creative();
+  // CHECK MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'really_creative' is not derived from 'std::exception'
+  // CHECK MESSAGES: 12:1: note: type defined here
+#endif
+}
+
+void allowed_throws() {
+  try {
+    throw std::exception();     // Ok
+  } catch (std::exception &e) { // Ok
+  }
+  throw std::exception();
+
+  try {
+    throw derived_exception();     // Ok
+  } catch (derived_exception &e) { // Ok
+  }
+  throw derived_exception(); // Ok
+
+  try {
+    throw deep_hierarchy();     // Ok, multiple levels of inheritance
+  } catch (deep_hierarchy &e) { // Ok
+  }
+  throw deep_hierarchy(); // Ok
+
+  try {
+    throw terrible_idea();     // Ok, but multiple inheritance isn't clean
+  } catch (std::exception &e) { // Can be caught as std::exception, even with multiple inheritance
+  }
+  throw terrible_idea(); // Ok, but multiple inheritance
+}
+
+// Templated function that throws exception based on template type
+template <typename T>
+void ThrowException() { throw T(); }
+// CHECK-MESSAGES: [[@LINE-1]]:31: warning: throwing an exception whose type 'bad_generic_exception<int>' is not derived from 'std::exception'
+// CHECK-MESSAGES: 120:1: note: type defined here
+// CHECK-MESSAGES: [[@LINE-3]]:31: warning: throwing an exception whose type 'bad_generic_exception<std::exception>' is not derived from 'std::exception'
+// CHECK-MESSAGES: 120:1: note: type defined here
+// CHECK-MESSAGES: [[@LINE-5]]:31: warning: throwing an exception whose type 'exotic_exception<non_derived_exception>' is not derived from 'std::exception'
+// CHECK-MESSAGES: 123:1: note: type defined here
+// CHECK-MESSAGES: [[@LINE-7]]:31: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+// CHECK-MESSAGES: [[@LINE-8]]:31: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
+// CHECK-MESSAGES: 9:1: note: type defined here
+#define THROW_EXCEPTION(CLASS) ThrowException<CLASS>()
+#define THROW_BAD_EXCEPTION throw int(42);
+#define THROW_GOOD_EXCEPTION throw std::exception();
+#define THROW_DERIVED_EXCEPTION throw deep_hierarchy();
+
+template <typename T>
+class generic_exception : std::exception {};
+
+template <typename T>
+class bad_generic_exception {};
+
+template <typename T>
+class exotic_exception : public T {};
+
+void generic_exceptions() {
+  THROW_EXCEPTION(int);
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+  THROW_EXCEPTION(non_derived_exception);
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
+  // CHECK MESSAGES: 9:1: note: type defined here
+  THROW_EXCEPTION(std::exception);    // Ok
+  THROW_EXCEPTION(derived_exception); // Ok
+  THROW_EXCEPTION(deep_hierarchy);    // Ok
+
+  THROW_BAD_EXCEPTION;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+  // CHECK-MESSAGES: [[@LINE-25]]:35: note: expanded from macro 'THROW_BAD_EXCEPTION'
+  THROW_GOOD_EXCEPTION;
+  THROW_DERIVED_EXCEPTION;
+
+  throw generic_exception<int>();            // Ok,
+  THROW_EXCEPTION(generic_exception<float>); // Ok
+
+  throw bad_generic_exception<int>();
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_generic_exception<int>' is not derived from 'std::exception'
+  throw bad_generic_exception<std::exception>();
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_generic_exception<std::exception>' is not derived from 'std::exception'
+  THROW_EXCEPTION(bad_generic_exception<int>);
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'bad_generic_exception<int>' is not derived from 'std::exception'
+  THROW_EXCEPTION(bad_generic_exception<std::exception>);
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'bad_generic_exception<std::exception>' is not derived from 'std::exception'
+
+  throw exotic_exception<non_derived_exception>();
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'exotic_exception<non_derived_exception>' is not derived from 'std::exception'
+  THROW_EXCEPTION(exotic_exception<non_derived_exception>);
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'exotic_exception<non_derived_exception>' is not derived from 'std::exception'
+
+  throw exotic_exception<derived_exception>();          // Ok
+  THROW_EXCEPTION(exotic_exception<derived_exception>); // Ok
+}
+
+// Test for typedefed exception types
+typedef int TypedefedBad;
+typedef derived_exception TypedefedGood;
+using UsingBad = int;
+using UsingGood = deep_hierarchy;
+
+void typedefed() {
+  throw TypedefedBad();
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'TypedefedBad' (aka 'int') is not derived from 'std::exception'
+  // CHECK-MESSAGES: 164:1: note: type defined here
+  throw TypedefedGood(); // Ok
+
+  throw UsingBad();
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'UsingBad' (aka 'int') is not derived from 'std::exception'
+  // CHECK-MESSAGES: 166:1: note: type defined here
+  throw UsingGood(); // Ok
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-multiway-paths-covered-else.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-multiway-paths-covered-else.cpp
new file mode 100644
index 0000000..34820b5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-multiway-paths-covered-else.cpp
@@ -0,0 +1,57 @@
+// RUN: %check_clang_tidy %s hicpp-multiway-paths-covered %t \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: hicpp-multiway-paths-covered.WarnOnMissingElse, value: 1}]}'\
+// RUN: --
+
+enum OS { Mac,
+          Windows,
+          Linux };
+
+void problematic_if(int i, enum OS os) {
+  if (i > 0) {
+    return;
+  } else if (i < 0) {
+    // CHECK-MESSAGES: [[@LINE-1]]:10: warning: potentially uncovered codepath; add an ending else statement
+    return;
+  }
+
+  // Could be considered as false positive because all paths are covered logically.
+  // I still think this is valid since the possibility of a final 'everything else'
+  // codepath is expected from if-else if.
+  if (i > 0) {
+    return;
+  } else if (i <= 0) {
+    // CHECK-MESSAGES: [[@LINE-1]]:10: warning: potentially uncovered codepath; add an ending else statement
+    return;
+  }
+
+  // Test if nesting of if-else chains does get caught as well.
+  if (os == Mac) {
+    return;
+  } else if (os == Linux) {
+    // These checks are kind of degenerated, but the check will not try to solve
+    // if logically all paths are covered, which is more the area of the static analyzer.
+    if (true) {
+      return;
+    } else if (false) {
+      // CHECK-MESSAGES: [[@LINE-1]]:12: warning: potentially uncovered codepath; add an ending else statement
+      return;
+    }
+    return;
+  } else {
+    /* unreachable */
+    if (true) // check if the parent would match here as well
+      return;
+    // No warning for simple if statements, since it is common to just test one condition
+    // and ignore the opposite.
+  }
+
+  // Ok, because all paths are covered
+  if (i > 0) {
+    return;
+  } else if (i < 0) {
+    return;
+  } else {
+    /* error, maybe precondition failed */
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-multiway-paths-covered.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-multiway-paths-covered.cpp
new file mode 100644
index 0000000..15a3407
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-multiway-paths-covered.cpp
@@ -0,0 +1,468 @@
+// RUN: %check_clang_tidy %s hicpp-multiway-paths-covered %t
+
+enum OS { Mac,
+          Windows,
+          Linux };
+
+struct Bitfields {
+  unsigned UInt : 3;
+  int SInt : 1;
+};
+
+int return_integer() { return 42; }
+
+void bad_switch(int i) {
+  switch (i) {
+    // CHECK-MESSAGES: [[@LINE-1]]:3: warning: switch with only one case; use an if statement
+  case 0:
+    break;
+  }
+  // No default in this switch
+  switch (i) {
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: potential uncovered code path; add a default label
+  case 0:
+    break;
+  case 1:
+    break;
+  case 2:
+    break;
+  }
+
+  // degenerate, maybe even warning
+  switch (i) {
+    // CHECK-MESSAGES: [[@LINE-1]]:3: warning: switch statement without labels has no effect
+  }
+
+  switch (int j = return_integer()) {
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: potential uncovered code path; add a default label
+  case 0:
+  case 1:
+  case 2:
+    break;
+  }
+
+  // Degenerated, only default case.
+  switch (i) {
+    // CHECK-MESSAGES: [[@LINE-1]]:3: warning: degenerated switch with default label only
+  default:
+    break;
+  }
+
+  // Degenerated, only one case label and default case -> Better as if-stmt.
+  switch (i) {
+    // CHECK-MESSAGES: [[@LINE-1]]:3: warning: switch could be better written as an if/else statement
+  case 0:
+    break;
+  default:
+    break;
+  }
+
+  unsigned long long BigNumber = 0;
+  switch (BigNumber) {
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: potential uncovered code path; add a default label
+  case 0:
+  case 1:
+    break;
+  }
+
+  const int &IntRef = i;
+  switch (IntRef) {
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: potential uncovered code path; add a default label
+  case 0:
+  case 1:
+    break;
+  }
+
+  char C = 'A';
+  switch (C) {
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: potential uncovered code path; add a default label
+  case 'A':
+    break;
+  case 'B':
+    break;
+  }
+
+  Bitfields Bf;
+  // UInt has 3 bits size.
+  switch (Bf.UInt) {
+    // CHECK-MESSAGES: [[@LINE-1]]:3: warning: potential uncovered code path; add a default label
+  case 0:
+  case 1:
+    break;
+  }
+  // All paths explicitly covered.
+  switch (Bf.UInt) {
+  case 0:
+  case 1:
+  case 2:
+  case 3:
+  case 4:
+  case 5:
+  case 6:
+  case 7:
+    break;
+  }
+  // SInt has 1 bit size, so this is somewhat degenerated.
+  switch (Bf.SInt) {
+    // CHECK-MESSAGES: [[@LINE-1]]:3: warning: switch with only one case; use an if statement
+  case 0:
+    break;
+  }
+  // All paths explicitly covered.
+  switch (Bf.SInt) {
+  case 0:
+  case 1:
+    break;
+  }
+
+  bool Flag = false;
+  switch (Flag) {
+    // CHECK-MESSAGES:[[@LINE-1]]:3: warning: switch with only one case; use an if statement
+  case true:
+    break;
+  }
+
+  switch (Flag) {
+    // CHECK-MESSAGES: [[@LINE-1]]:3: warning: degenerated switch with default label only
+  default:
+    break;
+  }
+
+  // This `switch` will create a frontend warning from '-Wswitch-bool' but is
+  // ok for this check.
+  switch (Flag) {
+  case true:
+    break;
+  case false:
+    break;
+  }
+}
+
+void unproblematic_switch(unsigned char c) {
+  //
+  switch (c) {
+  case 0:
+  case 1:
+  case 2:
+  case 3:
+  case 4:
+  case 5:
+  case 6:
+  case 7:
+  case 8:
+  case 9:
+  case 10:
+  case 11:
+  case 12:
+  case 13:
+  case 14:
+  case 15:
+  case 16:
+  case 17:
+  case 18:
+  case 19:
+  case 20:
+  case 21:
+  case 22:
+  case 23:
+  case 24:
+  case 25:
+  case 26:
+  case 27:
+  case 28:
+  case 29:
+  case 30:
+  case 31:
+  case 32:
+  case 33:
+  case 34:
+  case 35:
+  case 36:
+  case 37:
+  case 38:
+  case 39:
+  case 40:
+  case 41:
+  case 42:
+  case 43:
+  case 44:
+  case 45:
+  case 46:
+  case 47:
+  case 48:
+  case 49:
+  case 50:
+  case 51:
+  case 52:
+  case 53:
+  case 54:
+  case 55:
+  case 56:
+  case 57:
+  case 58:
+  case 59:
+  case 60:
+  case 61:
+  case 62:
+  case 63:
+  case 64:
+  case 65:
+  case 66:
+  case 67:
+  case 68:
+  case 69:
+  case 70:
+  case 71:
+  case 72:
+  case 73:
+  case 74:
+  case 75:
+  case 76:
+  case 77:
+  case 78:
+  case 79:
+  case 80:
+  case 81:
+  case 82:
+  case 83:
+  case 84:
+  case 85:
+  case 86:
+  case 87:
+  case 88:
+  case 89:
+  case 90:
+  case 91:
+  case 92:
+  case 93:
+  case 94:
+  case 95:
+  case 96:
+  case 97:
+  case 98:
+  case 99:
+  case 100:
+  case 101:
+  case 102:
+  case 103:
+  case 104:
+  case 105:
+  case 106:
+  case 107:
+  case 108:
+  case 109:
+  case 110:
+  case 111:
+  case 112:
+  case 113:
+  case 114:
+  case 115:
+  case 116:
+  case 117:
+  case 118:
+  case 119:
+  case 120:
+  case 121:
+  case 122:
+  case 123:
+  case 124:
+  case 125:
+  case 126:
+  case 127:
+  case 128:
+  case 129:
+  case 130:
+  case 131:
+  case 132:
+  case 133:
+  case 134:
+  case 135:
+  case 136:
+  case 137:
+  case 138:
+  case 139:
+  case 140:
+  case 141:
+  case 142:
+  case 143:
+  case 144:
+  case 145:
+  case 146:
+  case 147:
+  case 148:
+  case 149:
+  case 150:
+  case 151:
+  case 152:
+  case 153:
+  case 154:
+  case 155:
+  case 156:
+  case 157:
+  case 158:
+  case 159:
+  case 160:
+  case 161:
+  case 162:
+  case 163:
+  case 164:
+  case 165:
+  case 166:
+  case 167:
+  case 168:
+  case 169:
+  case 170:
+  case 171:
+  case 172:
+  case 173:
+  case 174:
+  case 175:
+  case 176:
+  case 177:
+  case 178:
+  case 179:
+  case 180:
+  case 181:
+  case 182:
+  case 183:
+  case 184:
+  case 185:
+  case 186:
+  case 187:
+  case 188:
+  case 189:
+  case 190:
+  case 191:
+  case 192:
+  case 193:
+  case 194:
+  case 195:
+  case 196:
+  case 197:
+  case 198:
+  case 199:
+  case 200:
+  case 201:
+  case 202:
+  case 203:
+  case 204:
+  case 205:
+  case 206:
+  case 207:
+  case 208:
+  case 209:
+  case 210:
+  case 211:
+  case 212:
+  case 213:
+  case 214:
+  case 215:
+  case 216:
+  case 217:
+  case 218:
+  case 219:
+  case 220:
+  case 221:
+  case 222:
+  case 223:
+  case 224:
+  case 225:
+  case 226:
+  case 227:
+  case 228:
+  case 229:
+  case 230:
+  case 231:
+  case 232:
+  case 233:
+  case 234:
+  case 235:
+  case 236:
+  case 237:
+  case 238:
+  case 239:
+  case 240:
+  case 241:
+  case 242:
+  case 243:
+  case 244:
+  case 245:
+  case 246:
+  case 247:
+  case 248:
+  case 249:
+  case 250:
+  case 251:
+  case 252:
+  case 253:
+  case 254:
+  case 255:
+    break;
+  }
+
+  // Some paths are covered by the switch and a default case is present.
+  switch (c) {
+  case 1:
+  case 2:
+  case 3:
+  default:
+    break;
+  }
+}
+
+OS return_enumerator() {
+  return Linux;
+}
+
+// Enumpaths are already covered by a warning, this is just to ensure, that there is
+// no interference or false positives.
+// -Wswitch warns about uncovered enum paths and each here described case is already
+// covered.
+void switch_enums(OS os) {
+  switch (os) {
+  case Linux:
+    break;
+  }
+
+  switch (OS another_os = return_enumerator()) {
+  case Linux:
+    break;
+  }
+
+  switch (os) {
+  }
+}
+
+/// All of these cases will not emit a warning per default, but with explicit activation.
+/// Covered in extra test file.
+void problematic_if(int i, enum OS os) {
+  if (i > 0) {
+    return;
+  } else if (i < 0) {
+    return;
+  }
+
+  if (os == Mac) {
+    return;
+  } else if (os == Linux) {
+    if (true) {
+      return;
+    } else if (false) {
+      return;
+    }
+    return;
+  } else {
+    /* unreachable */
+    if (true) // check if the parent would match here as well
+      return;
+  }
+
+  // Ok, because all paths are covered
+  if (i > 0) {
+    return;
+  } else if (i < 0) {
+    return;
+  } else {
+    /* error, maybe precondition failed */
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-no-assembler-msvc.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-no-assembler-msvc.cpp
new file mode 100644
index 0000000..d29a9e9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-no-assembler-msvc.cpp
@@ -0,0 +1,11 @@
+// REQUIRES: system-windows
+// FIXME: Re-enable test on windows (PR36855)
+// UNSUPPORTED: system-windows
+// RUN: %check_clang_tidy %s hicpp-no-assembler %t
+
+void f() {
+  _asm {
+    mov al, 2;
+    // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: do not use inline assembler in safety-critical code [hicpp-no-assembler]
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-no-assembler.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-no-assembler.cpp
new file mode 100644
index 0000000..d08ea74
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-no-assembler.cpp
@@ -0,0 +1,12 @@
+// RUN: %check_clang_tidy %s hicpp-no-assembler %t
+
+__asm__(".symver foo, bar@v");
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not use inline assembler in safety-critical code [hicpp-no-assembler]
+
+static int s asm("spam");
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use inline assembler in safety-critical code [hicpp-no-assembler]
+
+void f() {
+  __asm("mov al, 2");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use inline assembler in safety-critical code [hicpp-no-assembler]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-bug34747.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-bug34747.cpp
new file mode 100644
index 0000000..217df71
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-bug34747.cpp
@@ -0,0 +1,29 @@
+// RUN: %check_clang_tidy %s hicpp-signed-bitwise %t --
+
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+
+template <typename C>
+struct OutputStream {
+  OutputStream &operator<<(C);
+};
+
+template <typename C>
+struct foo {
+  typedef OutputStream<C> stream_type;
+  foo(stream_type &o) {
+    o << 'x'; // warning occured here, fixed now
+  }
+};
+
+void bar(OutputStream<signed char> &o) {
+  foo<signed char> f(o);
+}
+
+void silence_lit() {
+  int SValue = 42;
+  int SResult;
+
+  SResult = SValue & 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-standard-types.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-standard-types.cpp
new file mode 100644
index 0000000..c85fe20
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-standard-types.cpp
@@ -0,0 +1,197 @@
+// RUN: clang-tidy %s -checks='-*,hicpp-signed-bitwise' -- -std=c++11
+
+#include "hicpp-signed-bitwise-standard-types.h"
+
+void pure_bitmask_types() {
+  // std::locale::category
+  int SResult = 0;
+  std::locale::category C = std::locale::category::ctype;
+
+  SResult = std::locale::category::none | std::locale::category::collate;
+  SResult|= std::locale::category::collate;
+  SResult = std::locale::category::ctype & std::locale::category::monetary;
+  SResult&= std::locale::category::monetary;
+  SResult = std::locale::category::numeric ^ std::locale::category::time;
+  SResult^= std::locale::category::time;
+  SResult = std::locale::category::messages | std::locale::category::all;
+
+  SResult = std::locale::category::all & C;
+  SResult&= std::locale::category::all;
+  SResult = std::locale::category::all | C;
+  SResult|= std::locale::category::all;
+  SResult = std::locale::category::all ^ C;
+  SResult^= std::locale::category::all;
+
+  // std::ctype_base::mask
+  std::ctype_base::mask M = std::ctype_base::mask::punct;
+
+  SResult = std::ctype_base::mask::space | std::ctype_base::mask::print;
+  SResult = std::ctype_base::mask::cntrl & std::ctype_base::mask::upper;
+  SResult = std::ctype_base::mask::lower ^ std::ctype_base::mask::alpha;
+  SResult|= std::ctype_base::mask::digit | std::ctype_base::mask::punct;
+  SResult&= std::ctype_base::mask::xdigit & std::ctype_base::mask::alnum;
+  SResult^= std::ctype_base::mask::alnum ^ std::ctype_base::mask::graph;
+
+  SResult&= std::ctype_base::mask::space & M;
+  SResult|= std::ctype_base::mask::space | M;
+  SResult^= std::ctype_base::mask::space ^ M;
+
+  // std::ios_base::fmtflags
+  std::ios_base::fmtflags F = std::ios_base::fmtflags::floatfield;
+
+  SResult = std::ios_base::fmtflags::dec | std::ios_base::fmtflags::oct;
+  SResult = std::ios_base::fmtflags::hex & std::ios_base::fmtflags::basefield;
+  SResult = std::ios_base::fmtflags::left ^ std::ios_base::fmtflags::right;
+  SResult|= std::ios_base::fmtflags::internal | std::ios_base::fmtflags::adjustfield;
+  SResult&= std::ios_base::fmtflags::scientific & std::ios_base::fmtflags::fixed;
+  SResult^= std::ios_base::fmtflags::floatfield ^ std::ios_base::fmtflags::boolalpha;
+  SResult = std::ios_base::fmtflags::showbase | std::ios_base::fmtflags::showpoint;
+  SResult = std::ios_base::fmtflags::showpos & std::ios_base::fmtflags::skipws;
+  SResult = std::ios_base::fmtflags::unitbuf ^ std::ios_base::fmtflags::uppercase;
+
+  SResult|= std::ios_base::fmtflags::unitbuf | F;
+  SResult&= std::ios_base::fmtflags::unitbuf & F;
+  SResult^= std::ios_base::fmtflags::unitbuf ^ F;
+
+  // std::ios_base::iostate
+  std::ios_base::iostate S = std::ios_base::iostate::goodbit;
+
+  SResult^= std::ios_base::iostate::goodbit | std::ios_base::iostate::badbit;
+  SResult|= std::ios_base::iostate::failbit & std::ios_base::iostate::eofbit;
+  SResult&= std::ios_base::iostate::failbit ^ std::ios_base::iostate::eofbit;
+
+  SResult = std::ios_base::iostate::goodbit | S;
+  SResult = std::ios_base::iostate::goodbit & S;
+  SResult = std::ios_base::iostate::goodbit ^ S;
+
+  // std::ios_base::openmode
+  std::ios_base::openmode B = std::ios_base::openmode::binary;
+
+  SResult = std::ios_base::openmode::app | std::ios_base::openmode::binary;
+  SResult = std::ios_base::openmode::in & std::ios_base::openmode::out;
+  SResult = std::ios_base::openmode::trunc ^ std::ios_base::openmode::ate;
+
+  SResult&= std::ios_base::openmode::trunc | B;
+  SResult^= std::ios_base::openmode::trunc & B;
+  SResult|= std::ios_base::openmode::trunc ^ B;
+}
+
+void still_forbidden() {
+  // std::locale::category
+  unsigned int UResult = 0u;
+  int SResult = 0;
+
+  SResult = std::ctype_base::mask::print ^ 8u;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  SResult = std::ctype_base::mask::cntrl | 8;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  SResult = std::ctype_base::mask::upper & 8;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  SResult = std::ctype_base::mask::lower ^ -8;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  
+  // Staying within the allowed standard types is ok for bitwise assignment
+  // operations.
+  std::ctype_base::mask var = std::ctype_base::mask::print;
+  SResult<<= std::ctype_base::mask::upper;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  SResult>>= std::ctype_base::mask::upper;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  SResult &= std::ctype_base::mask::upper;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  SResult |= std::ctype_base::mask::upper;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  SResult ^= std::ctype_base::mask::upper;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+  UResult = std::locale::category::collate << 1u;
+  UResult = std::locale::category::ctype << 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::locale::category::monetary >> 1u;
+  UResult = std::locale::category::numeric >> 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+  UResult = ~std::locale::category::messages;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+  SResult = ~std::locale::category::all;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+
+  // std::ctype_base::mask
+  UResult = std::ctype_base::mask::space | 8;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::ctype_base::mask::print & 8u;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::ctype_base::mask::cntrl ^ -8;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+  UResult = std::ctype_base::mask::upper << 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::ctype_base::mask::lower << 1u;
+  UResult = std::ctype_base::mask::alpha >> 1u;
+  UResult = std::ctype_base::mask::digit >> 1u;
+
+  UResult = ~std::ctype_base::mask::punct;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+  SResult = ~std::ctype_base::mask::xdigit;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+
+  // std::ios_base::fmtflags
+  UResult = std::ios_base::fmtflags::dec | 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::ios_base::fmtflags::oct & 1u;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::ios_base::fmtflags::hex ^ -1;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+  UResult = std::ios_base::fmtflags::basefield >> 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::ios_base::fmtflags::left >> 1u;
+  UResult = std::ios_base::fmtflags::right << 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::ios_base::fmtflags::internal << 1u;
+
+  UResult = ~std::ios_base::fmtflags::adjustfield;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+  SResult = ~std::ios_base::fmtflags::scientific;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+
+  // std::ios_base::iostate
+  UResult = std::ios_base::iostate::goodbit | 8;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::ios_base::iostate::badbit & 8u;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::ios_base::iostate::failbit ^ -8;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+  UResult = std::ios_base::iostate::eofbit << 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::ios_base::iostate::goodbit << 1u;
+  UResult = std::ios_base::iostate::badbit >> 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::ios_base::iostate::failbit >> 1u;
+
+  UResult = ~std::ios_base::iostate::eofbit;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+  SResult = ~std::ios_base::iostate::goodbit;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+
+  // std::ios_base::openmode
+  UResult = std::ios_base::app | 8;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::ios_base::binary & 8u;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::ios_base::in ^ -8;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+  UResult = std::ios_base::out >> 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::ios_base::trunc >> 1u;
+  UResult = std::ios_base::ate << 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = std::ios_base::ate << 1u;
+
+  UResult = ~std::ios_base::openmode::app;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+  SResult = ~std::ios_base::openmode::binary;
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-standard-types.h b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-standard-types.h
new file mode 100644
index 0000000..e66fd09
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise-standard-types.h
@@ -0,0 +1,81 @@
+#pragma clang system_header
+
+// Implement standard types that are known to be defined as unsigned in some
+// implementations like MSVC.
+namespace std {
+namespace locale {
+enum category : int {
+  none = 0u,
+  collate = 1u << 1u,
+  ctype = 1u << 2u,
+  monetary = 1u << 3u,
+  numeric = 1u << 4u,
+  time = 1u << 5u,
+  messages = 1u << 6u,
+  all = none | collate | ctype | monetary | numeric | time | messages
+  // CHECK MESSAGES: [[@LINE-1]]:9: warning: use of a signed integer operand with a binary bitwise operator
+};
+} // namespace locale
+
+namespace ctype_base {
+enum mask : int {
+  space,
+  print,
+  cntrl,
+  upper,
+  lower,
+  alpha,
+  digit,
+  punct,
+  xdigit,
+  /* blank, // C++11 */
+  alnum = alpha | digit,
+  // CHECK MESSAGES: [[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+  graph = alnum | punct
+  // CHECK MESSAGES: [[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+};
+} // namespace ctype_base
+
+namespace ios_base {
+enum fmtflags : int {
+  dec = 0u,
+  oct = 1u << 2u,
+  hex = 1u << 3u,
+  basefield = dec | oct | hex | 0u,
+  // CHECK MESSAGES: [[@LINE-1]]:15: warning: use of a signed integer operand with a binary bitwise operator
+  left = 1u << 4u,
+  right = 1u << 5u,
+  internal = 1u << 6u,
+  adjustfield = left | right | internal,
+  // CHECK MESSAGES: [[@LINE-1]]:17: warning: use of a signed integer operand with a binary bitwise operator
+  scientific = 1u << 7u,
+  fixed = 1u << 8u,
+  floatfield = scientific | fixed | (scientific | fixed) | 0u,
+  // CHECK MESSAGES: [[@LINE-1]]:16: warning: use of a signed integer operand with a binary bitwise operator
+  // CHECK MESSAGES: [[@LINE-2]]:38: warning: use of a signed integer operand with a binary bitwise operator
+  boolalpha = 1u << 9u,
+  showbase = 1u << 10u,
+  showpoint = 1u << 11u,
+  showpos = 1u << 12u,
+  skipws = 1u << 13u,
+  unitbuf = 1u << 14u,
+  uppercase = 1u << 15u
+};
+
+enum iostate : int {
+  goodbit = 0u,
+  badbit = 1u << 1u,
+  failbit = 1u << 2u,
+  eofbit = 1u << 3u
+};
+
+enum openmode : int {
+  app = 0u,
+  binary = 0u << 1u,
+  in = 0u << 2u,
+  out = 0u << 3u,
+  trunc = 0u << 4u,
+  ate = 0u << 5u
+};
+} // namespace ios_base
+} // namespace std
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise.cpp
new file mode 100644
index 0000000..97a24b6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/hicpp-signed-bitwise.cpp
@@ -0,0 +1,240 @@
+// RUN: %check_clang_tidy %s hicpp-signed-bitwise %t -- -- -std=c++11 --target=x86_64-linux
+
+// These could cause false positives and should not be considered.
+struct StreamClass {
+};
+StreamClass &operator<<(StreamClass &os, unsigned int i) {
+  return os;
+}
+StreamClass &operator<<(StreamClass &os, int i) {
+  return os;
+}
+StreamClass &operator>>(StreamClass &os, unsigned int i) {
+  return os;
+}
+StreamClass &operator>>(StreamClass &os, int i) {
+  return os;
+}
+struct AnotherStream {
+  AnotherStream &operator<<(unsigned char c) { return *this; }
+  AnotherStream &operator<<(signed char c) { return *this; }
+
+  AnotherStream &operator>>(unsigned char c) { return *this; }
+  AnotherStream &operator>>(signed char c) { return *this; }
+};
+
+void binary_bitwise() {
+  int SValue = 42;
+  int SResult;
+
+  unsigned int UValue = 42;
+  unsigned int UResult;
+
+  SResult = SValue & 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  SResult = SValue & -1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  SResult = SValue & SValue;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+  UResult = SValue & 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = SValue & -1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult&= 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+
+  UResult = UValue & 1u;     // Ok
+  UResult = UValue & UValue; // Ok
+  UResult&= 2u;              // Ok
+
+  unsigned char UByte1 = 0u;
+  unsigned char UByte2 = 16u;
+  signed char SByte1 = 0;
+  signed char SByte2 = 16;
+
+  UByte1 = UByte1 & UByte2; // Ok
+  UByte1 = SByte1 & UByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+  UByte1 = SByte1 & SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+  SByte1 = SByte1 & SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+
+  // More complex expressions.
+  UResult = UValue & (SByte1 + (SByte1 | SByte2));
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  // CHECK-MESSAGES: :[[@LINE-2]]:33: warning: use of a signed integer operand with a binary bitwise operator
+
+  // The rest is to demonstrate functionality but all operators are matched equally.
+  // Therefore functionality is the same for all binary operations.
+  UByte1 = UByte1 | UByte2; // Ok
+  UByte1 = UByte1 | SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+  UByte1|= SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+  UByte1|= UByte2; // Ok
+
+  UByte1 = UByte1 ^ UByte2; // Ok
+  UByte1 = UByte1 ^ SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+  UByte1^= SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+  UByte1^= UByte2; // Ok
+
+  UByte1 = UByte1 >> UByte2; // Ok
+  UByte1 = UByte1 >> SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+  UByte1>>= SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+  UByte1>>= UByte2; // Ok
+
+  UByte1 = UByte1 << UByte2; // Ok
+  UByte1 = UByte1 << SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+  UByte1<<= SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+  UByte1<<= UByte2; // Ok
+
+  int SignedInt1 = 1 << 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use of a signed integer operand with a binary bitwise operator
+  int SignedInt2 = 1u << 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use of a signed integer operand with a binary bitwise operator
+}
+
+void f1(unsigned char c) {}
+void f2(signed char c) {}
+void f3(int c) {}
+
+void unary_bitwise() {
+  unsigned char UByte1 = 0u;
+  signed char SByte1 = 0;
+
+  UByte1 = ~UByte1; // Ok
+  SByte1 = ~UByte1;
+  SByte1 = ~SByte1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a unary bitwise operator
+  UByte1 = ~SByte1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a unary bitwise operator
+
+  unsigned int UInt = 0u;
+  int SInt = 0;
+
+  f1(~UByte1); // Ok
+  f1(~SByte1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use of a signed integer operand with a unary bitwise operator
+  f1(~UInt);
+  f1(~SInt);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use of a signed integer operand with a unary bitwise operator
+  f2(~UByte1);
+  f2(~SByte1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use of a signed integer operand with a unary bitwise operator
+  f2(~UInt);
+  f2(~SInt);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use of a signed integer operand with a unary bitwise operator
+  f3(~UByte1); // Ok
+  f3(~SByte1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use of a signed integer operand with a unary bitwise operator
+}
+
+/// HICPP uses these examples to demonstrate the rule.
+void standard_examples() {
+  int i = 3;
+  unsigned int k = 0u;
+
+  int r = i << -1; // Emits -Wshift-count-negative from clang
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+  r = i << 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+
+  r = -1 >> -1; // Emits -Wshift-count-negative from clang
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+  r = -1 >> 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+
+  r = -1 >> i;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+  r = -1 >> -i;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+
+  r = ~0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a unary bitwise operator
+  r = ~0u; // Ok
+  k = ~k;  // Ok
+
+  unsigned int u = (-1) & 2u;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use of a signed integer operand with a binary bitwise operator
+  u = (-1) | 1u;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+  u = (-1) ^ 1u;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+}
+
+void streams_should_work() {
+  StreamClass s;
+  s << 1u; // Ok
+  s << 1;  // Ok
+  s >> 1;  // Ok
+  s >> 1u; // Ok
+
+  AnotherStream as;
+  unsigned char uc = 1u;
+  signed char sc = 1;
+  as << uc; // Ok
+  as << sc; // Ok
+  as >> uc; // Ok
+  as >> sc; // Ok
+}
+
+enum OldEnum {
+  ValueOne,
+  ValueTwo,
+};
+
+enum OldSigned : int {
+  IntOne,
+  IntTwo,
+};
+
+void classicEnums() {
+  OldEnum e1 = ValueOne, e2 = ValueTwo;
+  int e3;                   // Using the enum type, results in an error.
+  e3 = ValueOne | ValueTwo; // Ok
+  e3 = ValueOne & ValueTwo; // Ok
+  e3 = ValueOne ^ ValueTwo; // Ok
+  e3 = e1 | e2;             // Ok
+  e3 = e1 & e2;             // Ok
+  e3 = e1 ^ e2;             // Ok
+
+  OldSigned s1 = IntOne, s2 = IntTwo;
+  int s3;
+  s3 = IntOne | IntTwo; // Signed
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+  s3|= IntTwo; // Signed
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+  s3 = IntOne & IntTwo; // Signed
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+  s3&= IntTwo; // Signed
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+  s3 = IntOne ^ IntTwo; // Signed
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+  s3^= IntTwo; // Signed
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator
+  s3 = s1 | s2; // Signed
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+  s3 = s1 & s2; // Signed
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+  s3 = s1 ^ s2; // Signed
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+}
+
+enum EnumConstruction {
+  one = 1,
+  two = 2,
+  test1 = 1 << 12,
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+  test2 = one << two,
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+  test3 = 1u << 12,
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/line-filter.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/line-filter.cpp
new file mode 100644
index 0000000..ad980cf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/line-filter.cpp
@@ -0,0 +1,27 @@
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -line-filter='[{"name":"line-filter.cpp","lines":[[18,18],[22,22]]},{"name":"header1.h","lines":[[1,2]]},{"name":"header2.h"},{"name":"header3.h"}]' -header-filter='header[12]\.h$' %s -- -I %S/Inputs/line-filter 2>&1 | FileCheck %s
+
+#include "header1.h"
+// CHECK-NOT: header1.h:{{.*}} warning
+// CHECK: header1.h:1:12: warning: single-argument constructors must be marked explicit
+// CHECK: header1.h:2:12: warning: single-argument constructors {{.*}}
+// CHECK-NOT: header1.h:{{.*}} warning
+
+#include "header2.h"
+// CHECK: header2.h:1:12: warning: single-argument constructors {{.*}}
+// CHECK: header2.h:2:12: warning: single-argument constructors {{.*}}
+// CHECK: header2.h:3:12: warning: single-argument constructors {{.*}}
+// CHECK-NOT: header2.h:{{.*}} warning
+
+#include "header3.h"
+// CHECK-NOT: header3.h:{{.*}} warning
+
+class A { A(int); };
+// CHECK: :[[@LINE-1]]:11: warning: single-argument constructors {{.*}}
+class B { B(int); };
+// CHECK-NOT: :[[@LINE-1]]:{{.*}} warning
+class C { C(int); };
+// CHECK: :[[@LINE-1]]:11: warning: single-argument constructors {{.*}}
+
+// CHECK-NOT: warning:
+
+// CHECK: Suppressed 3 warnings (1 in non-user code, 2 due to line filter)
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/list-checks.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/list-checks.cpp
new file mode 100644
index 0000000..674c118
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/list-checks.cpp
@@ -0,0 +1,4 @@
+// RUN: mkdir -p %T/clang-tidy/list-checks/
+// RUN: echo '{Checks: "-*,google-*"}' > %T/clang-tidy/.clang-tidy
+// RUN: cd %T/clang-tidy/list-checks
+// RUN: clang-tidy -list-checks | grep "^ *google-"
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/llvm-include-order.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/llvm-include-order.cpp
new file mode 100644
index 0000000..7272353
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/llvm-include-order.cpp
@@ -0,0 +1,42 @@
+// RUN: %check_clang_tidy %s llvm-include-order %t -- -- -isystem %S/Inputs/Headers
+
+// CHECK-MESSAGES: [[@LINE+2]]:1: warning: #includes are not sorted properly
+#include "j.h"
+#include "gtest/foo.h"
+#include "i.h"
+#include <s.h>
+#include "llvm/a.h"
+#include "clang/b.h"
+#include "clang-c/c.h" // hi
+#include "llvm-c/d.h" // -c
+
+// CHECK-FIXES: #include "j.h"
+// CHECK-FIXES-NEXT: #include "i.h"
+// CHECK-FIXES-NEXT: #include "clang-c/c.h" // hi
+// CHECK-FIXES-NEXT: #include "clang/b.h"
+// CHECK-FIXES-NEXT: #include "llvm-c/d.h" // -c
+// CHECK-FIXES-NEXT: #include "llvm/a.h"
+// CHECK-FIXES-NEXT: #include "gtest/foo.h"
+// CHECK-FIXES-NEXT: #include <s.h>
+
+#include "b.h"
+#ifdef FOO
+#include "a.h"
+#endif
+
+// CHECK-FIXES: #include "b.h"
+// CHECK-FIXES-NEXT: #ifdef FOO
+// CHECK-FIXES-NEXT: #include "a.h"
+// CHECK-FIXES-NEXT: #endif
+
+// CHECK-MESSAGES: [[@LINE+1]]:1: warning: #includes are not sorted properly
+#include "b.h"
+#include "a.h"
+
+// CHECK-FIXES: #include "a.h"
+// CHECK-FIXES-NEXT: #include "b.h"
+
+// CHECK-MESSAGES-NOT: [[@LINE+1]]:1: warning: #includes are not sorted properly
+#include "cross-file-c.h"
+// This line number should correspond to the position of the #include in cross-file-c.h
+#include "cross-file-a.h"
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/llvm-twine-local.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/llvm-twine-local.cpp
new file mode 100644
index 0000000..06eb761
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/llvm-twine-local.cpp
@@ -0,0 +1,64 @@
+// RUN: %check_clang_tidy %s llvm-twine-local %t
+
+namespace llvm {
+class Twine {
+public:
+  Twine(const char *);
+  Twine(int);
+  Twine();
+  Twine &operator+(const Twine &);
+};
+}
+
+using namespace llvm;
+
+void foo(const Twine &x);
+
+static Twine Moo = Twine("bark") + "bah";
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: static std::string Moo = (Twine("bark") + "bah").str();
+
+int main() {
+  const Twine t = Twine("a") + "b" + Twine(42);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: std::string t = (Twine("a") + "b" + Twine(42)).str();
+  foo(Twine("a") + "b");
+
+  Twine Prefix = false ? "__INT_FAST" : "__UINT_FAST";
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: const char * Prefix = false ? "__INT_FAST" : "__UINT_FAST";
+
+  const Twine t2 = Twine();
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: std::string t2 = (Twine()).str();
+  foo(Twine() + "b");
+
+  const Twine t3 = Twine(42);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: std::string t3 = (Twine(42)).str();
+
+  const Twine t4 = Twine(42) + "b";
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: std::string t4 = (Twine(42) + "b").str();
+
+  const Twine t5 = Twine() + "b";
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: std::string t5 = (Twine() + "b").str();
+
+  const Twine t6 = true ? Twine() : Twine(42);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: std::string t6 = (true ? Twine() : Twine(42)).str();
+
+  const Twine t7 = false ? Twine() : Twine("b");
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: twine variables are prone to use-after-free bugs
+// CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+// CHECK-FIXES: std::string t7 = (false ? Twine() : Twine("b")).str();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/macros.cpp
new file mode 100644
index 0000000..fa4f32a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/macros.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' %s -- | FileCheck %s
+
+#define Q(name) class name { name(int i); }
+
+Q(A);
+// CHECK: :[[@LINE-1]]:3: warning: single-argument constructors must be marked explicit
+// CHECK: :3:30: note: expanded from macro 'Q'
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-definitions-in-headers-1z.hpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-definitions-in-headers-1z.hpp
new file mode 100644
index 0000000..79fb7bc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-definitions-in-headers-1z.hpp
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s misc-definitions-in-headers %t -- -- -std=c++1z
+
+class CE {
+  constexpr static int i = 5; // OK: inline variable definition.
+};
+
+inline int i = 5; // OK: inline variable definition.
+
+int b = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'b' defined in a header file; variable definitions in header files can lead to ODR violations [misc-definitions-in-headers]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-definitions-in-headers.hpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-definitions-in-headers.hpp
new file mode 100644
index 0000000..5e83e68
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-definitions-in-headers.hpp
@@ -0,0 +1,181 @@
+// RUN: %check_clang_tidy %s misc-definitions-in-headers %t
+
+int f() {
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f' defined in a header file; function definitions in header files can lead to ODR violations [misc-definitions-in-headers]
+// CHECK-FIXES: inline int f() {
+  return 1;
+}
+
+class CA {
+  void f1() {} // OK: inline class member function definition.
+  void f2();
+  template<typename T>
+  T f3() {
+    T a = 1;
+    return a;
+  }
+  template<typename T>
+  struct CAA {
+    struct CAB {
+      void f4();
+    };
+  };
+};
+
+void CA::f2() { }
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: function 'f2' defined in a header file;
+// CHECK-FIXES: inline void CA::f2() {
+
+template <>
+int CA::f3() {
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: full function template specialization 'f3<int>' defined in a header file;
+// CHECK-FIXES: inline int CA::f3() {
+  int a = 1;
+  return a;
+}
+
+template <typename T>
+void CA::CAA<T>::CAB::f4() {
+// OK: member function definition of a nested template class in a class.
+}
+
+template <typename T>
+struct CB {
+  void f1();
+  struct CCA {
+    void f2(T a);
+  };
+  struct CCB;  // OK: forward declaration.
+  static int a; // OK: class static data member declaration.
+};
+
+template <typename T>
+void CB<T>::f1() { // OK: Member function definition of a class template.
+}
+
+template <typename T>
+void CB<T>::CCA::f2(T a) {
+// OK: member function definition of a nested class in a class template.
+}
+
+template <typename T>
+struct CB<T>::CCB {
+  void f3();
+};
+
+template <typename T>
+void CB<T>::CCB::f3() {
+// OK: member function definition of a nested class in a class template.
+}
+
+template <typename T>
+int CB<T>::a = 2; // OK: static data member definition of a class template.
+
+template class CB<int>; // OK: explicitly instantiated static data member of a class template.
+inline int callCB() {
+  CB<double> cb; // OK: implicitly instantiated static data member of a class template.
+  return cb.a;
+}
+
+template <typename T>
+T tf() { // OK: template function definition.
+  T a;
+  return a;
+}
+
+
+namespace NA {
+  int f() { return 1; }
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: function 'f' defined in a header file;
+// CHECK-FIXES: inline int f() { return 1; }
+}
+
+template <typename T>
+T f3() {
+  T a = 1;
+  return a;
+}
+
+template <>
+int f3() {
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: full function template specialization 'f3<int>' defined in a header file;
+// CHECK-FIXES: inline int f3() {
+  int a = 1;
+  return a;
+}
+
+int f5(); // OK: function declaration.
+inline int f6() { return 1; } // OK: inline function definition.
+namespace {
+  int f7() { return 1; }
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: function 'f7' defined in a header file;
+}
+
+int f8() = delete; // OK: the function being marked delete is not callable.
+
+template <typename T>
+int f9(T t) { return 1; }
+
+inline void callF9() { f9(1); } // OK: implicitly instantiated function.
+template int f9(double); // OK: explicitly instantiated function.
+
+int a = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'a' defined in a header file; variable definitions in header files can lead to ODR violations [misc-definitions-in-headers]
+CA a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:4: warning: variable 'a1' defined in a header file;
+
+namespace NB {
+  int b = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable 'b' defined in a header file;
+  const int c = 1; // OK: internal linkage variable definition.
+}
+
+class CC {
+  static int d; // OK: class static data member declaration.
+};
+
+int CC::d = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: variable 'd' defined in a header file;
+
+const char* ca = "foo";
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: variable 'ca' defined in a header file;
+
+namespace {
+  int e = 2;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable 'e' defined in a header file;
+}
+
+const char* const g = "foo"; // OK: internal linkage variable definition.
+static int h = 1; // OK: internal linkage variable definition.
+const int i = 1; // OK: internal linkage variable definition.
+extern int j; // OK: internal linkage variable definition.
+
+template <typename T, typename U>
+struct CD {
+  int f();
+};
+
+template <typename T>
+struct CD<T, int> {
+  int f();
+};
+
+template <>
+struct CD<int, int> {
+  int f();
+};
+
+int CD<int, int>::f() {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: function 'f' defined in a header file;
+// CHECK-FIXES: inline int CD<int, int>::f() {
+  return 0;
+}
+
+template <typename T>
+int CD<T, int>::f() { // OK: partial template specialization.
+  return 0;
+}
+
+constexpr int k = 1; // OK: constexpr variable has internal linkage.
+
+constexpr int f10() { return 0; } // OK: constexpr function definition.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const-cxx17.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const-cxx17.cpp
new file mode 100644
index 0000000..7816a09
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const-cxx17.cpp
@@ -0,0 +1,15 @@
+// RUN: %check_clang_tidy -expect-clang-tidy-error %s misc-misplaced-const %t -- -- -std=c++17
+
+// This test previously would cause a failed assertion because the structured
+// binding declaration had no valid type associated with it. This ensures the
+// expected clang diagnostic is generated instead.
+// CHECK-MESSAGES: :[[@LINE+1]]:6: error: decomposition declaration '[x]' requires an initializer [clang-diagnostic-error]
+auto [x];
+
+struct S { int a; };
+S f();
+
+int main() {
+  auto [x] = f();
+}
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const.c
new file mode 100644
index 0000000..cccf3a4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const.c
@@ -0,0 +1,45 @@
+// RUN: %check_clang_tidy %s misc-misplaced-const %t
+
+typedef int plain_i;
+typedef int *ip;
+typedef const int *cip;
+
+typedef void (*func_ptr)(void);
+
+void func(void) {
+  // ok
+  const int *i0 = 0;
+  const plain_i *i1 = 0;
+  const cip i2 = 0; // const applies to both pointer and pointee.
+
+  // Not ok
+  const ip i3 = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: 'i3' declared with a const-qualified typedef type; results in the type being 'int *const' instead of 'const int *'
+
+  ip const i4 = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: 'i4' declared with a const-qualified
+
+  const volatile ip i5 = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 'i5' declared with a const-qualified typedef type; results in the type being 'int *const volatile' instead of 'const int *volatile'
+}
+
+void func2(const plain_i *i1,
+           const cip i2,
+           const ip i3,
+           // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 'i3' declared with a const-qualified
+           const int *i4) {
+}
+
+struct S {
+  const int *i0;
+  const plain_i *i1;
+  const cip i2;
+  const ip i3;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: 'i3' declared with a const-qualified
+};
+
+// Function pointers should not be diagnosed because a function
+// pointer type can never be const.
+void func3(const func_ptr fp) {
+  const func_ptr fp2 = fp;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const.cpp
new file mode 100644
index 0000000..d7ea893
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-misplaced-const.cpp
@@ -0,0 +1,44 @@
+// RUN: %check_clang_tidy %s misc-misplaced-const %t
+
+typedef int plain_i;
+typedef int *ip;
+typedef const int *cip;
+
+void func() {
+  if (const int *i = 0)
+    ;
+  if (const plain_i *i = 0)
+    ;
+  if (const cip i = 0)
+    ;
+
+  // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: 'i' declared with a const-qualified typedef type; results in the type being 'int *const' instead of 'const int *'
+  if (const ip i = 0)
+    ;
+}
+
+template <typename Ty>
+struct S {
+  const Ty *i;
+  const Ty &i2;
+};
+
+template struct S<int>;
+template struct S<ip>; // ok
+template struct S<cip>;
+
+template <typename Ty>
+struct U {
+  const Ty *i;
+  const Ty &i2;
+};
+
+template struct U<int *>; // ok
+
+struct T {
+  typedef void (T::*PMF)();
+
+  void f() {
+    const PMF val = &T::f; // ok
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads-sized-dealloc.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads-sized-dealloc.cpp
new file mode 100644
index 0000000..2ba60e4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads-sized-dealloc.cpp
@@ -0,0 +1,20 @@
+// RUN: %check_clang_tidy %s misc-new-delete-overloads %t -- -- -std=c++14 -fsized-deallocation
+
+typedef decltype(sizeof(int)) size_t;
+
+struct S {
+  // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: declaration of 'operator delete' has no matching declaration of 'operator new' at the same scope [misc-new-delete-overloads]
+  void operator delete(void *ptr, size_t) noexcept; // not a placement delete
+};
+
+struct T {
+  // Because we have enabled sized deallocations explicitly, this new/delete
+  // pair matches.
+  void *operator new(size_t size) noexcept;
+  void operator delete(void *ptr, size_t) noexcept; // ok because sized deallocation is enabled
+};
+
+// While we're here, check that global operator delete with no operator new
+// is also matched.
+// CHECK-MESSAGES: :[[@LINE+1]]:6: warning: declaration of 'operator delete' has no matching declaration of 'operator new' at the same scope
+void operator delete(void *ptr) noexcept;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads.cpp
new file mode 100644
index 0000000..3e60537
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads.cpp
@@ -0,0 +1,81 @@
+// RUN: %check_clang_tidy %s misc-new-delete-overloads %t -- -- -std=c++14
+
+typedef decltype(sizeof(int)) size_t;
+
+struct S {
+  // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope [misc-new-delete-overloads]
+  void *operator new(size_t size) noexcept;
+  // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new[]' has no matching declaration of 'operator delete[]' at the same scope
+  void *operator new[](size_t size) noexcept;
+};
+
+// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope
+void *operator new(size_t size) noexcept(false);
+
+struct T {
+  // Sized deallocations are not enabled by default, and so this new/delete pair
+  // does not match. However, we expect only one warning, for the new, because
+  // the operator delete is a placement delete and we do not warn on mismatching
+  // placement operations.
+  // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope
+  void *operator new(size_t size) noexcept;
+  void operator delete(void *ptr, size_t) noexcept; // ok only if sized deallocation is enabled
+};
+
+struct U {
+  void *operator new(size_t size) noexcept;
+  void operator delete(void *ptr) noexcept;
+
+  void *operator new[](size_t) noexcept;
+  void operator delete[](void *) noexcept;
+};
+
+struct Z {
+  // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: declaration of 'operator delete' has no matching declaration of 'operator new' at the same scope
+  void operator delete(void *ptr) noexcept;
+  // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: declaration of 'operator delete[]' has no matching declaration of 'operator new[]' at the same scope
+  void operator delete[](void *ptr) noexcept;
+};
+
+struct A {
+  void *operator new(size_t size, Z) noexcept; // ok, placement new
+};
+
+struct B {
+  void operator delete(void *ptr, A) noexcept; // ok, placement delete
+};
+
+// It is okay to have a class with an inaccessible free store operator.
+struct C {
+  void *operator new(size_t, A) noexcept; // ok, placement new
+private:
+  void operator delete(void *) noexcept;
+};
+
+// It is also okay to have a class with a delete free store operator.
+struct D {
+  void *operator new(size_t, A) noexcept; // ok, placement new
+  void operator delete(void *) noexcept = delete;
+};
+
+struct E : U {
+  void *operator new(size_t) noexcept; // okay, we inherit operator delete from U
+};
+
+struct F : S {
+  // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope
+  void *operator new(size_t) noexcept;
+};
+
+class G {
+  void operator delete(void *) noexcept;
+};
+
+struct H : G {
+  // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope
+  void *operator new(size_t) noexcept; // base class operator is inaccessible
+};
+
+template <typename Base> struct Derived : Base {
+  void operator delete(void *);
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-non-copyable-objects.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-non-copyable-objects.c
new file mode 100644
index 0000000..ac6198e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-non-copyable-objects.c
@@ -0,0 +1,43 @@
+// RUN: %check_clang_tidy %s misc-non-copyable-objects %t
+
+typedef struct FILE {} FILE;
+typedef struct pthread_cond_t {} pthread_cond_t;
+typedef int pthread_mutex_t;
+
+// CHECK-MESSAGES: :[[@LINE+1]]:13: warning: 'f' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'? [misc-non-copyable-objects]
+void g(FILE f);
+// CHECK-MESSAGES: :[[@LINE+1]]:24: warning: 'm' declared as type 'pthread_mutex_t', which is unsafe to copy; did you mean 'pthread_mutex_t *'?
+void h(pthread_mutex_t m);
+// CHECK-MESSAGES: :[[@LINE+1]]:23: warning: 'c' declared as type 'pthread_cond_t', which is unsafe to copy; did you mean 'pthread_cond_t *'?
+void i(pthread_cond_t c);
+
+struct S {
+  pthread_cond_t c; // ok
+  // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: 'f' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+  FILE f;
+};
+
+void func(FILE *f) {
+  // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: 'f1' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+  FILE f1; // match
+  // CHECK-MESSAGES: :[[@LINE+2]]:8: warning: 'f2' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+  // CHECK-MESSAGES: :[[@LINE+1]]:13: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced
+  FILE f2 = *f;
+  // CHECK-MESSAGES: :[[@LINE+1]]:15: warning: 'f3' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+  struct FILE f3;
+  // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced
+  (void)sizeof(*f);
+  (void)sizeof(FILE);
+  // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced
+  g(*f);
+
+  pthread_mutex_t m; // ok
+  h(m); // ok
+
+  pthread_cond_t c; // ok
+  i(c); // ok
+
+  pthread_mutex_t *m1 = &m; // ok
+  // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: expression has opaque data structure type 'pthread_mutex_t'; type should only be used as a pointer and not dereferenced
+  h(*m1);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-non-copyable-objects.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-non-copyable-objects.cpp
new file mode 100644
index 0000000..3d716f4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-non-copyable-objects.cpp
@@ -0,0 +1,26 @@
+// RUN: %check_clang_tidy %s misc-non-copyable-objects %t
+
+namespace std {
+typedef struct FILE {} FILE;
+}
+using namespace std;
+
+// CHECK-MESSAGES: :[[@LINE+1]]:18: warning: 'f' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'? [misc-non-copyable-objects]
+void g(std::FILE f);
+
+struct S {
+  // CHECK-MESSAGES: :[[@LINE+1]]:10: warning: 'f' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+  ::FILE f;
+};
+
+void func(FILE *f) {
+  // CHECK-MESSAGES: :[[@LINE+1]]:13: warning: 'f1' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+  std::FILE f1; // match
+  // CHECK-MESSAGES: :[[@LINE+2]]:10: warning: 'f2' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+  // CHECK-MESSAGES: :[[@LINE+1]]:15: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced
+  ::FILE f2 = *f; // match, match
+  // CHECK-MESSAGES: :[[@LINE+1]]:15: warning: 'f3' declared as type 'FILE', which is unsafe to copy; did you mean 'FILE *'?
+  struct FILE f3; // match
+  // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: expression has opaque data structure type 'FILE'; type should only be used as a pointer and not dereferenced
+  (void)sizeof(*f); // match
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-redundant-expression.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-redundant-expression.cpp
new file mode 100644
index 0000000..3454318
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-redundant-expression.cpp
@@ -0,0 +1,727 @@
+// RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -std=c++11
+
+typedef __INT64_TYPE__ I64;
+
+struct Point {
+  int x;
+  int y;
+  int a[5];
+} P;
+
+extern Point P1;
+extern Point P2;
+
+extern int foo(int x);
+extern int bar(int x);
+extern int bat(int x, int y);
+
+int TestSimpleEquivalent(int X, int Y) {
+  if (X - X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent [misc-redundant-expression]
+  if (X / X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+  if (X % X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+
+  if (X & X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+  if (X | X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+  if (X ^ X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+
+  if (X < X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+  if (X <= X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+  if (X > X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+  if (X >= X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+
+  if (X && X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+  if (X || X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+
+  if (X != (((X)))) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+
+  if (X + 1 == X + 1) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+  if (X + 1 != X + 1) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+  if (X + 1 <= X + 1) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+  if (X + 1 >= X + 1) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+
+  if ((X != 1 || Y != 1) && (X != 1 || Y != 1)) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: both sides of operator are equivalent
+  if (P.a[X - P.x] != P.a[X - P.x]) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: both sides of operator are equivalent
+
+  if ((int)X < (int)X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
+  if (int(X) < int(X)) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
+
+  if ( + "dummy" == + "dummy") return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: both sides of operator are equivalent
+  if (L"abc" == L"abc") return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
+
+  if (foo(0) - 2 < foo(0) - 2) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: both sides of operator are equivalent
+  if (foo(bar(0)) < (foo(bar((0))))) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: both sides of operator are equivalent
+
+  if (P1.x < P2.x && P1.x < P2.x) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: both sides of operator are equivalent
+  if (P2.a[P1.x + 2] < P2.x && P2.a[(P1.x) + (2)] < (P2.x)) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: both sides of operator are equivalent
+
+  return 0;
+}
+
+int Valid(int X, int Y) {
+  if (X != Y) return 1;
+  if (X == Y + 0) return 1;
+  if (P.x == P.y) return 1;
+  if (P.a[P.x] < P.a[P.y]) return 1;
+  if (P.a[0] < P.a[1]) return 1;
+
+  if (P.a[0] < P.a[0ULL]) return 1;
+  if (0 < 0ULL) return 1;
+  if ((int)0 < (int)0ULL) return 1;
+
+  if (++X != ++X) return 1;
+  if (P.a[X]++ != P.a[X]++) return 1;
+  if (P.a[X++] != P.a[X++]) return 1;
+
+  if ("abc" == "ABC") return 1;
+  if (foo(bar(0)) < (foo(bat(0, 1)))) return 1;
+  return 0;
+}
+
+#define COND_OP_MACRO 9
+#define COND_OP_OTHER_MACRO 9
+int TestConditional(int x, int y) {
+  int k = 0;
+  k += (y < 0) ? x : x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: 'true' and 'false' expressions are equivalent
+  k += (y < 0) ? x + 1 : x + 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: 'true' and 'false' expressions are equivalent
+  k += (y < 0) ? COND_OP_MACRO : COND_OP_MACRO;
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: 'true' and 'false' expressions are equivalent
+
+  // Do not match for conditional operators with a macro and a const.
+  k += (y < 0) ? COND_OP_MACRO : 9;
+  // Do not match for conditional operators with expressions from different macros.
+  k += (y < 0) ? COND_OP_MACRO : COND_OP_OTHER_MACRO;
+  return k;
+}
+#undef COND_OP_MACRO
+#undef COND_OP_OTHER_MACRO
+
+// Overloaded operators that compare two instances of a struct.
+struct MyStruct {
+  int x;  
+  bool operator==(const MyStruct& rhs) const {return this->x == rhs.x; } // not modifing
+  bool operator>=(const MyStruct& rhs) const { return this->x >= rhs.x; } // not modifing
+  bool operator<=(MyStruct& rhs) const { return this->x <= rhs.x; }
+  bool operator&&(const MyStruct& rhs){ this->x++; return this->x && rhs.x; }
+} Q;
+
+bool operator!=(const MyStruct& lhs, const MyStruct& rhs) { return lhs.x == rhs.x; } // not modifing
+bool operator<(const MyStruct& lhs, const MyStruct& rhs) { return lhs.x < rhs.x; } // not modifing
+bool operator>(const MyStruct& lhs, MyStruct& rhs) { rhs.x--; return lhs.x > rhs.x; }
+bool operator||(MyStruct& lhs, const MyStruct& rhs) { lhs.x++; return lhs.x || rhs.x; }
+
+bool TestOverloadedOperator(MyStruct& S) {
+  if (S == Q) return false;
+
+  if (S <= S) return false;
+  if (S && S) return false;
+  if (S > S) return false;
+  if (S || S) return false;
+
+  if (S == S) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent
+  if (S < S) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent
+  if (S != S) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent
+  if (S >= S) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent
+
+  return true;
+}
+
+#define LT(x, y) (void)((x) < (y))
+#define COND(x, y, z) ((x)?(y):(z))
+#define EQUALS(x, y) (x) == (y)
+
+int TestMacro(int X, int Y) {
+  LT(0, 0);
+  LT(1, 0);
+  LT(X, X);
+  LT(X+1, X + 1);
+  COND(X < Y, X, X);
+  EQUALS(Q, Q);
+  return 0;
+}
+
+int TestFalsePositive(int* A, int X, float F) {
+  // Produced by bison.
+  X = A[(2) - (2)];
+  X = A['a' - 'a'];
+
+  // Testing NaN.
+  if (F != F && F == F) return 1;
+  return 0;
+}
+
+int TestBannedMacros() {
+#define EAGAIN 3
+#define NOT_EAGAIN 3
+  if (EAGAIN == 0 | EAGAIN == 0) return 0;
+  if (NOT_EAGAIN == 0 | NOT_EAGAIN == 0) return 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: both sides of operator are equivalent
+  return 0;
+}
+
+struct MyClass {
+static const int Value = 42;
+};
+template <typename T, typename U>
+void TemplateCheck() {
+  static_assert(T::Value == U::Value, "should be identical");
+  static_assert(T::Value == T::Value, "should be identical");
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: both sides of operator are equivalent
+}
+void TestTemplate() { TemplateCheck<MyClass, MyClass>(); }
+
+int TestArithmetic(int X, int Y) {
+  if (X + 1 == X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
+  if (X + 1 != X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+  if (X - 1 == X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
+  if (X - 1 != X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+  if (X + 1LL == X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
+  if (X + 1ULL == X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always false
+
+  if (X == X + 1) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always false
+  if (X != X + 1) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true
+  if (X == X - 1) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always false
+  if (X != X - 1) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true
+
+  if (X != X - 1U) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true
+  if (X != X - 1LL) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true
+
+  if ((X+X) != (X+X) - 1) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+  if (X + 1 == X + 2) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
+  if (X + 1 != X + 2) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+  if (X - 1 == X - 2) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
+  if (X - 1 != X - 2) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+  if (X + 1 == X - -1) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+  if (X + 1 != X - -1) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
+  if (X + 1 == X - -2) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
+  if (X + 1 != X - -2) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+  if (X + 1 == X - (~0)) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+  if (X + 1 == X - (~0U)) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+  if (X + 1 == X - (~0ULL)) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+  // Should not match.
+  if (X + 0.5 == X) return 1;
+  if (X + 1 == Y) return 1;
+  if (X + 1 == Y + 1) return 1;
+  if (X + 1 == Y + 2) return 1;
+
+  return 0;
+}
+
+int TestBitwise(int X, int Y) {
+
+  if ((X & 0xFF) == 0xF00) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+  if ((X & 0xFF) != 0xF00) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true
+  if ((X | 0xFF) == 0xF00) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+  if ((X | 0xFF) != 0xF00) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true
+
+  if ((X | 0xFFULL) != 0xF00) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: logical expression is always true
+  if ((X | 0xFF) != 0xF00ULL) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true
+
+  if ((0xFF & X) == 0xF00) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+  if ((0xFF & X) != 0xF00) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true
+  if ((0xFF & X) == 0xF00) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+  if ((0xFF & X) != 0xF00) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true
+
+  if ((0xFFLL & X) == 0xF00) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: logical expression is always false
+  if ((0xFF & X) == 0xF00ULL) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+
+  return 0;
+}
+
+// Overloaded operators that compare an instance of a struct and an integer
+// constant.
+struct S {
+  S() { x = 1; }
+  int x;
+  // Overloaded comparison operators without any possible side effect.
+  bool operator==(const int &i) const { return x == i; } // not modifying
+  bool operator!=(int i) const { return x != i; } // not modifying
+  bool operator>(const int &i) const { return x > i; } // not modifying
+  bool operator<(int i) const { return x < i; } // not modifying
+};
+
+bool operator<=(const S &s, int i) { return s.x <= i; } // not modifying
+bool operator>=(const S &s, const int &i) { return s.x >= i; } // not modifying
+
+struct S2 {
+  S2() { x = 1; }
+  int x;
+  // Overloaded comparison operators that are able to modify their params.
+  bool operator==(const int &i) {
+    this->x++;
+    return x == i;
+  }
+  bool operator!=(int i) { return x != i; }
+  bool operator>(const int &i) { return x > i; }
+  bool operator<(int i) {
+    this->x--;
+    return x < i;
+  }
+};
+
+bool operator>=(S2 &s, const int &i) { return s.x >= i; }
+bool operator<=(S2 &s, int i) {
+  s.x++;
+  return s.x <= i;
+}
+
+int TestLogical(int X, int Y){
+#define CONFIG 0
+  if (CONFIG && X) return 1;
+#undef CONFIG
+#define CONFIG 1
+  if (CONFIG || X) return 1;
+#undef CONFIG
+
+  if (X == 10 && X != 10) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
+  if (X == 10 && (X != 10)) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
+  if (X == 10 && !(X == 10)) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
+  if (!(X != 10) && !(X == 10)) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+
+  if (X == 10ULL && X != 10ULL) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+  if (!(X != 10U) && !(X == 10)) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: logical expression is always false
+  if (!(X != 10LL) && !(X == 10)) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: logical expression is always false
+  if (!(X != 10ULL) && !(X == 10)) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: logical expression is always false
+
+  if (X == 0 && X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
+  if (X != 0 && !X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
+  if (X && !X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always false
+
+  if (X && !!X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: equivalent expression on both sides of logical operator
+  if (X != 0 && X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator
+  if (X != 0 && !!X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator
+  if (X == 0 && !X) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator
+
+  // Should not match.
+  if (X == 10 && Y == 10) return 1;
+  if (X != 10 && X != 12) return 1;
+  if (X == 10 || X == 12) return 1;
+  if (!X && !Y) return 1;
+  if (!X && Y) return 1;
+  if (!X && Y == 0) return 1;
+  if (X == 10 && Y != 10) return 1;
+
+  // Test for overloaded operators with constant params.
+  S s1;
+  if (s1 == 1 && s1 == 1) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: equivalent expression on both sides of logical operator
+  if (s1 == 1 || s1 != 1) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true
+  if (s1 > 1 && s1 < 1) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
+  if (s1 >= 1 || s1 <= 1) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true
+
+  // Test for overloaded operators that may modify their params.
+  S2 s2;
+  if (s2 == 1 || s2 != 1) return true;
+  if (s2 == 1 || s2 == 1) return true;
+  if (s2 > 1 && s2 < 1) return true;
+  if (s2 >= 1 || s2 <= 1) return true;
+}
+
+int TestRelational(int X, int Y) {
+  if (X == 10 && X > 10) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
+  if (X == 10 && X < 10) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
+  if (X < 10 && X > 10) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
+  if (X <= 10 && X > 10) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
+  if (X < 10 && X >= 10) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
+  if (X < 10 && X == 10) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
+
+  if (X > 5 && X <= 5) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
+  if (X > -5 && X <= -5) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
+
+  if (X < 10 || X >= 10) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always true
+  if (X <= 10 || X > 10) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true
+  if (X <= 10 || X >= 11) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true
+  if (X != 7 || X != 14) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always true
+  if (X == 7 || X != 5) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+  if (X != 7 || X == 7) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always true
+
+  if (X < 7 && X < 6) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+  if (X < 7 && X < 7) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+  if (X < 7 && X < 8) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant
+
+  if (X < 7 && X <= 5) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+  if (X < 7 && X <= 6) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: equivalent expression on both sides of logical operator
+  if (X < 7 && X <= 7) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant
+  if (X < 7 && X <= 8) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant
+
+  if (X <= 7 && X < 6) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+  if (X <= 7 && X < 7) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+  if (X <= 7 && X < 8) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator
+
+  if (X >= 7 && X > 6) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator
+  if (X >= 7 && X > 7) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+  if (X >= 7 && X > 8) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+
+  if (X <= 7 && X <= 5) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+  if (X <= 7 && X <= 6) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+  if (X <= 7 && X <= 7) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
+  if (X <= 7 && X <= 8) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: expression is redundant
+
+  if (X == 11 && X > 10) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: expression is redundant
+  if (X == 11 && X < 12) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: expression is redundant
+  if (X > 10 && X == 11) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+  if (X < 12 && X == 11) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+
+  if (X != 11 && X == 42) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+  if (X != 11 && X > 11) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+  if (X != 11 && X < 11) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+  if (X != 11 && X < 8) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+  if (X != 11 && X > 14) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+
+  if (X < 7 || X < 6) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant
+  if (X < 7 || X < 7) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+  if (X < 7 || X < 8) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+
+  if (X > 7 || X > 6) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+  if (X > 7 || X > 7) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+  if (X > 7 || X > 8) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant
+
+  // Should not match.
+  if (X < 10 || X > 12) return 1;
+  if (X > 10 && X < 12) return 1;
+  if (X < 10 || X >= 12) return 1;
+  if (X > 10 && X <= 12) return 1;
+  if (X <= 10 || X > 12) return 1;
+  if (X >= 10 && X < 12) return 1;
+  if (X <= 10 || X >= 12) return 1;
+  if (X >= 10 && X <= 12) return 1;
+  if (X >= 10 && X <= 11) return 1;
+  if (X >= 10 && X < 11) return 1;
+  if (X > 10 && X <= 11) return 1;
+  if (X > 10 && X != 11) return 1;
+  if (X >= 10 && X <= 10) return 1;
+  if (X <= 10 && X >= 10) return 1;
+  if (X < 0 || X > 0) return 1;
+}
+
+int TestRelationalMacros(int X){
+#define SOME_MACRO 3
+#define SOME_MACRO_SAME_VALUE 3
+#define SOME_OTHER_MACRO 9
+  // Do not match for redundant relational macro expressions that can be
+  // considered intentional, and for some particular values, non redundant.
+
+  // Test cases for expressions with the same macro on both sides.
+  if (X < SOME_MACRO && X > SOME_MACRO) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always false
+  if (X < SOME_MACRO && X == SOME_MACRO) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always false
+  if (X < SOME_MACRO || X >= SOME_MACRO) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always true
+  if (X <= SOME_MACRO || X > SOME_MACRO) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: logical expression is always true
+  if (X != SOME_MACRO && X > SOME_MACRO) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+  if (X != SOME_MACRO && X < SOME_MACRO) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
+
+  // Test cases for two different macros.
+  if (X < SOME_MACRO && X > SOME_OTHER_MACRO) return 1;
+  if (X != SOME_MACRO && X >= SOME_OTHER_MACRO) return 1;
+  if (X != SOME_MACRO && X != SOME_OTHER_MACRO) return 1;
+  if (X == SOME_MACRO || X == SOME_MACRO_SAME_VALUE) return 1;
+  if (X == SOME_MACRO || X <= SOME_MACRO_SAME_VALUE) return 1;
+  if (X == SOME_MACRO || X > SOME_MACRO_SAME_VALUE) return 1;
+  if (X < SOME_MACRO && X <= SOME_OTHER_MACRO) return 1;
+  if (X == SOME_MACRO && X > SOME_OTHER_MACRO) return 1;
+  if (X == SOME_MACRO && X != SOME_OTHER_MACRO) return 1;
+  if (X == SOME_MACRO && X != SOME_MACRO_SAME_VALUE) return 1;
+  if (X == SOME_MACRO_SAME_VALUE && X == SOME_MACRO ) return 1;
+
+  // Test cases for a macro and a const.
+  if (X < SOME_MACRO && X > 9) return 1;
+  if (X != SOME_MACRO && X >= 9) return 1;
+  if (X != SOME_MACRO && X != 9) return 1;
+  if (X == SOME_MACRO || X == 3) return 1;
+  if (X == SOME_MACRO || X <= 3) return 1;
+  if (X < SOME_MACRO && X <= 9) return 1;
+  if (X == SOME_MACRO && X != 9) return 1;
+  if (X == SOME_MACRO && X == 9) return 1;
+
+#undef SOME_OTHER_MACRO
+#undef SOME_MACRO_SAME_VALUE
+#undef SOME_MACRO
+  return 0;
+}
+
+int TestValidExpression(int X) {
+  if (X - 1 == 1 - X) return 1;
+  if (2 * X == X) return 1;
+  if ((X << 1) == X) return 1;
+
+  return 0;
+}
+
+enum Color { Red, Yellow, Green };
+int TestRelationalWithEnum(enum Color C) {
+  if (C == Red && C == Yellow) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always false
+  if (C == Red && C != Red) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always false
+  if (C != Red || C != Yellow) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always true
+
+  // Should not match.
+  if (C == Red || C == Yellow) return 1;
+  if (C != Red && C != Yellow) return 1;
+
+  return 0;
+}
+
+template<class T>
+int TestRelationalTemplated(int X) {
+  // This test causes a corner case with |isIntegerConstantExpr| where the type
+  // is dependent. There is an assert failing when evaluating
+  // sizeof(<incomplet-type>).
+  if (sizeof(T) == 4 || sizeof(T) == 8) return 1;
+
+  if (X + 0 == -X) return 1;
+  if (X + 0 < X) return 1;
+
+  return 0;
+}
+
+int TestWithSignedUnsigned(int X) {
+  if (X + 1 == X + 1ULL) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
+
+  if ((X & 0xFFU) == 0xF00) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: logical expression is always false
+
+  if ((X & 0xFF) == 0xF00U) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
+
+  if ((X & 0xFFU) == 0xF00U) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: logical expression is always false
+
+  return 0;
+}
+
+int TestWithLong(int X, I64 Y) {
+  if (X + 0ULL == -X) return 1;
+  if (Y + 0 == -Y) return 1;
+  if (Y <= 10 && X >= 10LL) return 1;
+  if (Y <= 10 && X >= 10ULL) return 1;
+  if (X <= 10 || X > 12LL) return 1;
+  if (X <= 10 || X > 12ULL) return 1;
+  if (Y <= 10 || Y > 12) return 1;
+
+  return 0;
+}
+
+int TestWithMinMaxInt(int X) {
+  if (X <= X + 0xFFFFFFFFU) return 1;
+  if (X <= X + 0x7FFFFFFF) return 1;
+  if (X <= X + 0x80000000) return 1;
+
+  if (X <= 0xFFFFFFFFU && X > 0) return 1;
+  if (X <= 0xFFFFFFFFU && X > 0U) return 1;
+
+  if (X + 0x80000000 == X - 0x80000000) return 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always true
+
+  if (X > 0x7FFFFFFF || X < ((-0x7FFFFFFF)-1)) return 1;
+  if (X <= 0x7FFFFFFF && X >= ((-0x7FFFFFFF)-1)) return 1;
+
+  return 0;
+}
+
+#define FLAG1 1
+#define FLAG2 2
+#define FLAG3 4
+#define FLAGS (FLAG1 | FLAG2 | FLAG3)
+#define NOTFLAGS !(FLAG1 | FLAG2 | FLAG3)
+int operatorConfusion(int X, int Y, long Z)
+{
+  // Ineffective & expressions.
+  Y = (Y << 8) & 0xff;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and operation
+  Y = (Y << 12) & 0xfff;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and
+  Y = (Y << 12) & 0xff;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and
+  Y = (Y << 8) & 0x77;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and
+  Y = (Y << 5) & 0x11;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and
+
+  // Tests for unmatched types
+  Z = (Z << 8) & 0xff;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and operation
+  Y = (Y << 12) & 0xfffL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and
+  Z = (Y << 12) & 0xffLL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and
+  Y = (Z << 8L) & 0x77L;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and
+
+  Y = (Y << 8) & 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and
+
+  Y = (Y << 8) & -1;
+
+  // Effective expressions. Do not check.
+  Y = (Y << 4) & 0x15;
+  Y = (Y << 3) & 0x250;
+  Y = (Y << 9) & 0xF33;
+
+  int K = !(1 | 2 | 4);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: ineffective logical negation operator used; did you mean '~'?
+  // CHECK-FIXES: {{^}}  int K = ~(1 | 2 | 4);{{$}}
+  K = !(FLAG1 & FLAG2 & FLAG3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: ineffective logical negation operator
+  // CHECK-FIXES: {{^}}  K = ~(FLAG1 & FLAG2 & FLAG3);{{$}}
+  K = !(3 | 4);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: ineffective logical negation operator
+  // CHECK-FIXES: {{^}}  K = ~(3 | 4);{{$}}
+  int NotFlags = !FLAGS;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: ineffective logical negation operator
+  // CHECK-FIXES: {{^}}  int NotFlags = ~FLAGS;{{$}}
+  NotFlags = NOTFLAGS;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: ineffective logical negation operator
+  return !(1 | 2 | 4);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: ineffective logical negation operator
+  // CHECK-FIXES: {{^}}  return ~(1 | 2 | 4);{{$}}
+}
+#undef FLAG1
+#undef FLAG2
+#undef FLAG3
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-static-assert.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-static-assert.c
new file mode 100644
index 0000000..e3e8304
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-static-assert.c
@@ -0,0 +1,27 @@
+// RUN: %check_clang_tidy %s misc-static-assert %t -- -- -std=c11
+// RUN: clang-tidy %s -checks=-*,misc-static-assert -- -std=c99 | count 0
+
+void abort() {}
+#ifdef NDEBUG
+#define assert(x) 1
+#else
+#define assert(x)                                                              \
+  if (!(x))                                                                    \
+  abort()
+#endif
+
+void f(void) {
+  int x = 1;
+  assert(x == 0);
+  // CHECK-FIXES: {{^  }}assert(x == 0);
+
+  #define static_assert(x, msg) _Static_assert(x, msg)
+  assert(11 == 5 + 6);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+  // CHECK-FIXES: {{^  }}static_assert(11 == 5 + 6, "");
+  #undef static_assert
+
+  assert(10 == 5 + 5);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+  // CHECK-FIXES: {{^  }}static_assert(10 == 5 + 5, "");
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-static-assert.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-static-assert.cpp
new file mode 100644
index 0000000..85ae053
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-static-assert.cpp
@@ -0,0 +1,143 @@
+// RUN: %check_clang_tidy %s misc-static-assert %t
+
+void abort() {}
+#ifdef NDEBUG
+#define assert(x) 1
+#else
+#define assert(x)                                                              \
+  if (!(x))                                                                    \
+  abort()
+#endif
+
+void print(...);
+
+#define ZERO_MACRO 0
+
+#define False false
+#define FALSE 0
+
+#define my_macro() assert(0 == 1)
+// CHECK-FIXES: #define my_macro() assert(0 == 1)
+
+constexpr bool myfunc(int a, int b) { return a * b == 0; }
+
+typedef __SIZE_TYPE__ size_t;
+extern "C" size_t strlen(const char *s);
+
+class A {
+public:
+  bool method() { return true; }
+};
+
+class B {
+public:
+  constexpr bool method() { return true; }
+};
+
+template <class T> void doSomething(T t) {
+  assert(myfunc(1, 2));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be replaced by static_assert() [misc-static-assert]
+  // CHECK-FIXES: {{^  }}static_assert(myfunc(1, 2), "");
+
+  assert(t.method());
+  // CHECK-FIXES: {{^  }}assert(t.method());
+
+  assert(sizeof(T) == 123);
+}
+
+int main() {
+  my_macro();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+  // CHECK-FIXES: {{^  }}my_macro();
+
+  assert(myfunc(1, 2) && (3 == 4));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+  // CHECK-FIXES: {{^  }}static_assert(myfunc(1, 2) && (3 == 4), "");
+
+  int x = 1;
+  assert(x == 0);
+  // CHECK-FIXES: {{^  }}assert(x == 0);
+
+  A a;
+  B b;
+
+  doSomething<A>(a);
+  doSomething<B>(b);
+
+  assert(false);
+  // CHECK-FIXES: {{^  }}assert(false);
+
+  assert(False);
+  // CHECK-FIXES: {{^  }}assert(False);
+  assert(FALSE);
+  // CHECK-FIXES: {{^  }}assert(FALSE);
+
+  assert(ZERO_MACRO);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+  // CHECK-FIXES: {{^  }}static_assert(ZERO_MACRO, "");
+
+  assert(!"Don't report me!");
+  // CHECK-FIXES: {{^  }}assert(!"Don't report me!");
+
+  assert(0 && "Don't report me!");
+  // CHECK-FIXES: {{^  }}assert(0 && "Don't report me!");
+
+  assert(false && "Don't report me!");
+  // CHECK-FIXES: {{^  }}assert(false && "Don't report me!");
+
+#define NULL ((void*)0)
+  assert(NULL && "Don't report me!");
+  // CHECK-FIXES: {{^  }}assert(NULL && "Don't report me!");
+
+  assert(NULL == "Don't report me!");
+  // CHECK-FIXES: {{^  }}assert(NULL == "Don't report me!");
+
+  assert("Don't report me!" == NULL);
+  // CHECK-FIXES: {{^  }}assert("Don't report me!" == NULL);
+
+  assert(0 == "Don't report me!");
+  // CHECK-FIXES: {{^  }}assert(0 == "Don't report me!");
+
+#define NULL ((unsigned int)0)
+  assert(NULL && "Report me!");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+  // CHECK-FIXES: {{^  }}static_assert(NULL , "Report me!");
+
+#define NULL __null
+  assert(__null == "Don't report me!");
+  // CHECK-FIXES: {{^  }}assert(__null == "Don't report me!");
+  assert(NULL == "Don't report me!");
+  // CHECK-FIXES: {{^  }}assert(NULL == "Don't report me!");
+#undef NULL
+
+  assert(ZERO_MACRO && "Report me!");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+  // CHECK-FIXES: {{^  }}static_assert(ZERO_MACRO , "Report me!");
+
+  assert(0);
+
+#define false false
+  assert(false);
+
+#define false 0
+  assert(false);
+#undef false
+
+  assert(10==5 && "Report me!");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+  // CHECK-FIXES: {{^  }}static_assert(10==5 , "Report me!");
+
+  assert(strlen("12345") == 5);
+  // CHECK-FIXES: {{^  }}assert(strlen("12345") == 5);
+
+#define assert(e) (__builtin_expect(!(e), 0) ? print (#e, __FILE__, __LINE__) : (void)0)
+  assert(false);
+  // CHECK-FIXES: {{^  }}assert(false);
+
+  assert(10 == 5 + 5);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be
+  // CHECK-FIXES: {{^  }}static_assert(10 == 5 + 5, "");
+#undef assert
+
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-throw-by-value-catch-by-reference.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-throw-by-value-catch-by-reference.cpp
new file mode 100644
index 0000000..120b07e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-throw-by-value-catch-by-reference.cpp
@@ -0,0 +1,156 @@
+// RUN: %check_clang_tidy %s misc-throw-by-value-catch-by-reference %t -- -- -std=c++11 -fcxx-exceptions
+
+
+class logic_error {
+public:
+  logic_error(const char *message) {}
+};
+
+typedef logic_error *logic_ptr;
+typedef logic_ptr logic_double_typedef;
+
+int lastException;
+
+template <class T> struct remove_reference { typedef T type; };
+template <class T> struct remove_reference<T &> { typedef T type; };
+template <class T> struct remove_reference<T &&> { typedef T type; };
+
+template <typename T> typename remove_reference<T>::type &&move(T &&arg) {
+  return static_cast<typename remove_reference<T>::type &&>(arg);
+}
+
+logic_error CreateException() { return logic_error("created"); }
+
+void testThrowFunc() {
+  throw new logic_error("by pointer");
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression throws a pointer; it should throw a non-pointer value instead [misc-throw-by-value-catch-by-reference]
+  logic_ptr tmp = new logic_error("by pointer");
+  throw tmp;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: throw expression throws a pointer; it should throw a non-pointer value instead [misc-throw-by-value-catch-by-reference]
+  throw logic_error("by value");
+  auto *literal = "test";
+  throw logic_error(literal);
+  throw "test string literal";
+  throw L"throw wide string literal";
+  const char *characters = 0;
+  throw characters;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: throw expression throws a pointer; it should throw a non-pointer value instead [misc-throw-by-value-catch-by-reference]
+  logic_error lvalue("lvalue");
+  throw lvalue;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]
+
+  throw move(lvalue);
+  int &ex = lastException;
+  throw ex;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]
+  throw CreateException();
+}
+
+void throwReferenceFunc(logic_error &ref) { throw ref; }
+
+void catchByPointer() {
+  try {
+    testThrowFunc();
+  } catch (logic_error *e) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: catch handler catches a pointer value; should throw a non-pointer value and catch by reference instead [misc-throw-by-value-catch-by-reference]
+  }
+}
+
+void catchByValue() {
+  try {
+    testThrowFunc();
+  } catch (logic_error e) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: catch handler catches by value; should catch by reference instead [misc-throw-by-value-catch-by-reference]
+  }
+}
+
+void catchByReference() {
+  try {
+    testThrowFunc();
+  } catch (logic_error &e) {
+  }
+}
+
+void catchByConstReference() {
+  try {
+    testThrowFunc();
+  } catch (const logic_error &e) {
+  }
+}
+
+void catchTypedef() {
+  try {
+    testThrowFunc();
+  } catch (logic_ptr) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: catch handler catches a pointer value; should throw a non-pointer value and catch by reference instead [misc-throw-by-value-catch-by-reference]
+  }
+}
+
+void catchAll() {
+  try {
+    testThrowFunc();
+  } catch (...) {
+  }
+}
+
+void catchLiteral() {
+  try {
+    testThrowFunc();
+  } catch (const char *) {
+  } catch (const wchar_t *) {
+    // disabled for now until it is clear
+    // how to enable them in the test
+    //} catch (const char16_t*) {
+    //} catch (const char32_t*) {
+  }
+}
+
+// catching fundamentals should not warn
+void catchFundamental() {
+  try {
+    testThrowFunc();
+  } catch (int) {
+  } catch (double) {
+  } catch (unsigned long) {
+  }
+}
+
+struct TrivialType {
+  double x;
+  double y;
+};
+
+void catchTrivial() {
+  try {
+    testThrowFunc();
+  } catch (TrivialType) {
+  }
+}
+
+typedef logic_error &fine;
+void additionalTests() {
+  try {
+  } catch (int i) {  // ok
+    throw i;         // ok
+  } catch (fine e) { // ok
+    throw e;         // ok
+  } catch (logic_error *e) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: catch handler catches a pointer value; should throw a non-pointer value and catch by reference instead [misc-throw-by-value-catch-by-reference]
+    throw e;      // ok, despite throwing a pointer
+  } catch (...) { // ok
+    throw;        // ok
+  }
+}
+
+struct S {};
+
+S &returnByReference();
+S returnByValue();
+
+void f() {
+  throw returnByReference(); // Should diagnose
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]
+  throw returnByValue(); // Should not diagnose
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unconventional-assign-operator-cxx17.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unconventional-assign-operator-cxx17.cpp
new file mode 100644
index 0000000..ba1a685
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unconventional-assign-operator-cxx17.cpp
@@ -0,0 +1,12 @@
+// RUN: %check_clang_tidy %s misc-unconventional-assign-operator %t -- -- -std=c++17 -fno-delayed-template-parsing
+
+struct BadModifier {
+  BadModifier& operator=(const BadModifier&) const;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should not be marked 'const'
+};
+
+struct PR35468 {
+  template<typename T> auto &operator=(const T &) {
+    return *this;
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unconventional-assign-operator.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unconventional-assign-operator.cpp
new file mode 100644
index 0000000..4bd9cb2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unconventional-assign-operator.cpp
@@ -0,0 +1,111 @@
+// RUN: %check_clang_tidy %s misc-unconventional-assign-operator %t -- -- -std=c++11 -isystem %S/Inputs/Headers -fno-delayed-template-parsing
+
+namespace std {
+template <typename T>
+struct remove_reference { typedef T type; };
+template <typename T>
+struct remove_reference<T &> { typedef T type; };
+template <typename T>
+struct remove_reference<T &&> { typedef T type; };
+template <typename T>
+typename remove_reference<T>::type &&move(T &&t);
+}
+
+
+struct Good {
+  Good& operator=(const Good&);
+  Good& operator=(Good&&);
+
+  // Assign from other types is fine too.
+  Good& operator=(int);
+};
+
+struct AlsoGood {
+  // By value is also fine.
+  AlsoGood& operator=(AlsoGood);
+};
+
+struct BadReturnType {
+  void operator=(const BadReturnType&);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'BadReturnType&' [misc-unconventional-assign-operator]
+  const BadReturnType& operator=(BadReturnType&&);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'Bad
+  void operator=(int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'Bad
+};
+
+struct BadReturnType2 {
+  BadReturnType2&& operator=(const BadReturnType2&);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'Bad
+  int operator=(BadReturnType2&&);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'Bad
+};
+
+struct BadArgument {
+  BadArgument& operator=(BadArgument&);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should take 'BadArgument const&', 'BadArgument&&' or 'BadArgument'
+  BadArgument& operator=(const BadArgument&&);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should take 'BadAr
+};
+
+struct BadModifier {
+  BadModifier& operator=(const BadModifier&) const;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should not be marked 'const'
+};
+
+struct Deleted {
+  // We don't check the return value of deleted operators.
+  void operator=(const Deleted&) = delete;
+  void operator=(Deleted&&) = delete;
+};
+
+class Private {
+  // We don't check the return value of private operators.
+  // Pre-C++11 way of disabling assignment.
+  void operator=(const Private &);
+};
+
+struct Virtual {
+  virtual Virtual& operator=(const Virtual &);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should not be marked 'virtual'
+};
+
+class BadReturnStatement {
+  int n;
+
+public:
+  BadReturnStatement& operator=(BadReturnStatement&& rhs) {
+    n = std::move(rhs.n);
+    return rhs;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: operator=() should always return '*this'
+  }
+
+  // Do not check if return type is different from '&BadReturnStatement'
+  int operator=(int i) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'Bad
+    n = i;
+    return n;
+  }
+};
+
+namespace pr31531 {
+enum E { e };
+// This declaration makes the 'return *this' below have an unresolved operator
+// in the class template, but not in an instantiation.
+E operator*(E, E);
+
+template <typename>
+struct UnresolvedOperator {
+  UnresolvedOperator &operator=(const UnresolvedOperator &) { return *this; }
+};
+
+UnresolvedOperator<int> UnresolvedOperatorInt;
+
+template <typename>
+struct Template {
+  Template &operator=(const Template &) { return this; }
+  // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: operator=() should always return '*this'
+};
+
+Template<int> TemplateInt;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-uniqueptr-reset-release.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-uniqueptr-reset-release.cpp
new file mode 100644
index 0000000..1bd6e6f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-uniqueptr-reset-release.cpp
@@ -0,0 +1,69 @@
+// RUN: %check_clang_tidy %s misc-uniqueptr-reset-release %t
+
+namespace std {
+
+template <typename T>
+struct default_delete {};
+
+template <typename T, class Deleter = std::default_delete<T>>
+struct unique_ptr {
+  unique_ptr();
+  explicit unique_ptr(T *);
+  template <typename U, typename E>
+  unique_ptr(unique_ptr<U, E> &&);
+  void reset(T *);
+  T *release();
+};
+} // namespace std
+
+struct Foo {};
+struct Bar : Foo {};
+
+std::unique_ptr<Foo> Create();
+std::unique_ptr<Foo> &Look();
+std::unique_ptr<Foo> *Get();
+
+using FooFunc = void (*)(Foo *);
+using BarFunc = void (*)(Bar *);
+
+void f() {
+  std::unique_ptr<Foo> a, b;
+  std::unique_ptr<Bar> c;
+  std::unique_ptr<Foo> *x = &a;
+  std::unique_ptr<Foo> *y = &b;
+
+  a.reset(b.release());
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: prefer ptr1 = std::move(ptr2) over ptr1.reset(ptr2.release()) [misc-uniqueptr-reset-release]
+  // CHECK-FIXES: a = std::move(b);
+  a.reset(c.release());
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: prefer ptr1 = std::move(ptr2)
+  // CHECK-FIXES: a = std::move(c);
+  a.reset(Create().release());
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: prefer ptr = ReturnUnique() over ptr.reset(ReturnUnique().release()) [misc-uniqueptr-reset-release]
+  // CHECK-FIXES: a = Create();
+  x->reset(y->release());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: prefer ptr1 = std::move(ptr2)
+  // CHECK-FIXES: *x = std::move(*y);
+  Look().reset(Look().release());
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: prefer ptr1 = std::move(ptr2)
+  // CHECK-FIXES: Look() = std::move(Look());
+  Get()->reset(Get()->release());
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: prefer ptr1 = std::move(ptr2)
+  // CHECK-FIXES: *Get() = std::move(*Get());
+
+  std::unique_ptr<Bar, FooFunc> func_a, func_b;
+  func_a.reset(func_b.release());
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: prefer ptr1 = std::move(ptr2)
+  // CHECK-FIXES: func_a = std::move(func_b);
+}
+
+void negatives() {
+  std::unique_ptr<Foo> src;
+  struct OtherDeleter {};
+  std::unique_ptr<Foo, OtherDeleter> dest;
+  dest.reset(src.release());
+
+  std::unique_ptr<Bar, FooFunc> func_a;
+  std::unique_ptr<Bar, BarFunc> func_b;
+  func_a.reset(func_b.release());
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-alias-decls.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-alias-decls.cpp
new file mode 100644
index 0000000..6d63df4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-alias-decls.cpp
@@ -0,0 +1,12 @@
+// RUN: %check_clang_tidy %s misc-unused-alias-decls %t
+
+namespace my_namespace {
+class C {};
+}
+
+namespace unused_alias = ::my_namespace; // eol-comments aren't removed (yet)
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: namespace alias decl 'unused_alias' is unused
+// CHECK-FIXES: {{^}}// eol-comments aren't removed (yet)
+
+namespace used_alias = ::my_namespace;
+void f() { used_alias::C c; }
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters-strict.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters-strict.cpp
new file mode 100644
index 0000000..a334b45
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters-strict.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s misc-unused-parameters %t -- \
+// RUN:   -config="{CheckOptions: [{key: StrictMode, value: 1}]}" --
+
+// Warn on empty function bodies in StrictMode.
+namespace strict_mode {
+void f(int foo) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'foo' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void f(int  /*foo*/) {}{{$}}
+class E {
+  int i;
+
+public:
+  E(int j) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'j' is unused
+// CHECK-FIXES: {{^}}  E(int  /*j*/) {}{{$}}
+};
+class F {
+  int i;
+
+public:
+  F(int j) : i() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'j' is unused
+// CHECK-FIXES: {{^}}  F(int  /*j*/) : i() {}{{$}}
+};
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters.c
new file mode 100644
index 0000000..d824a80
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters.c
@@ -0,0 +1,17 @@
+// RUN: %check_clang_tidy %s misc-unused-parameters %t -- -- -xc
+
+// Basic removal
+// =============
+void a(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void a(int  /*i*/) {;}{{$}}
+
+static void b(); // In C, forward declarations can leave out parameters.
+static void b(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}static void b() {;}{{$}}
+
+// Unchanged cases
+// ===============
+void h(i, c, d) int i; char *c, *d; {} // Don't mess with K&R style
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters.cpp
new file mode 100644
index 0000000..ec1ee2d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-parameters.cpp
@@ -0,0 +1,277 @@
+// RUN: echo "static void staticFunctionHeader(int i) {;}" > %T/header.h
+// RUN: echo "static void staticFunctionHeader(int  /*i*/) {;}" > %T/header-fixed.h
+// RUN: %check_clang_tidy %s misc-unused-parameters %t -- -header-filter='.*' -- -std=c++11 -fno-delayed-template-parsing
+// RUN: diff %T/header.h %T/header-fixed.h
+
+#include "header.h"
+// CHECK-MESSAGES: header.h:1:38: warning
+
+// Basic removal
+// =============
+void a(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void a(int  /*i*/) {;}{{$}}
+
+void b(int i = 1) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void b(int  /*i*/ = 1) {;}{{$}}
+
+void c(int *i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void c(int * /*i*/) {;}{{$}}
+
+void d(int i[]) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void d(int  /*i*/[]) {;}{{$}}
+
+void e(int i[1]) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void e(int  /*i*/[1]) {;}{{$}}
+
+void f(void (*fn)()) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: parameter 'fn' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void f(void (* /*fn*/)()) {;}{{$}}
+
+// Unchanged cases
+// ===============
+void f(int i); // Don't remove stuff in declarations
+void g(int i = 1);
+void h(int i[]);
+void s(int i[1]);
+void u(void (*fn)());
+void w(int i) { (void)i; } // Don't remove used parameters
+
+bool useLambda(int (*fn)(int));
+static bool static_var = useLambda([] (int a) { return a; });
+
+// Remove parameters of local functions
+// ====================================
+static void staticFunctionA(int i);
+// CHECK-FIXES: {{^}}static void staticFunctionA();
+static void staticFunctionA(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning
+// CHECK-FIXES: {{^}}static void staticFunctionA()
+
+static void staticFunctionB(int i, int j) { (void)i; }
+// CHECK-MESSAGES: :[[@LINE-1]]:40: warning
+// CHECK-FIXES: {{^}}static void staticFunctionB(int i)
+
+static void staticFunctionC(int i, int j) { (void)j; }
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning
+// CHECK-FIXES: {{^}}static void staticFunctionC(int j)
+
+static void staticFunctionD(int i, int j, int k) { (void)i; (void)k; }
+// CHECK-MESSAGES: :[[@LINE-1]]:40: warning
+// CHECK-FIXES: {{^}}static void staticFunctionD(int i, int k)
+
+static void staticFunctionE(int i = 4) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning
+// CHECK-FIXES: {{^}}static void staticFunctionE()
+
+static void staticFunctionF(int i = 4);
+// CHECK-FIXES: {{^}}static void staticFunctionF();
+static void staticFunctionF(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning
+// CHECK-FIXES: {{^}}static void staticFunctionF()
+
+static void staticFunctionG(int i[]);
+// CHECK-FIXES: {{^}}static void staticFunctionG();
+static void staticFunctionG(int i[]) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning
+// CHECK-FIXES: {{^}}static void staticFunctionG()
+
+static void staticFunctionH(void (*fn)());
+// CHECK-FIXES: {{^}}static void staticFunctionH();
+static void staticFunctionH(void (*fn)()) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:36: warning
+// CHECK-FIXES: {{^}}static void staticFunctionH()
+
+static void someCallSites() {
+  staticFunctionA(1);
+// CHECK-FIXES: staticFunctionA();
+  staticFunctionB(1, 2);
+// CHECK-FIXES: staticFunctionB(1);
+  staticFunctionC(1, 2);
+// CHECK-FIXES: staticFunctionC(2);
+  staticFunctionD(1, 2, 3);
+// CHECK-FIXES: staticFunctionD(1, 3);
+  staticFunctionE(1);
+// CHECK-FIXES: staticFunctionE();
+  staticFunctionF(1);
+// CHECK-FIXES: staticFunctionF();
+  staticFunctionF();
+// CHECK-FIXES: staticFunctionF();
+  int t[] = {1};
+  staticFunctionG(t);
+// CHECK-FIXES: staticFunctionG();
+  void func();
+  staticFunctionH(&func);
+// CHECK-FIXES: staticFunctionH();
+}
+
+/*
+ * FIXME: This fails because the removals overlap and ClangTidy doesn't apply
+ *        them.
+ * static void bothVarsUnused(int a, int b) {;}
+ */
+
+// Regression test for long variable names and expressions
+// =======================================================
+static int variableWithLongName1(int LongName1, int LongName2) {
+// CHECK-MESSAGES: :[[@LINE-1]]:53: warning: parameter 'LongName2' is unused
+// CHECK-FIXES: {{^}}static int variableWithLongName1(int LongName1) {
+  return LongName1;
+}
+static int variableWithLongName2(int LongName1, int LongName2) {
+// CHECK-MESSAGES: :[[@LINE-1]]:38: warning: parameter 'LongName1' is unused
+// CHECK-FIXES: {{^}}static int variableWithLongName2(int LongName2) {
+  return LongName2;
+}
+static void someLongNameCallSites() {
+  int LongName1 = 7, LongName2 = 17;
+  variableWithLongName1(LongName1, LongName2);
+// CHECK-FIXES: variableWithLongName1(LongName1);
+  variableWithLongName2(LongName1, LongName2);
+// CHECK-FIXES: variableWithLongName2(LongName2);
+}
+
+class SomeClass {
+  static void f(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning
+// CHECK-FIXES: static void f(int  /*i*/) {;}
+  static void g(int i = 1) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning
+// CHECK-FIXES: static void g(int  /*i*/ = 1) {;}
+  static void h(int i[]) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning
+// CHECK-FIXES: static void h(int  /*i*/[]) {;}
+  static void s(void (*fn)()) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning
+// CHECK-FIXES: static void s(void (* /*fn*/)()) {;}
+};
+
+namespace {
+class C {
+public:
+  void f(int i);
+// CHECK-FIXES: void f();
+  void g(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning
+// CHECK-FIXES: void g() {;}
+  void h(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning
+// CHECK-FIXES: void h(int  /*i*/) {;}
+  void s(int i = 1) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning
+// CHECK-FIXES: void s(int  /*i*/ = 1) {;}
+  void u(int i[]) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning
+// CHECK-FIXES: void u(int  /*i*/[]) {;}
+  void w(void (*fn)()) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning
+// CHECK-FIXES: void w(void (* /*fn*/)()) {;}
+};
+
+void C::f(int i) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning
+// CHECK-FIXES: void C::f() {;}
+
+template <typename T>
+void useFunction(T t);
+
+void someMoreCallSites() {
+  C c;
+  c.f(1);
+// CHECK-FIXES: c.f();
+  c.g(1);
+// CHECK-FIXES: c.g();
+
+  useFunction(&C::h);
+  useFunction(&C::s);
+  useFunction(&C::u);
+  useFunction(&C::w);
+}
+
+class Base {
+  virtual void f(int i);
+};
+
+class Derived : public Base {
+  void f(int i) override {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning
+// CHECK-FIXES: void f(int  /*i*/) override {;}
+};
+
+} // end namespace
+
+template <typename T> void someFunctionTemplate(T b, T e) { (void)b; (void)e; }
+
+template <typename T> void someFunctionTemplateOneUnusedParam(T b, T e) { (void)e; }
+// CHECK-MESSAGES: :[[@LINE-1]]:65: warning
+// CHECK-FIXES: {{^}}template <typename T> void someFunctionTemplateOneUnusedParam(T  /*b*/, T e) { (void)e; }
+
+template <typename T> void someFunctionTemplateAllUnusedParams(T b, T e) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:66: warning
+// CHECK-MESSAGES: :[[@LINE-2]]:71: warning
+// CHECK-FIXES: {{^}}template <typename T> void someFunctionTemplateAllUnusedParams(T  /*b*/, T  /*e*/) {;}
+
+static void dontGetConfusedByParametersInFunctionTypes() { void (*F)(int i); }
+
+template <typename T> class Function {};
+static Function<void(int, int i)> dontGetConfusedByFunctionReturnTypes() {
+  return Function<void(int, int)>();
+}
+
+namespace PR38055 {
+namespace {
+struct a {
+  void b(int c) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: parameter 'c' is unused
+// CHECK-FIXES: {{^}}  void b() {;}{{$}}
+};
+template <class>
+class d {
+  a e;
+  void f() { e.b(); }
+};
+}  // namespace
+}  // namespace PR38055
+
+namespace strict_mode_off {
+// Do not warn on empty function bodies.
+void f1(int foo1) {}
+void f2(int foo2) {
+  // "empty" in the AST sense, not in textual sense.
+}
+void f3(int foo3) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: parameter 'foo3' is unused
+// CHECK-FIXES: {{^}}void f3(int  /*foo3*/) {;}{{$}}
+
+class E {
+  int i;
+
+public:
+  E(int j) {}
+};
+class F {
+  int i;
+
+public:
+  // Constructor initializer counts as a non-empty body.
+  F(int j) : i() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'j' is unused
+// CHECK-FIXES: {{^}}  F(int  /*j*/) : i() {}{{$}}
+};
+
+class A {
+public:
+  A();
+  A(int);
+};
+class B : public A {
+public:
+  B(int i) : A() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is unused
+// CHECK-FIXES: {{^}}  B(int  /*i*/) : A() {}{{$}}
+};
+} // namespace strict_mode_off
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-using-decls-errors.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-using-decls-errors.cpp
new file mode 100644
index 0000000..1c26a69
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-using-decls-errors.cpp
@@ -0,0 +1,12 @@
+// RUN: %check_clang_tidy -expect-clang-tidy-error %s misc-unused-using-decls %t
+
+namespace n {
+class C;
+}
+
+using n::C;
+
+void f() {
+  for (C *p : unknown()) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: error: use of undeclared identifier 'unknown' [clang-diagnostic-error]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-using-decls.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-using-decls.cpp
new file mode 100644
index 0000000..65ef0da
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/misc-unused-using-decls.cpp
@@ -0,0 +1,203 @@
+// RUN: %check_clang_tidy %s misc-unused-using-decls %t -- -- -fno-delayed-template-parsing -isystem %S/Inputs/
+
+
+// ----- Definitions -----
+template <typename T> class vector {};
+namespace n {
+class A;
+class B;
+class C;
+class D;
+class D { public: static int i; };
+template <typename T> class E {};
+template <typename T> class F {};
+class G { public: static void func() {} };
+class H { public: static int i; };
+class I {
+ public:
+  static int ii;
+};
+template <typename T> class J {};
+class G;
+class H;
+
+template <typename T> class K {};
+template <template <typename> class S>
+class L {};
+
+template <typename T> class M {};
+class N {};
+
+template <int T> class P {};
+const int Constant = 0;
+
+class Base {
+ public:
+  void f();
+};
+
+D UsedInstance;
+D UnusedInstance;
+
+int UsedFunc() { return 1; }
+int UnusedFunc() { return 1; }
+template <typename T> int UsedTemplateFunc() { return 1; }
+template <typename T> int UnusedTemplateFunc() { return 1; }
+template <typename T> int UsedInTemplateFunc() { return 1; }
+void OverloadFunc(int);
+void OverloadFunc(double);
+int FuncUsedByUsingDeclInMacro() { return 1; }
+
+class ostream {
+public:
+  ostream &operator<<(ostream &(*PF)(ostream &));
+};
+extern ostream cout;
+ostream &endl(ostream &os);
+
+enum Color1 { Green };
+
+enum Color2 { Red };
+
+enum Color3 { Yellow };
+
+enum Color4 { Blue };
+
+}  // namespace n
+
+#include "unused-using-decls.h"
+namespace ns {
+template <typename T>
+class AA {
+  T t;
+};
+template <typename T>
+T ff() { T t; return t; }
+} // namespace ns
+
+// ----- Using declarations -----
+// eol-comments aren't removed (yet)
+using n::A; // A
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'A' is unused
+// CHECK-FIXES: {{^}}// A
+using n::B;
+using n::C;
+using n::D;
+using n::E; // E
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'E' is unused
+// CHECK-FIXES: {{^}}// E
+using n::F;
+using n::G;
+using n::H;
+using n::I;
+int I::ii = 1;
+class Derived : public n::Base {
+ public:
+  using Base::f;
+};
+using n::UsedInstance;
+using n::UsedFunc;
+using n::UsedTemplateFunc;
+using n::UnusedInstance; // UnusedInstance
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'UnusedInstance' is unused
+// CHECK-FIXES: {{^}}// UnusedInstance
+using n::UnusedFunc; // UnusedFunc
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'UnusedFunc' is unused
+// CHECK-FIXES: {{^}}// UnusedFunc
+using n::cout;
+using n::endl;
+
+using n::UsedInTemplateFunc;
+using n::J;
+template <typename T> void Callee() {
+  J<T> j;
+  UsedInTemplateFunc<T>();
+}
+
+using n::OverloadFunc; // OverloadFunc
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'OverloadFunc' is unused
+// CHECK-FIXES: {{^}}// OverloadFunc
+
+#define DEFINE_INT(name)        \
+  namespace INT {               \
+  static const int _##name = 1; \
+  }                             \
+  using INT::_##name
+DEFINE_INT(test);
+#undef DEFIND_INT
+
+#define USING_FUNC \
+  using n::FuncUsedByUsingDeclInMacro;
+USING_FUNC
+#undef USING_FUNC
+
+namespace N1 {
+// n::G is used in namespace N2.
+// Currently, the check doesn't support multiple scopes. All the relevant
+// using-decls will be marked as used once we see an usage even the usage is in
+// other scope.
+using n::G;
+}
+
+namespace N2 {
+using n::G;
+void f(G g);
+}
+
+void IgnoreFunctionScope() {
+// Using-decls defined in function scope will be ignored.
+using n::H;
+}
+
+using n::Color1;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'Color1' is unused
+using n::Green;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'Green' is unused
+using n::Color2;
+using n::Color3;
+using n::Blue;
+
+using ns::AA;
+using ns::ff;
+
+using n::K;
+
+using n::N;
+
+// FIXME: Currently non-type template arguments are not supported.
+using n::Constant;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using decl 'Constant' is unused
+
+// ----- Usages -----
+void f(B b);
+void g() {
+  vector<C> data;
+  D::i = 1;
+  F<int> f;
+  void (*func)() = &G::func;
+  int *i = &H::i;
+  UsedInstance.i;
+  UsedFunc();
+  UsedTemplateFunc<int>();
+  cout << endl;
+  Color2 color2;
+  int t1 = Color3::Yellow;
+  int t2 = Blue;
+
+  MyClass a;
+  int t3 = 0;
+  a.func1<AA>(&t3);
+  a.func2<int, ff>(t3);
+
+  n::L<K> l;
+}
+
+template<class T>
+void h(n::M<T>* t) {}
+// n::N is used the explicit template instantiation.
+template void h(n::M<N>* t);
+
+// Test on Non-type template arguments.
+template <int T>
+void i(n::P<T>* t) {}
+template void i(n::P<Constant>* t);
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-avoid-bind.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-avoid-bind.cpp
new file mode 100644
index 0000000..1c78b9e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-avoid-bind.cpp
@@ -0,0 +1,79 @@
+// RUN: %check_clang_tidy %s modernize-avoid-bind %t -- -- -std=c++14
+
+namespace std {
+inline namespace impl {
+template <class Fp, class... Arguments>
+class bind_rt {};
+
+template <class Fp, class... Arguments>
+bind_rt<Fp, Arguments...> bind(Fp &&, Arguments &&...);
+}
+}
+
+int add(int x, int y) { return x + y; }
+
+void f() {
+  auto clj = std::bind(add, 2, 2);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind [modernize-avoid-bind]
+  // CHECK-FIXES: auto clj = [] { return add(2, 2); };
+}
+
+void g() {
+  int x = 2;
+  int y = 2;
+  auto clj = std::bind(add, x, y);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind
+  // CHECK-FIXES: auto clj = [=] { return add(x, y); };
+}
+
+struct placeholder {};
+placeholder _1;
+placeholder _2;
+
+void h() {
+  int x = 2;
+  auto clj = std::bind(add, x, _1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind
+  // CHECK-FIXES: auto clj = [=](auto && arg1) { return add(x, arg1); };
+}
+
+struct A;
+struct B;
+bool ABTest(const A &, const B &);
+
+void i() {
+  auto BATest = std::bind(ABTest, _2, _1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: prefer a lambda to std::bind
+  // CHECK-FIXES: auto BATest = [](auto && arg1, auto && arg2) { return ABTest(arg2, arg1); };
+}
+
+void j() {
+  auto clj = std::bind(add, 2, 2, 2);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind
+  // No fix is applied for argument mismatches.
+  // CHECK-FIXES: auto clj = std::bind(add, 2, 2, 2);
+}
+
+void k() {
+  auto clj = std::bind(add, _1, _1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind
+  // No fix is applied for reused placeholders.
+  // CHECK-FIXES: auto clj = std::bind(add, _1, _1);
+}
+
+void m() {
+  auto clj = std::bind(add, 1, add(2, 5));
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind
+  // No fix is applied for nested calls.
+  // CHECK-FIXES: auto clj = std::bind(add, 1, add(2, 5));
+}
+
+namespace C {
+  int add(int x, int y){ return x + y; }
+}
+
+void n() {
+  auto clj = std::bind(C::add, 1, 1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind
+  // CHECK-FIXES: auto clj = [] { return C::add(1, 1); };
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-deprecated-headers-cxx03.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-deprecated-headers-cxx03.cpp
new file mode 100644
index 0000000..c604ba4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-deprecated-headers-cxx03.cpp
@@ -0,0 +1,148 @@
+// RUN: %check_clang_tidy %s modernize-deprecated-headers %t -- -extra-arg-before=-isystem%S/Inputs/modernize-deprecated-headers -- -std=c++03 -v
+
+#include <assert.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'assert.h'; consider using 'cassert' instead [modernize-deprecated-headers]
+// CHECK-FIXES: {{^}}#include <cassert>{{$}}
+#include <complex.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'complex.h'; consider using 'complex' instead
+// CHECK-FIXES: {{^}}#include <complex>{{$}}
+#include <ctype.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'ctype.h'; consider using 'cctype' instead
+// CHECK-FIXES: {{^}}#include <cctype>{{$}}
+#include <errno.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'errno.h'; consider using 'cerrno' instead
+// CHECK-FIXES: {{^}}#include <cerrno>{{$}}
+#include <float.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'float.h'; consider using 'cfloat' instead
+// CHECK-FIXES: {{^}}#include <cfloat>{{$}}
+#include <limits.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'limits.h'; consider using 'climits' instead
+// CHECK-FIXES: {{^}}#include <climits>{{$}}
+#include <locale.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'locale.h'; consider using 'clocale' instead
+// CHECK-FIXES: {{^}}#include <clocale>{{$}}
+#include <math.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'math.h'; consider using 'cmath' instead
+// CHECK-FIXES: {{^}}#include <cmath>{{$}}
+#include <setjmp.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'setjmp.h'; consider using 'csetjmp' instead
+// CHECK-FIXES: {{^}}#include <csetjmp>{{$}}
+#include <signal.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'signal.h'; consider using 'csignal' instead
+// CHECK-FIXES: {{^}}#include <csignal>{{$}}
+#include <stdarg.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdarg.h'; consider using 'cstdarg' instead
+// CHECK-FIXES: {{^}}#include <cstdarg>{{$}}
+#include <stddef.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stddef.h'; consider using 'cstddef' instead
+// CHECK-FIXES: {{^}}#include <cstddef>{{$}}
+#include <stdio.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdio.h'; consider using 'cstdio' instead
+// CHECK-FIXES: {{^}}#include <cstdio>{{$}}
+#include <stdlib.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdlib.h'; consider using 'cstdlib' instead
+// CHECK-FIXES: {{^}}#include <cstdlib>{{$}}
+#include <string.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'string.h'; consider using 'cstring' instead
+// CHECK-FIXES: {{^}}#include <cstring>{{$}}
+#include <time.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'time.h'; consider using 'ctime' instead
+// CHECK-FIXES: {{^}}#include <ctime>{{$}}
+#include <wchar.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wchar.h'; consider using 'cwchar' instead
+// CHECK-FIXES: {{^}}#include <cwchar>{{$}}
+#include <wctype.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wctype.h'; consider using 'cwctype' instead
+// CHECK-FIXES: {{^}}#include <cwctype>{{$}}
+
+// Headers that have no effect in C++; remove them
+#include <stdalign.h> // <stdalign.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdalign.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// <stdalign.h>{{$}}
+#include <stdbool.h> // <stdbool.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdbool.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// <stdbool.h>{{$}}
+#include <iso646.h> // <iso646.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'iso646.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// <iso646.h>{{$}}
+
+// Headers deprecated since C++11: expect no diagnostics.
+#include <fenv.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <tgmath.h>
+#include <uchar.h>
+
+
+#include "assert.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'assert.h'; consider using 'cassert' instead
+// CHECK-FIXES: {{^}}#include <cassert>{{$}}
+#include "complex.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'complex.h'; consider using 'complex' instead
+// CHECK-FIXES: {{^}}#include <complex>{{$}}
+#include "ctype.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'ctype.h'; consider using 'cctype' instead
+// CHECK-FIXES: {{^}}#include <cctype>{{$}}
+#include "errno.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'errno.h'; consider using 'cerrno' instead
+// CHECK-FIXES: {{^}}#include <cerrno>{{$}}
+#include "float.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'float.h'; consider using 'cfloat' instead
+// CHECK-FIXES: {{^}}#include <cfloat>{{$}}
+#include "limits.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'limits.h'; consider using 'climits' instead
+// CHECK-FIXES: {{^}}#include <climits>{{$}}
+#include "locale.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'locale.h'; consider using 'clocale' instead
+// CHECK-FIXES: {{^}}#include <clocale>{{$}}
+#include "math.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'math.h'; consider using 'cmath' instead
+// CHECK-FIXES: {{^}}#include <cmath>{{$}}
+#include "setjmp.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'setjmp.h'; consider using 'csetjmp' instead
+// CHECK-FIXES: {{^}}#include <csetjmp>{{$}}
+#include "signal.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'signal.h'; consider using 'csignal' instead
+// CHECK-FIXES: {{^}}#include <csignal>{{$}}
+#include "stdarg.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdarg.h'; consider using 'cstdarg' instead
+// CHECK-FIXES: {{^}}#include <cstdarg>{{$}}
+#include "stddef.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stddef.h'; consider using 'cstddef' instead
+// CHECK-FIXES: {{^}}#include <cstddef>{{$}}
+#include "stdio.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdio.h'; consider using 'cstdio' instead
+// CHECK-FIXES: {{^}}#include <cstdio>{{$}}
+#include "stdlib.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdlib.h'; consider using 'cstdlib' instead
+// CHECK-FIXES: {{^}}#include <cstdlib>{{$}}
+#include "string.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'string.h'; consider using 'cstring' instead
+// CHECK-FIXES: {{^}}#include <cstring>{{$}}
+#include "time.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'time.h'; consider using 'ctime' instead
+// CHECK-FIXES: {{^}}#include <ctime>{{$}}
+#include "wchar.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wchar.h'; consider using 'cwchar' instead
+// CHECK-FIXES: {{^}}#include <cwchar>{{$}}
+#include "wctype.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wctype.h'; consider using 'cwctype' instead
+// CHECK-FIXES: {{^}}#include <cwctype>
+
+// Headers that have no effect in C++; remove them
+#include "stdalign.h" // "stdalign.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdalign.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// "stdalign.h"{{$}}
+#include "stdbool.h" // "stdbool.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdbool.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// "stdbool.h"{{$}}
+#include "iso646.h" // "iso646.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'iso646.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// "iso646.h"{{$}}
+
+// Headers deprecated since C++11; expect no diagnostics
+#include "fenv.h"
+#include "inttypes.h"
+#include "stdint.h"
+#include "tgmath.h"
+#include "uchar.h"
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-deprecated-headers-cxx11.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-deprecated-headers-cxx11.cpp
new file mode 100644
index 0000000..366f045
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-deprecated-headers-cxx11.cpp
@@ -0,0 +1,163 @@
+// RUN: %check_clang_tidy %s modernize-deprecated-headers %t -- -extra-arg-before=-isystem%S/Inputs/modernize-deprecated-headers -- -std=c++11 -v
+
+#include <assert.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'assert.h'; consider using 'cassert' instead [modernize-deprecated-headers]
+// CHECK-FIXES: {{^}}#include <cassert>{{$}}
+#include <complex.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'complex.h'; consider using 'complex' instead
+// CHECK-FIXES: {{^}}#include <complex>{{$}}
+#include <ctype.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'ctype.h'; consider using 'cctype' instead
+// CHECK-FIXES: {{^}}#include <cctype>{{$}}
+#include <errno.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'errno.h'; consider using 'cerrno' instead
+// CHECK-FIXES: {{^}}#include <cerrno>{{$}}
+#include <fenv.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'fenv.h'; consider using 'cfenv' instead
+// CHECK-FIXES: {{^}}#include <cfenv>{{$}}
+#include <float.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'float.h'; consider using 'cfloat' instead
+// CHECK-FIXES: {{^}}#include <cfloat>{{$}}
+#include <inttypes.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'inttypes.h'; consider using 'cinttypes' instead
+// CHECK-FIXES: {{^}}#include <cinttypes>{{$}}
+#include <limits.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'limits.h'; consider using 'climits' instead
+// CHECK-FIXES: {{^}}#include <climits>{{$}}
+#include <locale.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'locale.h'; consider using 'clocale' instead
+// CHECK-FIXES: {{^}}#include <clocale>{{$}}
+#include <math.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'math.h'; consider using 'cmath' instead
+// CHECK-FIXES: {{^}}#include <cmath>{{$}}
+#include <setjmp.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'setjmp.h'; consider using 'csetjmp' instead
+// CHECK-FIXES: {{^}}#include <csetjmp>{{$}}
+#include <signal.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'signal.h'; consider using 'csignal' instead
+// CHECK-FIXES: {{^}}#include <csignal>{{$}}
+#include <stdarg.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdarg.h'; consider using 'cstdarg' instead
+// CHECK-FIXES: {{^}}#include <cstdarg>{{$}}
+#include <stddef.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stddef.h'; consider using 'cstddef' instead
+// CHECK-FIXES: {{^}}#include <cstddef>{{$}}
+#include <stdint.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdint.h'; consider using 'cstdint' instead
+// CHECK-FIXES: {{^}}#include <cstdint>{{$}}
+#include <stdio.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdio.h'; consider using 'cstdio' instead
+// CHECK-FIXES: {{^}}#include <cstdio>{{$}}
+#include <stdlib.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdlib.h'; consider using 'cstdlib' instead
+// CHECK-FIXES: {{^}}#include <cstdlib>{{$}}
+#include <string.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'string.h'; consider using 'cstring' instead
+// CHECK-FIXES: {{^}}#include <cstring>{{$}}
+#include <tgmath.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'tgmath.h'; consider using 'ctgmath' instead
+// CHECK-FIXES: {{^}}#include <ctgmath>{{$}}
+#include <time.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'time.h'; consider using 'ctime' instead
+// CHECK-FIXES: {{^}}#include <ctime>{{$}}
+#include <uchar.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'uchar.h'; consider using 'cuchar' instead
+// CHECK-FIXES: {{^}}#include <cuchar>{{$}}
+#include <wchar.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wchar.h'; consider using 'cwchar' instead
+// CHECK-FIXES: {{^}}#include <cwchar>{{$}}
+#include <wctype.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wctype.h'; consider using 'cwctype' instead
+// CHECK-FIXES: {{^}}#include <cwctype>
+
+// Headers that have no effect in C++; remove them
+#include <stdalign.h> // <stdalign.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdalign.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// <stdalign.h>{{$}}
+#include <stdbool.h> // <stdbool.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdbool.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// <stdbool.h>{{$}}
+#include <iso646.h> // <iso646.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'iso646.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// <iso646.h>{{$}}
+
+#include "assert.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'assert.h'; consider using 'cassert' instead
+// CHECK-FIXES: {{^}}#include <cassert>{{$}}
+#include "complex.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'complex.h'; consider using 'complex' instead
+// CHECK-FIXES: {{^}}#include <complex>{{$}}
+#include "ctype.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'ctype.h'; consider using 'cctype' instead
+// CHECK-FIXES: {{^}}#include <cctype>{{$}}
+#include "errno.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'errno.h'; consider using 'cerrno' instead
+// CHECK-FIXES: {{^}}#include <cerrno>{{$}}
+#include "fenv.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'fenv.h'; consider using 'cfenv' instead
+// CHECK-FIXES: {{^}}#include <cfenv>{{$}}
+#include "float.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'float.h'; consider using 'cfloat' instead
+// CHECK-FIXES: {{^}}#include <cfloat>{{$}}
+#include "inttypes.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'inttypes.h'; consider using 'cinttypes' instead
+// CHECK-FIXES: {{^}}#include <cinttypes>{{$}}
+#include "limits.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'limits.h'; consider using 'climits' instead
+// CHECK-FIXES: {{^}}#include <climits>{{$}}
+#include "locale.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'locale.h'; consider using 'clocale' instead
+// CHECK-FIXES: {{^}}#include <clocale>{{$}}
+#include "math.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'math.h'; consider using 'cmath' instead
+// CHECK-FIXES: {{^}}#include <cmath>{{$}}
+#include "setjmp.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'setjmp.h'; consider using 'csetjmp' instead
+// CHECK-FIXES: {{^}}#include <csetjmp>{{$}}
+#include "signal.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'signal.h'; consider using 'csignal' instead
+// CHECK-FIXES: {{^}}#include <csignal>{{$}}
+#include "stdarg.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdarg.h'; consider using 'cstdarg' instead
+// CHECK-FIXES: {{^}}#include <cstdarg>{{$}}
+#include "stddef.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stddef.h'; consider using 'cstddef' instead
+// CHECK-FIXES: {{^}}#include <cstddef>{{$}}
+#include "stdint.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdint.h'; consider using 'cstdint' instead
+// CHECK-FIXES: {{^}}#include <cstdint>{{$}}
+#include "stdio.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdio.h'; consider using 'cstdio' instead
+// CHECK-FIXES: {{^}}#include <cstdio>{{$}}
+#include "stdlib.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'stdlib.h'; consider using 'cstdlib' instead
+// CHECK-FIXES: {{^}}#include <cstdlib>{{$}}
+#include "string.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'string.h'; consider using 'cstring' instead
+// CHECK-FIXES: {{^}}#include <cstring>{{$}}
+#include "tgmath.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'tgmath.h'; consider using 'ctgmath' instead
+// CHECK-FIXES: {{^}}#include <ctgmath>{{$}}
+#include "time.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'time.h'; consider using 'ctime' instead
+// CHECK-FIXES: {{^}}#include <ctime>{{$}}
+#include "uchar.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'uchar.h'; consider using 'cuchar' instead
+// CHECK-FIXES: {{^}}#include <cuchar>{{$}}
+#include "wchar.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wchar.h'; consider using 'cwchar' instead
+// CHECK-FIXES: {{^}}#include <cwchar>{{$}}
+#include "wctype.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'wctype.h'; consider using 'cwctype' instead
+// CHECK-FIXES: {{^}}#include <cwctype>
+
+// Headers that have no effect in C++; remove them
+#include "stdalign.h" // "stdalign.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdalign.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// "stdalign.h"{{$}}
+#include "stdbool.h" // "stdbool.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdbool.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// "stdbool.h"{{$}}
+#include "iso646.h" // "iso646.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'iso646.h' has no effect in C++; consider removing it
+// CHECK-FIXES: {{^}}// "iso646.h"{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-assert-failure.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-assert-failure.cpp
new file mode 100644
index 0000000..fab51da
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-assert-failure.cpp
@@ -0,0 +1,18 @@
+// RUN: not clang-tidy %s -checks=-*,modernize-loop-convert --
+
+// Note: this test expects no assert failure happened in clang-tidy.
+
+class LinguisticItem {
+  LinguisticItem *x0;
+  class x1 {
+    bool operator!= ( const x1 &;
+    operator* ( ;
+    LinguisticItem * &operator-> ( ;
+    operator++ (
+  } begin() const;
+  x1 end() const {
+    LinguisticStream x2;
+    for (x1 x3 = x2.begin x3 != x2.end; ++x3)
+      x3->x0
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-basic.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-basic.cpp
new file mode 100644
index 0000000..def7c4b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-basic.cpp
@@ -0,0 +1,793 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -std=c++11 -I %S/Inputs/modernize-loop-convert
+
+#include "structures.h"
+
+namespace Array {
+
+const int N = 6;
+const int NMinusOne = N - 1;
+int Arr[N] = {1, 2, 3, 4, 5, 6};
+const int ConstArr[N] = {1, 2, 3, 4, 5, 6};
+int (*PArr)[N] = &Arr;
+
+void f() {
+  int Sum = 0;
+
+  for (int I = 0; I < N; ++I) {
+    Sum += Arr[I];
+    int K;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead [modernize-loop-convert]
+  // CHECK-FIXES: for (int I : Arr)
+  // CHECK-FIXES-NEXT: Sum += I;
+  // CHECK-FIXES-NEXT: int K;
+
+  for (int I = 0; I < N; ++I) {
+    printf("Fibonacci number is %d\n", Arr[I]);
+    Sum += Arr[I] + 2;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : Arr)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+  // CHECK-FIXES-NEXT: Sum += I + 2;
+
+  for (int I = 0; I < N; ++I) {
+    int X = Arr[I];
+    int Y = Arr[I] + 2;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : Arr)
+  // CHECK-FIXES-NEXT: int X = I;
+  // CHECK-FIXES-NEXT: int Y = I + 2;
+
+  for (int I = 0; I < N; ++I) {
+    int X = N;
+    X = Arr[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : Arr)
+  // CHECK-FIXES-NEXT: int X = N;
+  // CHECK-FIXES-NEXT: X = I;
+
+  for (int I = 0; I < N; ++I) {
+    Arr[I] += 1;
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & I : Arr)
+  // CHECK-FIXES-NEXT: I += 1;
+
+  for (int I = 0; I < N; ++I) {
+    int X = Arr[I] + 2;
+    Arr[I]++;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & I : Arr)
+  // CHECK-FIXES-NEXT: int X = I + 2;
+  // CHECK-FIXES-NEXT: I++;
+
+  for (int I = 0; I < N; ++I) {
+    Arr[I] = 4 + Arr[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & I : Arr)
+  // CHECK-FIXES-NEXT: I = 4 + I;
+
+  for (int I = 0; I < NMinusOne + 1; ++I) {
+    Sum += Arr[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : Arr)
+  // CHECK-FIXES-NEXT: Sum += I;
+
+  for (int I = 0; I < N; ++I) {
+    printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
+    Sum += Arr[I] + 2;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & I : Arr)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
+  // CHECK-FIXES-NEXT: Sum += I + 2;
+
+  Val Teas[N];
+  for (int I = 0; I < N; ++I) {
+    Teas[I].g();
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & Tea : Teas)
+  // CHECK-FIXES-NEXT: Tea.g();
+}
+
+const int *constArray() {
+  for (int I = 0; I < N; ++I) {
+    printf("2 * %d = %d\n", ConstArr[I], ConstArr[I] + ConstArr[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : ConstArr)
+  // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I, I + I);
+
+  const NonTriviallyCopyable NonCopy[N]{};
+  for (int I = 0; I < N; ++I) {
+    printf("2 * %d = %d\n", NonCopy[I].X, NonCopy[I].X + NonCopy[I].X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & I : NonCopy)
+  // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);
+
+  const TriviallyCopyableButBig Big[N]{};
+  for (int I = 0; I < N; ++I) {
+    printf("2 * %d = %d\n", Big[I].X, Big[I].X + Big[I].X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & I : Big)
+  // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);
+
+  bool Something = false;
+  for (int I = 0; I < N; ++I) {
+    if (Something)
+      return &ConstArr[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const int & I : ConstArr)
+  // CHECK-FIXES-NEXT: if (Something)
+  // CHECK-FIXES-NEXT: return &I;
+}
+
+struct HasArr {
+  int Arr[N];
+  Val ValArr[N];
+  void implicitThis() {
+    for (int I = 0; I < N; ++I) {
+      printf("%d", Arr[I]);
+    }
+    // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (int I : Arr)
+    // CHECK-FIXES-NEXT: printf("%d", I);
+
+    for (int I = 0; I < N; ++I) {
+      printf("%d", ValArr[I].X);
+    }
+    // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (auto & I : ValArr)
+    // CHECK-FIXES-NEXT: printf("%d", I.X);
+  }
+
+  void explicitThis() {
+    for (int I = 0; I < N; ++I) {
+      printf("%d", this->Arr[I]);
+    }
+    // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (int I : this->Arr)
+    // CHECK-FIXES-NEXT: printf("%d", I);
+
+    for (int I = 0; I < N; ++I) {
+      printf("%d", this->ValArr[I].X);
+    }
+    // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (auto & I : this->ValArr)
+    // CHECK-FIXES-NEXT: printf("%d", I.X);
+  }
+};
+
+struct HasIndirectArr {
+  HasArr HA;
+  void implicitThis() {
+    for (int I = 0; I < N; ++I) {
+      printf("%d", HA.Arr[I]);
+    }
+    // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (int I : HA.Arr)
+    // CHECK-FIXES-NEXT: printf("%d", I);
+
+    for (int I = 0; I < N; ++I) {
+      printf("%d", HA.ValArr[I].X);
+    }
+    // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (auto & I : HA.ValArr)
+    // CHECK-FIXES-NEXT: printf("%d", I.X);
+  }
+
+  void explicitThis() {
+    for (int I = 0; I < N; ++I) {
+      printf("%d", this->HA.Arr[I]);
+    }
+    // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (int I : this->HA.Arr)
+    // CHECK-FIXES-NEXT: printf("%d", I);
+
+    for (int I = 0; I < N; ++I) {
+      printf("%d", this->HA.ValArr[I].X);
+    }
+    // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (auto & I : this->HA.ValArr)
+    // CHECK-FIXES-NEXT: printf("%d", I.X);
+  }
+};
+
+// Loops whose bounds are value-dependent should not be converted.
+template <int N>
+void dependentExprBound() {
+  for (int I = 0; I < N; ++I)
+    Arr[I] = 0;
+}
+template void dependentExprBound<20>();
+
+void memberFunctionPointer() {
+  Val V;
+  void (Val::*mfpArr[N])(void) = {&Val::g};
+  for (int I = 0; I < N; ++I)
+    (V.*mfpArr[I])();
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & I : mfpArr)
+  // CHECK-FIXES-NEXT: (V.*I)();
+
+  struct Foo {
+    int (Val::*f)();
+  } Foo[N];
+
+  for (int I = 0; I < N; ++I)
+    int R = (V.*(Foo[I].f))();
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & I : Foo)
+  // CHECK-FIXES-NEXT: int R = (V.*(I.f))();
+
+}
+
+} // namespace Array
+
+namespace Iterator {
+
+void f() {
+  /// begin()/end() - based for loops here:
+  T Tt;
+  for (T::iterator It = Tt.begin(), E = Tt.end(); It != E; ++It) {
+    printf("I found %d\n", *It);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : Tt)
+  // CHECK-FIXES-NEXT: printf("I found %d\n", It);
+
+  T *Pt;
+  for (T::iterator It = Pt->begin(), E = Pt->end(); It != E; ++It) {
+    printf("I found %d\n", *It);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : *Pt)
+  // CHECK-FIXES-NEXT: printf("I found %d\n", It);
+
+  S Ss;
+  for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+    printf("s has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+  S *Ps;
+  for (S::iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
+    printf("s has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & P : *Ps)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
+
+  for (S::const_iterator It = Ss.cbegin(), E = Ss.cend(); It != E; ++It) {
+    printf("s has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto It : Ss)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+  for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+    printf("s has value %d\n", It->X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+  for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+    It->X = 3;
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: It.X = 3;
+
+  for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+    (*It).X = 3;
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: It.X = 3;
+
+  for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+    It->nonConstFun(4, 5);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: It.nonConstFun(4, 5);
+
+  U Uu;
+  for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
+    printf("s has value %d\n", It->X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Uu)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+  for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
+    printf("s has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Uu)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+  for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
+    Val* a = It.operator->();
+  }
+
+  U::iterator A;
+  for (U::iterator I = Uu.begin(), E = Uu.end(); I != E; ++I)
+    int K = A->X + I->X;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & I : Uu)
+  // CHECK-FIXES-NEXT: int K = A->X + I.X;
+
+  dependent<int> V;
+  for (dependent<int>::iterator It = V.begin(), E = V.end();
+       It != E; ++It) {
+    printf("Fibonacci number is %d\n", *It);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : V)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
+
+  for (dependent<int>::iterator It(V.begin()), E = V.end();
+       It != E; ++It) {
+    printf("Fibonacci number is %d\n", *It);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : V)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
+
+  doublyDependent<int, int> Intmap;
+  for (doublyDependent<int, int>::iterator It = Intmap.begin(), E = Intmap.end();
+       It != E; ++It) {
+    printf("Intmap[%d] = %d", It->first, It->second);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Intmap)
+  // CHECK-FIXES: printf("Intmap[%d] = %d", It.first, It.second);
+
+  // PtrSet's iterator dereferences by value so auto & can't be used.
+  {
+    PtrSet<int *> Val_int_ptrs;
+    for (PtrSet<int *>::iterator I = Val_int_ptrs.begin(),
+                                 E = Val_int_ptrs.end();
+         I != E; ++I) {
+      (void) *I;
+    }
+    // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (auto Val_int_ptr : Val_int_ptrs)
+  }
+
+  // This container uses an iterator where the derefence type is a typedef of
+  // a reference type. Make sure non-const auto & is still used. A failure here
+  // means canonical types aren't being tested.
+  {
+    TypedefDerefContainer<int> Int_ptrs;
+    for (TypedefDerefContainer<int>::iterator I = Int_ptrs.begin(),
+                                              E = Int_ptrs.end();
+         I != E; ++I) {
+      (void) *I;
+    }
+    // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (int & Int_ptr : Int_ptrs)
+  }
+
+  {
+    // Iterators returning an rvalue reference should disqualify the loop from
+    // transformation.
+    RValueDerefContainer<int> Container;
+    for (RValueDerefContainer<int>::iterator I = Container.begin(),
+                                             E = Container.end();
+         I != E; ++I) {
+      (void) *I;
+    }
+  }
+
+  dependent<Val *> Dpp;
+  for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
+    printf("%d\n", (**I).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & I : Dpp)
+  // CHECK-FIXES-NEXT: printf("%d\n", (*I).X);
+
+  for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
+    printf("%d\n", (*I)->X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & I : Dpp)
+  // CHECK-FIXES-NEXT: printf("%d\n", I->X);
+}
+
+// Tests to verify the proper use of auto where the init variable type and the
+// initializer type differ or are mostly the same except for const qualifiers.
+void different_type() {
+  // Ss.begin() returns a type 'iterator' which is just a non-const pointer and
+  // differs from const_iterator only on the const qualification.
+  S Ss;
+  for (S::const_iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+    printf("s has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto It : Ss)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+  S *Ps;
+  for (S::const_iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
+    printf("s has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto P : *Ps)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
+
+  // V.begin() returns a user-defined type 'iterator' which, since it's
+  // different from const_iterator, disqualifies these loops from
+  // transformation.
+  dependent<int> V;
+  for (dependent<int>::const_iterator It = V.begin(), E = V.end();
+       It != E; ++It) {
+    printf("Fibonacci number is %d\n", *It);
+  }
+
+  for (dependent<int>::const_iterator It(V.begin()), E = V.end();
+       It != E; ++It) {
+    printf("Fibonacci number is %d\n", *It);
+  }
+}
+
+// Tests to ensure that an implicit 'this' is picked up as the container.
+// If member calls are made to 'this' within the loop, the transform becomes
+// risky as these calls may affect state that affects the loop.
+class C {
+public:
+  typedef MutableVal *iterator;
+  typedef const MutableVal *const_iterator;
+
+  iterator begin();
+  iterator end();
+  const_iterator begin() const;
+  const_iterator end() const;
+
+  void doSomething();
+  void doSomething() const;
+
+  void doLoop() {
+    for (iterator I = begin(), E = end(); I != E; ++I)
+      (void) *I;
+    // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (auto & I : *this)
+
+    for (iterator I = C::begin(), E = C::end(); I != E; ++I)
+      (void) *I;
+    // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (auto & I : *this)
+
+    for (iterator I = begin(), E = end(); I != E; ++I) {
+      (void) *I;
+      doSomething();
+    }
+
+    for (iterator I = begin(); I != end(); ++I)
+      (void) *I;
+    // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (auto & I : *this)
+
+    for (iterator I = begin(); I != end(); ++I) {
+      (void) *I;
+      doSomething();
+    }
+  }
+
+  void doLoop() const {
+    for (const_iterator I = begin(), E = end(); I != E; ++I)
+      (void) *I;
+    // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (auto I : *this)
+
+    for (const_iterator I = C::begin(), E = C::end(); I != E; ++I)
+      (void) *I;
+    // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (auto I : *this)
+
+    for (const_iterator I = begin(), E = end(); I != E; ++I) {
+      (void) *I;
+      doSomething();
+    }
+  }
+};
+
+class C2 {
+public:
+  typedef MutableVal *iterator;
+
+  iterator begin() const;
+  iterator end() const;
+
+  void doLoop() {
+    // The implicit 'this' will have an Implicit cast to const C2* wrapped
+    // around it. Make sure the replacement still happens.
+    for (iterator I = begin(), E = end(); I != E; ++I)
+      (void) *I;
+    // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (auto & I : *this)
+  }
+};
+
+} // namespace Iterator
+
+namespace PseudoArray {
+
+const int N = 6;
+dependent<int> V;
+dependent<int> *Pv;
+const dependent<NonTriviallyCopyable> Constv;
+const dependent<NonTriviallyCopyable> *Pconstv;
+
+transparent<dependent<int>> Cv;
+
+void f() {
+  int Sum = 0;
+  for (int I = 0, E = V.size(); I < E; ++I) {
+    printf("Fibonacci number is %d\n", V[I]);
+    Sum += V[I] + 2;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : V)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+  // CHECK-FIXES-NEXT: Sum += I + 2;
+
+  for (int I = 0, E = V.size(); I < E; ++I) {
+    printf("Fibonacci number is %d\n", V.at(I));
+    Sum += V.at(I) + 2;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : V)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+  // CHECK-FIXES-NEXT: Sum += I + 2;
+
+  for (int I = 0, E = Pv->size(); I < E; ++I) {
+    printf("Fibonacci number is %d\n", Pv->at(I));
+    Sum += Pv->at(I) + 2;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : *Pv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+  // CHECK-FIXES-NEXT: Sum += I + 2;
+
+  // This test will fail if size() isn't called repeatedly, since it
+  // returns unsigned int, and 0 is deduced to be signed int.
+  // FIXME: Insert the necessary explicit conversion, or write out the types
+  // explicitly.
+  for (int I = 0; I < Pv->size(); ++I) {
+    printf("Fibonacci number is %d\n", (*Pv).at(I));
+    Sum += (*Pv)[I] + 2;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : *Pv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+  // CHECK-FIXES-NEXT: Sum += I + 2;
+
+  for (int I = 0; I < Cv->size(); ++I) {
+    printf("Fibonacci number is %d\n", Cv->at(I));
+    Sum += Cv->at(I) + 2;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : *Cv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+  // CHECK-FIXES-NEXT: Sum += I + 2;
+}
+
+// Ensure that 'const auto &' is used with containers of non-trivial types.
+void constness() {
+  int Sum = 0;
+  for (int I = 0, E = Constv.size(); I < E; ++I) {
+    printf("Fibonacci number is %d\n", Constv[I].X);
+    Sum += Constv[I].X + 2;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & I : Constv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
+  // CHECK-FIXES-NEXT: Sum += I.X + 2;
+
+  for (int I = 0, E = Constv.size(); I < E; ++I) {
+    printf("Fibonacci number is %d\n", Constv.at(I).X);
+    Sum += Constv.at(I).X + 2;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & I : Constv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
+  // CHECK-FIXES-NEXT: Sum += I.X + 2;
+
+  for (int I = 0, E = Pconstv->size(); I < E; ++I) {
+    printf("Fibonacci number is %d\n", Pconstv->at(I).X);
+    Sum += Pconstv->at(I).X + 2;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & I : *Pconstv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
+  // CHECK-FIXES-NEXT: Sum += I.X + 2;
+
+  // This test will fail if size() isn't called repeatedly, since it
+  // returns unsigned int, and 0 is deduced to be signed int.
+  // FIXME: Insert the necessary explicit conversion, or write out the types
+  // explicitly.
+  for (int I = 0; I < Pconstv->size(); ++I) {
+    printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);
+    Sum += (*Pconstv)[I].X + 2;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & I : *Pconstv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
+  // CHECK-FIXES-NEXT: Sum += I.X + 2;
+}
+
+void constRef(const dependent<int>& ConstVRef) {
+  int sum = 0;
+  // FIXME: This does not work with size_t (probably due to the implementation
+  // of dependent); make dependent work exactly like a std container type.
+  for (int I = 0; I < ConstVRef.size(); ++I) {
+    sum += ConstVRef[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : ConstVRef)
+  // CHECK-FIXES-NEXT: sum += I;
+
+  for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) {
+    sum += *I;
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : ConstVRef)
+  // CHECK-FIXES-NEXT: sum += I;
+}
+
+// Check for loops that don't mention containers.
+void noContainer() {
+  for (auto I = 0; I < V.size(); ++I) {
+  }
+
+  for (auto I = 0; I < V.size(); ++I)
+    ;
+}
+
+struct NoBeginEnd {
+  unsigned size() const;
+  unsigned& operator[](int);
+  const unsigned& operator[](int) const;
+};
+
+struct NoConstBeginEnd {
+  NoConstBeginEnd();
+  unsigned size() const;
+  unsigned* begin();
+  unsigned* end();
+  unsigned& operator[](int);
+  const unsigned& operator[](int) const;
+};
+
+struct ConstBeginEnd {
+  ConstBeginEnd();
+  unsigned size() const;
+  unsigned* begin() const;
+  unsigned* end() const;
+  unsigned& operator[](int);
+  const unsigned& operator[](int) const;
+};
+
+// Shouldn't transform pseudo-array uses if the container doesn't provide
+// begin() and end() of the right const-ness.
+void NoBeginEndTest() {
+  NoBeginEnd NBE;
+  for (unsigned I = 0, E = NBE.size(); I < E; ++I)
+    printf("%d\n", NBE[I]);
+
+  const NoConstBeginEnd Const_NCBE;
+  for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I)
+    printf("%d\n", Const_NCBE[I]);
+
+  ConstBeginEnd CBE;
+  for (unsigned I = 0, E = CBE.size(); I < E; ++I)
+    printf("%d\n", CBE[I]);
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (unsigned int I : CBE)
+  // CHECK-FIXES-NEXT: printf("%d\n", I);
+
+  const ConstBeginEnd Const_CBE;
+  for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I)
+    printf("%d\n", Const_CBE[I]);
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (unsigned int I : Const_CBE)
+  // CHECK-FIXES-NEXT: printf("%d\n", I);
+}
+
+struct DerefByValue {
+  DerefByValue();
+  struct iter { unsigned operator*(); };
+  unsigned size() const;
+  iter begin();
+  iter end();
+  unsigned operator[](int);
+};
+
+void derefByValueTest() {
+  DerefByValue DBV;
+  for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
+    printf("%d\n", DBV[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (unsigned int I : DBV)
+  // CHECK-FIXES-NEXT: printf("%d\n", I);
+
+  for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
+    auto f = [DBV, I]() {};
+    printf("%d\n", DBV[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (unsigned int I : DBV)
+  // CHECK-FIXES-NEXT: auto f = [DBV, &I]() {};
+  // CHECK-FIXES-NEXT: printf("%d\n", I);
+}
+
+void fundamentalTypesTest() {
+  const int N = 10;
+  bool Bools[N];
+  for (int i = 0; i < N; ++i)
+    printf("%d", Bools[i]);
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (bool Bool : Bools)
+
+  int Ints[N];
+  unsigned short int Shorts[N];
+  for (int i = 0; i < N; ++i)
+    printf("%d", Shorts[i]);
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (unsigned short Short : Shorts)
+
+  signed long Longs[N];
+  for (int i = 0; i < N; ++i)
+    printf("%d", Longs[i]);
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (long Long : Longs)
+
+  long long int LongLongs[N];
+  for (int i = 0; i < N; ++i)
+    printf("%d", LongLongs[i]);
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (long long LongLong : LongLongs)
+
+  char Chars[N];
+  for (int i = 0; i < N; ++i)
+    printf("%d", Chars[i]);
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (char Char : Chars)
+
+  wchar_t WChars[N];
+  for (int i = 0; i < N; ++i)
+    printf("%d", WChars[i]);
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (wchar_t WChar : WChars)
+
+  float Floats[N];
+  for (int i = 0; i < N; ++i)
+    printf("%d", Floats[i]);
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (float Float : Floats)
+
+  double Doubles[N];
+  for (int i = 0; i < N; ++i)
+    printf("%d", Doubles[i]);
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (double Double : Doubles)
+}
+
+} // namespace PseudoArray
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-camelback.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-camelback.cpp
new file mode 100644
index 0000000..50044de
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-camelback.cpp
@@ -0,0 +1,33 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-loop-convert.NamingStyle, value: 'camelBack'}]}" \
+// RUN:   -- -std=c++11 -I %S/Inputs/modernize-loop-convert
+
+#include "structures.h"
+
+const int n = 10;
+int arr[n];
+int nums[n];
+
+void naming() {
+  for (int i = 0; i < n; ++i) {
+    printf("%d\n", arr[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
+  // CHECK-FIXES: for (int i : arr)
+  // CHECK-FIXES-NEXT: printf("%d\n", i);
+
+  for (int i = 0; i < n; ++i) {
+    printf("%d\n", nums[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int num : nums)
+  // CHECK-FIXES-NEXT: printf("%d\n", num);
+
+  int num = 0;
+  for (int i = 0; i < n; ++i) {
+    printf("%d\n", nums[i] + num);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int i : nums)
+  // CHECK-FIXES-NEXT: printf("%d\n", i + num);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-const.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-const.cpp
new file mode 100644
index 0000000..806b6c1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-const.cpp
@@ -0,0 +1,360 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -std=c++11
+
+struct Str {
+  Str() = default;
+  Str(const Str &) = default;
+  void constMember(int) const;
+  void nonConstMember(int);
+  bool operator<(const Str &str) const;     // const operator.
+  Str &operator=(const Str &str) = default; // non const operator.
+};
+
+// This class is non-trivially copyable because the copy-constructor and copy
+// assignment take non-const references.
+struct ModifiesRightSide {
+  ModifiesRightSide() = default;
+  ModifiesRightSide(ModifiesRightSide &) = default;
+  bool operator<(ModifiesRightSide &) const;
+  ModifiesRightSide &operator=(ModifiesRightSide &) = default;
+};
+
+template <typename T>
+void copyArg(T);
+
+template <typename T>
+void nonConstRefArg(T &);
+
+// If we define this as a template, the type is deduced to "T&",
+// and "const (T&) &" is the same as "T& &", and this collapses to "T&".
+void constRefArg(const Str &);
+void constRefArg(const ModifiesRightSide &);
+void constRefArg(const int &);
+
+void foo();
+
+const int N = 10;
+Str Array[N], OtherStr;
+ModifiesRightSide Right[N], OtherRight;
+int Ints[N], OtherInt;
+
+void memberFunctionsAndOperators() {
+  // Calling const member functions or operator is a const usage.
+  for (int I = 0; I < N; ++I) {
+    Array[I].constMember(0);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
+  // CHECK-FIXES: for (auto I : Array)
+  // CHECK-FIXES-NEXT: I.constMember(0);
+
+  for (int I = 0; I < N; ++I) {
+    if (Array[I] < OtherStr)
+      foo();
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto I : Array)
+  // CHECK-FIXES-NEXT: if (I < OtherStr)
+  for (int I = 0; I < N; ++I) {
+    if (Right[I] < OtherRight)
+      foo();
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (const auto & I : Right)
+  // CHECK-FIXES-NEXT: if (I < OtherRight)
+
+  // Calling non-const member functions is not.
+  for (int I = 0; I < N; ++I) {
+    Array[I].nonConstMember(0);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto & I : Array)
+  // CHECK-FIXES-NEXT: I.nonConstMember(0);
+
+  for (int I = 0; I < N; ++I) {
+    Array[I] = OtherStr;
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto & I : Array)
+  // CHECK-FIXES-NEXT: I = OtherStr;
+
+  for (int I = 0; I < N; ++I) {
+    Right[I] = OtherRight;
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto & I : Right)
+  // CHECK-FIXES-NEXT: I = OtherRight;
+}
+
+void usedAsParameterToFunctionOrOperator() {
+  // Copying is OK, as long as the copy constructor takes a const-reference.
+  for (int I = 0; I < N; ++I) {
+    copyArg(Array[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto I : Array)
+  // CHECK-FIXES-NEXT: copyArg(I);
+
+  for (int I = 0; I < N; ++I) {
+    copyArg(Right[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto & I : Right)
+  // CHECK-FIXES-NEXT: copyArg(I);
+
+  // Using as a const reference argument is allowed.
+  for (int I = 0; I < N; ++I) {
+    constRefArg(Array[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto I : Array)
+  // CHECK-FIXES-NEXT: constRefArg(I);
+
+  for (int I = 0; I < N; ++I) {
+    if (OtherStr < Array[I])
+      foo();
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto I : Array)
+  // CHECK-FIXES-NEXT: if (OtherStr < I)
+
+  for (int I = 0; I < N; ++I) {
+    constRefArg(Right[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (const auto & I : Right)
+  // CHECK-FIXES-NEXT: constRefArg(I);
+
+  // Using as a non-const reference is not.
+  for (int I = 0; I < N; ++I) {
+    nonConstRefArg(Array[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto & I : Array)
+  // CHECK-FIXES-NEXT: nonConstRefArg(I);
+  for (int I = 0; I < N; ++I) {
+    nonConstRefArg(Right[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto & I : Right)
+  // CHECK-FIXES-NEXT: nonConstRefArg(I);
+  for (int I = 0; I < N; ++I) {
+    if (OtherRight < Right[I])
+      foo();
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto & I : Right)
+  // CHECK-FIXES-NEXT: if (OtherRight < I)
+}
+
+void primitiveTypes() {
+  // As argument to a function.
+  for (int I = 0; I < N; ++I) {
+    copyArg(Ints[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int Int : Ints)
+  // CHECK-FIXES-NEXT: copyArg(Int);
+  for (int I = 0; I < N; ++I) {
+    constRefArg(Ints[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int Int : Ints)
+  // CHECK-FIXES-NEXT: constRefArg(Int);
+  for (int I = 0; I < N; ++I) {
+    nonConstRefArg(Ints[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int & Int : Ints)
+  // CHECK-FIXES-NEXT: nonConstRefArg(Int);
+
+  // Builtin operators.
+  // Comparisons.
+  for (int I = 0; I < N; ++I) {
+    if (Ints[I] < N)
+      foo();
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int Int : Ints)
+  // CHECK-FIXES-NEXT: if (Int < N)
+
+  for (int I = 0; I < N; ++I) {
+    if (N == Ints[I])
+      foo();
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int Int : Ints)
+  // CHECK-FIXES-NEXT: if (N == Int)
+
+  // Assignment.
+  for (int I = 0; I < N; ++I) {
+    Ints[I] = OtherInt;
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int & Int : Ints)
+  // CHECK-FIXES-NEXT: Int = OtherInt;
+
+  for (int I = 0; I < N; ++I) {
+    OtherInt = Ints[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int Int : Ints)
+  // CHECK-FIXES-NEXT: OtherInt = Int;
+
+  for (int I = 0; I < N; ++I) {
+    OtherInt = Ints[I] = OtherInt;
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int & Int : Ints)
+  // CHECK-FIXES-NEXT: OtherInt = Int = OtherInt;
+
+  // Arithmetic operations.
+  for (int I = 0; I < N; ++I) {
+    OtherInt += Ints[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int Int : Ints)
+  // CHECK-FIXES-NEXT: OtherInt += Int;
+
+  for (int I = 0; I < N; ++I) {
+    Ints[I] += Ints[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int & Int : Ints)
+  // CHECK-FIXES-NEXT: Int += Int;
+
+  for (int I = 0; I < N; ++I) {
+    int Res = 5 * (Ints[I] + 1) - Ints[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int Int : Ints)
+  // CHECK-FIXES-NEXT: int Res = 5 * (Int + 1) - Int;
+}
+
+void takingReferences() {
+  // We do it twice to prevent the check from thinking that they are aliases.
+
+  // Class type.
+  for (int I = 0; I < N; ++I) {
+    Str &J = Array[I];
+    Str &K = Array[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto & I : Array)
+  // CHECK-FIXES-NEXT: Str &J = I;
+  // CHECK-FIXES-NEXT: Str &K = I;
+  for (int I = 0; I < N; ++I) {
+    const Str &J = Array[I];
+    const Str &K = Array[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto I : Array)
+  // CHECK-FIXES-NEXT: const Str &J = I;
+  // CHECK-FIXES-NEXT: const Str &K = I;
+
+  // Primitive type.
+  for (int I = 0; I < N; ++I) {
+    int &J = Ints[I];
+    int &K = Ints[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int & Int : Ints)
+  // CHECK-FIXES-NEXT: int &J = Int;
+  // CHECK-FIXES-NEXT: int &K = Int;
+  for (int I = 0; I < N; ++I) {
+    const int &J = Ints[I];
+    const int &K = Ints[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int Int : Ints)
+  // CHECK-FIXES-NEXT: const int &J = Int;
+  // CHECK-FIXES-NEXT: const int &K = Int;
+
+  // Aliases.
+  for (int I = 0; I < N; ++I) {
+    const Str &J = Array[I];
+    (void)J;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto J : Array)
+  for (int I = 0; I < N; ++I) {
+    Str &J = Array[I];
+    (void)J;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto & J : Array)
+
+  for (int I = 0; I < N; ++I) {
+    const int &J = Ints[I];
+    (void)J;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int J : Ints)
+
+  for (int I = 0; I < N; ++I) {
+    int &J = Ints[I];
+    (void)J;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int & J : Ints)
+}
+
+template <class T>
+struct vector {
+  unsigned size() const;
+  const T &operator[](int) const;
+  T &operator[](int);
+  T *begin();
+  T *end();
+  const T *begin() const;
+  const T *end() const;
+};
+
+// If the elements are already constant, we won't do any ImplicitCast to const.
+void testContainerOfConstIents() {
+  const int Ints[N]{};
+  for (int I = 0; I < N; ++I) {
+    OtherInt -= Ints[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int Int : Ints)
+
+  vector<const Str> Strs;
+  for (int I = 0; I < Strs.size(); ++I) {
+    Strs[I].constMember(0);
+    constRefArg(Strs[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto Str : Strs)
+}
+
+// When we are inside a const-qualified member functions, all the data members
+// are implicitly set as const. As before, there won't be any ImplicitCast to
+// const in their usages.
+class TestInsideConstFunction {
+  const static int N = 10;
+  int Ints[N];
+  Str Array[N];
+  vector<int> V;
+
+  void foo() const {
+    for (int I = 0; I < N; ++I) {
+      if (Ints[I])
+        copyArg(Ints[I]);
+    }
+    // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop
+    // CHECK-FIXES: for (int Int : Ints)
+
+    for (int I = 0; I < N; ++I) {
+      Array[I].constMember(0);
+      constRefArg(Array[I]);
+    }
+    // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop
+    // CHECK-FIXES: for (auto I : Array)
+
+    for (int I = 0; I < V.size(); ++I) {
+      if (V[I])
+        copyArg(V[I]);
+    }
+    // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop
+    // CHECK-FIXES: for (int I : V)
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-extra.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-extra.cpp
new file mode 100644
index 0000000..b46ff25
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -0,0 +1,1074 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -std=c++11 -I %S/Inputs/modernize-loop-convert
+
+#include "structures.h"
+
+namespace Dependency {
+
+void f() {
+  const int N = 6;
+  const int M = 8;
+  int Arr[N][M];
+
+  for (int I = 0; I < N; ++I) {
+    int A = 0;
+    int B = Arr[I][A];
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & I : Arr)
+  // CHECK-FIXES-NEXT: int A = 0;
+  // CHECK-FIXES-NEXT: int B = I[A];
+
+  for (int J = 0; J < M; ++J) {
+    int A = 0;
+    int B = Arr[A][J];
+  }
+}
+
+} // namespace Dependency
+
+namespace NamingAlias {
+
+const int N = 10;
+
+Val Arr[N];
+dependent<Val> V;
+dependent<Val> *Pv;
+Val &func(Val &);
+void sideEffect(int);
+
+void aliasing() {
+  // If the loop container is only used for a declaration of a temporary
+  // variable to hold each element, we can name the new variable for the
+  // converted range-based loop as the temporary variable's name.
+
+  // In the following case, "T" is used as a temporary variable to hold each
+  // element, and thus we consider the name "T" aliased to the loop.
+  // The extra blank braces are left as a placeholder for after the variable
+  // declaration is deleted.
+  for (int I = 0; I < N; ++I) {
+    Val &T = Arr[I];
+    {}
+    int Y = T.X;
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & T : Arr)
+  // CHECK-FIXES-NOT: Val &{{[a-z_]+}} =
+  // CHECK-FIXES-NEXT: {}
+  // CHECK-FIXES-NEXT: int Y = T.X;
+
+  // The container was not only used to initialize a temporary loop variable for
+  // the container's elements, so we do not alias the new loop variable.
+  for (int I = 0; I < N; ++I) {
+    Val &T = Arr[I];
+    int Y = T.X;
+    int Z = Arr[I].X + T.X;
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & I : Arr)
+  // CHECK-FIXES-NEXT: Val &T = I;
+  // CHECK-FIXES-NEXT: int Y = T.X;
+  // CHECK-FIXES-NEXT: int Z = I.X + T.X;
+
+  for (int I = 0; I < N; ++I) {
+    Val T = Arr[I];
+    int Y = T.X;
+    int Z = Arr[I].X + T.X;
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & I : Arr)
+  // CHECK-FIXES-NEXT: Val T = I;
+  // CHECK-FIXES-NEXT: int Y = T.X;
+  // CHECK-FIXES-NEXT: int Z = I.X + T.X;
+
+  // The same for pseudo-arrays like std::vector<T> (or here dependent<Val>)
+  // which provide a subscript operator[].
+  for (int I = 0; I < V.size(); ++I) {
+    Val &T = V[I];
+    {}
+    int Y = T.X;
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & T : V)
+  // CHECK-FIXES-NEXT: {}
+  // CHECK-FIXES-NEXT: int Y = T.X;
+
+  // The same with a call to at()
+  for (int I = 0; I < Pv->size(); ++I) {
+    Val &T = Pv->at(I);
+    {}
+    int Y = T.X;
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & T : *Pv)
+  // CHECK-FIXES-NEXT: {}
+  // CHECK-FIXES-NEXT: int Y = T.X;
+
+  for (int I = 0; I < N; ++I) {
+    Val &T = func(Arr[I]);
+    int Y = T.X;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & I : Arr)
+  // CHECK-FIXES-NEXT: Val &T = func(I);
+  // CHECK-FIXES-NEXT: int Y = T.X;
+
+  int IntArr[N];
+  for (unsigned I = 0; I < N; ++I) {
+    if (int Alias = IntArr[I]) {
+      sideEffect(Alias);
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int Alias : IntArr)
+  // CHECK-FIXES-NEXT: if (Alias)
+
+  for (unsigned I = 0; I < N; ++I) {
+    while (int Alias = IntArr[I]) {
+      sideEffect(Alias);
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int Alias : IntArr)
+  // CHECK-FIXES-NEXT: while (Alias)
+
+  for (unsigned I = 0; I < N; ++I) {
+    switch (int Alias = IntArr[I]) {
+    default:
+      sideEffect(Alias);
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int Alias : IntArr)
+  // CHECK-FIXES-NEXT: switch (Alias)
+
+  for (unsigned I = 0; I < N; ++I) {
+    for (int Alias = IntArr[I]; Alias < N; ++Alias) {
+      sideEffect(Alias);
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int Alias : IntArr)
+  // CHECK-FIXES-NEXT: for (; Alias < N; ++Alias)
+
+  for (unsigned I = 0; I < N; ++I) {
+    for (unsigned J = 0; int Alias = IntArr[I]; ++J) {
+      sideEffect(Alias);
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int Alias : IntArr)
+  // CHECK-FIXES-NEXT: for (unsigned J = 0; Alias; ++J)
+
+  struct IntRef { IntRef(); IntRef(const int& i); operator int*(); };
+  for (int I = 0; I < N; ++I) {
+    IntRef Int(IntArr[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : IntArr)
+  // CHECK-FIXES-NEXT: IntRef Int(I);
+
+  int *PtrArr[N];
+  for (unsigned I = 0; I < N; ++I) {
+    const int* const P = PtrArr[I];
+    printf("%d\n", *P);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto P : PtrArr)
+  // CHECK-FIXES-NEXT: printf("%d\n", *P);
+
+  IntRef Refs[N];
+  for (unsigned I = 0; I < N; ++I) {
+    int *P = Refs[I];
+    printf("%d\n", *P);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & Ref : Refs)
+  // CHECK-FIXES-NEXT: int *P = Ref;
+  // CHECK-FIXES-NEXT: printf("%d\n", *P);
+
+  // Ensure that removing the alias doesn't leave empty lines behind.
+  for (int I = 0; I < N; ++I) {
+    auto &X = IntArr[I];
+    X = 0;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & X : IntArr) {
+  // CHECK-FIXES-NEXT: {{^    X = 0;$}}
+  // CHECK-FIXES-NEXT: {{^  }$}}
+}
+
+void refs_and_vals() {
+  // The following tests check that the transform correctly preserves the
+  // reference or value qualifiers of the aliased variable. That is, if the
+  // variable was declared as a value, the loop variable will be declared as a
+  // value and vice versa for references.
+
+  S Ss;
+  const S S_const = Ss;
+
+  for (S::const_iterator It = S_const.begin(); It != S_const.end(); ++It) {
+    MutableVal Alias = *It;
+    {}
+    Alias.X = 0;
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto Alias : S_const)
+  // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} =
+  // CHECK-FIXES-NEXT: {}
+  // CHECK-FIXES-NEXT: Alias.X = 0;
+
+  for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+    MutableVal Alias = *It;
+    {}
+    Alias.X = 0;
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto Alias : Ss)
+  // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} =
+  // CHECK-FIXES-NEXT: {}
+  // CHECK-FIXES-NEXT: Alias.X = 0;
+
+  for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
+    MutableVal &Alias = *It;
+    {}
+    Alias.X = 0;
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & Alias : Ss)
+  // CHECK-FIXES-NOT: MutableVal &{{[a-z_]+}} =
+  // CHECK-FIXES-NEXT: {}
+  // CHECK-FIXES-NEXT: Alias.X = 0;
+
+  dependent<int> Dep, Other;
+  for (dependent<int>::iterator It = Dep.begin(), E = Dep.end(); It != E; ++It) {
+    printf("%d\n", *It);
+    const int& Idx = Other[0];
+    unsigned Othersize = Other.size();
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : Dep)
+  // CHECK-FIXES-NEXT: printf("%d\n", It);
+  // CHECK-FIXES-NEXT: const int& Idx = Other[0];
+  // CHECK-FIXES-NEXT: unsigned Othersize = Other.size();
+
+  for (int i = 0; i <  Other.size(); ++i) {
+    Other.at(i);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & i : Other)
+  // CHECK-FIXES: i;
+
+  for (int I = 0, E = Dep.size(); I != E; ++I) {
+    int Idx = Other.at(I);
+    Other.at(I, I);  // Should not trigger assert failure.
+  }
+}
+
+struct MemberNaming {
+  const static int N = 10;
+  int Ints[N], Ints_[N];
+  dependent<int> DInts;
+  void loops() {
+    for (int I = 0; I < N; ++I) {
+      printf("%d\n", Ints[I]);
+    }
+    // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (int Int : Ints)
+    // CHECK-FIXES-NEXT: printf("%d\n", Int);
+
+    for (int I = 0; I < N; ++I) {
+      printf("%d\n", Ints_[I]);
+    }
+    // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (int Int : Ints_)
+    // CHECK-FIXES-NEXT: printf("%d\n", Int);
+
+    for (int I = 0; I < DInts.size(); ++I) {
+      printf("%d\n", DInts[I]);
+    }
+    // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
+    // CHECK-FIXES: for (int DInt : DInts)
+    // CHECK-FIXES-NEXT: printf("%d\n", DInt);
+  }
+
+  void outOfLine();
+};
+void MemberNaming::outOfLine() {
+  for (int I = 0; I < N; ++I) {
+    printf("%d\n", Ints[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int Int : Ints)
+  // CHECK-FIXES-NEXT: printf("%d\n", Int);
+
+  for (int I = 0; I < N; ++I) {
+    printf("%d\n", Ints_[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int Int : Ints_)
+  // CHECK-FIXES-NEXT: printf("%d\n", Int);
+}
+
+} // namespace NamingAlias
+
+namespace NamingConlict {
+
+#define MAX(a, b) (a > b) ? a : b
+#define DEF 5
+
+const int N = 10;
+int Nums[N];
+int Sum = 0;
+
+namespace ns {
+struct St {
+  int X;
+};
+}
+
+void sameNames() {
+  int Num = 0;
+  for (int I = 0; I < N; ++I) {
+    printf("Fibonacci number is %d\n", Nums[I]);
+    Sum += Nums[I] + 2 + Num;
+    (void)Nums[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & I : Nums)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+  // CHECK-FIXES-NEXT: Sum += I + 2 + Num;
+  // CHECK-FIXES-NEXT: (void)I;
+
+  int Elem = 0;
+  for (int I = 0; I < N; ++I) {
+    printf("Fibonacci number is %d\n", Nums[I]);
+    Sum += Nums[I] + 2 + Num + Elem;
+    (void)Nums[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & I : Nums)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
+  // CHECK-FIXES-NEXT: Sum += I + 2 + Num + Elem;
+  // CHECK-FIXES-NEXT: (void)I;
+}
+
+void oldIndexConflict() {
+  for (int Num = 0; Num < N; ++Num) {
+    printf("Num: %d\n", Nums[Num]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int Num : Nums)
+  // CHECK-FIXES-NEXT: printf("Num: %d\n", Num);
+
+  S Things;
+  for (S::iterator Thing = Things.begin(), End = Things.end(); Thing != End; ++Thing) {
+    printf("Thing: %d %d\n", Thing->X, (*Thing).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & Thing : Things)
+  // CHECK-FIXES-NEXT: printf("Thing: %d %d\n", Thing.X, Thing.X);
+}
+
+void macroConflict() {
+  S MAXs;
+  for (S::iterator It = MAXs.begin(), E = MAXs.end(); It != E; ++It) {
+    printf("s has value %d\n", (*It).X);
+    printf("Max of 3 and 5: %d\n", MAX(3, 5));
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : MAXs)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+  // CHECK-FIXES-NEXT: printf("Max of 3 and 5: %d\n", MAX(3, 5));
+
+  for (S::const_iterator It = MAXs.begin(), E = MAXs.end(); It != E; ++It) {
+    printf("s has value %d\n", (*It).X);
+    printf("Max of 3 and 5: %d\n", MAX(3, 5));
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto It : MAXs)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+  // CHECK-FIXES-NEXT: printf("Max of 3 and 5: %d\n", MAX(3, 5));
+
+  T DEFs;
+  for (T::iterator It = DEFs.begin(), E = DEFs.end(); It != E; ++It) {
+    if (*It == DEF) {
+      printf("I found %d\n", *It);
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : DEFs)
+  // CHECK-FIXES-NEXT: if (It == DEF)
+  // CHECK-FIXES-NEXT: printf("I found %d\n", It);
+}
+
+void keywordConflict() {
+  T ints;
+  for (T::iterator It = ints.begin(), E = ints.end(); It != E; ++It) {
+    *It = 5;
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : ints)
+  // CHECK-FIXES-NEXT: It = 5;
+
+  U __FUNCTION__s;
+  for (U::iterator It = __FUNCTION__s.begin(), E = __FUNCTION__s.end();
+       It != E; ++It) {
+    int __FUNCTION__s_It = (*It).X + 2;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : __FUNCTION__s)
+  // CHECK-FIXES-NEXT: int __FUNCTION__s_It = It.X + 2;
+}
+
+void typeConflict() {
+  T Vals;
+  // Using the name "Val", although it is the name of an existing struct, is
+  // safe in this loop since it will only exist within this scope.
+  for (T::iterator It = Vals.begin(), E = Vals.end(); It != E; ++It)
+    (void) *It;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & Val : Vals)
+
+  // We cannot use the name "Val" in this loop since there is a reference to
+  // it in the body of the loop.
+  for (T::iterator It = Vals.begin(), E = Vals.end(); It != E; ++It) {
+    *It = sizeof(Val);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : Vals)
+  // CHECK-FIXES-NEXT: It = sizeof(Val);
+
+  typedef struct Val TD;
+  U TDs;
+  // Naming the variable "TD" within this loop is safe because the typedef
+  // was never used within the loop.
+  for (U::iterator It = TDs.begin(), E = TDs.end(); It != E; ++It)
+    (void) *It;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & TD : TDs)
+
+  // "TD" cannot be used in this loop since the typedef is being used.
+  for (U::iterator It = TDs.begin(), E = TDs.end(); It != E; ++It) {
+    TD V;
+    V.X = 5;
+    (void) *It;
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : TDs)
+  // CHECK-FIXES-NEXT: TD V;
+  // CHECK-FIXES-NEXT: V.X = 5;
+
+  using ns::St;
+  T Sts;
+  for (T::iterator It = Sts.begin(), E = Sts.end(); It != E; ++It) {
+    *It = sizeof(St);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : Sts)
+  // CHECK-FIXES-NEXT: It = sizeof(St);
+}
+
+} // namespace NamingConflict
+
+namespace FreeBeginEnd {
+
+// FIXME: Loop Convert should detect free begin()/end() functions.
+
+struct MyArray {
+  unsigned size();
+};
+
+template <typename T>
+struct MyContainer {
+};
+
+int *begin(const MyArray &Arr);
+int *end(const MyArray &Arr);
+
+template <typename T>
+T *begin(const MyContainer<T> &C);
+template <typename T>
+T *end(const MyContainer<T> &C);
+
+// The Loop Convert Transform doesn't detect free functions begin()/end() and
+// so fails to transform these cases which it should.
+void f() {
+  MyArray Arr;
+  for (unsigned I = 0, E = Arr.size(); I < E; ++I) {
+  }
+
+  MyContainer<int> C;
+  for (int *I = begin(C), *E = end(C); I != E; ++I) {
+  }
+}
+
+} // namespace FreeBeginEnd
+
+namespace Nesting {
+
+void g(S::iterator It);
+void const_g(S::const_iterator It);
+class Foo {
+ public:
+  void g(S::iterator It);
+  void const_g(S::const_iterator It);
+};
+
+void f() {
+  const int N = 10;
+  const int M = 15;
+  Val Arr[N];
+  for (int I = 0; I < N; ++I) {
+    for (int J = 0; J < N; ++J) {
+      int K = Arr[I].X + Arr[J].X;
+      // The repeat is there to allow FileCheck to make sure the two variable
+      // names aren't the same.
+      int L = Arr[I].X + Arr[J].X;
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-8]]:3: warning: use range-based for loop instead
+  // CHECK-MESSAGES: :[[@LINE-8]]:5: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & I : Arr)
+  // CHECK-FIXES-NEXT: for (auto & J : Arr)
+  // CHECK-FIXES-NEXT: int K = I.X + J.X;
+  // CHECK-FIXES-NOT: int L = I.X + I.X;
+
+  // The inner loop is also convertible, but doesn't need to be converted
+  // immediately. FIXME: update this test when that changes.
+  Val Nest[N][M];
+  for (int I = 0; I < N; ++I) {
+    for (int J = 0; J < M; ++J) {
+      printf("Got item %d", Nest[I][J].X);
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & I : Nest)
+  // CHECK-FIXES-NEXT: for (int J = 0; J < M; ++J)
+  // CHECK-FIXES-NEXT: printf("Got item %d", I[J].X);
+
+  // Note that the order of M and N are switched for this test.
+  for (int J = 0; J < M; ++J) {
+    for (int I = 0; I < N; ++I) {
+      printf("Got item %d", Nest[I][J].X);
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop instead
+  // CHECK-FIXES-NOT: for (auto & {{[a-zA-Z_]+}} : Nest[I])
+  // CHECK-FIXES: for (int J = 0; J < M; ++J)
+  // CHECK-FIXES-NEXT: for (auto & I : Nest)
+  // CHECK-FIXES-NEXT: printf("Got item %d", I[J].X);
+
+  // The inner loop is also convertible.
+  Nested<T> NestT;
+  for (Nested<T>::iterator I = NestT.begin(), E = NestT.end(); I != E; ++I) {
+    for (T::iterator TI = (*I).begin(), TE = (*I).end(); TI != TE; ++TI) {
+      printf("%d", *TI);
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & I : NestT)
+  // CHECK-FIXES-NEXT: for (T::iterator TI = I.begin(), TE = I.end(); TI != TE; ++TI)
+  // CHECK-FIXES-NEXT: printf("%d", *TI);
+
+  // The inner loop is also convertible.
+  Nested<S> NestS;
+  for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
+    for (S::const_iterator SI = (*I).begin(), SE = (*I).end(); SI != SE; ++SI) {
+      printf("%d", *SI);
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto I : NestS)
+  // CHECK-FIXES-NEXT: for (S::const_iterator SI = I.begin(), SE = I.end(); SI != SE; ++SI)
+  // CHECK-FIXES-NEXT: printf("%d", *SI);
+
+  for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
+    const S &Ss = *I;
+    for (S::const_iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {
+      printf("%d", *SI);
+      const_g(SI);
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto Ss : NestS)
+
+  for (Nested<S>::iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
+    S &Ss = *I;
+    for (S::iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {
+      printf("%d", *SI);
+      g(SI);
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & Ss : NestS)
+
+  Foo foo;
+  for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
+    const S &Ss = *I;
+    for (S::const_iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {
+      printf("%d", *SI);
+      foo.const_g(SI);
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto Ss : NestS)
+
+  for (Nested<S>::iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
+    S &Ss = *I;
+    for (S::iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {
+      printf("%d", *SI);
+      foo.g(SI);
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & Ss : NestS)
+
+}
+
+} // namespace Nesting
+
+namespace SingleIterator {
+
+void complexContainer() {
+  X Exes[5];
+  int Index = 0;
+
+  for (S::iterator I = Exes[Index].getS().begin(), E = Exes[Index].getS().end(); I != E; ++I) {
+    MutableVal K = *I;
+    MutableVal J = *I;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & I : Exes[Index].getS())
+  // CHECK-FIXES-NEXT: MutableVal K = I;
+  // CHECK-FIXES-NEXT: MutableVal J = I;
+}
+
+void f() {
+  /// begin()/end() - based for loops here:
+  T Tt;
+  for (T::iterator It = Tt.begin(); It != Tt.end(); ++It) {
+    printf("I found %d\n", *It);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : Tt)
+  // CHECK-FIXES-NEXT: printf("I found %d\n", It);
+
+  T *Pt;
+  for (T::iterator It = Pt->begin(); It != Pt->end(); ++It) {
+    printf("I found %d\n", *It);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : *Pt)
+  // CHECK-FIXES-NEXT: printf("I found %d\n", It);
+
+  S Ss;
+  for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {
+    printf("s has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+  S *Ps;
+  for (S::iterator It = Ps->begin(); It != Ps->end(); ++It) {
+    printf("s has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & P : *Ps)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
+
+  for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {
+    printf("s has value %d\n", It->X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+  for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {
+    It->X = 3;
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: It.X = 3;
+
+  for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {
+    (*It).X = 3;
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: It.X = 3;
+
+  for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {
+    It->nonConstFun(4, 5);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Ss)
+  // CHECK-FIXES-NEXT: It.nonConstFun(4, 5);
+
+  U Uu;
+  for (U::iterator It = Uu.begin(); It != Uu.end(); ++It) {
+    printf("s has value %d\n", It->X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Uu)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+  for (U::iterator It = Uu.begin(); It != Uu.end(); ++It) {
+    printf("s has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : Uu)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+  U::iterator A;
+  for (U::iterator I = Uu.begin(); I != Uu.end(); ++I)
+    int K = A->X + I->X;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & I : Uu)
+  // CHECK-FIXES-NEXT: int K = A->X + I.X;
+
+  dependent<int> V;
+  for (dependent<int>::iterator It = V.begin();
+       It != V.end(); ++It) {
+    printf("Fibonacci number is %d\n", *It);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : V)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
+
+  for (dependent<int>::iterator It(V.begin());
+       It != V.end(); ++It) {
+    printf("Fibonacci number is %d\n", *It);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : V)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
+
+  doublyDependent<int, int> intmap;
+  for (doublyDependent<int, int>::iterator It = intmap.begin();
+       It != intmap.end(); ++It) {
+    printf("intmap[%d] = %d", It->first, It->second);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & It : intmap)
+  // CHECK-FIXES-NEXT: printf("intmap[%d] = %d", It.first, It.second);
+}
+
+void different_type() {
+  // Tests to verify the proper use of auto where the init variable type and the
+  // initializer type differ or are mostly the same except for const qualifiers.
+
+  // Ss.begin() returns a type 'iterator' which is just a non-const pointer and
+  // differs from const_iterator only on the const qualification.
+  S Ss;
+  for (S::const_iterator It = Ss.begin(); It != Ss.end(); ++It) {
+    printf("s has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto It : Ss)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
+
+  S *Ps;
+  for (S::const_iterator It = Ps->begin(); It != Ps->end(); ++It) {
+    printf("s has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto P : *Ps)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
+
+  // V.begin() returns a user-defined type 'iterator' which, since it's
+  // different from const_iterator, disqualifies these loops from
+  // transformation.
+  dependent<int> V;
+  for (dependent<int>::const_iterator It = V.begin(); It != V.end(); ++It) {
+    printf("Fibonacci number is %d\n", *It);
+  }
+
+  for (dependent<int>::const_iterator It(V.begin()); It != V.end(); ++It) {
+    printf("Fibonacci number is %d\n", *It);
+  }
+}
+
+} // namespace SingleIterator
+
+
+namespace Macros {
+
+#define TWO_PARAM(x, y) if (x == y) {}
+#define THREE_PARAM(x, y, z) if (x == y) {z;}
+
+const int N = 10;
+int Arr[N];
+
+void messing_with_macros() {
+  for (int I = 0; I < N; ++I) {
+    printf("Value: %d\n", Arr[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : Arr)
+  // CHECK-FIXES-NEXT:  printf("Value: %d\n", I);
+
+  for (int I = 0; I < N; ++I) {
+    printf("Value: %d\n", CONT Arr[I]);
+  }
+
+  // Multiple macro arguments.
+  for (int I = 0; I < N; ++I) {
+    TWO_PARAM(Arr[I], Arr[I]);
+    THREE_PARAM(Arr[I], Arr[I], Arr[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & I : Arr)
+  // CHECK-FIXES-NEXT: TWO_PARAM(I, I);
+  // CHECK-FIXES-NEXT: THREE_PARAM(I, I, I);
+}
+
+} // namespace Macros
+
+namespace Templates {
+
+template <class Container>
+void set_union(Container &container) {
+  for (typename Container::const_iterator SI = container.begin(),
+       SE = container.end(); SI != SE; ++SI) {
+    (void) *SI;
+  }
+
+  S Ss;
+  for (S::iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI)
+    (void) *SI;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & SI : Ss)
+}
+
+void template_instantiation() {
+  S Ss;
+  set_union(Ss);
+}
+
+} // namespace Templates
+
+namespace Lambdas {
+
+void capturesIndex() {
+  const int N = 10;
+  int Arr[N];
+  // FIXME: the next four loops could be convertible, if the capture list is
+  // also changed.
+
+  for (int I = 0; I < N; ++I)
+    auto F1 = [Arr, I]() { int R1 = Arr[I] + 1; };
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : Arr)
+  // CHECK-FIXES-NEXT: auto F1 = [Arr, &I]() { int R1 = I + 1; };
+
+  for (int I = 0; I < N; ++I)
+    auto F2 = [Arr, &I]() { int R2 = Arr[I] + 3; };
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : Arr)
+  // CHECK-FIXES-NEXT: auto F2 = [Arr, &I]() { int R2 = I + 3; };
+
+  // FIXME: alias don't work if the index is captured.
+  // Alias declared inside lambda (by value).
+  for (int I = 0; I < N; ++I)
+    auto F3 = [&Arr, I]() { int R3 = Arr[I]; };
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : Arr)
+  // CHECK-FIXES-NEXT: auto F3 = [&Arr, &I]() { int R3 = I; };
+
+
+  for (int I = 0; I < N; ++I)
+    auto F4 = [&Arr, &I]() { int R4 = Arr[I]; };
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : Arr)
+  // CHECK-FIXES-NEXT: auto F4 = [&Arr, &I]() { int R4 = I; };
+
+  // Alias declared inside lambda (by reference).
+  for (int I = 0; I < N; ++I)
+    auto F5 = [&Arr, I]() { int &R5 = Arr[I]; };
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & I : Arr)
+  // CHECK-FIXES-NEXT: auto F5 = [&Arr, &I]() { int &R5 = I; };
+
+
+  for (int I = 0; I < N; ++I)
+    auto F6 = [&Arr, &I]() { int &R6 = Arr[I]; };
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & I : Arr)
+  // CHECK-FIXES-NEXT: auto F6 = [&Arr, &I]() { int &R6 = I; };
+
+  for (int I = 0; I < N; ++I) {
+    auto F = [Arr, I](int k) {
+      printf("%d\n", Arr[I] + k);
+    };
+    F(Arr[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : Arr)
+  // CHECK-FIXES-NEXT: auto F = [Arr, &I](int k)
+  // CHECK-FIXES-NEXT: printf("%d\n", I + k);
+  // CHECK-FIXES: F(I);
+}
+
+void implicitCapture() {
+  const int N = 10;
+  int Arr[N];
+  // Index is used, not convertible.
+  for (int I = 0; I < N; ++I) {
+    auto G1 = [&]() {
+      int R = Arr[I];
+      int J = I;
+    };
+  }
+
+  for (int I = 0; I < N; ++I) {
+    auto G2 = [=]() {
+      int R = Arr[I];
+      int J = I;
+    };
+  }
+
+  // Convertible.
+  for (int I = 0; I < N; ++I) {
+    auto G3 = [&]() {
+      int R3 = Arr[I];
+      int J3 = Arr[I] + R3;
+    };
+  }
+  // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : Arr)
+  // CHECK-FIXES-NEXT: auto G3 = [&]()
+  // CHECK-FIXES-NEXT: int R3 = I;
+  // CHECK-FIXES-NEXT: int J3 = I + R3;
+
+  for (int I = 0; I < N; ++I) {
+    auto G4 = [=]() {
+      int R4 = Arr[I] + 5;
+    };
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : Arr)
+  // CHECK-FIXES-NEXT: auto G4 = [=]()
+  // CHECK-FIXES-NEXT: int R4 = I + 5;
+
+  // Alias by value.
+  for (int I = 0; I < N; ++I) {
+    auto G5 = [&]() {
+      int R5 = Arr[I];
+      int J5 = 8 + R5;
+    };
+  }
+  // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int R5 : Arr)
+  // CHECK-FIXES-NEXT: auto G5 = [&]()
+  // CHECK-FIXES-NEXT: int J5 = 8 + R5;
+
+  // Alias by reference.
+  for (int I = 0; I < N; ++I) {
+    auto G6 = [&]() {
+      int &R6 = Arr[I];
+      int J6 = -1 + R6;
+    };
+  }
+  // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & R6 : Arr)
+  // CHECK-FIXES-NEXT: auto G6 = [&]()
+  // CHECK-FIXES-NEXT: int J6 = -1 + R6;
+}
+
+void iterators() {
+  dependent<int> Dep;
+
+  for (dependent<int>::iterator I = Dep.begin(), E = Dep.end(); I != E; ++I)
+    auto H1 = [&I]() { int R = *I; };
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & I : Dep)
+  // CHECK-FIXES-NEXT: auto H1 = [&I]() { int R = I; };
+
+  for (dependent<int>::iterator I = Dep.begin(), E = Dep.end(); I != E; ++I)
+    auto H2 = [&]() { int R = *I + 2; };
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & I : Dep)
+  // CHECK-FIXES-NEXT: auto H2 = [&]() { int R = I + 2; };
+
+  // FIXME: It doesn't work with const iterators.
+  for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
+       I != E; ++I)
+    auto H3 = [I]() { int R = *I; };
+
+  for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
+       I != E; ++I)
+    auto H4 = [&]() { int R = *I + 1; };
+
+  for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
+       I != E; ++I)
+    auto H5 = [=]() { int R = *I; };
+}
+
+void captureByValue() {
+  // When the index is captured by value, we should replace this by a capture
+  // by reference. This avoids extra copies.
+  // FIXME: this could change semantics on array or pseudoarray loops if the
+  // container is captured by copy.
+  const int N = 10;
+  int Arr[N];
+  dependent<int> Dep;
+
+  for (int I = 0; I < N; ++I) {
+    auto C1 = [&Arr, I]() { if (Arr[I] == 1); };
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : Arr)
+  // CHECK-FIXES-NEXT: auto C1 = [&Arr, &I]() { if (I == 1); };
+
+  for (unsigned I = 0; I < Dep.size(); ++I) {
+    auto C2 = [&Dep, I]() { if (Dep[I] == 2); };
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : Dep)
+  // CHECK-FIXES-NEXT: auto C2 = [&Dep, &I]() { if (I == 2); };
+}
+
+} // namespace Lambdas
+
+namespace InitLists {
+
+struct D { int Ii; };
+struct E { D Dd; };
+int g(int B);
+
+void f() {
+  const unsigned N = 3;
+  int Array[N];
+
+  // Subtrees of InitListExpr are visited twice. Test that we do not do repeated
+  // replacements.
+  for (unsigned I = 0; I < N; ++I) {
+    int A{ Array[I] };
+    int B{ g(Array[I]) };
+    int C{ g( { Array[I] } ) };
+    D Dd{ { g( { Array[I] } ) } };
+    E Ee{ { { g( { Array[I] } ) } } };
+  }
+  // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : Array)
+  // CHECK-FIXES-NEXT: int A{ I };
+  // CHECK-FIXES-NEXT: int B{ g(I) };
+  // CHECK-FIXES-NEXT: int C{ g( { I } ) };
+  // CHECK-FIXES-NEXT: D Dd{ { g( { I } ) } };
+  // CHECK-FIXES-NEXT: E Ee{ { { g( { I } ) } } };
+}
+
+} // namespace InitLists
+
+void bug28341() {
+  char v[5];
+  for(int i = 0; i < 5; ++i) {
+      unsigned char value = v[i];
+      if (value > 127)
+        ;
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for(unsigned char value : v)
+  // CHECK-FIXES-NEXT: if (value > 127)
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-lowercase.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-lowercase.cpp
new file mode 100644
index 0000000..c7bb221
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-lowercase.cpp
@@ -0,0 +1,41 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-loop-convert.NamingStyle, value: 'lower_case'}]}" \
+// RUN:   -- -std=c++11 -I %S/Inputs/modernize-loop-convert
+
+#include "structures.h"
+
+const int n = 10;
+int arr[n];
+int nums[n];
+int nums_[n];
+
+void naming() {
+  for (int i = 0; i < n; ++i) {
+    printf("%d\n", arr[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
+  // CHECK-FIXES: for (int i : arr)
+  // CHECK-FIXES-NEXT: printf("%d\n", i);
+
+  for (int i = 0; i < n; ++i) {
+    printf("%d\n", nums[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int num : nums)
+  // CHECK-FIXES-NEXT: printf("%d\n", num);
+
+  for (int i = 0; i < n; ++i) {
+    printf("%d\n", nums_[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int num : nums_)
+  // CHECK-FIXES-NEXT: printf("%d\n", num);
+
+  int num = 0;
+  for (int i = 0; i < n; ++i) {
+    printf("%d\n", nums[i] + num);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int i : nums)
+  // CHECK-FIXES-NEXT: printf("%d\n", i + num);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-negative.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-negative.cpp
new file mode 100644
index 0000000..c038437
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-negative.cpp
@@ -0,0 +1,485 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -std=c++11 -I %S/Inputs/modernize-loop-convert
+
+#include "structures.h"
+
+// CHECK-FIXES-NOT: for ({{.*[^:]:[^:].*}})
+// CHECK-MESSAGES-NOT: modernize-loop-convert
+
+namespace Negative {
+
+const int N = 6;
+int Arr[N] = {1, 2, 3, 4, 5, 6};
+int (*pArr)[N] = &Arr;
+int Sum = 0;
+
+// Checks for the Index start and end:
+void IndexStartAndEnd() {
+  for (int I = 0; I < N + 1; ++I)
+    Sum += Arr[I];
+
+  for (int I = 0; I < N - 1; ++I)
+    Sum += Arr[I];
+
+  for (int I = 1; I < N; ++I)
+    Sum += Arr[I];
+
+  for (int I = 1; I < N; ++I)
+    Sum += Arr[I];
+
+  for (int I = 0;; ++I)
+    Sum += (*pArr)[I];
+}
+
+// Checks for invalid increment steps:
+void increment() {
+  for (int I = 0; I < N; --I)
+    Sum += Arr[I];
+
+  for (int I = 0; I < N; I)
+    Sum += Arr[I];
+
+  for (int I = 0; I < N;)
+    Sum += Arr[I];
+
+  for (int I = 0; I < N; I += 2)
+    Sum++;
+}
+
+// Checks to make sure that the Index isn't used outside of the array:
+void IndexUse() {
+  for (int I = 0; I < N; ++I)
+    Arr[I] += 1 + I;
+}
+
+// Check for loops that don't mention arrays
+void noArray() {
+  for (int I = 0; I < N; ++I)
+    Sum += I;
+
+  for (int I = 0; I < N; ++I) {
+  }
+
+  for (int I = 0; I < N; ++I)
+    ;
+}
+
+// Checks for incorrect loop variables.
+void mixedVariables() {
+  int BadIndex;
+  for (int I = 0; BadIndex < N; ++I)
+    Sum += Arr[I];
+
+  for (int I = 0; I < N; ++BadIndex)
+    Sum += Arr[I];
+
+  for (int I = 0; BadIndex < N; ++BadIndex)
+    Sum += Arr[I];
+
+  for (int I = 0; BadIndex < N; ++BadIndex)
+    Sum += Arr[BadIndex];
+}
+
+// Checks for multiple arrays Indexed.
+void multipleArrays() {
+  int BadArr[N];
+
+  for (int I = 0; I < N; ++I)
+    Sum += Arr[I] + BadArr[I];
+
+  for (int I = 0; I < N; ++I) {
+    int K = BadArr[I];
+    Sum += Arr[I] + K;
+  }
+}
+
+}
+
+namespace NegativeIterator {
+
+S Ss;
+T Tt;
+U Tu;
+
+struct BadBeginEnd : T {
+  iterator notBegin();
+  iterator notEnd();
+};
+
+void notBeginOrEnd() {
+  BadBeginEnd Bad;
+  for (T::iterator I = Bad.notBegin(), E = Bad.end();  I != E; ++I)
+    int K = *I;
+
+  for (T::iterator I = Bad.begin(), E = Bad.notEnd();  I != E; ++I)
+    int K = *I;
+}
+
+void badLoopShapes() {
+  for (T::iterator I = Tt.begin(), E = Tt.end(), F = E;  I != E; ++I)
+    int K = *I;
+
+  for (T::iterator I = Tt.begin(), E = Tt.end();  I != E;)
+    int K = *I;
+
+  for (T::iterator I = Tt.begin(), E = Tt.end();; ++I)
+    int K = *I;
+
+  T::iterator OutsideI;
+  T::iterator OutsideE;
+
+  for (; OutsideI != OutsideE; ++OutsideI)
+    int K = *OutsideI;
+}
+
+void iteratorArrayMix() {
+  int Lower;
+  const int N = 6;
+  for (T::iterator I = Tt.begin(), E = Tt.end(); Lower < N; ++I)
+    int K = *I;
+
+  for (T::iterator I = Tt.begin(), E = Tt.end(); Lower < N; ++Lower)
+    int K = *I;
+}
+
+struct ExtraConstructor : T::iterator {
+  ExtraConstructor(T::iterator, int);
+  explicit ExtraConstructor(T::iterator);
+};
+
+void badConstructor() {
+  for (T::iterator I = ExtraConstructor(Tt.begin(), 0), E = Tt.end();
+        I != E; ++I)
+    int K = *I;
+  for (T::iterator I = ExtraConstructor(Tt.begin()), E = Tt.end();  I != E; ++I)
+    int K = *I;
+}
+
+void foo(S::iterator It) {}
+class Foo {public: void bar(S::iterator It); };
+Foo Fo;
+
+void iteratorUsed() {
+  for (S::iterator I = Ss.begin(), E = Ss.end();  I != E; ++I)
+    foo(I);
+
+  for (S::iterator I = Ss.begin(), E = Ss.end();  I != E; ++I)
+    Fo.bar(I);
+
+  S::iterator Ret;
+  for (S::iterator I = Ss.begin(), E = Ss.end();  I != E; ++I)
+    Ret = I;
+}
+
+void iteratorMemberUsed() {
+  for (T::iterator I = Tt.begin(), E = Tt.end();  I != E; ++I)
+    I.X = *I;
+
+  for (T::iterator I = Tt.begin(), E = Tt.end();  I != E; ++I)
+    int K = I.X + *I;
+
+  for (T::iterator I = Tt.begin(), E = Tt.end();  I != E; ++I)
+    int K = E.X + *I;
+}
+
+void iteratorMethodCalled() {
+  for (T::iterator I = Tt.begin(), E = Tt.end();  I != E; ++I)
+    I.insert(3);
+
+  for (T::iterator I = Tt.begin(), E = Tt.end();  I != E; ++I)
+    if (I != I)
+      int K = 3;
+}
+
+void iteratorOperatorCalled() {
+  for (T::iterator I = Tt.begin(), E = Tt.end();  I != E; ++I)
+    int K = *(++I);
+
+  for (S::iterator I = Ss.begin(), E = Ss.end();  I != E; ++I)
+    MutableVal K = *(++I);
+}
+
+void differentContainers() {
+  T Other;
+  for (T::iterator I = Tt.begin(), E = Other.end();  I != E; ++I)
+    int K = *I;
+
+  for (T::iterator I = Other.begin(), E = Tt.end();  I != E; ++I)
+    int K = *I;
+
+  S OtherS;
+  for (S::iterator I = Ss.begin(), E = OtherS.end();  I != E; ++I)
+    MutableVal K = *I;
+
+  for (S::iterator I = OtherS.begin(), E = Ss.end();  I != E; ++I)
+    MutableVal K = *I;
+}
+
+void wrongIterators() {
+  T::iterator Other;
+  for (T::iterator I = Tt.begin(), E = Tt.end(); I != Other; ++I)
+    int K = *I;
+}
+
+struct EvilArrow : U {
+  // Please, no one ever write code like this.
+  U *operator->();
+};
+
+void differentMemberAccessTypes() {
+  EvilArrow A;
+  for (EvilArrow::iterator I = A.begin(), E = A->end();  I != E; ++I)
+    Val K = *I;
+  for (EvilArrow::iterator I = A->begin(), E = A.end();  I != E; ++I)
+    Val K = *I;
+}
+
+void f(const T::iterator &It, int);
+void f(const T &It, int);
+void g(T &It, int);
+
+void iteratorPassedToFunction() {
+  for (T::iterator I = Tt.begin(), E = Tt.end();  I != E; ++I)
+    f(I, *I);
+}
+
+// FIXME: These tests can be removed if this tool ever does enough analysis to
+// decide that this is a safe transformation. Until then, we don't want it
+// applied.
+void iteratorDefinedOutside() {
+  T::iterator TheEnd = Tt.end();
+  for (T::iterator I = Tt.begin(); I != TheEnd; ++I)
+    int K = *I;
+
+  T::iterator TheBegin = Tt.begin();
+  for (T::iterator E = Tt.end(); TheBegin != E; ++TheBegin)
+    int K = *TheBegin;
+}
+
+} // namespace NegativeIterator
+
+namespace NegativePseudoArray {
+
+const int N = 6;
+dependent<int> V;
+dependent<int> *Pv;
+
+int Sum = 0;
+
+// Checks for the Index start and end:
+void IndexStartAndEnd() {
+  for (int I = 0; I < V.size() + 1; ++I)
+    Sum += V[I];
+
+  for (int I = 0; I < V.size() - 1; ++I)
+    Sum += V[I];
+
+  for (int I = 1; I < V.size(); ++I)
+    Sum += V[I];
+
+  for (int I = 1; I < V.size(); ++I)
+    Sum += V[I];
+
+  for (int I = 0;; ++I)
+    Sum += (*Pv)[I];
+}
+
+// Checks for invalid increment steps:
+void increment() {
+  for (int I = 0; I < V.size(); --I)
+    Sum += V[I];
+
+  for (int I = 0; I < V.size(); I)
+    Sum += V[I];
+
+  for (int I = 0; I < V.size();)
+    Sum += V[I];
+
+  for (int I = 0; I < V.size(); I += 2)
+    Sum++;
+}
+
+// Checks to make sure that the Index isn't used outside of the container:
+void IndexUse() {
+  for (int I = 0; I < V.size(); ++I)
+    V[I] += 1 + I;
+}
+
+// Checks for incorrect loop variables.
+void mixedVariables() {
+  int BadIndex;
+  for (int I = 0; BadIndex < V.size(); ++I)
+    Sum += V[I];
+
+  for (int I = 0; I < V.size(); ++BadIndex)
+    Sum += V[I];
+
+  for (int I = 0; BadIndex < V.size(); ++BadIndex)
+    Sum += V[I];
+
+  for (int I = 0; BadIndex < V.size(); ++BadIndex)
+    Sum += V[BadIndex];
+}
+
+// Checks for an array Indexed in addition to the container.
+void multipleArrays() {
+  int BadArr[N];
+
+  for (int I = 0; I < V.size(); ++I)
+    Sum += V[I] + BadArr[I];
+
+  for (int I = 0; I < V.size(); ++I)
+    Sum += BadArr[I];
+
+  for (int I = 0; I < V.size(); ++I) {
+    int K = BadArr[I];
+    Sum += K + 2;
+  }
+
+  for (int I = 0; I < V.size(); ++I) {
+    int K = BadArr[I];
+    Sum += V[I] + K;
+  }
+}
+
+// Checks for multiple containers being Indexed container.
+void multipleContainers() {
+  dependent<int> BadArr;
+
+  for (int I = 0; I < V.size(); ++I)
+    Sum += V[I] + BadArr[I];
+
+  for (int I = 0; I < V.size(); ++I)
+    Sum += BadArr[I];
+
+  for (int I = 0; I < V.size(); ++I) {
+    int K = BadArr[I];
+    Sum += K + 2;
+  }
+
+  for (int I = 0; I < V.size(); ++I) {
+    int K = BadArr[I];
+    Sum += V[I] + K;
+  }
+}
+
+// Check to make sure that dereferenced pointers-to-containers behave nicely.
+void derefContainer() {
+  // Note the dependent<T>::operator*() returns another dependent<T>.
+  // This test makes sure that we don't allow an arbitrary number of *'s.
+  for (int I = 0; I < Pv->size(); ++I)
+    Sum += (**Pv).at(I);
+
+  for (int I = 0; I < Pv->size(); ++I)
+    Sum += (**Pv)[I];
+}
+
+void wrongEnd() {
+  int Bad;
+  for (int I = 0, E = V.size(); I < Bad; ++I)
+    Sum += V[I];
+}
+
+// Checks to see that non-const member functions are not called on the container
+// object.
+// These could be conceivably allowed with a lower required confidence level.
+void memberFunctionCalled() {
+  for (int I = 0; I < V.size(); ++I) {
+    Sum += V[I];
+    V.foo();
+  }
+
+  for (int I = 0; I < V.size(); ++I) {
+    Sum += V[I];
+    dependent<int>::iterator It = V.begin();
+  }
+}
+
+} // namespace NegativePseudoArray
+
+namespace NegativeMultiEndCall {
+
+S Ss;
+T Tt;
+U Uu;
+
+void f(X);
+void f(S);
+void f(T);
+
+void complexContainer() {
+  X Xx;
+  for (S::iterator I = Xx.Ss.begin(), E = Xx.Ss.end();  I != E; ++I) {
+    f(Xx);
+    MutableVal K = *I;
+  }
+
+  for (T::iterator I = Xx.Tt.begin(), E = Xx.Tt.end();  I != E; ++I) {
+    f(Xx);
+    int K = *I;
+  }
+
+  for (S::iterator I = Xx.Ss.begin(), E = Xx.Ss.end();  I != E; ++I) {
+    f(Xx.Ss);
+    MutableVal K = *I;
+  }
+
+  for (T::iterator I = Xx.Tt.begin(), E = Xx.Tt.end();  I != E; ++I) {
+    f(Xx.Tt);
+    int K = *I;
+  }
+
+  for (S::iterator I = Xx.getS().begin(), E = Xx.getS().end();  I != E; ++I) {
+    f(Xx.getS());
+    MutableVal K = *I;
+  }
+
+  X Exes[5];
+  int Index = 0;
+
+  for (S::iterator I = Exes[Index].getS().begin(),
+                   E = Exes[Index].getS().end();
+        I != E; ++I) {
+    Index++;
+    MutableVal K = *I;
+  }
+}
+
+} // namespace NegativeMultiEndCall
+
+namespace NoUsages {
+
+const int N = 6;
+int Arr[N] = {1, 2, 3, 4, 5, 6};
+S Ss;
+dependent<int> V;
+int Count = 0;
+
+void foo();
+
+void f() {
+  for (int I = 0; I < N; ++I) {}
+  for (int I = 0; I < N; ++I)
+    printf("Hello world\n");
+  for (int I = 0; I < N; ++I)
+    ++Count;
+  for (int I = 0; I < N; ++I)
+    foo();
+
+  for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I) {}
+  for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
+    printf("Hello world\n");
+  for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
+    ++Count;
+  for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
+    foo();
+
+  for (int I = 0; I < V.size(); ++I) {}
+  for (int I = 0; I < V.size(); ++I)
+    printf("Hello world\n");
+  for (int I = 0; I < V.size(); ++I)
+    ++Count;
+  for (int I = 0; I < V.size(); ++I)
+    foo();
+}
+
+} // namespace NoUsages
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-uppercase.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-uppercase.cpp
new file mode 100644
index 0000000..4d1d5c2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-uppercase.cpp
@@ -0,0 +1,41 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-loop-convert.NamingStyle, value: 'UPPER_CASE'}]}" \
+// RUN:   -- -std=c++11 -I %S/Inputs/modernize-loop-convert
+
+#include "structures.h"
+
+const int N = 10;
+int ARR[N];
+int NUMS[N];
+int NUMS_[N];
+
+void naming() {
+  for (int I = 0; I < N; ++I) {
+    printf("%d\n", ARR[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
+  // CHECK-FIXES: for (int I : ARR)
+  // CHECK-FIXES-NEXT: printf("%d\n", I);
+
+  for (int I = 0; I < N; ++I) {
+    printf("%d\n", NUMS[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int NUM : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUM);
+
+  for (int I = 0; I < N; ++I) {
+    printf("%d\n", NUMS_[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int NUM : NUMS_)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUM);
+
+  int NUM = 0;
+  for (int I = 0; I < N; ++I) {
+    printf("%d\n", NUMS[I] + NUM);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int I : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", I + NUM);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert.c
new file mode 100644
index 0000000..4c7d956
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert.c
@@ -0,0 +1,12 @@
+// RUN: clang-tidy %s -checks=-*,modernize-loop-convert -- -std=c11 | count 0
+
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+
+int arr[6] = {1, 2, 3, 4, 5, 6};
+
+void f(void) {
+  for (int i = 0; i < 6; ++i) {
+    (void)arr[i];
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-shared-header.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-shared-header.cpp
new file mode 100644
index 0000000..21b07ee
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-shared-header.cpp
@@ -0,0 +1,17 @@
+// RUN: %check_clang_tidy %s modernize-make-shared %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:     [{key: modernize-make-shared.MakeSmartPtrFunction, \
+// RUN:       value: 'my::MakeShared'}, \
+// RUN:      {key: modernize-make-shared.MakeSmartPtrFunctionHeader, \
+// RUN:       value: 'make_shared_util.h'} \
+// RUN:     ]}" \
+// RUN:   -- -std=c++11 -I%S/Inputs/modernize-smart-ptr
+
+#include "shared_ptr.h"
+// CHECK-FIXES: #include "make_shared_util.h"
+
+void f() {
+  std::shared_ptr<int> P1 = std::shared_ptr<int>(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use my::MakeShared instead
+  // CHECK-FIXES: std::shared_ptr<int> P1 = my::MakeShared<int>();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-shared.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-shared.cpp
new file mode 100644
index 0000000..ed4da99
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-shared.cpp
@@ -0,0 +1,286 @@
+// RUN: %check_clang_tidy %s modernize-make-shared %t -- -- -std=c++11 \
+// RUN:   -I%S/Inputs/modernize-smart-ptr
+
+#include "shared_ptr.h"
+// CHECK-FIXES: #include <memory>
+
+struct Base {
+  Base();
+  Base(int, int);
+};
+
+struct Derived : public Base {
+  Derived();
+  Derived(int, int);
+};
+
+struct APair {
+  int a, b;
+};
+
+struct DPair {
+  DPair() : a(0), b(0) {}
+  DPair(int x, int y) : a(y), b(x) {}
+  int a, b;
+};
+
+struct Empty {};
+
+template <class T>
+using shared_ptr_ = std::shared_ptr<T>;
+
+void *operator new(__SIZE_TYPE__ Count, void *Ptr);
+
+int g(std::shared_ptr<int> P);
+
+std::shared_ptr<Base> getPointer() {
+  return std::shared_ptr<Base>(new Base);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_shared instead
+  // CHECK-FIXES: return std::make_shared<Base>();
+}
+
+void basic() {
+  std::shared_ptr<int> P1 = std::shared_ptr<int>(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_shared instead [modernize-make-shared]
+  // CHECK-FIXES: std::shared_ptr<int> P1 = std::make_shared<int>();
+
+  P1.reset(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_shared instead [modernize-make-shared]
+  // CHECK-FIXES: P1 = std::make_shared<int>();
+
+  P1 = std::shared_ptr<int>(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_shared instead [modernize-make-shared]
+  // CHECK-FIXES: P1 = std::make_shared<int>();
+
+  // Without parenthesis.
+  std::shared_ptr<int> P2 = std::shared_ptr<int>(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_shared instead [modernize-make-shared]
+  // CHECK-FIXES: std::shared_ptr<int> P2 = std::make_shared<int>();
+
+  P2.reset(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_shared instead [modernize-make-shared]
+  // CHECK-FIXES: P2 = std::make_shared<int>();
+
+  P2 = std::shared_ptr<int>(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_shared instead [modernize-make-shared]
+  // CHECK-FIXES: P2 = std::make_shared<int>();
+
+  // With auto.
+  auto P3 = std::shared_ptr<int>(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_shared instead
+  // CHECK-FIXES: auto P3 = std::make_shared<int>();
+
+  {
+    // No std.
+    using namespace std;
+    shared_ptr<int> Q = shared_ptr<int>(new int());
+    // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use std::make_shared instead
+    // CHECK-FIXES: shared_ptr<int> Q = std::make_shared<int>();
+
+    Q = shared_ptr<int>(new int());
+    // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead
+    // CHECK-FIXES: Q = std::make_shared<int>();
+  }
+
+  std::shared_ptr<int> R(new int());
+
+  // Create the shared_ptr as a parameter to a function.
+  int T = g(std::shared_ptr<int>(new int()));
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_shared instead
+  // CHECK-FIXES: int T = g(std::make_shared<int>());
+
+  // Only replace if the type in the template is the same as the type returned
+  // by the new operator.
+  auto Pderived = std::shared_ptr<Base>(new Derived());
+
+  // OK to replace for reset and assign
+  Pderived.reset(new Derived());
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::make_shared instead
+  // CHECK-FIXES: Pderived = std::make_shared<Derived>();
+
+  Pderived = std::shared_ptr<Derived>(new Derived());
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use std::make_shared instead
+  // CHECK-FIXES: Pderived = std::make_shared<Derived>();
+
+  // FIXME: OK to replace if assigned to shared_ptr<Base>
+  Pderived = std::shared_ptr<Base>(new Derived());
+
+  // FIXME: OK to replace when auto is not used
+  std::shared_ptr<Base> PBase = std::shared_ptr<Base>(new Derived());
+
+  // The pointer is returned by the function, nothing to do.
+  std::shared_ptr<Base> RetPtr = getPointer();
+
+  // This emulates std::move.
+  std::shared_ptr<int> Move = static_cast<std::shared_ptr<int> &&>(P1);
+
+  // Placement arguments should not be removed.
+  int *PInt = new int;
+  std::shared_ptr<int> Placement = std::shared_ptr<int>(new (PInt) int{3});
+  Placement.reset(new (PInt) int{3});
+  Placement = std::shared_ptr<int>(new (PInt) int{3});
+}
+
+// Calling make_smart_ptr from within a member function of a type with a
+// private or protected constructor would be ill-formed.
+class Private {
+private:
+  Private(int z) {}
+
+public:
+  Private() {}
+  void create() {
+    auto callsPublic = std::shared_ptr<Private>(new Private);
+    // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_shared instead
+    // CHECK-FIXES: auto callsPublic = std::make_shared<Private>();
+    auto ptr = std::shared_ptr<Private>(new Private(42));
+    ptr.reset(new Private(42));
+    ptr = std::shared_ptr<Private>(new Private(42));
+  }
+
+  virtual ~Private();
+};
+
+class Protected {
+protected:
+  Protected() {}
+
+public:
+  Protected(int, int) {}
+  void create() {
+    auto callsPublic = std::shared_ptr<Protected>(new Protected(1, 2));
+    // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_shared instead
+    // CHECK-FIXES: auto callsPublic = std::make_shared<Protected>(1, 2);
+    auto ptr = std::shared_ptr<Protected>(new Protected);
+    ptr.reset(new Protected);
+    ptr = std::shared_ptr<Protected>(new Protected);
+  }
+};
+
+void initialization(int T, Base b) {
+  // Test different kinds of initialization of the pointee.
+
+  // Direct initialization with parenthesis.
+  std::shared_ptr<DPair> PDir1 = std::shared_ptr<DPair>(new DPair(1, T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
+  // CHECK-FIXES: std::shared_ptr<DPair> PDir1 = std::make_shared<DPair>(1, T);
+  PDir1.reset(new DPair(1, T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead
+  // CHECK-FIXES: PDir1 = std::make_shared<DPair>(1, T);
+
+  // Direct initialization with braces.
+  std::shared_ptr<DPair> PDir2 = std::shared_ptr<DPair>(new DPair{2, T});
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
+  // CHECK-FIXES: std::shared_ptr<DPair> PDir2 = std::make_shared<DPair>(2, T);
+  PDir2.reset(new DPair{2, T});
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead
+  // CHECK-FIXES: PDir2 = std::make_shared<DPair>(2, T);
+
+  // Aggregate initialization.
+  std::shared_ptr<APair> PAggr = std::shared_ptr<APair>(new APair{T, 1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
+  // CHECK-FIXES: std::shared_ptr<APair> PAggr = std::make_shared<APair>(APair{T, 1});
+  PAggr.reset(new APair{T, 1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead
+  // CHECK-FIXES: std::make_shared<APair>(APair{T, 1});
+
+  // Test different kinds of initialization of the pointee, when the shared_ptr
+  // is initialized with braces.
+
+  // Direct initialization with parenthesis.
+  std::shared_ptr<DPair> PDir3 = std::shared_ptr<DPair>{new DPair(3, T)};
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
+  // CHECK-FIXES: std::shared_ptr<DPair> PDir3 = std::make_shared<DPair>(3, T);
+
+  // Direct initialization with braces.
+  std::shared_ptr<DPair> PDir4 = std::shared_ptr<DPair>{new DPair{4, T}};
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
+  // CHECK-FIXES: std::shared_ptr<DPair> PDir4 = std::make_shared<DPair>(4, T);
+
+  // Aggregate initialization.
+  std::shared_ptr<APair> PAggr2 = std::shared_ptr<APair>{new APair{T, 2}};
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_shared instead
+  // CHECK-FIXES: std::shared_ptr<APair> PAggr2 = std::make_shared<APair>(APair{T, 2});
+
+  // Direct initialization with parenthesis, without arguments.
+  std::shared_ptr<DPair> PDir5 = std::shared_ptr<DPair>(new DPair());
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
+  // CHECK-FIXES: std::shared_ptr<DPair> PDir5 = std::make_shared<DPair>();
+
+  // Direct initialization with braces, without arguments.
+  std::shared_ptr<DPair> PDir6 = std::shared_ptr<DPair>(new DPair{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
+  // CHECK-FIXES: std::shared_ptr<DPair> PDir6 = std::make_shared<DPair>();
+
+  // Aggregate initialization without arguments.
+  std::shared_ptr<Empty> PEmpty = std::shared_ptr<Empty>(new Empty{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_shared instead
+  // CHECK-FIXES: std::shared_ptr<Empty> PEmpty = std::make_shared<Empty>(Empty{});
+}
+
+void aliases() {
+  typedef std::shared_ptr<int> IntPtr;
+  IntPtr Typedef = IntPtr(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use std::make_shared instead
+  // CHECK-FIXES: IntPtr Typedef = std::make_shared<int>();
+
+  // We use 'bool' instead of '_Bool'.
+  typedef std::shared_ptr<bool> BoolPtr;
+  BoolPtr BoolType = BoolPtr(new bool);
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use std::make_shared instead
+  // CHECK-FIXES: BoolPtr BoolType = std::make_shared<bool>();
+
+  // We use 'Base' instead of 'struct Base'.
+  typedef std::shared_ptr<Base> BasePtr;
+  BasePtr StructType = BasePtr(new Base);
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_shared instead
+// CHECK-FIXES: BasePtr StructType = std::make_shared<Base>();
+
+#define PTR shared_ptr<int>
+  std::shared_ptr<int> Macro = std::PTR(new int);
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_shared instead
+// CHECK-FIXES: std::shared_ptr<int> Macro = std::make_shared<int>();
+#undef PTR
+
+  std::shared_ptr<int> Using = shared_ptr_<int>(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_shared instead
+  // CHECK-FIXES: std::shared_ptr<int> Using = std::make_shared<int>();
+}
+
+void whitespaces() {
+  // clang-format off
+  auto Space = std::shared_ptr <int>(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_shared instead
+  // CHECK-FIXES: auto Space = std::make_shared<int>();
+
+  auto Spaces = std  ::    shared_ptr  <int>(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use std::make_shared instead
+  // CHECK-FIXES: auto Spaces = std::make_shared<int>();
+  // clang-format on
+}
+
+void nesting() {
+  auto Nest = std::shared_ptr<std::shared_ptr<int>>(new std::shared_ptr<int>(new int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use std::make_shared instead
+  // CHECK-FIXES: auto Nest = std::make_shared<std::shared_ptr<int>>(new int);
+  Nest.reset(new std::shared_ptr<int>(new int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_shared instead
+  // CHECK-FIXES: Nest = std::make_shared<std::shared_ptr<int>>(new int);
+  Nest->reset(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead
+  // CHECK-FIXES: *Nest = std::make_shared<int>();
+}
+
+void reset() {
+  std::shared_ptr<int> P;
+  P.reset();
+  P.reset(nullptr);
+  P.reset(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use std::make_shared instead
+  // CHECK-FIXES: P = std::make_shared<int>();
+
+  auto Q = &P;
+  Q->reset(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_shared instead
+  // CHECK-FIXES: *Q = std::make_shared<int>();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-cxx11.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-cxx11.cpp
new file mode 100644
index 0000000..89beb08
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-cxx11.cpp
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s modernize-make-unique %t -- -- -std=c++11 \
+// RUN:   -I%S/Inputs/modernize-smart-ptr
+
+#include "unique_ptr.h"
+// CHECK-FIXES: #include "unique_ptr.h"
+
+void f() {
+  auto my_ptr = std::unique_ptr<int>(new int(1));
+  // CHECK-FIXES: auto my_ptr = std::unique_ptr<int>(new int(1));
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-cxx14.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-cxx14.cpp
new file mode 100644
index 0000000..cd35f75
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-cxx14.cpp
@@ -0,0 +1,11 @@
+// RUN: %check_clang_tidy %s modernize-make-unique %t -- -- -std=c++14 \
+// RUN:   -I%S/Inputs/modernize-smart-ptr
+
+#include "unique_ptr.h"
+// CHECK-FIXES: #include <memory>
+
+void f() {
+  auto my_ptr = std::unique_ptr<int>(new int(1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use std::make_unique instead
+  // CHECK-FIXES: auto my_ptr = std::make_unique<int>(1);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-header.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-header.cpp
new file mode 100644
index 0000000..e6c2a61
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-header.cpp
@@ -0,0 +1,17 @@
+// RUN: %check_clang_tidy %s modernize-make-unique %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:     [{key: modernize-make-unique.MakeSmartPtrFunction, \
+// RUN:       value: 'my::MakeUnique'}, \
+// RUN:      {key: modernize-make-unique.MakeSmartPtrFunctionHeader, \
+// RUN:       value: 'make_unique_util.h'} \
+// RUN:     ]}" \
+// RUN:   -- -std=c++11 -I%S/Inputs/modernize-smart-ptr
+
+#include "unique_ptr.h"
+// CHECK-FIXES: #include "make_unique_util.h"
+
+void f() {
+  std::unique_ptr<int> P1 = std::unique_ptr<int>(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use my::MakeUnique instead
+  // CHECK-FIXES: std::unique_ptr<int> P1 = my::MakeUnique<int>();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-macros.cpp
new file mode 100644
index 0000000..117a45c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique-macros.cpp
@@ -0,0 +1,28 @@
+// RUN: %check_clang_tidy %s modernize-make-unique %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-make-unique.IgnoreMacros, value: 0}]}" \
+// RUN:   -- -std=c++14  -I%S/Inputs/modernize-smart-ptr
+
+#include "unique_ptr.h"
+
+class Foo {};
+class Bar {};
+#define DEFINE(...) __VA_ARGS__
+// CHECK-FIXES: {{^}}#define DEFINE(...) __VA_ARGS__{{$}}
+template<typename T>
+void g2(std::unique_ptr<Foo> *t) {
+  DEFINE(
+  // CHECK-FIXES: {{^ *}}DEFINE({{$}}
+      auto p = std::unique_ptr<Foo>(new Foo);
+      // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_unique instead
+      // CHECK-FIXES: {{^ *}}auto p = std::unique_ptr<Foo>(new Foo);{{$}}
+      t->reset(new Foo);
+      // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_unique instead
+      // CHECK-FIXES: {{^ *}}t->reset(new Foo);{{$}}
+      );
+      // CHECK-FIXES: {{^ *}});{{$}}
+}
+void macro() {
+  std::unique_ptr<Foo> *t;
+  g2<Bar>(t);
+}
+#undef DEFINE
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique.cpp
new file mode 100644
index 0000000..9685203
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-make-unique.cpp
@@ -0,0 +1,517 @@
+// RUN: %check_clang_tidy %s modernize-make-unique %t -- -- -std=c++14 \
+// RUN:   -I%S/Inputs/modernize-smart-ptr
+
+#include "unique_ptr.h"
+#include "initializer_list.h"
+// CHECK-FIXES: #include <memory>
+
+struct Base {
+  Base();
+  Base(int, int);
+};
+
+struct Derived : public Base {
+  Derived();
+  Derived(int, int);
+};
+
+struct APair {
+  int a, b;
+};
+
+struct DPair {
+  DPair() : a(0), b(0) {}
+  DPair(int x, int y) : a(y), b(x) {}
+  int a, b;
+};
+
+template<typename T>
+struct MyVector {
+  MyVector(std::initializer_list<T>);
+};
+
+struct Empty {};
+
+struct E {
+  E(std::initializer_list<int>);
+  E();
+};
+
+struct F {
+  F(std::initializer_list<int>);
+  F();
+  int a;
+};
+
+struct G {
+  G(std::initializer_list<int>);
+  G(int);
+};
+
+struct H {
+  H(std::vector<int>);
+  H(std::vector<int> &, double);
+  H(MyVector<int>, int);
+};
+
+struct I {
+  I(G);
+};
+
+namespace {
+class Foo {};
+} // namespace
+
+namespace bar {
+class Bar {};
+} // namespace bar
+
+template <class T>
+using unique_ptr_ = std::unique_ptr<T>;
+
+void *operator new(__SIZE_TYPE__ Count, void *Ptr);
+
+int g(std::unique_ptr<int> P);
+
+std::unique_ptr<Base> getPointer() {
+  return std::unique_ptr<Base>(new Base);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_unique instead
+  // CHECK-FIXES: return std::make_unique<Base>();
+}
+
+void basic() {
+  std::unique_ptr<int> P1 = std::unique_ptr<int>(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: std::unique_ptr<int> P1 = std::make_unique<int>();
+
+  P1.reset(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: P1 = std::make_unique<int>();
+
+  P1 = std::unique_ptr<int>(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: P1 = std::make_unique<int>();
+
+  // Without parenthesis.
+  std::unique_ptr<int> P2 = std::unique_ptr<int>(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: std::unique_ptr<int> P2 = std::make_unique<int>();
+
+  P2.reset(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: P2 = std::make_unique<int>();
+
+  P2 = std::unique_ptr<int>(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: P2 = std::make_unique<int>();
+
+  // With auto.
+  auto P3 = std::unique_ptr<int>(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+  // CHECK-FIXES: auto P3 = std::make_unique<int>();
+
+  {
+    // No std.
+    using namespace std;
+    unique_ptr<int> Q = unique_ptr<int>(new int());
+    // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use std::make_unique instead
+    // CHECK-FIXES: unique_ptr<int> Q = std::make_unique<int>();
+
+    Q = unique_ptr<int>(new int());
+    // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead
+    // CHECK-FIXES: Q = std::make_unique<int>();
+  }
+
+  std::unique_ptr<int> R(new int());
+
+  // Create the unique_ptr as a parameter to a function.
+  int T = g(std::unique_ptr<int>(new int()));
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+  // CHECK-FIXES: int T = g(std::make_unique<int>());
+
+  // Only replace if the type in the template is the same as the type returned
+  // by the new operator.
+  auto Pderived = std::unique_ptr<Base>(new Derived());
+
+  // OK to replace for reset and assign
+  Pderived.reset(new Derived());
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::make_unique instead
+  // CHECK-FIXES: Pderived = std::make_unique<Derived>();
+
+  Pderived = std::unique_ptr<Derived>(new Derived());
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use std::make_unique instead
+  // CHECK-FIXES: Pderived = std::make_unique<Derived>();
+
+  // FIXME: OK to replace if assigned to unique_ptr<Base>
+  Pderived = std::unique_ptr<Base>(new Derived());
+
+  // FIXME: OK to replace when auto is not used
+  std::unique_ptr<Base> PBase = std::unique_ptr<Base>(new Derived());
+
+  // The pointer is returned by the function, nothing to do.
+  std::unique_ptr<Base> RetPtr = getPointer();
+
+  // This emulates std::move.
+  std::unique_ptr<int> Move = static_cast<std::unique_ptr<int> &&>(P1);
+
+  // Placement arguments should not be removed.
+  int *PInt = new int;
+  std::unique_ptr<int> Placement = std::unique_ptr<int>(new (PInt) int{3});
+  Placement.reset(new (PInt) int{3});
+  Placement = std::unique_ptr<int>(new (PInt) int{3});
+}
+
+// Calling make_smart_ptr from within a member function of a type with a
+// private or protected constructor would be ill-formed.
+class Private {
+private:
+  Private(int z) {}
+
+public:
+  Private() {}
+  void create() {
+    auto callsPublic = std::unique_ptr<Private>(new Private);
+    // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_unique instead
+    // CHECK-FIXES: auto callsPublic = std::make_unique<Private>();
+    auto ptr = std::unique_ptr<Private>(new Private(42));
+    ptr.reset(new Private(42));
+    ptr = std::unique_ptr<Private>(new Private(42));
+  }
+
+  virtual ~Private();
+};
+
+class Protected {
+protected:
+  Protected() {}
+
+public:
+  Protected(int, int) {}
+  void create() {
+    auto callsPublic = std::unique_ptr<Protected>(new Protected(1, 2));
+    // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_unique instead
+    // CHECK-FIXES: auto callsPublic = std::make_unique<Protected>(1, 2);
+    auto ptr = std::unique_ptr<Protected>(new Protected);
+    ptr.reset(new Protected);
+    ptr = std::unique_ptr<Protected>(new Protected);
+  }
+};
+
+void initialization(int T, Base b) {
+  // Test different kinds of initialization of the pointee.
+
+  // Direct initialization with parenthesis.
+  std::unique_ptr<DPair> PDir1 = std::unique_ptr<DPair>(new DPair(1, T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<DPair> PDir1 = std::make_unique<DPair>(1, T);
+  PDir1.reset(new DPair(1, T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead
+  // CHECK-FIXES: PDir1 = std::make_unique<DPair>(1, T);
+
+  // Direct initialization with braces.
+  std::unique_ptr<DPair> PDir2 = std::unique_ptr<DPair>(new DPair{2, T});
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<DPair> PDir2 = std::make_unique<DPair>(2, T);
+  PDir2.reset(new DPair{2, T});
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead
+  // CHECK-FIXES: PDir2 = std::make_unique<DPair>(2, T);
+
+  // Aggregate initialization.
+  std::unique_ptr<APair> PAggr = std::unique_ptr<APair>(new APair{T, 1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<APair> PAggr = std::make_unique<APair>(APair{T, 1});
+  PAggr.reset(new APair{T, 1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead
+  // CHECK-FIXES: std::make_unique<APair>(APair{T, 1});
+
+  // Test different kinds of initialization of the pointee, when the unique_ptr
+  // is initialized with braces.
+
+  // Direct initialization with parenthesis.
+  std::unique_ptr<DPair> PDir3 = std::unique_ptr<DPair>{new DPair(3, T)};
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<DPair> PDir3 = std::make_unique<DPair>(3, T);
+
+  // Direct initialization with braces.
+  std::unique_ptr<DPair> PDir4 = std::unique_ptr<DPair>{new DPair{4, T}};
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<DPair> PDir4 = std::make_unique<DPair>(4, T);
+
+  // Aggregate initialization.
+  std::unique_ptr<APair> PAggr2 = std::unique_ptr<APair>{new APair{T, 2}};
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<APair> PAggr2 = std::make_unique<APair>(APair{T, 2});
+
+  // Direct initialization with parenthesis, without arguments.
+  std::unique_ptr<DPair> PDir5 = std::unique_ptr<DPair>(new DPair());
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<DPair> PDir5 = std::make_unique<DPair>();
+
+  // Direct initialization with braces, without arguments.
+  std::unique_ptr<DPair> PDir6 = std::unique_ptr<DPair>(new DPair{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<DPair> PDir6 = std::make_unique<DPair>();
+
+  // Aggregate initialization without arguments.
+  std::unique_ptr<Empty> PEmpty = std::unique_ptr<Empty>(new Empty{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<Empty> PEmpty = std::make_unique<Empty>(Empty{});
+
+  // Initialization with default constructor.
+  std::unique_ptr<E> PE1 = std::unique_ptr<E>(new E{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<E> PE1 = std::make_unique<E>();
+  PE1.reset(new E{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PE1 = std::make_unique<E>();
+
+  //============================================================================
+  //  NOTE: For initlializer-list constructors, the check only gives warnings,
+  //  and no fixes are generated.
+  //============================================================================
+
+  // Initialization with the initializer-list constructor.
+  std::unique_ptr<E> PE2 = std::unique_ptr<E>(new E{1, 2});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<E> PE2 = std::unique_ptr<E>(new E{1, 2});
+  PE2.reset(new E{1, 2});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PE2.reset(new E{1, 2});
+
+  // Initialization with default constructor.
+  std::unique_ptr<F> PF1 = std::unique_ptr<F>(new F());
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<F> PF1 = std::make_unique<F>();
+  PF1.reset(new F());
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PF1 = std::make_unique<F>();
+
+  // Initialization with default constructor.
+  std::unique_ptr<F> PF2 = std::unique_ptr<F>(new F{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<F> PF2 = std::make_unique<F>();
+  PF2.reset(new F());
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PF2 = std::make_unique<F>();
+
+  // Initialization with the initializer-list constructor.
+  std::unique_ptr<F> PF3 = std::unique_ptr<F>(new F{1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<F> PF3 = std::unique_ptr<F>(new F{1});
+  PF3.reset(new F{1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PF3.reset(new F{1});
+
+  // Initialization with the initializer-list constructor.
+  std::unique_ptr<F> PF4 = std::unique_ptr<F>(new F{1, 2});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<F> PF4 = std::unique_ptr<F>(new F{1, 2});
+
+  // Initialization with the initializer-list constructor.
+  std::unique_ptr<F> PF5 = std::unique_ptr<F>(new F({1, 2}));
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<F> PF5 = std::unique_ptr<F>(new F({1, 2}));
+
+  // Initialization with the initializer-list constructor as the default
+  // constructor is not present.
+  std::unique_ptr<G> PG1 = std::unique_ptr<G>(new G{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<G> PG1 = std::unique_ptr<G>(new G{});
+  PG1.reset(new G{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PG1.reset(new G{});
+
+  // Initialization with the initializer-list constructor.
+  std::unique_ptr<G> PG2 = std::unique_ptr<G>(new G{1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<G> PG2 = std::unique_ptr<G>(new G{1});
+
+  // Initialization with the initializer-list constructor.
+  std::unique_ptr<G> PG3 = std::unique_ptr<G>(new G{1, 2});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<G> PG3 = std::unique_ptr<G>(new G{1, 2});
+
+  std::unique_ptr<H> PH1 = std::unique_ptr<H>(new H({1, 2, 3}));
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<H> PH1 = std::unique_ptr<H>(new H({1, 2, 3}));
+  PH1.reset(new H({1, 2, 3}));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PH1.reset(new H({1, 2, 3}));
+
+  std::unique_ptr<H> PH2 = std::unique_ptr<H>(new H({1, 2, 3}, 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<H> PH2 = std::unique_ptr<H>(new H({1, 2, 3}, 1));
+  PH2.reset(new H({1, 2, 3}, 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PH2.reset(new H({1, 2, 3}, 1));
+
+  std::unique_ptr<H> PH3 = std::unique_ptr<H>(new H({1, 2, 3}, 1.0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<H> PH3 = std::unique_ptr<H>(new H({1, 2, 3}, 1.0));
+  PH3.reset(new H({1, 2, 3}, 1.0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PH3.reset(new H({1, 2, 3}, 1.0));
+
+  std::unique_ptr<I> PI1 = std::unique_ptr<I>(new I(G({1, 2, 3})));
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<I> PI1 = std::make_unique<I>(G({1, 2, 3}));
+  PI1.reset(new I(G({1, 2, 3})));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PI1 = std::make_unique<I>(G({1, 2, 3}));
+
+  std::unique_ptr<Foo> FF = std::unique_ptr<Foo>(new Foo());
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning:
+  // CHECK-FIXES: std::unique_ptr<Foo> FF = std::make_unique<Foo>();
+  FF.reset(new Foo());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+  // CHECK-FIXES: FF = std::make_unique<Foo>();
+
+  std::unique_ptr<bar::Bar> BB = std::unique_ptr<bar::Bar>(new bar::Bar());
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning:
+  // CHECK-FIXES: std::unique_ptr<bar::Bar> BB = std::make_unique<bar::Bar>();
+  BB.reset(new bar::Bar());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+  // CHECK-FIXES: BB = std::make_unique<bar::Bar>();
+
+  std::unique_ptr<Foo[]> FFs;
+  FFs.reset(new Foo[5]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning:
+  // CHECK-FIXES: FFs = std::make_unique<Foo[]>(5);
+  FFs.reset(new Foo[5]());
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning:
+  // CHECK-FIXES: FFs = std::make_unique<Foo[]>(5);
+  const int Num = 1;
+  FFs.reset(new Foo[Num]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning:
+  // CHECK-FIXES: FFs = std::make_unique<Foo[]>(Num);
+  int Num2 = 1;
+  FFs.reset(new Foo[Num2]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning:
+  // CHECK-FIXES: FFs = std::make_unique<Foo[]>(Num2);
+
+  std::unique_ptr<int[]> FI;
+  FI.reset(new int[5]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+  // CHECK-FIXES: FI = std::make_unique<int[]>(5);
+  FI.reset(new int[5]());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+  // CHECK-FIXES: FI = std::make_unique<int[]>(5);
+  FI.reset(new int[Num]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+  // CHECK-FIXES: FI = std::make_unique<int[]>(Num);
+  FI.reset(new int[Num2]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+  // CHECK-FIXES: FI = std::make_unique<int[]>(Num2);
+}
+
+void aliases() {
+  typedef std::unique_ptr<int> IntPtr;
+  IntPtr Typedef = IntPtr(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use std::make_unique instead
+  // CHECK-FIXES: IntPtr Typedef = std::make_unique<int>();
+
+  // We use 'bool' instead of '_Bool'.
+  typedef std::unique_ptr<bool> BoolPtr;
+  BoolPtr BoolType = BoolPtr(new bool);
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use std::make_unique instead
+  // CHECK-FIXES: BoolPtr BoolType = std::make_unique<bool>();
+
+  // We use 'Base' instead of 'struct Base'.
+  typedef std::unique_ptr<Base> BasePtr;
+  BasePtr StructType = BasePtr(new Base);
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_unique instead
+// CHECK-FIXES: BasePtr StructType = std::make_unique<Base>();
+
+#define PTR unique_ptr<int>
+  std::unique_ptr<int> Macro = std::PTR(new int);
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead
+// CHECK-FIXES: std::unique_ptr<int> Macro = std::make_unique<int>();
+#undef PTR
+
+  std::unique_ptr<int> Using = unique_ptr_<int>(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<int> Using = std::make_unique<int>();
+}
+
+void whitespaces() {
+  // clang-format off
+  auto Space = std::unique_ptr <int>(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_unique instead
+  // CHECK-FIXES: auto Space = std::make_unique<int>();
+
+  auto Spaces = std  ::    unique_ptr  <int>(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use std::make_unique instead
+  // CHECK-FIXES: auto Spaces = std::make_unique<int>();
+  // clang-format on
+}
+
+void nesting() {
+  auto Nest = std::unique_ptr<std::unique_ptr<int>>(new std::unique_ptr<int>(new int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use std::make_unique instead
+  // CHECK-FIXES: auto Nest = std::make_unique<std::unique_ptr<int>>(new int);
+  Nest.reset(new std::unique_ptr<int>(new int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_unique instead
+  // CHECK-FIXES: Nest = std::make_unique<std::unique_ptr<int>>(new int);
+  Nest->reset(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead
+  // CHECK-FIXES: *Nest = std::make_unique<int>();
+}
+
+void reset() {
+  std::unique_ptr<int> P;
+  P.reset();
+  P.reset(nullptr);
+  P.reset(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use std::make_unique instead
+  // CHECK-FIXES: P = std::make_unique<int>();
+
+  auto Q = &P;
+  Q->reset(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead
+  // CHECK-FIXES: *Q = std::make_unique<int>();
+}
+
+#define DEFINE(...) __VA_ARGS__
+template<typename T>
+void g2(std::unique_ptr<Foo> *t) {
+  DEFINE(auto p = std::unique_ptr<Foo>(new Foo); t->reset(new Foo););
+}
+void macro() {
+  std::unique_ptr<Foo> *t;
+  g2<bar::Bar>(t);
+}
+#undef DEFINE
+
+class UniqueFoo : public std::unique_ptr<Foo> {
+ public:
+  void foo() {
+    reset(new Foo);
+    this->reset(new Foo);
+    // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use std::make_unique instead
+    // CHECK-FIXES: *this = std::make_unique<Foo>();
+    (*this).reset(new Foo);
+    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+    // CHECK-FIXES: (*this) = std::make_unique<Foo>();
+  }
+};
+
+// Ignore statements inside a template instantiation.
+template<typename T>
+void template_fun(T* t) {
+  std::unique_ptr<T> t2 = std::unique_ptr<T>(new T);
+  t2.reset(new T);
+}
+
+void invoke_template() {
+  Foo* foo;
+  template_fun(foo);
+}
+
+void no_fix_for_invalid_new_loc() {
+  // FIXME: Although the code is valid, the end location of `new struct Base` is
+  // invalid. Correct it once https://bugs.llvm.org/show_bug.cgi?id=35952 is
+  // fixed.
+  auto T = std::unique_ptr<Base>(new struct Base);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::make_unique instead
+  // CHECK-FIXES: auto T = std::unique_ptr<Base>(new struct Base);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-header.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-header.cpp
new file mode 100644
index 0000000..95ad623
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-header.cpp
@@ -0,0 +1,8 @@
+// RUN: cp %S/Inputs/modernize-pass-by-value/header.h %T/pass-by-value-header.h
+// RUN: clang-tidy %s -checks='-*,modernize-pass-by-value' -header-filter='.*' -fix -- -std=c++11 -I %T | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not="{{warning|error}}:"
+// RUN: FileCheck -input-file=%T/pass-by-value-header.h %s -check-prefix=CHECK-FIXES
+
+#include "pass-by-value-header.h"
+// CHECK-MESSAGES: :8:5: warning: pass by value and use std::move [modernize-pass-by-value]
+// CHECK-FIXES: #include <utility>
+// CHECK-FIXES: A(ThreadId tid) : threadid(std::move(tid)) {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-macro-header.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-macro-header.cpp
new file mode 100644
index 0000000..543b7e4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-macro-header.cpp
@@ -0,0 +1,18 @@
+// RUN: %check_clang_tidy %s modernize-pass-by-value %t -- -- -std=c++11 -isystem %S/Inputs/Headers
+
+// CHECK-FIXES: #include <utility>
+
+#define HEADER <./a.h>
+#include HEADER
+
+struct A {
+  A(const A &) {}
+  A(A &&) {}
+};
+
+struct B {
+  B(const A &a) : a(a) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move [modernize-pass-by-value]
+// CHECK-FIXES: B(A a) : a(std::move(a)) {}
+  A a;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-multi-fixes.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-multi-fixes.cpp
new file mode 100644
index 0000000..7980c30
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value-multi-fixes.cpp
@@ -0,0 +1,12 @@
+// RUN: cat %S/Inputs/modernize-pass-by-value/header-with-fix.h > %T/pass-by-value-header-with-fix.h
+// RUN: sed -e 's#//.*$##' %s > %t.cpp
+// RUN: clang-tidy %t.cpp -checks='-*,modernize-pass-by-value' -header-filter='.*' -fix -- -std=c++11 -I %T | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not="{{warning|error}}:"
+// RUN: FileCheck -input-file=%t.cpp %s -check-prefix=CHECK-FIXES
+// RUN: FileCheck -input-file=%T/pass-by-value-header-with-fix.h %s -check-prefix=CHECK-HEADER-FIXES
+
+#include "pass-by-value-header-with-fix.h"
+// CHECK-HEADER-FIXES: Foo(S s);
+Foo::Foo(const S &s) : s(s) {}
+// CHECK-MESSAGES: :9:10: warning: pass by value and use std::move [modernize-pass-by-value]
+// CHECK-FIXES: #include <utility>
+// CHECK-FIXES: Foo::Foo(S s) : s(std::move(s)) {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value.cpp
new file mode 100644
index 0000000..87e22ba
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-pass-by-value.cpp
@@ -0,0 +1,215 @@
+// RUN: %check_clang_tidy %s modernize-pass-by-value %t -- -- -std=c++11 -fno-delayed-template-parsing
+
+namespace {
+// POD types are trivially move constructible.
+struct POD {
+  int a, b, c;
+};
+
+struct Movable {
+  int a, b, c;
+  Movable() = default;
+  Movable(const Movable &) {}
+  Movable(Movable &&) {}
+};
+
+struct NotMovable {
+  NotMovable() = default;
+  NotMovable(const NotMovable &) = default;
+  NotMovable(NotMovable &&) = delete;
+  int a, b, c;
+};
+}
+
+struct A {
+  A(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move [modernize-pass-by-value]
+  // CHECK-FIXES: A(Movable M) : M(std::move(M)) {}
+  Movable M;
+};
+
+// Test that we aren't modifying other things than a parameter.
+Movable GlobalObj;
+struct B {
+  B(const Movable &M) : M(GlobalObj) {}
+  // CHECK-FIXES: B(const Movable &M) : M(GlobalObj) {}
+  Movable M;
+};
+
+// Test that a parameter with more than one reference to it won't be changed.
+struct C {
+  // Tests extra-reference in body.
+  C(const Movable &M) : M(M) { this->i = M.a; }
+  // CHECK-FIXES: C(const Movable &M) : M(M) { this->i = M.a; }
+
+  // Tests extra-reference in init-list.
+  C(const Movable &M, int) : M(M), i(M.a) {}
+  // CHECK-FIXES: C(const Movable &M, int) : M(M), i(M.a) {}
+  Movable M;
+  int i;
+};
+
+// Test that both declaration and definition are updated.
+struct D {
+  D(const Movable &M);
+  // CHECK-FIXES: D(Movable M);
+  Movable M;
+};
+D::D(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: D::D(Movable M) : M(std::move(M)) {}
+
+// Test with default parameter.
+struct E {
+  E(const Movable &M = Movable()) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: E(Movable M = Movable()) : M(std::move(M)) {}
+  Movable M;
+};
+
+// Test with object that can't be moved.
+struct F {
+  F(const NotMovable &NM) : NM(NM) {}
+  // CHECK-FIXES: F(const NotMovable &NM) : NM(NM) {}
+  NotMovable NM;
+};
+
+// Test unnamed parameter in declaration.
+struct G {
+  G(const Movable &);
+  // CHECK-FIXES: G(Movable );
+  Movable M;
+};
+G::G(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: G::G(Movable M) : M(std::move(M)) {}
+
+// Test parameter with and without qualifier.
+namespace ns_H {
+typedef ::Movable HMovable;
+}
+struct H {
+  H(const ns_H::HMovable &M);
+  // CHECK-FIXES: H(ns_H::HMovable M);
+  ns_H::HMovable M;
+};
+using namespace ns_H;
+H::H(const HMovable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: H(HMovable M) : M(std::move(M)) {}
+
+// Try messing up with macros.
+#define MOVABLE_PARAM(Name) const Movable & Name
+// CHECK-FIXES: #define MOVABLE_PARAM(Name) const Movable & Name
+struct I {
+  I(MOVABLE_PARAM(M)) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: I(MOVABLE_PARAM(M)) : M(M) {}
+  Movable M;
+};
+#undef MOVABLE_PARAM
+
+// Test that templates aren't modified.
+template <typename T> struct J {
+  J(const T &M) : M(M) {}
+  // CHECK-FIXES: J(const T &M) : M(M) {}
+  T M;
+};
+J<Movable> j1(Movable());
+J<NotMovable> j2(NotMovable());
+
+struct K_Movable {
+  K_Movable() = default;
+  K_Movable(const K_Movable &) = default;
+  K_Movable(K_Movable &&o) { dummy = o.dummy; }
+  int dummy;
+};
+
+// Test with movable type with an user defined move constructor.
+struct K {
+  K(const K_Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: K(K_Movable M) : M(std::move(M)) {}
+  K_Movable M;
+};
+
+template <typename T> struct L {
+  L(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: L(Movable M) : M(std::move(M)) {}
+  Movable M;
+};
+L<int> l(Movable());
+
+// Test with a non-instantiated template class.
+template <typename T> struct N {
+  N(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: N(Movable M) : M(std::move(M)) {}
+
+  Movable M;
+  T A;
+};
+
+// Test with value parameter.
+struct O {
+  O(Movable M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: O(Movable M) : M(std::move(M)) {}
+  Movable M;
+};
+
+// Test with a const-value parameter.
+struct P {
+  P(const Movable M) : M(M) {}
+  // CHECK-FIXES: P(const Movable M) : M(M) {}
+  Movable M;
+};
+
+// Test with multiples parameters where some need to be changed and some don't.
+// need to.
+struct Q {
+  Q(const Movable &A, const Movable &B, const Movable &C, double D)
+      : A(A), B(B), C(C), D(D) {}
+  // CHECK-MESSAGES: :[[@LINE-2]]:23: warning: pass by value and use std::move
+  // CHECK-MESSAGES: :[[@LINE-3]]:41: warning: pass by value and use std::move
+  // CHECK-FIXES:      Q(const Movable &A, Movable B, Movable C, double D)
+  // CHECK-FIXES:     : A(A), B(std::move(B)), C(std::move(C)), D(D) {}
+  const Movable &A;
+  Movable B;
+  Movable C;
+  double D;
+};
+
+// Test that value-parameters with a nested name specifier are left as-is.
+namespace ns_R {
+typedef ::Movable RMovable;
+}
+struct R {
+  R(ns_R::RMovable M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: R(ns_R::RMovable M) : M(std::move(M)) {}
+  ns_R::RMovable M;
+};
+
+// Test with rvalue parameter.
+struct S {
+  S(Movable &&M) : M(M) {}
+  // CHECK-FIXES: S(Movable &&M) : M(M) {}
+  Movable M;
+};
+
+template <typename T, int N> struct array { T A[N]; };
+
+// Test that types that are trivially copyable will not use std::move. This will
+// cause problems with performance-move-const-arg, as it will revert it.
+struct T {
+  T(array<int, 10> a) : a_(a) {}
+  // CHECK-FIXES: T(array<int, 10> a) : a_(a) {}
+  array<int, 10> a_;
+};
+
+struct U {
+  U(const POD &M) : M(M) {}
+  POD M;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal-delimiter.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal-delimiter.cpp
new file mode 100644
index 0000000..1dd3e13
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal-delimiter.cpp
@@ -0,0 +1,9 @@
+// RUN: %check_clang_tidy %s modernize-raw-string-literal %t -- -config='{CheckOptions: [{key: "modernize-raw-string-literal.DelimiterStem", value: "str"}, {key: modernize-raw-string-literal.ReplaceShorterLiterals, value: 1}]}' -- -std=c++11
+
+char const *const ContainsSentinel{"who\\ops)\""};
+// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const ContainsSentinel{R"str(who\ops)")str"};{{$}}
+
+//char const *const ContainsDelim{"whoops)\")lit\""};
+// CHECK-XMESSAGES: :[[@LINE-1]]:33: warning: {{.*}} can be written as a raw string literal
+// CHECK-XFIXES: {{^}}char const *const ContainsDelim{R"lit1(whoops)")lit")lit1"};{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal-replace-shorter.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal-replace-shorter.cpp
new file mode 100644
index 0000000..673a8aa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal-replace-shorter.cpp
@@ -0,0 +1,13 @@
+// RUN: %check_clang_tidy %s modernize-raw-string-literal %t
+
+// Don't replace these, because the raw literal would be longer.
+char const *const JustAQuote("quote:\'");
+char const *const NeedDelimiter("\":)\"");
+
+char const *const ManyQuotes("quotes:\'\'\'\'");
+// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const ManyQuotes(R"(quotes:'''')");{{$}}
+
+char const *const LongOctal("\042\072\051\042");
+// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const LongOctal(R"lit(":)")lit");{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal.cpp
new file mode 100644
index 0000000..b6d4995
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-raw-string-literal.cpp
@@ -0,0 +1,131 @@
+// RUN: %check_clang_tidy %s modernize-raw-string-literal %t -- -config="{CheckOptions: [{key: modernize-raw-string-literal.ReplaceShorterLiterals, value: 1}]}" -- -std=c++11
+
+char const *const BackSlash("goink\\frob");
+// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: escaped string literal can be written as a raw string literal [modernize-raw-string-literal]
+// CHECK-FIXES: {{^}}char const *const BackSlash(R"(goink\frob)");{{$}}
+
+char const *const PlainLiteral("plain literal");
+
+// Non-printable ASCII characters.
+char const *const Nul("goink\\\000");
+char const *const Soh("goink\\\001");
+char const *const Stx("goink\\\002");
+char const *const Etx("goink\\\003");
+char const *const Enq("goink\\\004");
+char const *const Ack("goink\\\005");
+char const *const Bell("goink\\\afrob");
+char const *const BackSpace("goink\\\bfrob");
+char const *const HorizontalTab("goink\\\tfrob");
+char const *const NewLine("goink\nfrob");
+char const *const VerticalTab("goink\\\vfrob");
+char const *const FormFeed("goink\\\ffrob");
+char const *const CarraigeReturn("goink\\\rfrob");
+char const *const So("goink\\\016");
+char const *const Si("goink\\\017");
+char const *const Dle("goink\\\020");
+char const *const Dc1("goink\\\021");
+char const *const Dc2("goink\\\022");
+char const *const Dc3("goink\\\023");
+char const *const Dc4("goink\\\024");
+char const *const Nak("goink\\\025");
+char const *const Syn("goink\\\026");
+char const *const Etb("goink\\\027");
+char const *const Can("goink\\\030");
+char const *const Em("goink\\\031");
+char const *const Sub("goink\\\032");
+char const *const Esc("goink\\\033");
+char const *const Fs("goink\\\034");
+char const *const Gs("goink\\\035");
+char const *const Rs("goink\\\036");
+char const *const Us("goink\\\037");
+char const *const HexNonPrintable("\\\x03");
+char const *const Delete("\\\177");
+char const *const MultibyteSnowman("\xE2\x98\x83");
+// CHECK-FIXES: {{^}}char const *const MultibyteSnowman("\xE2\x98\x83");{{$}}
+
+char const *const TrailingSpace("A line \\with space. \n");
+char const *const TrailingNewLine("A single \\line.\n");
+char const *const AlreadyRaw(R"(foobie\\bletch)");
+char const *const UTF8Literal(u8"foobie\\bletch");
+char const *const UTF8RawLiteral(u8R"(foobie\\bletch)");
+// TODO: enable these tests once all supported compilers
+// support char16_t and char32_t (VS2013 does not)
+// char16_t const *const UTF16Literal(u"foobie\\bletch");
+// char16_t const *const UTF16RawLiteral(uR"(foobie\\bletch)");
+// char32_t const *const UTF32Literal(U"foobie\\bletch");
+// char32_t const *const UTF32RawLiteral(UR"(foobie\\bletch)");
+wchar_t const *const WideLiteral(L"foobie\\bletch");
+wchar_t const *const WideRawLiteral(LR"(foobie\\bletch)");
+
+char const *const SingleQuote("goink\'frob");
+// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: {{.*}} can be written as a raw string literal
+// CHECK-XFIXES: {{^}}char const *const SingleQuote(R"(goink'frob)");{{$}}
+
+char const *const DoubleQuote("goink\"frob");
+// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const DoubleQuote(R"(goink"frob)");{{$}}
+
+char const *const QuestionMark("goink\?frob");
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const QuestionMark(R"(goink?frob)");{{$}}
+
+char const *const RegEx("goink\\(one|two\\)\\\\\\?.*\\nfrob");
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const RegEx(R"(goink\(one|two\)\\\?.*\nfrob)");{{$}}
+
+char const *const Path("C:\\Program Files\\Vendor\\Application\\Application.exe");
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const Path(R"(C:\Program Files\Vendor\Application\Application.exe)");{{$}}
+
+char const *const ContainsSentinel("who\\ops)\"");
+// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const ContainsSentinel(R"lit(who\ops)")lit");{{$}}
+
+char const *const ContainsDelim("whoops)\")lit\"");
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const ContainsDelim(R"lit1(whoops)")lit")lit1");{{$}}
+
+char const *const OctalPrintable("\100\\");
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const OctalPrintable(R"(@\)");{{$}}
+
+char const *const HexPrintable("\x40\\");
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: {{.*}} can be written as a raw string literal
+// CHECK-FIXES: {{^}}char const *const HexPrintable(R"(@\)");{{$}}
+
+char const *const prettyFunction(__PRETTY_FUNCTION__);
+char const *const function(__FUNCTION__);
+char const *const func(__func__);
+
+#define TRICK(arg_) #arg_
+char const *const MacroBody = TRICK(foo\\bar);
+
+#define HAT(rabbit_) #rabbit_ "foo\\bar"
+char const *const StringizedMacroArgument = HAT(foo\\bar);
+
+#define SUBST(lit_) lit_
+char const *const MacroArgument = SUBST("foo\\bar");
+// FIXME: We should be able to replace this string literal macro argument
+
+template <typename T>
+void fn(char const *const Arg) {
+  char const *const Str("foo\\bar");
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: {{.*}} can be written as a raw string literal
+  // CHECK-FIXES: {{^}}  char const *const Str(R"(foo\bar)");{{$}}
+}
+
+template <>
+void fn<int>(char const *const Arg) {
+  char const *const Str("foo\\bar");
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: {{.*}} can be written as a raw string literal
+  // CHECK-FIXES: {{^}}  char const *const Str(R"(foo\bar)");{{$}}
+}
+
+void callFn() {
+  fn<int>("foo\\bar");
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} can be written as a raw string literal
+  // CHECK-FIXES: {{^}}  fn<int>(R"(foo\bar)");{{$}}
+  fn<double>("foo\\bar");
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} can be written as a raw string literal
+  // CHECK-FIXES: {{^}}  fn<double>(R"(foo\bar)");{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg-delayed.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg-delayed.cpp
new file mode 100644
index 0000000..dd88775
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg-delayed.cpp
@@ -0,0 +1,28 @@
+// RUN: %check_clang_tidy %s modernize-redundant-void-arg %t -- -- -fdelayed-template-parsing
+
+int foo(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant void argument list in function definition [modernize-redundant-void-arg]
+// CHECK-FIXES: {{^}}int foo() {{{$}}
+    return 0;
+}
+
+template <class T>
+struct MyFoo {
+  int foo(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant void argument list in function definition [modernize-redundant-void-arg]
+// CHECK-FIXES: {{^}}  int foo() {{{$}}
+    return 0;
+  }
+};
+// Explicit instantiation.
+template class MyFoo<int>;
+
+template <class T>
+struct MyBar {
+  // This declaration isn't instantiated and won't be parsed 'delayed-template-parsing'.
+  int foo(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant void argument list in function definition [modernize-redundant-void-arg]
+// CHECK-FIXES: {{^}}  int foo() {{{$}}
+    return 0;
+  }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg.c
new file mode 100644
index 0000000..fdaf375
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg.c
@@ -0,0 +1,58 @@
+// RUN: clang-tidy -checks=-*,modernize-redundant-void-arg %s -- -x c | count 0
+
+#define NULL 0
+
+extern int i;
+
+int foo2() {
+  return 0;
+}
+
+int j = 1;
+
+int foo(void) {
+  return 0;
+}
+
+typedef unsigned int my_uint;
+
+typedef void my_void;
+
+// A function taking void and returning a pointer to function taking void
+// and returning int.
+int (*returns_fn_void_int(void))(void);
+
+typedef int (*returns_fn_void_int_t(void))(void);
+
+int (*returns_fn_void_int(void))(void) {
+  return NULL;
+}
+
+// A function taking void and returning a pointer to a function taking void
+// and returning a pointer to a function taking void and returning void.
+void (*(*returns_fn_returns_fn_void_void(void))(void))(void);
+
+typedef void (*(*returns_fn_returns_fn_void_void_t(void))(void))(void);
+
+void (*(*returns_fn_returns_fn_void_void(void))(void))(void) {
+  return NULL;
+}
+
+void bar() {
+  int i;
+  int *pi = NULL;
+  void *pv = (void *) pi;
+  float f;
+  float *fi;
+  double d;
+  double *pd;
+}
+
+void (*f1)(void);
+void (*f2)(void) = NULL;
+void (*f3)(void) = bar;
+void (*fa)();
+void (*fb)() = NULL;
+void (*fc)() = bar;
+
+typedef void (function_ptr)(void);
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg.cpp
new file mode 100644
index 0000000..ea4b75f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-redundant-void-arg.cpp
@@ -0,0 +1,447 @@
+// RUN: %check_clang_tidy %s modernize-redundant-void-arg %t
+
+#define NULL 0
+
+int foo();
+
+void bar();
+
+void bar2();
+
+extern "C" void ecfoo(void);
+
+extern "C" void ecfoo(void) {
+}
+
+extern int i;
+
+int j = 1;
+
+int foo(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant void argument list in function definition [modernize-redundant-void-arg]
+// CHECK-FIXES: {{^}}int foo() {{{$}}
+    return 0;
+}
+
+typedef unsigned int my_uint;
+
+typedef void my_void;
+
+// A function taking void and returning a pointer to function taking void
+// and returning int.
+int (*returns_fn_void_int(void))(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: {{.*}} in function declaration
+// CHECK-MESSAGES: :[[@LINE-2]]:34: warning: {{.*}} in function declaration
+// CHECK-FIXES: {{^}}int (*returns_fn_void_int())();{{$}}
+
+typedef int (*returns_fn_void_int_t(void))(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: {{.*}} in typedef
+// CHECK-MESSAGES: :[[@LINE-2]]:44: warning: {{.*}} in typedef
+// CHECK-FIXES: {{^}}typedef int (*returns_fn_void_int_t())();{{$}}
+
+// Should work for type aliases as well as typedef.
+using returns_fn_void_int_t2 = int (*(void))(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: {{.*}} in type alias
+// CHECK-MESSAGES: :[[@LINE-2]]:46: warning: {{.*}} in type alias
+// CHECK-FIXES: {{^}}using returns_fn_void_int_t2 = int (*())();{{$}}
+
+int (*returns_fn_void_int(void))(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: {{.*}} in function definition
+// CHECK-MESSAGES: :[[@LINE-2]]:34: warning: {{.*}} in function definition
+// CHECK-FIXES: {{^}}int (*returns_fn_void_int())() {{{$}}
+  return nullptr;
+}
+
+// A function taking void and returning a pointer to a function taking void
+// and returning a pointer to a function taking void and returning void.
+void (*(*returns_fn_returns_fn_void_void(void))(void))(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: {{.*}} in function declaration
+// CHECK-MESSAGES: :[[@LINE-2]]:49: warning: {{.*}} in function declaration
+// CHECK-MESSAGES: :[[@LINE-3]]:56: warning: {{.*}} in function declaration
+// CHECK-FIXES: {{^}}void (*(*returns_fn_returns_fn_void_void())())();{{$}}
+
+typedef void (*(*returns_fn_returns_fn_void_void_t(void))(void))(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:52: warning: {{.*}} in typedef
+// CHECK-MESSAGES: :[[@LINE-2]]:59: warning: {{.*}} in typedef
+// CHECK-MESSAGES: :[[@LINE-3]]:66: warning: {{.*}} in typedef
+// CHECK-FIXES: {{^}}typedef void (*(*returns_fn_returns_fn_void_void_t())())();{{$}}
+
+void (*(*returns_fn_returns_fn_void_void(void))(void))(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: {{.*}} in function definition
+// CHECK-MESSAGES: :[[@LINE-2]]:49: warning: {{.*}} in function definition
+// CHECK-MESSAGES: :[[@LINE-3]]:56: warning: {{.*}} in function definition
+// CHECK-FIXES: {{^}}void (*(*returns_fn_returns_fn_void_void())())() {{{$}}
+    return nullptr;
+}
+
+void bar(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: {{.*}} in function definition
+// CHECK-FIXES: {{^}}void bar() {{{$}}
+}
+
+void op_fn(int i) {
+}
+
+class gronk {
+public:
+  gronk();
+  ~gronk();
+
+    void foo();
+    void bar();
+    void bar2
+        ();
+    void operation(int i) { }
+
+private:
+    int m_i;
+    int *m_pi;
+    float m_f;
+    float *m_pf;
+    double m_d;
+    double *m_pd;
+
+    void (*f1)(void);
+    // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: {{.*}} in field declaration
+    // CHECK-FIXES: {{^    }}void (*f1)();{{$}}
+
+  void (*op)(int i);
+
+  void (gronk::*p1)(void);
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}} in field declaration
+  // CHECK-FIXES: {{^  }}void (gronk::*p1)();{{$}}
+
+  int (gronk::*p_mi);
+
+  void (gronk::*p2)(int);
+
+  void (*(*returns_fn_returns_fn_void_void(void))(void))(void);
+  // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: {{.*}} in function declaration
+  // CHECK-MESSAGES: :[[@LINE-2]]:51: warning: {{.*}} in function declaration
+  // CHECK-MESSAGES: :[[@LINE-3]]:58: warning: {{.*}} in function declaration
+  // CHECK-FIXES: {{^}}  void (*(*returns_fn_returns_fn_void_void())())();{{$}}
+
+  void (*(*(gronk::*returns_fn_returns_fn_void_void_mem)(void))(void))(void);
+  // CHECK-MESSAGES: :[[@LINE-1]]:58: warning: {{.*}} in field declaration
+  // CHECK-MESSAGES: :[[@LINE-2]]:65: warning: {{.*}} in field declaration
+  // CHECK-MESSAGES: :[[@LINE-3]]:72: warning: {{.*}} in field declaration
+  // CHECK-FIXES: {{^}}  void (*(*(gronk::*returns_fn_returns_fn_void_void_mem)())())();{{$}}
+};
+
+int i;
+int *pi;
+void *pv = (void *) pi;
+float f;
+float *fi;
+double d;
+double *pd;
+
+void (*f1)(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}} in variable declaration
+// CHECK-FIXES: {{^}}void (*f1)();{{$}}
+
+void (*f2)(void) = nullptr;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (*f2)() = nullptr;{{$}}
+
+void (*f2b)(void)(nullptr);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (*f2b)()(nullptr);{{$}}
+
+void (*f2c)(void){nullptr};
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (*f2c)(){nullptr};{{$}}
+
+void (*f2d)(void) = NULL;
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (*f2d)() = NULL;{{$}}
+
+void (*f2e)(void)(NULL);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (*f2e)()(NULL);{{$}}
+
+void (*f2f)(void){NULL};
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (*f2f)(){NULL};{{$}}
+
+void (*f3)(void) = bar;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (*f3)() = bar;{{$}}
+
+void (*o1)(int i);
+void (*o2)(int i) = nullptr;
+void (*o3)(int i)(nullptr);
+void (*o4)(int i){nullptr};
+void (*o5)(int i) = NULL;
+void (*o6)(int i)(NULL);
+void (*o7)(int i){NULL};
+void (*o8)(int i) = op_fn;
+
+void (*fa)();
+
+void (*fb)() = nullptr;
+
+void (*fc)() = bar;
+
+typedef void (function_ptr)(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: {{.*}} in typedef
+// CHECK-FIXES: {{^}}typedef void (function_ptr)();{{$}}
+
+// intentionally not LLVM style to check preservation of whitesapce
+typedef void (function_ptr2)
+    (
+        void
+    );
+// CHECK-MESSAGES: :[[@LINE-2]]:9: warning: {{.*}} in typedef
+// CHECK-FIXES:      {{^typedef void \(function_ptr2\)$}}
+// CHECK-FIXES-NEXT: {{^    \($}}
+// CHECK-FIXES-NEXT: {{^        $}}
+// CHECK-FIXES-NEXT: {{^    \);$}}
+
+// intentionally not LLVM style to check preservation of whitesapce
+typedef
+void
+(
+*
+(
+*
+returns_fn_returns_fn_void_void_t2
+(
+void
+)
+)
+(
+void
+)
+)
+(
+void
+)
+;
+// CHECK-MESSAGES: :[[@LINE-11]]:1: warning: {{.*}} in typedef
+// CHECK-MESSAGES: :[[@LINE-8]]:1: warning: {{.*}} in typedef
+// CHECK-MESSAGES: :[[@LINE-5]]:1: warning: {{.*}} in typedef
+// CHECK-FIXES:      {{^typedef$}}
+// CHECK-FIXES-NEXT: {{^void$}}
+// CHECK-FIXES-NEXT: {{^\($}}
+// CHECK-FIXES-NEXT: {{^\*$}}
+// CHECK-FIXES-NEXT: {{^\($}}
+// CHECK-FIXES-NEXT: {{^\*$}}
+// CHECK-FIXES-NEXT: {{^returns_fn_returns_fn_void_void_t2$}}
+// CHECK-FIXES-NEXT: {{^\($}}
+// CHECK-FIXES-NOT:  {{[^ ]}}
+// CHECK-FIXES:      {{^\)$}}
+// CHECK-FIXES-NEXT: {{^\)$}}
+// CHECK-FIXES-NEXT: {{^\($}}
+// CHECK-FIXES-NOT:  {{[^ ]}}
+// CHECK-FIXES:      {{^\)$}}
+// CHECK-FIXES-NEXT: {{^\)$}}
+// CHECK-FIXES-NEXT: {{^\($}}
+// CHECK-FIXES-NOT:  {{[^ ]}}
+// CHECK-FIXES:      {{^\)$}}
+// CHECK-FIXES-NEXT: {{^;$}}
+
+
+void (gronk::*p1)(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: {{.*}} in variable declaration
+// CHECK-FIXES: {{^}}void (gronk::*p1)();{{$}}
+
+void (gronk::*p2)(void) = &gronk::foo;
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: {{.*}} in variable declaration with initializer
+// CHECK-FIXES: {{^}}void (gronk::*p2)() = &gronk::foo;{{$}}
+
+typedef void (gronk::*member_function_ptr)(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:44: warning: {{.*}} in typedef
+// CHECK-FIXES: {{^}}typedef void (gronk::*member_function_ptr)();{{$}}
+
+// intentionally not LLVM style to check preservation of whitesapce
+typedef void (gronk::*member_function_ptr2)
+    (
+        void
+    );
+// CHECK-MESSAGES: :[[@LINE-2]]:9: warning: {{.*}} in typedef
+// CHECK-FIXES:      {{^typedef void \(gronk::\*member_function_ptr2\)$}}
+// CHECK-FIXES-NEXT: {{^    \($}}
+// CHECK-FIXES-NEXT: {{^        $}}
+// CHECK-FIXES-NEXT: {{^    \);$}}
+
+void gronk::foo() {
+  void (*f1)(void) = &::bar;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in variable declaration with initializer
+  // CHECK-FIXES: {{^  }}void (*f1)() = &::bar;{{$}}
+
+  void (*f2)(void);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in variable declaration
+  // CHECK-FIXES: {{^  }}void (*f2)();{{$}}
+
+  // intentionally not LLVM style to check preservation of whitesapce
+  void (*f3)
+      (
+          void
+      );
+  // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: {{.*}} in variable declaration
+  // CHECK-FIXES:      {{^  }}void (*f3){{$}}
+  // CHECK-FIXES-NEXT: {{^      \($}}
+  // CHECK-FIXES-NEXT: {{^          $}}
+  // CHECK-FIXES-NEXT: {{^      \);$}}
+}
+
+void gronk::bar(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} in function definition
+// CHECK-FIXES: {{^}}void gronk::bar() {{{$}}
+  void (gronk::*p3)(void) = &gronk::foo;
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}} in variable declaration with initializer
+  // CHECK-FIXES: {{^  }}void (gronk::*p3)() = &gronk::foo;{{$}}
+
+  void (gronk::*p4)(void);
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}} in variable declaration
+  // CHECK-FIXES: {{^  }}void (gronk::*p4)();{{$}}
+
+  // intentionally not LLVM style to check preservation of whitesapce
+  void (gronk::*p5)
+      (
+          void
+      );
+  // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: {{.*}} in variable declaration
+  // CHECK-FIXES:      {{^  }}void (gronk::*p5){{$}}
+  // CHECK-FIXES-NEXT: {{^      \($}}
+  // CHECK-FIXES-NExT: {{^          $}}
+  // CHECK-FIXES-NExT: {{^      \);$}}
+}
+
+// intentionally not LLVM style to check preservation of whitesapce
+void gronk::bar2
+  (
+  void
+  )
+// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: {{.*}} in function definition
+// CHECK-FIXES:      {{^void gronk::bar2$}}
+// CHECK-FIXES-NEXT: {{^  \($}}
+// CHECK-FIXES-NEXT: {{^  $}}
+// CHECK-FIXES-NEXT: {{^  \)$}}
+{
+}
+
+gronk::gronk(void)
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in function definition
+// CHECK-FIXES: {{^}}gronk::gronk(){{$}}
+  : f1(nullptr),
+  p1(nullptr) {
+}
+
+gronk::~gronk(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} in function definition
+// CHECK-FIXES: {{^}}gronk::~gronk() {{{$}}
+}
+
+class nutter {
+public:
+  nutter();
+};
+
+nutter::nutter(void) {
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: {{.*}} in function definition
+// CHECK-FIXES: {{^}}nutter::nutter() {{{$}}
+  void (*f3)(void) = static_cast<void (*)(void)>(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in variable declaration with initializer
+  // CHECK-MESSAGES: :[[@LINE-2]]:43: warning: {{.*}} in named cast
+  // CHECK-FIXES: void (*f3)() = static_cast<void (*)()>(0);{{$}}
+
+  void (*f4)(void) = (void (*)(void)) 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in variable declaration with initializer
+  // CHECK-MESSAGES: :[[@LINE-2]]:32: warning: {{.*}} in cast expression
+  // CHECK-FIXES: void (*f4)() = (void (*)()) 0;{{$}}
+
+  void (*f5)(void) = reinterpret_cast<void (*)(void)>(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in variable declaration with initializer
+  // CHECK-MESSAGES: :[[@LINE-2]]:48: warning: {{.*}} in named cast
+  // CHECK-FIXES: void (*f5)() = reinterpret_cast<void (*)()>(0);{{$}}
+
+  // intentionally not LLVM style to check preservation of whitesapce
+  void (*f6)(void) = static_cast<void (*)
+      (
+          void
+      )>(0);
+  // CHECK-MESSAGES: :[[@LINE-4]]:14: warning: {{.*}} in variable declaration with initializer
+  // CHECK-MESSAGES: :[[@LINE-3]]:11: warning: {{.*}} in named cast
+  // CHECK-FIXES:      {{^  }}void (*f6)() = static_cast<void (*){{$}}
+  // CHECK-FIXES-NEXT: {{^      \($}}
+  // CHECK-FIXES-NEXT: {{^          $}}
+  // CHECK-FIXES-NEXT: {{^      }})>(0);{{$}}
+
+  // intentionally not LLVM style to check preservation of whitesapce
+  void (*f7)(void) = (void (*)
+      (
+          void
+      )) 0;
+  // CHECK-MESSAGES: :[[@LINE-4]]:14: warning: {{.*}} in variable declaration with initializer
+  // CHECK-MESSAGES: :[[@LINE-3]]:11: warning: {{.*}} in cast expression
+  // CHECK-FIXES:      {{^  }}void (*f7)() = (void (*){{$}}
+  // CHECK-FIXES-NEXT: {{^      \($}}
+  // CHECK-FIXES-NEXT: {{^          $}}
+  // CHECK-FIXES-NEXT: {{^      \)\) 0;$}}
+
+  // intentionally not LLVM style to check preservation of whitesapce
+  void (*f8)(void) = reinterpret_cast<void (*)
+      (
+          void
+      )>(0);
+  // CHECK-MESSAGES: :[[@LINE-4]]:14: warning: {{.*}} in variable declaration with initializer
+  // CHECK-MESSAGES: :[[@LINE-3]]:11: warning: {{.*}} in named cast
+  // CHECK-FIXES:      {{^  }}void (*f8)() = reinterpret_cast<void (*){{$}}
+  // CHECK-FIXES-NEXT: {{^      \($}}
+  // CHECK-FIXES-NEXT: {{^          $}}
+  // CHECK-FIXES-NEXT: {{^      \)>\(0\);$}}
+
+  void (*o1)(int) = static_cast<void (*)(int)>(0);
+  void (*o2)(int) = (void (*)(int)) 0;
+  void (*o3)(int) = reinterpret_cast<void (*)(int)>(0);
+}
+
+class generator {
+public:
+  int operator()(void) { return 1; }
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: {{.*}} in function definition
+  // CHECK-FIXES: {{^  }}int operator()() { return 1; }{{$}}
+};
+
+void test_lambda_functions() {
+  auto lamb_duh = [](void (*fn)(void)) { (*fn)(); };
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: {{.*}} in variable declaration
+  // CHECK-FIXES: {{^  }}auto lamb_duh = [](void (*fn)()) { (*fn)(); };{{$}}
+
+  auto lambda_generator = [](void) { return 1; };
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: {{.*}} in lambda expression
+  // CHECK-FIXES: {{^  }}auto lambda_generator = []() { return 1; };{{$}}
+
+  auto gen2 = []() { return 1; };
+
+  auto gen3 = []{ return 1; };
+
+  auto void_returner = [](void) -> void (*)(void) { return f1; };
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: {{.*}} in lambda expression
+  // CHECK-MESSAGES: [[@LINE-2]]:45: warning: {{.*}} in lambda expression
+  // CHECK-FIXES: {{^  }}auto void_returner = []() -> void (*)() { return f1; };{{$}}
+}
+
+#define M(x) x
+
+M(void inmacro(void) {})
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: {{.*}} in function definition
+// CHECK-FIXES: M(void inmacro() {})
+
+#define F(A, B)        \
+  struct F_##A##_##B { \
+    F_##A##_##B(void); \
+  };                   \
+  F_##A##_##B::F_##A##_##B(void)
+
+F(Foo, Bar) {
+
+}
+
+struct DefinitionWithNoBody {
+  DefinitionWithNoBody(void) = delete;
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: {{.*}} in function definition
+  // CHECK-FIXES: DefinitionWithNoBody() = delete;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-replace-auto-ptr.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-replace-auto-ptr.cpp
new file mode 100644
index 0000000..13405b2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-replace-auto-ptr.cpp
@@ -0,0 +1,304 @@
+// RUN: %check_clang_tidy %s modernize-replace-auto-ptr %t -- -- \
+// RUN:   -std=c++11 -I %S/Inputs/modernize-replace-auto-ptr
+
+// CHECK-FIXES: #include <utility>
+
+#include "memory.h"
+
+// Instrumentation for auto_ptr_ref test.
+struct Base {};
+struct Derived : Base {};
+std::auto_ptr<Derived> create_derived_ptr();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: auto_ptr is deprecated, use unique_ptr instead [modernize-replace-auto-ptr]
+// CHECK-FIXES: std::unique_ptr<Derived> create_derived_ptr();
+
+
+// Test function return values (declaration)
+std::auto_ptr<char> f_5();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: auto_ptr is deprecated
+// CHECK-FIXES: std::unique_ptr<char> f_5()
+
+
+// Test function parameters.
+void f_6(std::auto_ptr<int>);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: auto_ptr is deprecated
+// CHECK-FIXES: void f_6(std::unique_ptr<int>);
+void f_7(const std::auto_ptr<int> &);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: auto_ptr is deprecated
+// CHECK-FIXES: void f_7(const std::unique_ptr<int> &);
+
+
+// Test on record type fields.
+struct A {
+  std::auto_ptr<int> field;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr<int> field;
+
+  typedef std::auto_ptr<int> int_ptr_type;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: auto_ptr is deprecated
+  // CHECK-FIXES: typedef std::unique_ptr<int> int_ptr_type;
+};
+
+
+// FIXME: Test template WITH instantiation.
+template <typename T> struct B {
+  typedef typename std::auto_ptr<T> created_type;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: auto_ptr is deprecated
+  // CHECK-FIXES: typedef typename std::unique_ptr<T> created_type;
+
+  created_type create() { return std::auto_ptr<T>(new T()); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: auto_ptr is deprecated
+  // CHECK-FIXES: created_type create() { return std::unique_ptr<T>(new T()); }
+};
+
+
+// Test 'using' in a namespace (declaration)
+namespace ns_1 {
+// Test multiple using declarations.
+  using std::auto_ptr;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated
+  // CHECK-FIXES: using std::unique_ptr;
+  using std::auto_ptr;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated
+  // CHECK-FIXES: using std::unique_ptr;
+}
+
+
+namespace ns_2 {
+template <typename T> struct auto_ptr {};
+}
+
+void f_1() {
+  std::auto_ptr<int> a;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr<int> a;
+
+  // Check that spaces aren't modified unnecessarily.
+  std:: auto_ptr <int> b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std:: unique_ptr <int> b;
+  std :: auto_ptr < char > c(new char());
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std :: unique_ptr < char > c(new char());
+
+  // Test construction from a temporary.
+  std::auto_ptr<char> d = std::auto_ptr<char>();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-MESSAGES: :[[@LINE-2]]:32: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr<char> d = std::unique_ptr<char>();
+
+  typedef std::auto_ptr<int> int_ptr_t;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: auto_ptr is deprecated
+  // CHECK-FIXES: typedef std::unique_ptr<int> int_ptr_t;
+  int_ptr_t e(new int());
+
+  // Test pointers.
+  std::auto_ptr<int> *f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr<int> *f;
+
+  // Test 'static' declarations.
+  static std::auto_ptr<int> g;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: auto_ptr is deprecated
+  // CHECK-FIXES: static std::unique_ptr<int> g;
+
+  // Test with cv-qualifiers.
+  const std::auto_ptr<int> h;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated
+  // CHECK-FIXES: const std::unique_ptr<int> h;
+  volatile std::auto_ptr<int> i;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: auto_ptr is deprecated
+  // CHECK-FIXES: volatile std::unique_ptr<int> i;
+  const volatile std::auto_ptr<int> j;
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: auto_ptr is deprecated
+  // CHECK-FIXES: const volatile std::unique_ptr<int> j;
+
+  // Test auto and initializer-list.
+  auto k = std::auto_ptr<int>{};
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: auto_ptr is deprecated
+  // CHECK-FIXES: auto k = std::unique_ptr<int>{};
+  std::auto_ptr<int> l{std::auto_ptr<int>()};
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-MESSAGES: :[[@LINE-2]]:29: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr<int> l{std::unique_ptr<int>()};
+
+  // Test interlocked auto_ptr.
+  std::auto_ptr<std::auto_ptr<int> > m;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-MESSAGES: :[[@LINE-2]]:22: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr<std::unique_ptr<int> > m;
+
+  // Test temporaries.
+  std::auto_ptr<char>();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr<char>();
+
+  // Test void-specialization.
+  std::auto_ptr<void> n;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr<void> n;
+
+  // Test template WITH instantiation (instantiation).
+  B<double> o;
+  std::auto_ptr<double> p(o.create());
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr<double> p(o.create());
+
+  // Test 'using' in a namespace ("definition").
+  ns_1::auto_ptr<int> q;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: auto_ptr is deprecated
+  // CHECK-FIXES: ns_1::unique_ptr<int> q;
+
+  // Test construction with an 'auto_ptr_ref'.
+  std::auto_ptr<Base> r(create_derived_ptr());
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr<Base> r(create_derived_ptr());
+}
+
+// Test without the nested name specifiers.
+void f_2() {
+  using namespace std;
+
+  auto_ptr<int> a;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: auto_ptr is deprecated
+  // CHECK-FIXES: unique_ptr<int> a;
+}
+
+// Test using declaration.
+void f_3() {
+  using std::auto_ptr;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated
+  // CHECK-FIXES: using std::unique_ptr;
+
+  auto_ptr<int> a;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: auto_ptr is deprecated
+  // CHECK-FIXES: unique_ptr<int> a;
+}
+
+// Test messing-up with macros.
+void f_4() {
+#define MACRO_1 <char>
+  std::auto_ptr MACRO_1 p(new char());
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr MACRO_1 p(new char());
+#define MACRO_2 auto_ptr
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: auto_ptr is deprecated
+  // CHECK-FIXES: #define MACRO_2 unique_ptr
+  std::MACRO_2<int> q;
+#define MACRO_3(Type) std::auto_ptr<Type>
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: auto_ptr is deprecated
+  // CHECK-FIXES: #define MACRO_3(Type) std::unique_ptr<Type>
+  MACRO_3(float)r(new float());
+#define MACRO_4 std::auto_ptr
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: auto_ptr is deprecated
+  // CHECK-FIXES: #define MACRO_4 std::unique_ptr
+  using MACRO_4;
+#undef MACRO_1
+#undef MACRO_2
+#undef MACRO_3
+#undef MACRO_4
+}
+
+// Test function return values (definition).
+std::auto_ptr<char> f_5()
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr<char> f_5()
+{
+  // Test constructor.
+  return std::auto_ptr<char>(new char());
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: auto_ptr is deprecated
+  // CHECK-FIXES: return std::unique_ptr<char>(new char());
+}
+
+// Test that non-std auto_ptr aren't replaced.
+void f_8() {
+  ns_2::auto_ptr<char> a;
+  using namespace ns_2;
+  auto_ptr<int> b;
+}
+
+// Fail to modify when the template is never instantiated.
+//
+// This might not be an issue. If it's never used it doesn't really matter if
+// it's changed or not. If it's a header and one of the source use it, then it
+// will still be changed.
+template <typename X>
+void f() {
+  std::auto_ptr<X> p;
+}
+
+// FIXME: Alias template could be replaced if a matcher existed.
+namespace std {
+template <typename T> using aaaaaaaa = auto_ptr<T>;
+}
+
+// We want to avoid replacing 'aaaaaaaa' by unique_ptr here. It's better to
+// change the type alias directly.
+std::aaaaaaaa<int> d;
+
+
+void takes_ownership_fn(std::auto_ptr<int> x);
+// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: auto_ptr is deprecated
+// CHECK-FIXES: void takes_ownership_fn(std::unique_ptr<int> x);
+
+std::auto_ptr<int> get_by_value();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: auto_ptr is deprecated
+// CHECK-FIXES: std::unique_ptr<int> get_by_value();
+
+class Wrapper {
+ public:
+  std::auto_ptr<int> &get_wrapped();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+
+ private:
+  std::auto_ptr<int> wrapped;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+};
+
+void f() {
+  std::auto_ptr<int> a, b, c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr<int> a, b, c;
+  Wrapper wrapper_a, wrapper_b;
+
+  a = b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::move to transfer ownership
+  // CHECK-FIXES: a = std::move(b);
+
+  wrapper_a.get_wrapped() = wrapper_b.get_wrapped();
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::move to transfer ownership
+  // CHECK-FIXES: wrapper_a.get_wrapped() = std::move(wrapper_b.get_wrapped());
+
+  // Test that 'std::move()' is inserted when call to the
+  // copy-constructor are made.
+  takes_ownership_fn(c);
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use std::move to transfer ownership
+  // CHECK-FIXES: takes_ownership_fn(std::move(c));
+  takes_ownership_fn(wrapper_a.get_wrapped());
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use std::move to transfer ownership
+  // CHECK-FIXES: takes_ownership_fn(std::move(wrapper_a.get_wrapped()));
+
+  std::auto_ptr<int> d[] = { std::auto_ptr<int>(new int(1)),
+                             std::auto_ptr<int>(new int(2)) };
+  // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: auto_ptr is deprecated
+  // CHECK-MESSAGES: :[[@LINE-3]]:35: warning: auto_ptr is deprecated
+  // CHECK-MESSAGES: :[[@LINE-3]]:35: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr<int> d[] = { std::unique_ptr<int>(new int(1)),
+  // CHECK-FIXES-NEXT:                         std::unique_ptr<int>(new int(2)) };
+  std::auto_ptr<int> e = d[0];
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-MESSAGES: :[[@LINE-2]]:26: warning: use std::move to transfer ownership
+  // CHECK: std::unique_ptr<int> e = std::move(d[0]);
+
+  // Test that std::move() is not used when assigning an rvalue
+  std::auto_ptr<int> f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr<int> f;
+  f = std::auto_ptr<int>(new int(0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: auto_ptr is deprecated
+  // CHECK-NEXT: f = std::unique_ptr<int>(new int(0));
+
+  std::auto_ptr<int> g = get_by_value();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr<int> g = get_by_value();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-replace-random-shuffle.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-replace-random-shuffle.cpp
new file mode 100644
index 0000000..019471e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-replace-random-shuffle.cpp
@@ -0,0 +1,57 @@
+// RUN: %check_clang_tidy %s modernize-replace-random-shuffle %t -- -- -std=c++11
+
+//CHECK-FIXES: #include <random>
+
+namespace std {
+template <typename T> struct vec_iterator {
+  T *ptr;
+  vec_iterator operator++(int);
+};
+
+template <typename T> struct vector {
+  typedef vec_iterator<T> iterator;
+
+  iterator begin();
+  iterator end();
+};
+
+template <typename FwIt>
+void random_shuffle(FwIt begin, FwIt end);
+
+template <typename FwIt, typename randomFunc>
+void random_shuffle(FwIt begin, FwIt end, randomFunc& randomfunc);
+
+template <typename FwIt>
+void shuffle(FwIt begin, FwIt end);
+} // namespace std
+
+// Random Func
+int myrandom (int i) { return i;}
+
+using namespace std;
+
+int main() {
+  std::vector<int> vec;
+
+  std::random_shuffle(vec.begin(), vec.end());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::random_shuffle' has been removed in C++17; use 'std::shuffle' instead
+  // CHECK-FIXES: std::shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()()));
+
+  std::shuffle(vec.begin(), vec.end());
+
+  random_shuffle(vec.begin(), vec.end());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::random_shuffle' has been removed in C++17; use 'std::shuffle' instead
+  // CHECK-FIXES: shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()()));
+  
+  std::random_shuffle(vec.begin(), vec.end(), myrandom);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::random_shuffle' has been removed in C++17; use 'std::shuffle' and an alternative random mechanism instead
+  // CHECK-FIXES: std::shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()()));
+
+  random_shuffle(vec.begin(), vec.end(), myrandom);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::random_shuffle' has been removed in C++17; use 'std::shuffle' and an alternative random mechanism instead
+  // CHECK-FIXES: shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()()));
+
+  shuffle(vec.begin(), vec.end());
+
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-return-braced-init-list.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-return-braced-init-list.cpp
new file mode 100644
index 0000000..49a41ae
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-return-braced-init-list.cpp
@@ -0,0 +1,198 @@
+// RUN: %check_clang_tidy %s modernize-return-braced-init-list %t -- -- -std=c++14
+
+namespace std {
+typedef decltype(sizeof(int)) size_t;
+
+// libc++'s implementation
+template <class _E>
+class initializer_list {
+  const _E *__begin_;
+  size_t __size_;
+
+  initializer_list(const _E *__b, size_t __s)
+      : __begin_(__b),
+        __size_(__s) {}
+
+public:
+  typedef _E value_type;
+  typedef const _E &reference;
+  typedef const _E &const_reference;
+  typedef size_t size_type;
+
+  typedef const _E *iterator;
+  typedef const _E *const_iterator;
+
+  initializer_list() : __begin_(nullptr), __size_(0) {}
+
+  size_t size() const { return __size_; }
+  const _E *begin() const { return __begin_; }
+  const _E *end() const { return __begin_ + __size_; }
+};
+
+template <typename T>
+class vector {
+public:
+  vector(T) {}
+  vector(std::initializer_list<T>) {}
+};
+}
+
+class Bar {};
+
+Bar b0;
+
+class Foo {
+public:
+  Foo(Bar) {}
+  explicit Foo(Bar, unsigned int) {}
+  Foo(unsigned int) {}
+};
+
+class Baz {
+public:
+  Foo m() {
+    Bar bm;
+    return Foo(bm);
+    // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: avoid repeating the return type from the declaration; use a braced initializer list instead [modernize-return-braced-init-list]
+    // CHECK-FIXES: return {bm};
+  }
+};
+
+class Quux : public Foo {
+public:
+  Quux(Bar bar) : Foo(bar) {}
+  Quux(unsigned, unsigned, unsigned k = 0) : Foo(k) {}
+};
+
+Foo f() {
+  Bar b1;
+  return Foo(b1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+  // CHECK-FIXES: return {b1};
+}
+
+Foo f2() {
+  Bar b2;
+  return {b2};
+}
+
+auto f3() {
+  Bar b3;
+  return Foo(b3);
+}
+
+#define A(b) Foo(b)
+
+Foo f4() {
+  Bar b4;
+  return A(b4);
+}
+
+Foo f5() {
+  Bar b5;
+  return Quux(b5);
+}
+
+Foo f6() {
+  Bar b6;
+  return Foo(b6, 1);
+}
+
+std::vector<int> f7() {
+  int i7 = 1;
+  return std::vector<int>(i7);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+}
+
+Bar f8() {
+  return {};
+}
+
+Bar f9() {
+  return Bar();
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+}
+
+Bar f10() {
+  return Bar{};
+}
+
+Foo f11(Bar b11) {
+  return Foo(b11);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+  // CHECK-FIXES: return {b11};
+}
+
+Foo f12() {
+  return f11(Bar());
+}
+
+Foo f13() {
+  return Foo(Bar()); // 13
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+  // CHECK-FIXES: return {Bar()}; // 13
+}
+
+Foo f14() {
+  // FIXME: Type narrowing should not occur!
+  return Foo(-1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+  // CHECK-FIXES: return {-1};
+}
+
+Foo f15() {
+  return Foo(f10());
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+  // CHECK-FIXES: return {f10()};
+}
+
+Quux f16() {
+  return Quux(1, 2);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+  // CHECK-FIXES: return {1, 2};
+}
+
+Quux f17() {
+  return Quux(1, 2, 3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+  // CHECK-FIXES: return {1, 2, 3};
+}
+
+template <typename T>
+T f19() {
+  return T();
+}
+
+Bar i1 = f19<Bar>();
+Baz i2 = f19<Baz>();
+
+template <typename T>
+Foo f20(T t) {
+  return Foo(t);
+}
+
+Foo i3 = f20(b0);
+
+template <typename T>
+class BazT {
+public:
+  T m() {
+    Bar b;
+    return T(b);
+  }
+
+  Foo m2(T t) {
+    return Foo(t);
+  }
+};
+
+BazT<Foo> bazFoo;
+Foo i4 = bazFoo.m();
+Foo i5 = bazFoo.m2(b0);
+
+BazT<Quux> bazQuux;
+Foo i6 = bazQuux.m();
+Foo i7 = bazQuux.m2(b0);
+
+auto v1 = []() { return std::vector<int>({1, 2}); }();
+auto v2 = []() -> std::vector<int> { return std::vector<int>({1, 2}); }();
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-shrink-to-fit.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-shrink-to-fit.cpp
new file mode 100644
index 0000000..6993d30
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-shrink-to-fit.cpp
@@ -0,0 +1,87 @@
+// RUN: %check_clang_tidy %s modernize-shrink-to-fit %t
+
+namespace std {
+template <typename T> struct vector { void swap(vector &other); };
+}
+
+void f() {
+  std::vector<int> v;
+
+  std::vector<int>(v).swap(v);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should be used to reduce the capacity of a shrinkable container [modernize-shrink-to-fit]
+  // CHECK-FIXES: {{^  }}v.shrink_to_fit();{{$}}
+
+  std::vector<int> &vref = v;
+  std::vector<int>(vref).swap(vref);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+  // CHECK-FIXES: {{^  }}vref.shrink_to_fit();{{$}}
+
+  std::vector<int> *vptr = &v;
+  std::vector<int>(*vptr).swap(*vptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+  // CHECK-FIXES: {{^  }}vptr->shrink_to_fit();{{$}}
+}
+
+struct X {
+  std::vector<int> v;
+  void f() {
+    std::vector<int>(v).swap(v);
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: the shrink_to_fit method should
+    // CHECK-FIXES: {{^    }}v.shrink_to_fit();{{$}}
+
+    std::vector<int> *vptr = &v;
+    std::vector<int>(*vptr).swap(*vptr);
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: the shrink_to_fit method should
+    // CHECK-FIXES: {{^    }}vptr->shrink_to_fit();{{$}}
+  }
+};
+
+template <typename T> void g() {
+  std::vector<int> v;
+  std::vector<int>(v).swap(v);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+  // CHECK-FIXES: {{^  }}v.shrink_to_fit();{{$}}
+
+  std::vector<T> v2;
+  std::vector<T>(v2).swap(v2);
+  // CHECK-FIXES: {{^  }}std::vector<T>(v2).swap(v2);{{$}}
+}
+
+template <typename T> void g2() {
+  std::vector<int> v;
+  std::vector<int>(v).swap(v);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+  // CHECK-FIXES: {{^  }}v.shrink_to_fit();{{$}}
+
+  T v3;
+  T(v3).swap(v3);
+  // CHECK-FIXES: {{^  }}T(v3).swap(v3);{{$}}
+}
+
+#define COPY_AND_SWAP_INT_VEC(x) std::vector<int>(x).swap(x)
+// CHECK-FIXES: #define COPY_AND_SWAP_INT_VEC(x) std::vector<int>(x).swap(x)
+
+void h() {
+  g<int>();
+  g<double>();
+  g<bool>();
+  g2<std::vector<int>>();
+  std::vector<int> v;
+  COPY_AND_SWAP_INT_VEC(v);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+  // CHECK-FIXES: {{^  }}COPY_AND_SWAP_INT_VEC(v);{{$}}
+}
+
+void PR38315() {
+  typedef std::vector<int> Vector;
+  Vector v;
+  Vector(v).swap(v);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+  // CHECK-FIXES: {{^  }}v.shrink_to_fit();{{$}}
+
+  using Vector2 = std::vector<int>;
+  Vector2 v2;
+  Vector2(v2).swap(v2);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+  // CHECK-FIXES: {{^  }}v2.shrink_to_fit();{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-unary-static-assert.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-unary-static-assert.cpp
new file mode 100644
index 0000000..fd39d5b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-unary-static-assert.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s modernize-unary-static-assert %t -- -- -std=c++1z
+
+#define FOO static_assert(sizeof(a) <= 15, "");
+#define MSG ""
+
+void f_textless(int a) {
+  static_assert(sizeof(a) <= 10, "");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use unary 'static_assert' when the string literal is an empty string [modernize-unary-static-assert]
+  // CHECK-FIXES: {{^}}  static_assert(sizeof(a) <= 10 );{{$}}
+  static_assert(sizeof(a) <= 12, L"");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use unary 'static_assert' when
+  // CHECK-FIXES: {{^}}  static_assert(sizeof(a) <= 12 );{{$}}
+  FOO
+  // CHECK-FIXES: {{^}}  FOO{{$}}
+  static_assert(sizeof(a) <= 17, MSG);
+  // CHECK-FIXES: {{^}}  static_assert(sizeof(a) <= 17, MSG);{{$}}
+}
+
+void f_with_tex(int a) {
+  static_assert(sizeof(a) <= 10, "Size of variable a is out of range!");
+}
+
+void f_unary(int a) { static_assert(sizeof(a) <= 10); }
+
+void f_incorrect_assert() { static_assert(""); }
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-cast-remove-stars.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-cast-remove-stars.cpp
new file mode 100644
index 0000000..97b87b8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-cast-remove-stars.cpp
@@ -0,0 +1,233 @@
+// RUN: %check_clang_tidy %s modernize-use-auto %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-auto.RemoveStars, value: '1'} , {key: modernize-use-auto.MinTypeNameLength, value: '0'}]}" \
+// RUN:   -- -std=c++11 -frtti
+
+struct A {
+  virtual ~A() {}
+};
+
+struct B : public A {};
+
+struct C {};
+
+void f_static_cast() {
+  long l = 1;
+  int i1 = static_cast<int>(l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto  i1 = static_cast<int>(l);
+
+  const int i2 = static_cast<int>(l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: const auto  i2 = static_cast<int>(l);
+
+  long long ll = static_cast<long long>(l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto  ll = static_cast<long long>(l);
+  unsigned long long ull = static_cast<unsigned long long>(l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto  ull = static_cast<unsigned long long>(l);
+  unsigned int ui = static_cast<unsigned int>(l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto  ui = static_cast<unsigned int>(l);
+  long double ld = static_cast<long double>(l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto  ld = static_cast<long double>(l);
+
+  A *a = new B();
+  B *b1 = static_cast<B *>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto b1 = static_cast<B *>(a);
+
+  B *const b2 = static_cast<B *>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto const b2 = static_cast<B *>(a);
+
+  const B *b3 = static_cast<const B *>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: const auto b3 = static_cast<const B *>(a);
+
+  B &b4 = static_cast<B &>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto  &b4 = static_cast<B &>(*a);
+
+  const B &b5 = static_cast<const B &>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: const auto  &b5 = static_cast<const B &>(*a);
+
+  B &b6 = static_cast<B &>(*a), &b7 = static_cast<B &>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto  &b6 = static_cast<B &>(*a), &b7 = static_cast<B &>(*a);
+
+  // Don't warn when non-cast involved
+  long double cast = static_cast<long double>(l), noncast = 5;
+
+  // Don't warn when auto is already being used.
+  auto i3 = static_cast<int>(l);
+  auto *b8 = static_cast<B *>(a);
+  auto &b9 = static_cast<B &>(*a);
+}
+
+void f_dynamic_cast() {
+  A *a = new B();
+  B *b1 = dynamic_cast<B *>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto b1 = dynamic_cast<B *>(a);
+
+  B &b2 = dynamic_cast<B &>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto  &b2 = dynamic_cast<B &>(*a);
+}
+
+void f_reinterpret_cast() {
+  auto *a = new A();
+  C *c1 = reinterpret_cast<C *>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto c1 = reinterpret_cast<C *>(a);
+
+  C &c2 = reinterpret_cast<C &>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto  &c2 = reinterpret_cast<C &>(*a);
+}
+
+void f_const_cast() {
+  const A *a1 = new A();
+  A *a2 = const_cast<A *>(a1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto a2 = const_cast<A *>(a1);
+  A &a3 = const_cast<A &>(*a1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto  &a3 = const_cast<A &>(*a1);
+}
+
+typedef unsigned char xmlChar;
+#define BAD_CAST (xmlChar *)
+
+#define XMLCHAR_CAST(x) (xmlChar *)(x)
+
+#define CAST_IN_MACRO(x)         \
+  do {                           \
+    xmlChar *s = (xmlChar *)(x); \
+  } while (false);
+// CHECK-FIXES: xmlChar *s = (xmlChar *)(x);
+
+void f_cstyle_cast() {
+  auto *a = new A();
+  C *c1 = (C *)a;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto c1 = (C *)a;
+
+  C &c2 = (C &)*a;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto  &c2 = (C &)*a;
+
+  xmlChar  *s = BAD_CAST "xml";
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto s = BAD_CAST "xml";
+  xmlChar  *t = XMLCHAR_CAST("xml");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto t = XMLCHAR_CAST("xml");
+  CAST_IN_MACRO("xml");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+}
+
+void f_functional_cast() {
+  long l = 1;
+  int i1 = int(l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto  i1 = int(l);
+
+  B b;
+  A a = A(b);
+}
+
+class StringRef
+{
+public:
+  StringRef(const char *);
+  const char *begin() const;
+  const char *end() const;
+};
+
+template <typename T, typename U>
+T template_value_cast(const U &u);
+
+template <typename T, typename U>
+T *template_pointer_cast(U *u);
+
+template <typename T, typename U>
+T &template_reference_cast(U &u);
+
+template <typename T, typename U>
+const T *template_const_pointer_cast(const U *u);
+
+template <typename T, typename U>
+const T &template_const_reference_cast(const U &u);
+
+template <typename T>
+T template_value_get(StringRef s);
+
+struct S {
+  template <typename T>
+  const T *template_member_get();
+};
+
+template <typename T>
+T max(T t1, T t2);
+
+void f_template_cast()
+{
+  double d = 0;
+  int i1 = template_value_cast<int>(d);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: auto  i1 = template_value_cast<int>(d);
+
+  A *a = new B();
+  B *b1 = template_value_cast<B *>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: auto b1 = template_value_cast<B *>(a);
+  B &b2 = template_value_cast<B &>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: auto  &b2 = template_value_cast<B &>(*a);
+  B *b3 = template_pointer_cast<B>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: auto b3 = template_pointer_cast<B>(a);
+  B &b4 = template_reference_cast<B>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: auto  &b4 = template_reference_cast<B>(*a);
+  const B *b5 = template_const_pointer_cast<B>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: const auto b5 = template_const_pointer_cast<B>(a);
+  const B &b6 = template_const_reference_cast<B>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: const auto  &b6 = template_const_reference_cast<B>(*a);
+  B *b7 = template_value_get<B *>("foo");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: auto b7 = template_value_get<B *>("foo");
+  B *b8 = template_value_get<B *>("foo"), *b9 = template_value_get<B *>("bar");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: auto b8 = template_value_get<B *>("foo"), b9 = template_value_get<B *>("bar");
+
+  S s;
+  const B *b10 = s.template_member_get<B>();
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: const auto b10 = s.template_member_get<B>();
+
+  // Don't warn when auto is already being used.
+  auto i2 = template_value_cast<int>(d);
+  auto *i3 = template_value_cast<int *>(d);
+  auto **i4 = template_value_cast<int **>(d);
+  auto &i5 = template_reference_cast<int>(d);
+
+  // Don't warn for implicit template arguments.
+  int i6 = max(i1, i2);
+
+  // Don't warn for mismatched var and initializer types.
+  A *a1 = template_value_cast<B *>(a);
+
+  // Don't warn for mismatched var types.
+  B *b11 = template_value_get<B *>("foo"), b12 = template_value_get<B>("bar");
+
+  // Don't warn for implicit variables.
+  for (auto &c : template_reference_cast<StringRef>(*a)) {
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-cast.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-cast.cpp
new file mode 100644
index 0000000..e07c9cb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-cast.cpp
@@ -0,0 +1,233 @@
+// RUN: %check_clang_tidy %s modernize-use-auto %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-auto.MinTypeNameLength, value: '0'}]}" \
+// RUN:   -- -std=c++11 -I %S/Inputs/modernize-use-auto -frtti
+
+struct A {
+  virtual ~A() {}
+};
+
+struct B : public A {};
+
+struct C {};
+
+void f_static_cast() {
+  long l = 1;
+  int i1 = static_cast<int>(l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto i1 = static_cast<int>(l);
+
+  const int i2 = static_cast<int>(l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: const auto i2 = static_cast<int>(l);
+
+  long long ll = static_cast<long long>(l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto ll = static_cast<long long>(l);
+  unsigned long long ull = static_cast<unsigned long long>(l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto ull = static_cast<unsigned long long>(l);
+  unsigned int ui = static_cast<unsigned int>(l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto ui = static_cast<unsigned int>(l);
+  long double ld = static_cast<long double>(l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto ld = static_cast<long double>(l);
+
+  A *a = new B();
+  B *b1 = static_cast<B *>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto *b1 = static_cast<B *>(a);
+
+  B *const b2 = static_cast<B *>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto *const b2 = static_cast<B *>(a);
+
+  const B *b3 = static_cast<const B *>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: const auto *b3 = static_cast<const B *>(a);
+
+  B &b4 = static_cast<B &>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto &b4 = static_cast<B &>(*a);
+
+  const B &b5 = static_cast<const B &>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: const auto &b5 = static_cast<const B &>(*a);
+
+  B &b6 = static_cast<B &>(*a), &b7 = static_cast<B &>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto &b6 = static_cast<B &>(*a), &b7 = static_cast<B &>(*a);
+
+  // Don't warn when non-cast involved
+  long double cast = static_cast<long double>(l), noncast = 5;
+
+  // Don't warn when auto is already being used.
+  auto i3 = static_cast<int>(l);
+  auto *b8 = static_cast<B *>(a);
+  auto &b9 = static_cast<B &>(*a);
+}
+
+void f_dynamic_cast() {
+  A *a = new B();
+  B *b1 = dynamic_cast<B *>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto *b1 = dynamic_cast<B *>(a);
+
+  B &b2 = dynamic_cast<B &>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto &b2 = dynamic_cast<B &>(*a);
+}
+
+void f_reinterpret_cast() {
+  auto *a = new A();
+  C *c1 = reinterpret_cast<C *>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto *c1 = reinterpret_cast<C *>(a);
+
+  C &c2 = reinterpret_cast<C &>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto &c2 = reinterpret_cast<C &>(*a);
+}
+
+void f_const_cast() {
+  const A *a1 = new A();
+  A *a2 = const_cast<A *>(a1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto *a2 = const_cast<A *>(a1);
+  A &a3 = const_cast<A &>(*a1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto &a3 = const_cast<A &>(*a1);
+}
+
+typedef unsigned char xmlChar;
+#define BAD_CAST (xmlChar *)
+
+#define XMLCHAR_CAST(x) (xmlChar *)(x)
+
+#define CAST_IN_MACRO(x)         \
+  do {                           \
+    xmlChar *s = (xmlChar *)(x); \
+  } while (false);
+// CHECK-FIXES: xmlChar *s = (xmlChar *)(x);
+
+void f_cstyle_cast() {
+  auto *a = new A();
+  C *c1 = (C *)a;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto *c1 = (C *)a;
+
+  C &c2 = (C &)*a;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto &c2 = (C &)*a;
+
+  xmlChar *s = BAD_CAST "xml";
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto *s = BAD_CAST "xml";
+  xmlChar *t = XMLCHAR_CAST("xml");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto *t = XMLCHAR_CAST("xml");
+  CAST_IN_MACRO("xml");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+}
+
+void f_functional_cast() {
+  long l = 1;
+  int i1 = int(l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
+  // CHECK-FIXES: auto i1 = int(l);
+
+  B b;
+  A a = A(b);
+}
+
+class StringRef
+{
+public:
+  StringRef(const char *);
+  const char *begin() const;
+  const char *end() const;
+};
+
+template <typename T, typename U>
+T template_value_cast(const U &u);
+
+template <typename T, typename U>
+T *template_pointer_cast(U *u);
+
+template <typename T, typename U>
+T &template_reference_cast(U &u);
+
+template <typename T, typename U>
+const T *template_const_pointer_cast(const U *u);
+
+template <typename T, typename U>
+const T &template_const_reference_cast(const U &u);
+
+template <typename T>
+T template_value_get(StringRef s);
+
+struct S {
+  template <typename T>
+  const T *template_member_get();
+};
+
+template <typename T>
+T max(T t1, T t2);
+
+void f_template_cast()
+{
+  double d = 0;
+  int i1 = template_value_cast<int>(d);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: auto i1 = template_value_cast<int>(d);
+
+  A *a = new B();
+  B *b1 = template_value_cast<B *>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: auto *b1 = template_value_cast<B *>(a);
+  B &b2 = template_value_cast<B &>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: auto &b2 = template_value_cast<B &>(*a);
+  B *b3 = template_pointer_cast<B>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: auto *b3 = template_pointer_cast<B>(a);
+  B &b4 = template_reference_cast<B>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: auto &b4 = template_reference_cast<B>(*a);
+  const B *b5 = template_const_pointer_cast<B>(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: const auto *b5 = template_const_pointer_cast<B>(a);
+  const B &b6 = template_const_reference_cast<B>(*a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: const auto &b6 = template_const_reference_cast<B>(*a);
+  B *b7 = template_value_get<B *>("foo");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: auto *b7 = template_value_get<B *>("foo");
+  B *b8 = template_value_get<B *>("foo"), *b9 = template_value_get<B *>("bar");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: auto *b8 = template_value_get<B *>("foo"), *b9 = template_value_get<B *>("bar");
+
+  S s;
+  const B *b10 = s.template_member_get<B>();
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a template cast to avoid duplicating the type name
+  // CHECK-FIXES: const auto *b10 = s.template_member_get<B>();
+
+  // Don't warn when auto is already being used.
+  auto i2 = template_value_cast<int>(d);
+  auto *i3 = template_value_cast<int *>(d);
+  auto **i4 = template_value_cast<int **>(d);
+  auto &i5 = template_reference_cast<int>(d);
+
+  // Don't warn for implicit template arguments.
+  int i6 = max(i1, i2);
+
+  // Don't warn for mismatched var and initializer types.
+  A *a1 = template_value_cast<B *>(a);
+
+  // Don't warn for mismatched var types.
+  B *b11 = template_value_get<B *>("foo"), b12 = template_value_get<B>("bar");
+
+  // Don't warn for implicit variables.
+  for (auto &c : template_reference_cast<StringRef>(*a)) {
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-iterator.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-iterator.cpp
new file mode 100644
index 0000000..98117fc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-iterator.cpp
@@ -0,0 +1,320 @@
+// RUN: %check_clang_tidy %s modernize-use-auto %t -- -- \
+// RUN:   -std=c++11 -I %S/Inputs/modernize-use-auto
+
+#include "containers.h"
+
+void f_array() {
+  std::array<int, 4> C;
+  std::array<int, 4>::iterator ArrayI1 = C.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators [modernize-use-auto]
+  // CHECK-FIXES: auto ArrayI1 = C.begin();
+
+  std::array<int, 5>::reverse_iterator ArrayI2 = C.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto ArrayI2 = C.rbegin();
+
+  const std::array<int, 3> D;
+  std::array<int, 3>::const_iterator ArrayI3 = D.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto ArrayI3 = D.begin();
+
+  std::array<int, 5>::const_reverse_iterator ArrayI4 = D.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto ArrayI4 = D.rbegin();
+}
+
+void f_deque() {
+  std::deque<int> C;
+  std::deque<int>::iterator DequeI1 = C.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto DequeI1 = C.begin();
+
+  std::deque<int>::reverse_iterator DequeI2 = C.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto DequeI2 = C.rbegin();
+
+  const std::deque<int> D;
+  std::deque<int>::const_iterator DequeI3 = D.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto DequeI3 = D.begin();
+
+  std::deque<int>::const_reverse_iterator DequeI4 = D.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto DequeI4 = D.rbegin();
+}
+
+void f_forward_list() {
+  std::forward_list<int> C;
+  std::forward_list<int>::iterator FListI1 = C.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto FListI1 = C.begin();
+
+  const std::forward_list<int> D;
+  std::forward_list<int>::const_iterator FListI2 = D.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto FListI2 = D.begin();
+}
+
+void f_list() {
+  std::list<int> C;
+  std::list<int>::iterator ListI1 = C.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto ListI1 = C.begin();
+  std::list<int>::reverse_iterator ListI2 = C.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto ListI2 = C.rbegin();
+
+  const std::list<int> D;
+  std::list<int>::const_iterator ListI3 = D.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto ListI3 = D.begin();
+  std::list<int>::const_reverse_iterator ListI4 = D.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto ListI4 = D.rbegin();
+}
+
+void f_vector() {
+  std::vector<int> C;
+  std::vector<int>::iterator VecI1 = C.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto VecI1 = C.begin();
+
+  std::vector<int>::reverse_iterator VecI2 = C.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto VecI2 = C.rbegin();
+
+  const std::vector<int> D;
+  std::vector<int>::const_iterator VecI3 = D.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto VecI3 = D.begin();
+
+  std::vector<int>::const_reverse_iterator VecI4 = D.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto VecI4 = D.rbegin();
+}
+
+void f_map() {
+  std::map<int, int> C;
+  std::map<int, int>::iterator MapI1 = C.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto MapI1 = C.begin();
+
+  std::map<int, int>::reverse_iterator MapI2 = C.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto MapI2 = C.rbegin();
+
+  const std::map<int, int> D;
+  std::map<int, int>::const_iterator MapI3 = D.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto MapI3 = D.begin();
+
+  std::map<int, int>::const_reverse_iterator MapI4 = D.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto MapI4 = D.rbegin();
+}
+
+void f_multimap() {
+  std::multimap<int, int> C;
+  std::multimap<int, int>::iterator MMapI1 = C.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto MMapI1 = C.begin();
+
+  std::multimap<int, int>::reverse_iterator MMapI2 = C.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto MMapI2 = C.rbegin();
+
+  const std::multimap<int, int> D;
+  std::multimap<int, int>::const_iterator MMapI3 = D.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto MMapI3 = D.begin();
+
+  std::multimap<int, int>::const_reverse_iterator MMapI4 = D.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto MMapI4 = D.rbegin();
+}
+
+void f_set() {
+  std::set<int> C;
+  std::set<int>::iterator SetI1 = C.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto SetI1 = C.begin();
+
+  std::set<int>::reverse_iterator SetI2 = C.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto SetI2 = C.rbegin();
+
+  const std::set<int> D;
+  std::set<int>::const_iterator SetI3 = D.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto SetI3 = D.begin();
+
+  std::set<int>::const_reverse_iterator SetI4 = D.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto SetI4 = D.rbegin();
+}
+
+void f_multiset() {
+  std::multiset<int> C;
+  std::multiset<int>::iterator MSetI1 = C.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto MSetI1 = C.begin();
+
+  std::multiset<int>::reverse_iterator MSetI2 = C.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto MSetI2 = C.rbegin();
+
+  const std::multiset<int> D;
+  std::multiset<int>::const_iterator MSetI3 = D.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto MSetI3 = D.begin();
+
+  std::multiset<int>::const_reverse_iterator MSetI4 = D.rbegin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto MSetI4 = D.rbegin();
+}
+
+void f_unordered_map() {
+  std::unordered_map<int, int> C;
+  std::unordered_map<int, int>::iterator UMapI1 = C.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto UMapI1 = C.begin();
+
+  const std::unordered_map<int, int> D;
+  std::unordered_map<int, int>::const_iterator UMapI2 = D.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto UMapI2 = D.begin();
+}
+
+void f_unordered_multimap() {
+  std::unordered_multimap<int, int> C;
+  std::unordered_multimap<int, int>::iterator UMMapI1 = C.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto UMMapI1 = C.begin();
+
+  const std::unordered_multimap<int, int> D;
+  std::unordered_multimap<int, int>::const_iterator UMMapI2 = D.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto UMMapI2 = D.begin();
+}
+
+void f_unordered_set() {
+  std::unordered_set<int> C;
+  std::unordered_set<int>::iterator USetI1 = C.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto USetI1 = C.begin();
+
+  const std::unordered_set<int> D;
+  std::unordered_set<int>::const_iterator USetI2 = D.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto USetI2 = D.begin();
+}
+
+void f_unordered_multiset() {
+  std::unordered_multiset<int> C;
+  std::unordered_multiset<int>::iterator UMSetI1 = C.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto UMSetI1 = C.begin();
+
+  const std::unordered_multiset<int> D;
+  std::unordered_multiset<int>::const_iterator UMSetI2 = D.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto UMSetI2 = D.begin();
+}
+
+typedef std::vector<int>::iterator int_iterator;
+
+std::vector<int> Vec;
+std::unordered_map<int, int> Map;
+
+void sugar() {
+  // Types with more sugar should work. Types with less should not.
+  int_iterator more_sugar = Vec.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto more_sugar = Vec.begin();
+}
+
+void initializer_list() {
+  // Initialization from initializer lists isn't allowed. Using 'auto' would
+  // result in std::initializer_list being deduced for the type.
+  std::unordered_map<int, int>::iterator I{Map.begin()};
+  std::unordered_map<int, int>::iterator I2 = {Map.begin()};
+}
+
+void construction() {
+  // Various forms of construction. Default constructors and constructors with
+  // all-default parameters shouldn't get transformed. Construction from other
+  // types is also not allowed.
+
+  std::unordered_map<int, int>::iterator copy(Map.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto copy(Map.begin());
+
+  std::unordered_map<int, int>::iterator def;
+  std::unordered_map<int, int>::const_iterator constI;
+
+  // Implicit conversion.
+  std::unordered_map<int, int>::const_iterator constI2 = def;
+  std::unordered_map<int, int>::const_iterator constI3(def);
+
+  // Explicit conversion
+  std::unordered_map<int, int>::const_iterator constI4
+      = std::unordered_map<int, int>::const_iterator(def);
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto constI4
+  // CHECK-FIXES-NEXT: = std::unordered_map<int, int>::const_iterator(def);
+}
+
+void pointer_to_iterator() {
+  int_iterator I = Vec.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto I = Vec.begin();
+
+  // Pointers and references to iterators are not transformed.
+  int_iterator *IPtr = &I;
+  int_iterator &IRef = I;
+}
+
+void loop() {
+  for (std::vector<int>::iterator I = Vec.begin(); I != Vec.end(); ++I) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use auto when declaring iterators
+    // CHECK-FIXES: for (auto I = Vec.begin(); I != Vec.end(); ++I)
+  }
+
+  for (int_iterator I = Vec.begin(), E = Vec.end(); I != E; ++I) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use auto when declaring iterators
+    // CHECK-FIXES: for (auto I = Vec.begin(), E = Vec.end(); I != E; ++I)
+  }
+
+  std::vector<std::vector<int>::iterator> IterVec;
+  for (std::vector<int>::iterator I : IterVec) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use auto when declaring iterators
+    // CHECK-FIXES: for (auto I : IterVec)
+  }
+}
+
+void cv_qualifiers() {
+  // Make sure references and cv qualifiers don't get removed (i.e. replaced
+  // with just 'auto').
+  const auto & I = Vec.begin();
+  auto && I2 = Vec.begin();
+}
+
+void cleanup() {
+  // Passing a string as an argument to introduce a temporary object that will
+  // create an expression with cleanups.
+  std::map<std::string, int> MapFind;
+  std::map<std::string, int>::iterator I = MapFind.find("foo");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto I = MapFind.find("foo");
+}
+
+void declaration_lists() {
+  // Declaration lists that match the declaration type with written no-list
+  // initializer are transformed.
+  std::vector<int>::iterator I = Vec.begin(), E = Vec.end();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declaring iterators
+  // CHECK-FIXES: auto I = Vec.begin(), E = Vec.end();
+
+  // Declaration lists with non-initialized variables should not be transformed.
+  std::vector<int>::iterator J = Vec.begin(), K;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-min-type-name-length.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-min-type-name-length.cpp
new file mode 100644
index 0000000..1cd9158
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-min-type-name-length.cpp
@@ -0,0 +1,85 @@
+// RUN: %check_clang_tidy -check-suffix=0-0 %s modernize-use-auto %t  -- -config="{CheckOptions: [{key: modernize-use-auto.RemoveStars, value: 0}, {key: modernize-use-auto.MinTypeNameLength, value: 0}]}" -- --std=c++11 -frtti
+// RUN: %check_clang_tidy -check-suffix=0-8 %s modernize-use-auto %t  -- -config="{CheckOptions: [{key: modernize-use-auto.RemoveStars, value: 0}, {key: modernize-use-auto.MinTypeNameLength, value: 8}]}" -- --std=c++11 -frtti
+// RUN: %check_clang_tidy -check-suffix=1-0 %s modernize-use-auto %t  -- -config="{CheckOptions: [{key: modernize-use-auto.RemoveStars, value: 1}, {key: modernize-use-auto.MinTypeNameLength, value: 0}]}" -- --std=c++11 -frtti
+// RUN: %check_clang_tidy -check-suffix=1-8 %s modernize-use-auto %t  -- -config="{CheckOptions: [{key: modernize-use-auto.RemoveStars, value: 1}, {key: modernize-use-auto.MinTypeNameLength, value: 8}]}" -- --std=c++11 -frtti
+
+template <class T> extern T foo();
+template <class T> struct P {  explicit P(T t) : t_(t) {}  T t_;};
+template <class T> P<T> *foo_ptr();
+template <class T> P<T> &foo_ref();
+
+int bar() {
+  {
+    // Lenth(long) = 4
+    long i = static_cast<long>(foo<long>());
+    // CHECK-FIXES-0-0: auto i = {{.*}}
+    // CHECK-FIXES-0-8: long i = {{.*}}
+    // CHECK-FIXES-1-0: auto  i = {{.*}}
+    // CHECK-FIXES-1-8: long i = {{.*}}
+    const long ci = static_cast<long>(foo<const long>());
+    // CHECK-FIXES-0-0: auto ci = {{.*}}
+    // CHECK-FIXES-0-8: long ci = {{.*}}
+    // CHECK-FIXES-1-0: auto  ci = {{.*}}
+    // CHECK-FIXES-1-8: long ci = {{.*}}
+    long *pi = static_cast<long *>(foo<long *>());
+    // CHECK-FIXES-0-0: auto *pi = {{.*}}
+    // CHECK-FIXES-0-8: long *pi = {{.*}}
+    // CHECK-FIXES-1-0: auto pi = {{.*}}
+    // CHECK-FIXES-1-8: long *pi = {{.*}}
+
+    // Length(long       *) is still 5
+    long      *     pi2 = static_cast<long *>(foo<long *>());
+    // CHECK-FIXES-0-0: auto      *     pi2 = {{.*}}
+    // CHECK-FIXES-0-8: long      *     pi2 = {{.*}}
+    // CHECK-FIXES-1-0: auto      pi2 = {{.*}}
+    // CHECK-FIXES-1-8: long      *     pi2 = {{.*}}
+
+    // Length(long **) = 6
+    long **ppi = static_cast<long **>(foo<long **>());
+    // CHECK-FIXES-0-0: auto **ppi = {{.*}}
+    // CHECK-FIXES-0-8: long **ppi = {{.*}}
+    // CHECK-FIXES-1-0: auto ppi = {{.*}}
+    // CHECK-FIXES-1-8: long **ppi = {{.*}}
+  }
+
+  {
+    // Lenth(long int) = 4 + 1 + 3 = 8
+    // Lenth(long        int) is still 8
+    long int i = static_cast<long int>(foo<long int>());
+    // CHECK-FIXES-0-0: auto i = {{.*}}
+    // CHECK-FIXES-0-8: auto i = {{.*}}
+    // CHECK-FIXES-1-0: auto  i = {{.*}}
+    // CHECK-FIXES-1-8: auto  i = {{.*}}
+
+    long int *pi = static_cast<long int *>(foo<long int *>());
+    // CHECK-FIXES-0-0: auto *pi = {{.*}}
+    // CHECK-FIXES-0-8: auto *pi = {{.*}}
+    // CHECK-FIXES-1-0: auto pi = {{.*}}
+    // CHECK-FIXES-1-8: auto pi = {{.*}}
+  }
+
+  // Templates
+  {
+    // Length(P<long>) = 7
+    P<long>& i = static_cast<P<long>&>(foo_ref<long>());
+    // CHECK-FIXES-0-0: auto& i = {{.*}}
+    // CHECK-FIXES-0-8: P<long>& i = {{.*}}
+    // CHECK-FIXES-1-0: auto & i = {{.*}}
+    // CHECK-FIXES-1-8: P<long>& i = {{.*}}
+
+    // Length(P<long*>) = 8
+    P<long*>& pi = static_cast<P<long*> &>(foo_ref<long*>());
+    // CHECK-FIXES-0-0: auto& pi = {{.*}}
+    // CHECK-FIXES-0-8: auto& pi = {{.*}}
+    // CHECK-FIXES-1-0: auto & pi = {{.*}}
+    // CHECK-FIXES-1-8: auto & pi = {{.*}}
+
+    P<long>* pi2 = static_cast<P<long>*>(foo_ptr<long>());
+    // CHECK-FIXES-0-0: auto* pi2 = {{.*}}
+    // CHECK-FIXES-0-8: P<long>* pi2 = {{.*}}
+    // CHECK-FIXES-1-0: auto  pi2 = {{.*}}
+    // CHECK-FIXES-1-8: auto  pi2 = {{.*}}
+  }
+
+  return 1;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-new-remove-stars.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-new-remove-stars.cpp
new file mode 100644
index 0000000..00e3c89
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-new-remove-stars.cpp
@@ -0,0 +1,106 @@
+// RUN: %check_clang_tidy %s modernize-use-auto %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-auto.RemoveStars, value: '1'}, {key: modernize-use-auto.MinTypeNameLength, value: '0'}]}" \
+// RUN:   -- -std=c++11
+
+class MyType {};
+
+class MyDerivedType : public MyType {};
+
+// FIXME: the replacement sometimes results in two consecutive spaces after
+// the word 'auto' (due to the presence of spaces at both sides of '*').
+void auto_new() {
+  MyType *a_new = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto a_new = new MyType();
+
+  static MyType *a_static = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto when initializing with new
+  // CHECK-FIXES: static auto a_static = new MyType();
+
+  MyType *derived = new MyDerivedType();
+
+  void *vd = new MyType();
+
+  // CV-qualifier tests.
+  //
+  // NOTE : the form "type const" is expected here because of a deficiency in
+  // TypeLoc where CV qualifiers are not considered part of the type location
+  // info. That is, all that is being replaced in each case is "MyType *" and
+  // not "MyType * const".
+  static MyType * const d_static = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto when initializing with new
+  // CHECK-FIXES: static auto  const d_static = new MyType();
+
+  MyType * const a_const = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto  const a_const = new MyType();
+
+  MyType * volatile vol = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto  volatile vol = new MyType();
+
+  struct SType {} *stype = new SType;
+
+  int (**func)(int, int) = new (int(*[5])(int,int));
+
+  int *array = new int[5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto array = new int[5];
+
+  MyType *ptr(new MyType);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto ptr(new MyType);
+
+  MyType *ptr2{new MyType};
+
+  {
+    // Test for declaration lists.
+    MyType *a = new MyType(), *b = new MyType(), *c = new MyType();
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+    // CHECK-FIXES: auto a = new MyType(), b = new MyType(), c = new MyType();
+
+    // Non-initialized declaration should not be transformed.
+    MyType *d = new MyType(), *e;
+
+    MyType **f = new MyType*(), **g = new MyType*();
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+    // CHECK-FIXES: auto f = new MyType*(), g = new MyType*();
+
+    // Mismatching types in declaration lists should not be transformed.
+    MyType *h = new MyType(), **i = new MyType*();
+
+    // '*' shouldn't be removed in case of mismatching types with multiple
+    // declarations.
+    MyType *j = new MyType(), *k = new MyType(), **l = new MyType*();
+  }
+
+  {
+    // Test for typedefs.
+    typedef int * int_p;
+    // CHECK-FIXES: typedef int * int_p;
+
+    int_p a = new int;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+    // CHECK-FIXES: auto  a = new int;
+    int_p *b = new int*;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+    // CHECK-FIXES: auto b = new int*;
+
+    // Test for typedefs in declarations lists.
+    int_p c = new int, d = new int;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+    // CHECK-FIXES: auto  c = new int, d = new int;
+
+    // Different types should not be transformed.
+    int_p e = new int, *f = new int_p;
+
+    int_p *g = new int*, *h = new int_p;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+    // CHECK-FIXES: auto g = new int*, h = new int_p;
+  }
+
+  // Don't warn when 'auto' is already being used.
+  auto aut = new MyType();
+  auto *paut = new MyType();
+  const auto *pcaut = new MyType();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-new.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-new.cpp
new file mode 100644
index 0000000..3c872c9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-auto-new.cpp
@@ -0,0 +1,110 @@
+// RUN: %check_clang_tidy %s modernize-use-auto %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-auto.MinTypeNameLength, value: '0'}]}" \
+// RUN:   -- -std=c++11 -frtti
+
+class MyType {};
+
+class MyDerivedType : public MyType {};
+
+// FIXME: the replacement sometimes results in two consecutive spaces after
+// the word 'auto' (due to the presence of spaces at both sides of '*').
+void auto_new() {
+  MyType *a_new = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto *a_new = new MyType();
+
+  static MyType *a_static = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto when initializing with new
+  // CHECK-FIXES: static auto *a_static = new MyType();
+
+  long long *ll = new long long();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto *ll = new long long();
+
+  MyType *derived = new MyDerivedType();
+
+  void *vd = new MyType();
+
+  // CV-qualifier tests.
+  //
+  // NOTE : the form "type const" is expected here because of a deficiency in
+  // TypeLoc where CV qualifiers are not considered part of the type location
+  // info. That is, all that is being replaced in each case is "MyType *" and
+  // not "MyType * const".
+  static MyType * const d_static = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto when initializing with new
+  // CHECK-FIXES: static auto * const d_static = new MyType();
+
+  MyType * const a_const = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto * const a_const = new MyType();
+
+  MyType * volatile vol = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto * volatile vol = new MyType();
+
+  struct SType {} *stype = new SType;
+
+  int (**func)(int, int) = new (int(*[5])(int,int));
+
+  int *array = new int[5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto *array = new int[5];
+
+  MyType *ptr(new MyType);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto *ptr(new MyType);
+
+  MyType *ptr2{new MyType};
+
+  {
+    // Test for declaration lists.
+    MyType *a = new MyType(), *b = new MyType(), *c = new MyType();
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+    // CHECK-FIXES: auto *a = new MyType(), *b = new MyType(), *c = new MyType();
+
+    // Non-initialized declaration should not be transformed.
+    MyType *d = new MyType(), *e;
+
+    MyType **f = new MyType*(), **g = new MyType*();
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+    // CHECK-FIXES: auto **f = new MyType*(), **g = new MyType*();
+
+    // Mismatching types in declaration lists should not be transformed.
+    MyType *h = new MyType(), **i = new MyType*();
+
+    // '*' shouldn't be removed in case of mismatching types with multiple
+    // declarations.
+    MyType *j = new MyType(), *k = new MyType(), **l = new MyType*();
+  }
+
+  {
+    // Test for typedefs.
+    typedef int * int_p;
+    // CHECK-FIXES: typedef int * int_p;
+
+    int_p a = new int;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+    // CHECK-FIXES: auto a = new int;
+    int_p *b = new int*;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+    // CHECK-FIXES: auto *b = new int*;
+
+    // Test for typedefs in declarations lists.
+    int_p c = new int, d = new int;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+    // CHECK-FIXES: auto c = new int, d = new int;
+
+    // Different types should not be transformed.
+    int_p e = new int, *f = new int_p;
+
+    int_p *g = new int*, *h = new int_p;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+    // CHECK-FIXES: auto *g = new int*, *h = new int_p;
+  }
+
+  // Don't warn when 'auto' is already being used.
+  auto aut = new MyType();
+  auto *paut = new MyType();
+  const auto *pcaut = new MyType();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-bool-literals-ignore-macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-bool-literals-ignore-macros.cpp
new file mode 100644
index 0000000..cf8f72c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-bool-literals-ignore-macros.cpp
@@ -0,0 +1,148 @@
+// RUN: %check_clang_tidy %s modernize-use-bool-literals %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:             [{key: modernize-use-bool-literals.IgnoreMacros, \
+// RUN:               value: 1}]}" \
+// RUN:   -- -std=c++11
+
+bool IntToTrue = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: converting integer literal to bool, use bool literal instead [modernize-use-bool-literals]
+// CHECK-FIXES: {{^}}bool IntToTrue = true;{{$}}
+
+bool IntToFalse(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool IntToFalse(false);{{$}}
+
+bool LongLongToTrue{0x1LL};
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool LongLongToTrue{true};{{$}}
+
+bool ExplicitCStyleIntToFalse = (bool)0;
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ExplicitCStyleIntToFalse = false;{{$}}
+
+bool ExplicitFunctionalIntToFalse = bool(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ExplicitFunctionalIntToFalse = false;{{$}}
+
+bool ExplicitStaticIntToFalse = static_cast<bool>(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ExplicitStaticIntToFalse = false;{{$}}
+
+#define TRUE_MACRO 1
+// CHECK-FIXES: {{^}}#define TRUE_MACRO 1{{$}}
+
+bool MacroIntToTrue = TRUE_MACRO;
+// CHECK-FIXES: {{^}}bool MacroIntToTrue = TRUE_MACRO;{{$}}
+
+#define FALSE_MACRO bool(0)
+// CHECK-FIXES: {{^}}#define FALSE_MACRO bool(0){{$}}
+
+bool TrueBool = true; // OK
+
+bool FalseBool = bool(FALSE_MACRO);
+// CHECK-FIXES: {{^}}bool FalseBool = bool(FALSE_MACRO);{{$}}
+
+void boolFunction(bool bar) {
+
+}
+
+char Character = 0; // OK
+
+unsigned long long LongInteger = 1; // OK
+
+#define MACRO_DEPENDENT_CAST(x) static_cast<bool>(x)
+// CHECK-FIXES: {{^}}#define MACRO_DEPENDENT_CAST(x) static_cast<bool>(x){{$}}
+
+bool MacroDependentBool = MACRO_DEPENDENT_CAST(0);
+// CHECK-FIXES: {{^}}bool MacroDependentBool = MACRO_DEPENDENT_CAST(0);{{$}}
+
+bool ManyMacrosDependent = MACRO_DEPENDENT_CAST(FALSE_MACRO);
+// CHECK-FIXES: {{^}}bool ManyMacrosDependent = MACRO_DEPENDENT_CAST(FALSE_MACRO);{{$}}
+
+class FooClass {
+  public:
+  FooClass() : JustBool(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}FooClass() : JustBool(false) {}{{$}}
+  FooClass(int) : JustBool{0} {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}FooClass(int) : JustBool{false} {}{{$}}
+  private:
+  bool JustBool;
+  bool BoolWithBraces{0};
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}bool BoolWithBraces{false};{{$}}
+  bool BoolFromInt = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}bool BoolFromInt = false;{{$}}
+  bool SimpleBool = true; // OK
+};
+
+template<typename type>
+void templateFunction(type) {
+  type TemplateType = 0;
+  // CHECK-FIXES: {{^ *}}type TemplateType = 0;{{$}}
+}
+
+template<int c>
+void valueDependentTemplateFunction() {
+  bool Boolean = c;
+  // CHECK-FIXES: {{^ *}}bool Boolean = c;{{$}}
+}
+
+template<typename type>
+void anotherTemplateFunction(type) {
+  bool JustBool = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}bool JustBool = false;{{$}}
+}
+
+int main() {
+  boolFunction(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}boolFunction(true);{{$}}
+
+  boolFunction(false);
+
+  templateFunction(0);
+
+  templateFunction(false);
+
+  valueDependentTemplateFunction<1>();
+
+  anotherTemplateFunction(1);
+
+  IntToTrue = 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}IntToTrue = true;{{$}}
+}
+
+static int Value = 1;
+
+bool Function1() {
+  bool Result = Value == 1 ? 1 : 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: converting integer literal to bool
+  // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}bool Result = Value == 1 ? true : false;{{$}}
+  return Result;
+}
+
+bool Function2() {
+  return Value == 1 ? 1 : 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: converting integer literal to bool
+  // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}return Value == 1 ? true : false;{{$}}
+}
+
+void foo() {
+  bool Result;
+  Result = Value == 1 ? true : 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}Result = Value == 1 ? true : false;{{$}}
+  Result = Value == 1 ? false : bool(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}Result = Value == 1 ? false : false;{{$}}
+  Result = Value == 1 ? (bool)0 : false;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}Result = Value == 1 ? false : false;{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-bool-literals.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-bool-literals.cpp
new file mode 100644
index 0000000..f2ab9ce
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-bool-literals.cpp
@@ -0,0 +1,152 @@
+// RUN: %check_clang_tidy %s modernize-use-bool-literals %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:             [{key: modernize-use-bool-literals.IgnoreMacros, \
+// RUN:               value: 0}]}" \
+// RUN:   -- -std=c++11
+
+bool IntToTrue = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: converting integer literal to bool, use bool literal instead [modernize-use-bool-literals]
+// CHECK-FIXES: {{^}}bool IntToTrue = true;{{$}}
+
+bool IntToFalse(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool IntToFalse(false);{{$}}
+
+bool LongLongToTrue{0x1LL};
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool LongLongToTrue{true};{{$}}
+
+bool ExplicitCStyleIntToFalse = (bool)0;
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ExplicitCStyleIntToFalse = false;{{$}}
+
+bool ExplicitFunctionalIntToFalse = bool(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ExplicitFunctionalIntToFalse = false;{{$}}
+
+bool ExplicitStaticIntToFalse = static_cast<bool>(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ExplicitStaticIntToFalse = false;{{$}}
+
+#define TRUE_MACRO 1
+// CHECK-FIXES: {{^}}#define TRUE_MACRO 1{{$}}
+
+bool MacroIntToTrue = TRUE_MACRO;
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool MacroIntToTrue = TRUE_MACRO;{{$}}
+
+#define FALSE_MACRO bool(0)
+// CHECK-FIXES: {{^}}#define FALSE_MACRO bool(0){{$}}
+
+bool TrueBool = true; // OK
+
+bool FalseBool = bool(FALSE_MACRO);
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool FalseBool = bool(FALSE_MACRO);{{$}}
+
+void boolFunction(bool bar) {
+
+}
+
+char Character = 0; // OK
+
+unsigned long long LongInteger = 1; // OK
+
+#define MACRO_DEPENDENT_CAST(x) static_cast<bool>(x)
+// CHECK-FIXES: {{^}}#define MACRO_DEPENDENT_CAST(x) static_cast<bool>(x){{$}}
+
+bool MacroDependentBool = MACRO_DEPENDENT_CAST(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool MacroDependentBool = MACRO_DEPENDENT_CAST(0);{{$}}
+
+bool ManyMacrosDependent = MACRO_DEPENDENT_CAST(FALSE_MACRO);
+// CHECK-MESSAGES: :[[@LINE-1]]:49: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ManyMacrosDependent = MACRO_DEPENDENT_CAST(FALSE_MACRO);{{$}}
+
+class FooClass {
+  public:
+  FooClass() : JustBool(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}FooClass() : JustBool(false) {}{{$}}
+  FooClass(int) : JustBool{0} {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}FooClass(int) : JustBool{false} {}{{$}}
+  private:
+  bool JustBool;
+  bool BoolWithBraces{0};
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}bool BoolWithBraces{false};{{$}}
+  bool BoolFromInt = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}bool BoolFromInt = false;{{$}}
+  bool SimpleBool = true; // OK
+};
+
+template<typename type>
+void templateFunction(type) {
+  type TemplateType = 0;
+  // CHECK-FIXES: {{^ *}}type TemplateType = 0;{{$}}
+}
+
+template<int c>
+void valueDependentTemplateFunction() {
+  bool Boolean = c;
+  // CHECK-FIXES: {{^ *}}bool Boolean = c;{{$}}
+}
+
+template<typename type>
+void anotherTemplateFunction(type) {
+  bool JustBool = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}bool JustBool = false;{{$}}
+}
+
+int main() {
+  boolFunction(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}boolFunction(true);{{$}}
+
+  boolFunction(false);
+
+  templateFunction(0);
+
+  templateFunction(false);
+
+  valueDependentTemplateFunction<1>();
+
+  anotherTemplateFunction(1);
+
+  IntToTrue = 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}IntToTrue = true;{{$}}
+}
+
+static int Value = 1;
+
+bool Function1() {
+  bool Result = Value == 1 ? 1 : 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: converting integer literal to bool
+  // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}bool Result = Value == 1 ? true : false;{{$}}
+  return Result;
+}
+
+bool Function2() {
+  return Value == 1 ? 1 : 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: converting integer literal to bool
+  // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}return Value == 1 ? true : false;{{$}}
+}
+
+void foo() {
+  bool Result;
+  Result = Value == 1 ? true : 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}Result = Value == 1 ? true : false;{{$}}
+  Result = Value == 1 ? false : bool(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}Result = Value == 1 ? false : false;{{$}}
+  Result = Value == 1 ? (bool)0 : false;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}Result = Value == 1 ? false : false;{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-assignment.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-assignment.cpp
new file mode 100644
index 0000000..fdc0db1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-assignment.cpp
@@ -0,0 +1,184 @@
+// RUN: %check_clang_tidy %s modernize-use-default-member-init %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-default-member-init.UseAssignment, value: 1}]}" -- -std=c++11
+
+struct S {
+};
+
+struct PositiveValueChar {
+  PositiveValueChar() : c0(), c1()/*, c2(), c3()*/ {}
+  // CHECK-FIXES: PositiveValueChar()  {}
+  const char c0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use default member initializer for 'c0' [modernize-use-default-member-init]
+  // CHECK-FIXES: const char c0 = '\0';
+  wchar_t c1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use default member initializer for 'c1'
+  // CHECK-FIXES: wchar_t c1 = L'\0';
+  // FIXME: char16_t c2;
+  // C HECK-MESSAGES: :[[@LINE-1]]:12: warning: use default member initializer for 'c2'
+  // C HECK-FIXES: char16_t c2 = u'\0';
+  // FIXME: char32_t c3;
+  // C HECK-MESSAGES: :[[@LINE-1]]:12: warning: use default member initializer for 'c3'
+  // C HECK-FIXES: char32_t c3 = U'\0';
+};
+
+struct PositiveChar {
+  PositiveChar() : d('a') {}
+  // CHECK-FIXES: PositiveChar()  {}
+  char d;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'd'
+  // CHECK-FIXES: char d = 'a';
+};
+
+struct PositiveValueInt {
+  PositiveValueInt() : i() {}
+  // CHECK-FIXES: PositiveValueInt()  {}
+  const int i;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use default member initializer for 'i'
+  // CHECK-FIXES: const int i = 0;
+};
+
+struct PositiveInt {
+  PositiveInt() : j(1) {}
+  // CHECK-FIXES: PositiveInt()  {}
+  int j;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+  // CHECK-FIXES: int j = 1;
+};
+
+struct PositiveUnaryMinusInt {
+  PositiveUnaryMinusInt() : j(-1) {}
+  // CHECK-FIXES: PositiveUnaryMinusInt()  {}
+  int j;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+  // CHECK-FIXES: int j = -1;
+};
+
+struct PositiveUnaryPlusInt {
+  PositiveUnaryPlusInt() : j(+1) {}
+  // CHECK-FIXES: PositiveUnaryPlusInt()  {}
+  int j;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+  // CHECK-FIXES: int j = +1;
+};
+
+struct PositiveValueComplexInt {
+  PositiveValueComplexInt() : i() {}
+  // CHECK-FIXES: PositiveValueComplexInt()  {}
+  _Complex int i;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use default member initializer for 'i'
+  // CHECK-FIXES: _Complex int i = 0;
+};
+
+struct PositiveValueFloat {
+  PositiveValueFloat() : f() {}
+  // CHECK-FIXES: PositiveValueFloat()  {}
+  float f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use default member initializer for 'f'
+  // CHECK-FIXES: float f = 0.0f;
+};
+
+struct PositiveValueDouble {
+  PositiveValueDouble() : d() {}
+  // CHECK-FIXES: PositiveValueDouble()  {}
+  double d;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'd'
+  // CHECK-FIXES: double d = 0.0;
+};
+
+struct PositiveDouble {
+  PositiveDouble() : f(2.5463e43) {}
+  // CHECK-FIXES: PositiveDouble()  {}
+  double f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+  // CHECK-FIXES: double f = 2.5463e43;
+};
+
+struct PositiveValueComplexFloat {
+  PositiveValueComplexFloat() : f() {}
+  // CHECK-FIXES: PositiveValueComplexFloat()  {}
+  _Complex float f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use default member initializer for 'f'
+  // CHECK-FIXES: _Complex float f = 0.0f;
+};
+
+struct PositiveValueComplexDouble {
+  PositiveValueComplexDouble() : f() {}
+  // CHECK-FIXES: PositiveValueComplexDouble()  {}
+  _Complex double f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use default member initializer for 'f'
+  // CHECK-FIXES: _Complex double f = 0.0;
+};
+
+struct PositiveUnaryMinusDouble {
+  PositiveUnaryMinusDouble() : f(-2.5463e43) {}
+  // CHECK-FIXES: PositiveUnaryMinusDouble()  {}
+  double f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+  // CHECK-FIXES: double f = -2.5463e43;
+};
+
+struct PositiveUnaryPlusDouble {
+  PositiveUnaryPlusDouble() : f(+2.5463e43) {}
+  // CHECK-FIXES: PositiveUnaryPlusDouble()  {}
+  double f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+  // CHECK-FIXES: double f = +2.5463e43;
+};
+
+struct PositiveValueBool {
+  PositiveValueBool() : b() {}
+  // CHECK-FIXES: PositiveValueBool()  {}
+  bool b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'b'
+  // CHECK-FIXES: bool b = false;
+};
+
+struct PositiveBool {
+  PositiveBool() : a(true) {}
+  // CHECK-FIXES: PositiveBool()  {}
+  bool a;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'a'
+  // CHECK-FIXES: bool a = true;
+};
+
+struct PositiveValuePointer {
+  PositiveValuePointer() : p() {}
+  // CHECK-FIXES: PositiveValuePointer()  {}
+  int *p;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'p'
+  // CHECK-FIXES: int *p = nullptr;
+};
+
+struct PositiveNullPointer {
+  PositiveNullPointer() : q(nullptr) {}
+  // CHECK-FIXES: PositiveNullPointer()  {}
+  int *q;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'q'
+  // CHECK-FIXES: int *q = nullptr;
+};
+
+enum Enum { Foo };
+struct PositiveEnum {
+  PositiveEnum() : e(Foo) {}
+  // CHECK-FIXES: PositiveEnum()  {}
+  Enum e;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'e'
+  // CHECK-FIXES: Enum e = Foo;
+};
+
+struct PositiveString {
+  PositiveString() : s("foo") {}
+  // CHECK-FIXES: PositiveString()  {}
+  const char *s;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use default member initializer for 's'
+  // CHECK-FIXES: const char *s = "foo";
+};
+
+template <typename T>
+struct NegativeTemplate {
+    NegativeTemplate() : t() {}
+    T t;
+};
+
+NegativeTemplate<int> nti;
+NegativeTemplate<double> ntd;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-bitfield.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-bitfield.cpp
new file mode 100644
index 0000000..1ff08f9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-bitfield.cpp
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s modernize-use-default-member-init %t -- -- -std=c++2a
+
+struct PositiveBitField
+{
+  PositiveBitField() : i(6) {}
+  // CHECK-FIXES: PositiveBitField()  {}
+  int i : 5;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'i' [modernize-use-default-member-init]
+  // CHECK-FIXES: int i : 5{6};
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-macros.cpp
new file mode 100644
index 0000000..5b366b5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init-macros.cpp
@@ -0,0 +1,18 @@
+// RUN: %check_clang_tidy %s modernize-use-default-member-init %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-default-member-init.IgnoreMacros, value: 0}]}" \
+// RUN:   -- -std=c++11
+
+#define MACRO() \
+  struct S { \
+    void *P; \
+    S() : P(nullptr) {} \
+  };
+
+MACRO();
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use default member initializer for 'P'
+
+struct S2 {
+  void *P;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use default member initializer for 'P'
+  S2() : P(nullptr) {}
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init.cpp
new file mode 100644
index 0000000..0ed65df
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-default-member-init.cpp
@@ -0,0 +1,401 @@
+// RUN: %check_clang_tidy %s modernize-use-default-member-init %t -- -- -std=c++11
+
+struct S {
+};
+
+struct PositiveValueChar {
+  PositiveValueChar() : c0(), c1()/*, c2(), c3()*/ {}
+  // CHECK-FIXES: PositiveValueChar()  {}
+  const char c0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use default member initializer for 'c0' [modernize-use-default-member-init]
+  // CHECK-FIXES: const char c0{};
+  wchar_t c1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use default member initializer for 'c1'
+  // CHECK-FIXES: wchar_t c1{};
+  // FIXME: char16_t c2;
+  // C HECK-MESSAGES: :[[@LINE-1]]:12: warning: use default member initializer for 'c2'
+  // C HECK-FIXES: char16_t c2{};
+  // FIXME: char32_t c3;
+  // C HECK-MESSAGES: :[[@LINE-1]]:12: warning: use default member initializer for 'c3'
+  // C HECK-FIXES: char32_t c3{};
+};
+
+struct PositiveChar {
+  PositiveChar() : d('a') {}
+  // CHECK-FIXES: PositiveChar()  {}
+  char d;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'd'
+  // CHECK-FIXES: char d{'a'};
+};
+
+struct PositiveValueInt {
+  PositiveValueInt() : i() {}
+  // CHECK-FIXES: PositiveValueInt()  {}
+  const int i;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use default member initializer for 'i'
+  // CHECK-FIXES: const int i{};
+};
+
+struct PositiveInt {
+  PositiveInt() : j(1) {}
+  // CHECK-FIXES: PositiveInt()  {}
+  int j;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+  // CHECK-FIXES: int j{1};
+};
+
+struct PositiveUnaryMinusInt {
+  PositiveUnaryMinusInt() : j(-1) {}
+  // CHECK-FIXES: PositiveUnaryMinusInt()  {}
+  int j;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+  // CHECK-FIXES: int j{-1};
+};
+
+struct PositiveUnaryPlusInt {
+  PositiveUnaryPlusInt() : j(+1) {}
+  // CHECK-FIXES: PositiveUnaryPlusInt()  {}
+  int j;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+  // CHECK-FIXES: int j{+1};
+};
+
+struct PositiveValueComplexInt {
+  PositiveValueComplexInt() : i() {}
+  // CHECK-FIXES: PositiveValueComplexInt()  {}
+  _Complex int i;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use default member initializer for 'i'
+  // CHECK-FIXES: _Complex int i{};
+};
+
+struct PositiveValueFloat {
+  PositiveValueFloat() : f() {}
+  // CHECK-FIXES: PositiveValueFloat()  {}
+  float f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use default member initializer for 'f'
+  // CHECK-FIXES: float f{};
+};
+
+struct PositiveValueDouble {
+  PositiveValueDouble() : d() {}
+  // CHECK-FIXES: PositiveValueDouble()  {}
+  double d;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'd'
+  // CHECK-FIXES: double d{};
+};
+
+struct PositiveDouble {
+  PositiveDouble() : f(2.5463e43) {}
+  // CHECK-FIXES: PositiveDouble()  {}
+  double f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+  // CHECK-FIXES: double f{2.5463e43};
+};
+
+struct PositiveValueComplexFloat {
+  PositiveValueComplexFloat() : f() {}
+  // CHECK-FIXES: PositiveValueComplexFloat()  {}
+  _Complex float f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use default member initializer for 'f'
+  // CHECK-FIXES: _Complex float f{};
+};
+
+struct PositiveValueComplexDouble {
+  PositiveValueComplexDouble() : f() {}
+  // CHECK-FIXES: PositiveValueComplexDouble()  {}
+  _Complex double f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use default member initializer for 'f'
+  // CHECK-FIXES: _Complex double f{};
+};
+
+struct PositiveUnaryMinusDouble {
+  PositiveUnaryMinusDouble() : f(-2.5463e43) {}
+  // CHECK-FIXES: PositiveUnaryMinusDouble()  {}
+  double f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+  // CHECK-FIXES: double f{-2.5463e43};
+};
+
+struct PositiveUnaryPlusDouble {
+  PositiveUnaryPlusDouble() : f(+2.5463e43) {}
+  // CHECK-FIXES: PositiveUnaryPlusDouble()  {}
+  double f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+  // CHECK-FIXES: double f{+2.5463e43};
+};
+
+struct PositiveValueBool {
+  PositiveValueBool() : b() {}
+  // CHECK-FIXES: PositiveValueBool()  {}
+  bool b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'b'
+  // CHECK-FIXES: bool b{};
+};
+
+struct PositiveBool {
+  PositiveBool() : a(true) {}
+  // CHECK-FIXES: PositiveBool()  {}
+  bool a;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'a'
+  // CHECK-FIXES: bool a{true};
+};
+
+struct PositiveValuePointer {
+  PositiveValuePointer() : p() {}
+  // CHECK-FIXES: PositiveValuePointer()  {}
+  int *p;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'p'
+  // CHECK-FIXES: int *p{};
+};
+
+struct PositiveNullPointer {
+  PositiveNullPointer() : q(nullptr) {}
+  // CHECK-FIXES: PositiveNullPointer()  {}
+  int *q;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'q'
+  // CHECK-FIXES: int *q{nullptr};
+};
+
+enum Enum { Foo, Bar };
+struct PositiveEnum {
+  PositiveEnum() : e(Foo) {}
+  // CHECK-FIXES: PositiveEnum()  {}
+  Enum e;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'e'
+  // CHECK-FIXES: Enum e{Foo};
+};
+
+struct PositiveString {
+  PositiveString() : s("foo") {}
+  // CHECK-FIXES: PositiveString()  {}
+  const char *s;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use default member initializer for 's'
+  // CHECK-FIXES: const char *s{"foo"};
+};
+
+struct PositiveStruct {
+  PositiveStruct() : s(7) {}
+  // CHECK-FIXES: PositiveStruct()  {}
+  struct {
+    int s;
+    // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use default member initializer for 's'
+    // CHECK-FIXES: int s{7};
+  };
+};
+
+template <typename T>
+struct NegativeTemplate {
+    NegativeTemplate() : t() {}
+    T t;
+};
+
+NegativeTemplate<int> nti;
+NegativeTemplate<double> ntd;
+
+struct NegativeDefaultMember {
+  NegativeDefaultMember() {}
+  int i = 2;
+};
+
+struct NegativeClass : S {
+  NegativeClass() : s() {}
+  S s;
+};
+
+struct NegativeBase : S {
+  NegativeBase() : S() {}
+};
+
+struct NegativeDefaultOtherMember{
+  NegativeDefaultOtherMember() : i(3) {}
+  int i = 4;
+};
+
+struct NegativeUnion {
+  NegativeUnion() : d(5.0) {}
+  union {
+    int i;
+    double d;
+  };
+};
+
+struct NegativeBitField
+{
+  NegativeBitField() : i(6) {}
+  int i : 5;
+};
+
+struct NegativeNotDefaultInt
+{
+  NegativeNotDefaultInt(int) : i(7) {}
+  int i;
+};
+
+struct NegativeDefaultArg
+{
+  NegativeDefaultArg(int i = 4) : i(i) {}
+  int i;
+};
+
+struct ExistingChar {
+  ExistingChar(short) : e1(), e2(), e3(), e4() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+  // CHECK-MESSAGES: :[[@LINE-2]]:31: warning: member initializer for 'e2' is redundant
+  // CHECK-MESSAGES: :[[@LINE-3]]:37: warning: member initializer for 'e3' is redundant
+  // CHECK-FIXES: ExistingChar(short) :  e4() {}
+  ExistingChar(int) : e1(0), e2(0), e3(0), e4(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: member initializer for 'e1' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:30: warning: member initializer for 'e2' is redundant
+  // CHECK-MESSAGES: :[[@LINE-3]]:37: warning: member initializer for 'e3' is redundant
+  // CHECK-FIXES: ExistingChar(int) :  e4(0) {}
+  ExistingChar(long) : e1('\0'), e2('\0'), e3('\0'), e4('\0') {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: member initializer for 'e1' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: member initializer for 'e2' is redundant
+  // CHECK-MESSAGES: :[[@LINE-3]]:44: warning: member initializer for 'e3' is redundant
+  // CHECK-FIXES: ExistingChar(long) :  e4('\0') {}
+  ExistingChar(char) : e1('a'), e2('a'), e3('a'), e4('a') {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:51: warning: member initializer for 'e4' is redundant
+  // CHECK-FIXES: ExistingChar(char) : e1('a'), e2('a'), e3('a') {}
+  char e1{};
+  char e2 = 0;
+  char e3 = '\0';
+  char e4 = 'a';
+};
+
+struct ExistingInt {
+  ExistingInt(short) : e1(), e2(), e3(), e4(), e5(), e6() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+  // CHECK-MESSAGES: :[[@LINE-2]]:30: warning: member initializer for 'e2' is redundant
+  // CHECK-FIXES: ExistingInt(short) :  e3(), e4(), e5(), e6() {}
+  ExistingInt(int) : e1(0), e2(0), e3(0), e4(0), e5(0), e6(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: member initializer for 'e1' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:29: warning: member initializer for 'e2' is redundant
+  // CHECK-FIXES: ExistingInt(int) :  e3(0), e4(0), e5(0), e6(0) {}
+  ExistingInt(long) : e1(5), e2(5), e3(5), e4(5), e5(5), e6(5) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: member initializer for 'e3' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:44: warning: member initializer for 'e4' is redundant
+  // CHECK-MESSAGES: :[[@LINE-3]]:58: warning: member initializer for 'e6' is redundant
+  // CHECK-FIXES: ExistingInt(long) : e1(5), e2(5),  e5(5) {}
+  ExistingInt(char) : e1(-5), e2(-5), e3(-5), e4(-5), e5(-5), e6(-5) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:55: warning: member initializer for 'e5' is redundant
+  // CHECK-FIXES: ExistingInt(char) : e1(-5), e2(-5), e3(-5), e4(-5),  e6(-5) {}
+  int e1{};
+  int e2 = 0;
+  int e3 = {5};
+  int e4 = 5;
+  int e5 = -5;
+  int e6 = +5;
+};
+
+struct ExistingDouble {
+  ExistingDouble(short) : e1(), e2(), e3(), e4(), e5() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: member initializer for 'e1' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:33: warning: member initializer for 'e2' is redundant
+  // CHECK-FIXES: ExistingDouble(short) :  e3(), e4(), e5() {}
+  ExistingDouble(int) : e1(0.0), e2(0.0), e3(0.0), e4(0.0), e5(0.0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: member initializer for 'e2' is redundant
+  // CHECK-FIXES: ExistingDouble(int) :  e3(0.0), e4(0.0), e5(0.0) {}
+  ExistingDouble(long) : e1(5.0), e2(5.0), e3(5.0), e4(5.0), e5(5.0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: member initializer for 'e3' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:62: warning: member initializer for 'e5' is redundant
+  // CHECK-FIXES: ExistingDouble(long) : e1(5.0), e2(5.0),  e4(5.0) {}
+  ExistingDouble(char) : e1(-5.0), e2(-5.0), e3(-5.0), e4(-5.0), e5(-5.0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: member initializer for 'e4' is redundant
+  // CHECK-FIXES: ExistingDouble(char) : e1(-5.0), e2(-5.0), e3(-5.0),  e5(-5.0) {}
+  double e1{};
+  double e2 = 0.0;
+  double e3 = 5.0;
+  double e4 = -5.0;
+  double e5 = +5.0;
+};
+
+struct ExistingBool {
+  ExistingBool(short) : e1(), e2(), e3() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:31: warning: member initializer for 'e2' is redundant
+  // CHECK-FIXES: ExistingBool(short) :  e3() {}
+  ExistingBool(int) : e1(false), e2(false), e3(false) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: member initializer for 'e1' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: member initializer for 'e2' is redundant
+  // CHECK-FIXES: ExistingBool(int) :  e3(false) {}
+  ExistingBool(long) : e1(true), e2(true), e3(true) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: member initializer for 'e3' is redundant
+  // CHECK-FIXES: ExistingBool(long) : e1(true), e2(true) {}
+  bool e1{};
+  bool e2 = false;
+  bool e3 = true;
+};
+
+struct ExistingEnum {
+  ExistingEnum(short) : e1(Foo), e2(Foo) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant
+  // CHECK-FIXES: ExistingEnum(short) :  e2(Foo) {}
+  ExistingEnum(int) : e1(Bar), e2(Bar) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: member initializer for 'e2' is redundant
+  // CHECK-FIXES: ExistingEnum(int) : e1(Bar) {}
+  Enum e1 = Foo;
+  Enum e2{Bar};
+};
+
+struct ExistingPointer {
+  ExistingPointer(short) : e1(), e2(), e3(), e4() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: member initializer for 'e1' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: member initializer for 'e2' is redundant
+  // CHECK-MESSAGES: :[[@LINE-3]]:40: warning: member initializer for 'e3' is redundant
+  // CHECK-FIXES: ExistingPointer(short) :  e4() {}
+  ExistingPointer(int) : e1(0), e2(0), e3(0), e4(&e1) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: member initializer for 'e1' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:33: warning: member initializer for 'e2' is redundant
+  // CHECK-MESSAGES: :[[@LINE-3]]:40: warning: member initializer for 'e3' is redundant
+  // CHECK-FIXES: ExistingPointer(int) :  e4(&e1) {}
+  ExistingPointer(long) : e1(nullptr), e2(nullptr), e3(nullptr), e4(&e2) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: member initializer for 'e1' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:40: warning: member initializer for 'e2' is redundant
+  // CHECK-MESSAGES: :[[@LINE-3]]:53: warning: member initializer for 'e3' is redundant
+  // CHECK-FIXES: ExistingPointer(long) :  e4(&e2) {}
+  int *e1{};
+  int *e2 = 0;
+  int *e3 = nullptr;
+  int **e4 = &e1;
+};
+
+struct ExistingString {
+  ExistingString(short) : e1(), e2(), e3(), e4() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+  // CHECK-MESSAGES: :[[@LINE-2]]:33: warning: member initializer for 'e2' is redundant
+  // CHECK-FIXES: ExistingString(short) :  e3(), e4() {}
+  ExistingString(int) : e1(0), e2(0), e3(0), e4(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:32: warning: member initializer for 'e2' is redundant
+  // CHECK-FIXES: ExistingString(int) :  e3(0), e4(0) {}
+  ExistingString(long) : e1(nullptr), e2(nullptr), e3(nullptr), e4(nullptr) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: member initializer for 'e1' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:39: warning: member initializer for 'e2' is redundant
+  // CHECK-FIXES: ExistingString(long) :  e3(nullptr), e4(nullptr) {}
+  ExistingString(char) : e1("foo"), e2("foo"), e3("foo"), e4("foo") {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: member initializer for 'e3' is redundant
+  // CHECK-FIXES: ExistingString(char) : e1("foo"), e2("foo"),  e4("foo") {}
+  const char *e1{};
+  const char *e2 = nullptr;
+  const char *e3 = "foo";
+  const char *e4 = "bar";
+};
+
+template <typename T>
+struct NegativeTemplateExisting {
+  NegativeTemplateExisting(int) : t(0) {}
+  T t{};
+};
+
+NegativeTemplateExisting<int> ntei(0);
+NegativeTemplateExisting<double> nted(0);
+
+// This resulted in a warning by default.
+#define MACRO() \
+  struct MacroS { \
+    void *P; \
+    MacroS() : P(nullptr) {} \
+  };
+
+MACRO();
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-emplace-ignore-implicit-constructors.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-emplace-ignore-implicit-constructors.cpp
new file mode 100644
index 0000000..2f6b37f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-emplace-ignore-implicit-constructors.cpp
@@ -0,0 +1,123 @@
+// RUN: %check_clang_tidy %s modernize-use-emplace %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:             [{key: modernize-use-emplace.IgnoreImplicitConstructors, \
+// RUN:               value: 1}] \
+// RUN:             }" -- -std=c++11
+
+namespace std {
+template <typename>
+class initializer_list
+{
+public:
+  initializer_list() noexcept {}
+};
+
+template <typename T>
+class vector {
+public:
+  vector() = default;
+  vector(initializer_list<T>) {}
+
+  void push_back(const T &) {}
+  void push_back(T &&) {}
+
+  template <typename... Args>
+  void emplace_back(Args &&... args){};
+  ~vector();
+};
+
+} // namespace std
+
+void testInts() {
+  std::vector<int> v;
+  v.push_back(42);
+  v.push_back(int(42));
+  v.push_back(int{42});
+  v.push_back(42.0);
+  int z;
+  v.push_back(z);
+}
+
+struct Something {
+  Something(int a, int b = 41) {}
+  Something() {}
+  void push_back(Something);
+  int getInt() { return 42; }
+};
+
+struct Convertable {
+  operator Something() { return Something{}; }
+};
+
+struct Zoz {
+  Zoz(Something, int = 42) {}
+};
+
+Zoz getZoz(Something s) { return Zoz(s); }
+
+void test_Something() {
+  std::vector<Something> v;
+
+  v.push_back(Something(1, 2));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back instead of push_back [modernize-use-emplace]
+  // CHECK-FIXES: v.emplace_back(1, 2);
+
+  v.push_back(Something{1, 2});
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(1, 2);
+
+  v.push_back(Something());
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back();
+
+  v.push_back(Something{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back();
+
+  Something Different;
+  v.push_back(Something(Different.getInt(), 42));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(Different.getInt(), 42);
+
+  v.push_back(Different.getInt());
+  v.push_back(42);
+
+  Something temporary(42, 42);
+  temporary.push_back(temporary);
+  v.push_back(temporary);
+
+  v.push_back(Convertable());
+  v.push_back(Convertable{});
+  Convertable s;
+  v.push_back(s);
+}
+
+template <typename ElemType>
+void dependOnElem() {
+  std::vector<ElemType> v;
+  v.push_back(ElemType(42));
+}
+
+template <typename ContainerType>
+void dependOnContainer() {
+  ContainerType v;
+  v.push_back(Something(42));
+}
+
+void callDependent() {
+  dependOnElem<Something>();
+  dependOnContainer<std::vector<Something>>();
+}
+
+void test2() {
+  std::vector<Zoz> v;
+  v.push_back(Zoz(Something(21, 37)));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(Something(21, 37));
+
+  v.push_back(Zoz(Something(21, 37), 42));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(Something(21, 37), 42);
+
+  v.push_back(getZoz(Something(1, 2)));
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-emplace.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-emplace.cpp
new file mode 100644
index 0000000..c03d024
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-emplace.cpp
@@ -0,0 +1,607 @@
+// RUN: %check_clang_tidy %s modernize-use-emplace %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:             [{key: modernize-use-emplace.ContainersWithPushBack, \
+// RUN:               value: '::std::vector; ::std::list; ::std::deque; llvm::LikeASmallVector'}, \
+// RUN:              {key: modernize-use-emplace.TupleTypes, \
+// RUN:               value: '::std::pair; std::tuple; ::test::Single'}, \
+// RUN:              {key: modernize-use-emplace.TupleMakeFunctions, \
+// RUN:               value: '::std::make_pair; ::std::make_tuple; ::test::MakeSingle'}] \
+// RUN:             }" -- -std=c++11
+
+namespace std {
+template <typename>
+class initializer_list
+{
+public:
+  initializer_list() noexcept {}
+};
+
+template <typename T>
+class vector {
+public:
+  vector() = default;
+  vector(initializer_list<T>) {}
+
+  void push_back(const T &) {}
+  void push_back(T &&) {}
+
+  template <typename... Args>
+  void emplace_back(Args &&... args){};
+  ~vector();
+};
+template <typename T>
+class list {
+public:
+  void push_back(const T &) {}
+  void push_back(T &&) {}
+
+  template <typename... Args>
+  void emplace_back(Args &&... args){};
+  ~list();
+};
+
+template <typename T>
+class deque {
+public:
+  void push_back(const T &) {}
+  void push_back(T &&) {}
+
+  template <typename... Args>
+  void emplace_back(Args &&... args){};
+  ~deque();
+};
+
+template <typename T> struct remove_reference { using type = T; };
+template <typename T> struct remove_reference<T &> { using type = T; };
+template <typename T> struct remove_reference<T &&> { using type = T; };
+
+template <typename T1, typename T2> class pair {
+public:
+  pair() = default;
+  pair(const pair &) = default;
+  pair(pair &&) = default;
+
+  pair(const T1 &, const T2 &) {}
+  pair(T1 &&, T2 &&) {}
+
+  template <typename U1, typename U2> pair(const pair<U1, U2> &){};
+  template <typename U1, typename U2> pair(pair<U1, U2> &&){};
+};
+
+template <typename T1, typename T2>
+pair<typename remove_reference<T1>::type, typename remove_reference<T2>::type>
+make_pair(T1 &&, T2 &&) {
+  return {};
+};
+
+template <typename... Ts> class tuple {
+public:
+  tuple() = default;
+  tuple(const tuple &) = default;
+  tuple(tuple &&) = default;
+
+  tuple(const Ts &...) {}
+  tuple(Ts &&...) {}
+
+  template <typename... Us> tuple(const tuple<Us...> &){};
+  template <typename... Us> tuple(tuple<Us...> &&) {}
+
+  template <typename U1, typename U2> tuple(const pair<U1, U2> &) {
+    static_assert(sizeof...(Ts) == 2, "Wrong tuple size");
+  };
+  template <typename U1, typename U2> tuple(pair<U1, U2> &&) {
+    static_assert(sizeof...(Ts) == 2, "Wrong tuple size");
+  };
+};
+
+template <typename... Ts>
+tuple<typename remove_reference<Ts>::type...> make_tuple(Ts &&...) {
+  return {};
+}
+
+template <typename T>
+class unique_ptr {
+public:
+  explicit unique_ptr(T *) {}
+  ~unique_ptr();
+};
+} // namespace std
+
+namespace llvm {
+template <typename T>
+class LikeASmallVector {
+public:
+  void push_back(const T &) {}
+  void push_back(T &&) {}
+
+  template <typename... Args>
+  void emplace_back(Args &&... args){};
+};
+
+} // llvm
+
+void testInts() {
+  std::vector<int> v;
+  v.push_back(42);
+  v.push_back(int(42));
+  v.push_back(int{42});
+  v.push_back(42.0);
+  int z;
+  v.push_back(z);
+}
+
+struct Something {
+  Something(int a, int b = 41) {}
+  Something() {}
+  void push_back(Something);
+  int getInt() { return 42; }
+};
+
+struct Convertable {
+  operator Something() { return Something{}; }
+};
+
+struct Zoz {
+  Zoz(Something, int = 42) {}
+};
+
+Zoz getZoz(Something s) { return Zoz(s); }
+
+void test_Something() {
+  std::vector<Something> v;
+
+  v.push_back(Something(1, 2));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back instead of push_back [modernize-use-emplace]
+  // CHECK-FIXES: v.emplace_back(1, 2);
+
+  v.push_back(Something{1, 2});
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(1, 2);
+
+  v.push_back(Something());
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back();
+
+  v.push_back(Something{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back();
+
+  Something Different;
+  v.push_back(Something(Different.getInt(), 42));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(Different.getInt(), 42);
+
+  v.push_back(Different.getInt());
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(Different.getInt());
+
+  v.push_back(42);
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(42);
+
+  Something temporary(42, 42);
+  temporary.push_back(temporary);
+  v.push_back(temporary);
+
+  v.push_back(Convertable());
+  v.push_back(Convertable{});
+  Convertable s;
+  v.push_back(s);
+}
+
+template <typename ElemType>
+void dependOnElem() {
+  std::vector<ElemType> v;
+  v.push_back(ElemType(42));
+}
+
+template <typename ContainerType>
+void dependOnContainer() {
+  ContainerType v;
+  v.push_back(Something(42));
+}
+
+void callDependent() {
+  dependOnElem<Something>();
+  dependOnContainer<std::vector<Something>>();
+}
+
+void test2() {
+  std::vector<Zoz> v;
+  v.push_back(Zoz(Something(21, 37)));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(Something(21, 37));
+
+  v.push_back(Zoz(Something(21, 37), 42));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(Something(21, 37), 42);
+
+  v.push_back(getZoz(Something(1, 2)));
+}
+
+struct GetPair {
+  std::pair<int, long> getPair();
+};
+void testPair() {
+  std::vector<std::pair<int, int>> v;
+  v.push_back(std::pair<int, int>(1, 2));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(1, 2);
+
+  GetPair g;
+  v.push_back(g.getPair());
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(g.getPair());
+
+  std::vector<std::pair<Something, Zoz>> v2;
+  v2.push_back(std::pair<Something, Zoz>(Something(42, 42), Zoz(Something(21, 37))));
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back
+  // CHECK-FIXES: v2.emplace_back(Something(42, 42), Zoz(Something(21, 37)));
+}
+
+void testTuple() {
+  std::vector<std::tuple<bool, char, int>> v;
+  v.push_back(std::tuple<bool, char, int>(false, 'x', 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(false, 'x', 1);
+
+  v.push_back(std::tuple<bool, char, int>{false, 'y', 2});
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(false, 'y', 2);
+
+  v.push_back({true, 'z', 3});
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(true, 'z', 3);
+
+  std::vector<std::tuple<int, bool>> x;
+  x.push_back(std::make_pair(1, false));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: x.emplace_back(1, false);
+
+  x.push_back(std::make_pair(2LL, 1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: x.emplace_back(2LL, 1);
+}
+
+struct Base {
+  Base(int, int *, int = 42);
+};
+
+struct Derived : Base {
+  Derived(int *, Something) : Base(42, nullptr) {}
+};
+
+void testDerived() {
+  std::vector<Base> v;
+  v.push_back(Derived(nullptr, Something{}));
+}
+
+void testNewExpr() {
+  std::vector<Derived> v;
+  v.push_back(Derived(new int, Something{}));
+}
+
+void testSpaces() {
+  std::vector<Something> v;
+
+  // clang-format off
+
+  v.push_back(Something(1, //arg1
+                2 // arg2
+               ) // Something
+              );
+  // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(1, //arg1
+  // CHECK-FIXES:                2 // arg2
+  // CHECK-FIXES:                  // Something
+  // CHECK-FIXES:                );
+
+  v.push_back(    Something   (1, 2)    );
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(1, 2   );
+
+  v.push_back(    Something   {1, 2}    );
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(1, 2   );
+
+  v.push_back(  Something {}    );
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(   );
+
+  v.push_back(
+             Something(1, 2)    );
+  // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(1, 2   );
+
+  std::vector<Base> v2;
+  v2.push_back(
+    Base(42, nullptr));
+  // CHECK-MESSAGES: :[[@LINE-2]]:6: warning: use emplace_back
+  // CHECK-FIXES: v2.emplace_back(42, nullptr);
+
+  // clang-format on
+}
+
+void testPointers() {
+  std::vector<int *> v;
+  v.push_back(new int(5));
+
+  std::vector<std::unique_ptr<int>> v2;
+  v2.push_back(std::unique_ptr<int>(new int(42)));
+  // This call can't be replaced with emplace_back.
+  // If emplacement will fail (not enough memory to add to vector)
+  // we will have leak of int because unique_ptr won't be constructed
+  // (and destructed) as in push_back case.
+
+  auto *ptr = new int;
+  v2.push_back(std::unique_ptr<int>(ptr));
+  // Same here
+}
+
+void testMakePair() {
+  std::vector<std::pair<int, int>> v;
+  v.push_back(std::make_pair(1, 2));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(1, 2);
+
+  v.push_back(std::make_pair(42LL, 13));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(42LL, 13);
+
+  v.push_back(std::make_pair<char, char>(0, 3));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(std::make_pair<char, char>(0, 3));
+  //
+  // Even though the call above could be turned into v.emplace_back(0, 3),
+  // we don't eliminate the make_pair call here, because of the explicit
+  // template parameters provided. make_pair's arguments can be convertible
+  // to its explicitly provided template parameter, but not to the pair's
+  // element type. The examples below illustrate the problem.
+  struct D {
+    D(...) {}
+    operator char() const { return 0; }
+  };
+  v.push_back(std::make_pair<D, int>(Something(), 2));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(std::make_pair<D, int>(Something(), 2));
+
+  struct X {
+    X(std::pair<int, int>) {}
+  };
+  std::vector<X> x;
+  x.push_back(std::make_pair(1, 2));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: x.emplace_back(std::make_pair(1, 2));
+  // make_pair cannot be removed here, as X is not constructible with two ints.
+
+  struct Y {
+    Y(std::pair<int, int>&&) {}
+  };
+  std::vector<Y> y;
+  y.push_back(std::make_pair(2, 3));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: y.emplace_back(std::make_pair(2, 3));
+  // make_pair cannot be removed here, as Y is not constructible with two ints.
+}
+
+void testMakeTuple() {
+  std::vector<std::tuple<int, bool, char>> v;
+  v.push_back(std::make_tuple(1, true, 'v'));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(1, true, 'v');
+
+  v.push_back(std::make_tuple(2ULL, 1, 0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(2ULL, 1, 0);
+
+  v.push_back(std::make_tuple<long long, int, int>(3LL, 1, 0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(std::make_tuple<long long, int, int>(3LL, 1, 0));
+  // make_tuple is not removed when there are explicit template
+  // arguments provided.
+}
+
+namespace test {
+template <typename T> struct Single {
+  Single() = default;
+  Single(const Single &) = default;
+  Single(Single &&) = default;
+
+  Single(const T &) {}
+  Single(T &&) {}
+
+  template <typename U> Single(const Single<U> &) {}
+  template <typename U> Single(Single<U> &&) {}
+
+  template <typename U> Single(const std::tuple<U> &) {}
+  template <typename U> Single(std::tuple<U> &&) {}
+};
+
+template <typename T>
+Single<typename std::remove_reference<T>::type> MakeSingle(T &&) {
+  return {};
+}
+} // namespace test
+
+void testOtherTuples() {
+  std::vector<test::Single<int>> v;
+  v.push_back(test::Single<int>(1));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(1);
+
+  v.push_back({2});
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(2);
+
+  v.push_back(test::MakeSingle(3));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(3);
+
+  v.push_back(test::MakeSingle<long long>(4));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(test::MakeSingle<long long>(4));
+  // We don't remove make functions with explicit template parameters.
+
+  v.push_back(test::MakeSingle(5LL));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(5LL);
+
+  v.push_back(std::make_tuple(6));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(6);
+
+  v.push_back(std::make_tuple(7LL));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(7LL);
+}
+
+void testOtherContainers() {
+  std::list<Something> l;
+  l.push_back(Something(42, 41));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: l.emplace_back(42, 41);
+
+  std::deque<Something> d;
+  d.push_back(Something(42));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: d.emplace_back(42);
+
+  llvm::LikeASmallVector<Something> ls;
+  ls.push_back(Something(42));
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back
+  // CHECK-FIXES: ls.emplace_back(42);
+}
+
+class IntWrapper {
+public:
+  IntWrapper(int x) : value(x) {}
+  IntWrapper operator+(const IntWrapper other) const {
+    return IntWrapper(value + other.value);
+  }
+
+private:
+  int value;
+};
+
+void testMultipleOpsInPushBack() {
+  std::vector<IntWrapper> v;
+  v.push_back(IntWrapper(42) + IntWrapper(27));
+}
+
+// Macro tests.
+#define PUSH_BACK_WHOLE(c, x) c.push_back(x)
+#define PUSH_BACK_NAME push_back
+#define PUSH_BACK_ARG(x) (x)
+#define SOME_OBJ Something(10)
+#define MILLION 3
+#define SOME_WEIRD_PUSH(v) v.push_back(Something(
+#define OPEN (
+#define CLOSE )
+void macroTest() {
+  std::vector<Something> v;
+  Something s;
+
+  PUSH_BACK_WHOLE(v, Something(5, 6));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use emplace_back
+
+  v.PUSH_BACK_NAME(Something(5));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+
+  v.push_back PUSH_BACK_ARG(Something(5, 6));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+
+  v.push_back(SOME_OBJ);
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+
+  v.push_back(Something(MILLION));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(MILLION);
+
+  // clang-format off
+  v.push_back(  Something OPEN 3 CLOSE  );
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // clang-format on
+  PUSH_BACK_WHOLE(s, Something(1));
+}
+
+struct A {
+  int value1, value2;
+};
+
+struct B {
+  B(A) {}
+};
+
+struct C {
+  int value1, value2, value3;
+};
+
+void testAggregation() {
+  // This should not be noticed or fixed; after the correction, the code won't
+  // compile.
+
+  std::vector<A> v;
+  v.push_back(A({1, 2}));
+
+  std::vector<B> vb;
+  vb.push_back(B({10, 42}));
+}
+
+struct Bitfield {
+  unsigned bitfield : 1;
+  unsigned notBitfield;
+};
+
+void testBitfields() {
+  std::vector<Something> v;
+  Bitfield b;
+  v.push_back(Something(42, b.bitfield));
+  v.push_back(Something(b.bitfield));
+
+  v.push_back(Something(42, b.notBitfield));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(42, b.notBitfield);
+  int var;
+  v.push_back(Something(42, var));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(42, var);
+}
+
+class PrivateCtor {
+  PrivateCtor(int z);
+
+public:
+  void doStuff() {
+    std::vector<PrivateCtor> v;
+    // This should not change it because emplace back doesn't have permission.
+    // Check currently doesn't support friend declarations because pretty much
+    // nobody would want to be friend with std::vector :(.
+    v.push_back(PrivateCtor(42));
+  }
+};
+
+struct WithDtor {
+  WithDtor(int) {}
+  ~WithDtor();
+};
+
+void testWithDtor() {
+  std::vector<WithDtor> v;
+
+  v.push_back(WithDtor(42));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(42);
+}
+
+void testInitializerList() {
+  std::vector<std::vector<int>> v;
+  v.push_back(std::vector<int>({1}));
+  // Test against the bug reported in PR32896.
+
+  v.push_back({{2}});
+
+  using PairIntVector = std::pair<int, std::vector<int>>;
+  std::vector<PairIntVector> x;
+  x.push_back(PairIntVector(3, {4}));
+  x.push_back({5, {6}});
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-copy.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-copy.cpp
new file mode 100644
index 0000000..39a864d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-copy.cpp
@@ -0,0 +1,507 @@
+// RUN: %check_clang_tidy %s modernize-use-equals-default %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-equals-default.IgnoreMacros, value: 0}]}" \
+// RUN:   -- -std=c++11 -fno-delayed-template-parsing -fexceptions
+
+// Out of line definition.
+struct OL {
+  OL(const OL &);
+  OL &operator=(const OL &);
+  int Field;
+};
+OL::OL(const OL &Other) : Field(Other.Field) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default' to define a trivial copy constructor [modernize-use-equals-default]
+// CHECK-FIXES: OL::OL(const OL &Other)  = default;
+OL &OL::operator=(const OL &Other) {
+  Field = Other.Field;
+  return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:9: warning: use '= default' to define a trivial copy-assignment operator [modernize-use-equals-default]
+// CHECK-FIXES: OL &OL::operator=(const OL &Other) = default;
+
+// Inline.
+struct IL {
+  IL(const IL &Other) : Field(Other.Field) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: IL(const IL &Other)  = default;
+  IL &operator=(const IL &Other) {
+    Field = Other.Field;
+    return *this;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: use '= default'
+  // CHECK-FIXES: IL &operator=(const IL &Other) = default;
+  int Field;
+};
+
+// Wrong type.
+struct WT {
+  WT(const IL &Other) {}
+  WT &operator=(const IL &);
+};
+WT &WT::operator=(const IL &Other) { return *this; }
+
+// Qualifiers.
+struct Qual {
+  Qual(const Qual &Other) : Field(Other.Field), Volatile(Other.Volatile),
+                            Mutable(Other.Mutable), Reference(Other.Reference),
+                            Const(Other.Const) {}
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use '= default'
+  // CHECK-FIXES: Qual(const Qual &Other)
+  // CHECK-FIXES:                          = default;
+
+  int Field;
+  volatile char Volatile;
+  mutable bool Mutable;
+  const OL &Reference; // This makes this class non-assignable.
+  const IL Const;      // This also makes this class non-assignable.
+  static int Static;
+};
+
+// Wrong init arguments.
+struct WI {
+  WI(const WI &Other) : Field1(Other.Field1), Field2(Other.Field1) {}
+  WI &operator=(const WI &);
+  int Field1, Field2;
+};
+WI &WI::operator=(const WI &Other) {
+  Field1 = Other.Field1;
+  Field2 = Other.Field1;
+  return *this;
+}
+
+// Missing field.
+struct MF {
+  MF(const MF &Other) : Field1(Other.Field1), Field2(Other.Field2) {}
+  MF &operator=(const MF &);
+  int Field1, Field2, Field3;
+};
+MF &MF::operator=(const MF &Other) {
+  Field1 = Other.Field1;
+  Field2 = Other.Field2;
+  return *this;
+}
+
+struct Comments {
+  Comments(const Comments &Other)
+      /* don't delete */ : /* this comment */ Field(Other.Field) {}
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
+  // CHECK-FIXES: /* don't delete */  = default;
+  int Field;
+};
+
+struct MoreComments {
+  MoreComments(const MoreComments &Other) /* this comment is OK */
+      : Field(Other.Field) {}
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
+  // CHECK-FIXES: MoreComments(const MoreComments &Other) /* this comment is OK */
+  // CHECK-FIXES-NEXT: = default;
+  int Field;
+};
+
+struct ColonInComment {
+  ColonInComment(const ColonInComment &Other) /* : */ : Field(Other.Field) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: ColonInComment(const ColonInComment &Other) /* : */  = default;
+  int Field;
+};
+
+// No members or bases (in particular, no colon).
+struct Empty {
+  Empty(const Empty &Other) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: Empty(const Empty &Other) = default;
+  Empty &operator=(const Empty &);
+};
+Empty &Empty::operator=(const Empty &Other) { return *this; }
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use '= default'
+// CHECK-FIXES: Empty &Empty::operator=(const Empty &Other) = default;
+
+// Bit fields.
+struct BF {
+  BF() = default;
+  BF(const BF &Other) : Field1(Other.Field1), Field2(Other.Field2), Field3(Other.Field3),
+                        Field4(Other.Field4) {}
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
+  // CHECK-FIXES: BF(const BF &Other) {{$}}
+  // CHECK-FIXES:                     = default;
+  BF &operator=(const BF &);
+
+  unsigned Field1 : 3;
+  int : 7;
+  char Field2 : 6;
+  int : 0;
+  int Field3 : 24;
+  unsigned char Field4;
+};
+BF &BF::operator=(const BF &Other) {
+  Field1 = Other.Field1;
+  Field2 = Other.Field2;
+  Field3 = Other.Field3;
+  Field4 = Other.Field4;
+  return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-7]]:9: warning: use '= default'
+// CHECK-FIXES: BF &BF::operator=(const BF &Other) = default;
+
+// Base classes.
+struct BC : IL, OL, BF {
+  BC(const BC &Other) : IL(Other), OL(Other), BF(Other) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: BC(const BC &Other)  = default;
+  BC &operator=(const BC &Other);
+};
+BC &BC::operator=(const BC &Other) {
+  IL::operator=(Other);
+  OL::operator=(Other);
+  BF::operator=(Other);
+  return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-6]]:9: warning: use '= default'
+// CHECK-FIXES: BC &BC::operator=(const BC &Other) = default;
+
+// Base classes with member.
+struct BCWM : IL, OL {
+  BCWM(const BCWM &Other) : IL(Other), OL(Other), Bf(Other.Bf) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: BCWM(const BCWM &Other)  = default;
+  BCWM &operator=(const BCWM &);
+  BF Bf;
+};
+BCWM &BCWM::operator=(const BCWM &Other) {
+  IL::operator=(Other);
+  OL::operator=(Other);
+  Bf = Other.Bf;
+  return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-6]]:13: warning: use '= default'
+// CHECK-FIXES: BCWM &BCWM::operator=(const BCWM &Other) = default;
+
+// Missing base class.
+struct MBC : IL, OL, BF {
+  MBC(const MBC &Other) : IL(Other), OL(Other) {}
+  MBC &operator=(const MBC &);
+};
+MBC &MBC::operator=(const MBC &Other) {
+  IL::operator=(Other);
+  OL::operator=(Other);
+  return *this;
+}
+
+// Base classes, incorrect parameter.
+struct BCIP : BCWM, BF {
+  BCIP(const BCIP &Other) : BCWM(Other), BF(Other.Bf) {}
+  BCIP &operator=(const BCIP &);
+};
+BCIP &BCIP::operator=(const BCIP &Other) {
+  BCWM::operator=(Other);
+  BF::operator=(Other.Bf);
+  return *this;
+}
+
+// Virtual base classes.
+struct VA : virtual OL {};
+struct VB : virtual OL {};
+struct VBC : VA, VB, virtual OL {
+  // OL is the first thing that is going to be initialized, despite the fact
+  // that it is the last in the list of bases, because it is virtual and there
+  // is a virtual OL at the beginning of VA (which is the same).
+  VBC(const VBC &Other) : OL(Other), VA(Other), VB(Other) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: VBC(const VBC &Other)  = default;
+  VBC &operator=(const VBC &Other);
+};
+VBC &VBC::operator=(const VBC &Other) {
+  OL::operator=(Other);
+  VA::operator=(Other);
+  VB::operator=(Other);
+  return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-6]]:11: warning: use '= default'
+// CHECK-FIXES: VBC &VBC::operator=(const VBC &Other) = default;
+
+// Indirect base.
+struct IB : VBC {
+  IB(const IB &Other) : OL(Other), VBC(Other) {}
+  IB &operator=(const IB &);
+};
+IB &IB::operator=(const IB &Other) {
+  OL::operator=(Other);
+  VBC::operator=(Other);
+  return *this;
+}
+
+// Class template.
+template <class T>
+struct Template {
+  Template() = default;
+  Template(const Template &Other) : Field(Other.Field) {}
+  Template &operator=(const Template &Other);
+  void foo(const T &t);
+  int Field;
+};
+template <class T>
+Template<T> &Template<T>::operator=(const Template<T> &Other) {
+  Field = Other.Field;
+  return *this;
+}
+Template<int> T1;
+
+// Dependent types.
+template <class T>
+struct DT1 {
+  DT1() = default;
+  DT1(const DT1 &Other) : Field(Other.Field) {}
+  DT1 &operator=(const DT1 &);
+  T Field;
+};
+template <class T>
+DT1<T> &DT1<T>::operator=(const DT1<T> &Other) {
+  Field = Other.Field;
+  return *this;
+}
+DT1<int> Dt1;
+
+template <class T>
+struct DT2 {
+  DT2() = default;
+  DT2(const DT2 &Other) : Field(Other.Field), Dependent(Other.Dependent) {}
+  DT2 &operator=(const DT2 &);
+  T Field;
+  typename T::TT Dependent;
+};
+template <class T>
+DT2<T> &DT2<T>::operator=(const DT2<T> &Other) {
+  Field = Other.Field;
+  Dependent = Other.Dependent;
+  return *this;
+}
+struct T {
+  typedef int TT;
+};
+DT2<T> Dt2;
+
+// Default arguments.
+struct DA {
+  DA(int Int);
+  DA(const DA &Other = DA(0)) : Field1(Other.Field1), Field2(Other.Field2) {}
+  DA &operator=(const DA &);
+  int Field1;
+  char Field2;
+};
+// Overloaded operator= cannot have a default argument.
+DA &DA::operator=(const DA &Other) {
+  Field1 = Other.Field1;
+  Field2 = Other.Field2;
+  return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:9: warning: use '= default'
+// CHECK-FIXES: DA &DA::operator=(const DA &Other) = default;
+
+struct DA2 {
+  // Can be used as copy-constructor but cannot be explicitly defaulted.
+  DA2(const DA &Other, int Def = 0) {}
+};
+
+// Default initialization.
+struct DI {
+  DI(const DI &Other) : Field1(Other.Field1), Field2(Other.Field2) {}
+  int Field1;
+  int Field2 = 0;
+  int Fiedl3;
+};
+
+// Statement inside body.
+void foo();
+struct SIB {
+  SIB(const SIB &Other) : Field(Other.Field) { foo(); }
+  SIB &operator=(const SIB &);
+  int Field;
+};
+SIB &SIB::operator=(const SIB &Other) {
+  Field = Other.Field;
+  foo();
+  return *this;
+}
+
+// Comment inside body.
+struct CIB {
+  CIB(const CIB &Other) : Field(Other.Field) { /* Don't erase this */
+  }
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
+  CIB &operator=(const CIB &);
+  int Field;
+};
+CIB &CIB::operator=(const CIB &Other) {
+  Field = Other.Field;
+  // FIXME: don't erase this comment.
+  return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:11: warning: use '= default'
+// CHECK-FIXES: CIB &CIB::operator=(const CIB &Other) = default;
+
+// Take non-const reference as argument.
+struct NCRef {
+  NCRef(NCRef &Other) : Field1(Other.Field1), Field2(Other.Field2) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: NCRef(NCRef &Other)  = default;
+  NCRef &operator=(NCRef &);
+  int Field1, Field2;
+};
+NCRef &NCRef::operator=(NCRef &Other) {
+  Field1 = Other.Field1;
+  Field2 = Other.Field2;
+  return *this;
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:15: warning: use '= default'
+// CHECK-FIXES: NCRef &NCRef::operator=(NCRef &Other) = default;
+
+// Already defaulted.
+struct IAD {
+  IAD(const IAD &Other) = default;
+  IAD &operator=(const IAD &Other) = default;
+};
+
+struct OAD {
+  OAD(const OAD &Other);
+  OAD &operator=(const OAD &);
+};
+OAD::OAD(const OAD &Other) = default;
+OAD &OAD::operator=(const OAD &Other) = default;
+
+// Deleted.
+struct ID {
+  ID(const ID &Other) = delete;
+  ID &operator=(const ID &Other) = delete;
+};
+
+// Non-reference parameter.
+struct NRef {
+  NRef &operator=(NRef Other);
+  int Field1;
+};
+NRef &NRef::operator=(NRef Other) {
+  Field1 = Other.Field1;
+  return *this;
+}
+
+// RValue reference parameter.
+struct RVR {
+  RVR(RVR &&Other) {}
+  RVR &operator=(RVR &&);
+};
+RVR &RVR::operator=(RVR &&Other) { return *this; }
+
+// Similar function.
+struct SF {
+  SF &foo(const SF &);
+  int Field1;
+};
+SF &SF::foo(const SF &Other) {
+  Field1 = Other.Field1;
+  return *this;
+}
+
+// No return.
+struct NR {
+  NR &operator=(const NR &);
+};
+NR &NR::operator=(const NR &Other) {}
+
+// Return misplaced.
+struct RM {
+  RM &operator=(const RM &);
+  int Field;
+};
+RM &RM::operator=(const RM &Other) {
+  return *this;
+  Field = Other.Field;
+}
+
+// Wrong return value.
+struct WRV {
+  WRV &operator=(WRV &);
+};
+WRV &WRV::operator=(WRV &Other) {
+  return Other;
+}
+
+// Wrong return type.
+struct WRT : IL {
+  IL &operator=(const WRT &);
+};
+IL &WRT::operator=(const WRT &Other) {
+  return *this;
+}
+
+// Try-catch.
+struct ITC {
+  ITC(const ITC &Other)
+  try : Field(Other.Field) {
+  } catch (...) {
+  }
+  ITC &operator=(const ITC &Other) try {
+    Field = Other.Field;
+  } catch (...) {
+  }
+  int Field;
+};
+
+struct OTC {
+  OTC(const OTC &);
+  OTC &operator=(const OTC &);
+  int Field;
+};
+OTC::OTC(const OTC &Other) try : Field(Other.Field) {
+} catch (...) {
+}
+OTC &OTC::operator=(const OTC &Other) try {
+  Field = Other.Field;
+} catch (...) {
+}
+
+// FIXME: the check is not able to detect exception specification.
+// noexcept(true).
+struct NET {
+  // This is the default.
+  //NET(const NET &Other) noexcept {}
+  NET &operator=(const NET &Other) noexcept;
+};
+//NET &NET::operator=(const NET &Other) noexcept { return *this; }
+
+// noexcept(false).
+struct NEF {
+  // This is the default.
+  //NEF(const NEF &Other) noexcept(false) {}
+  NEF &operator=(const NEF &Other) noexcept(false);
+};
+//NEF &NEF::operator=(const NEF &Other) noexcept(false) { return *this; }
+
+#define STRUCT_WITH_COPY_CONSTRUCT(_base, _type) \
+  struct _type {                                 \
+    _type(const _type &v) : value(v.value) {}    \
+    _base value;                                 \
+  };
+
+STRUCT_WITH_COPY_CONSTRUCT(unsigned char, Hex8CopyConstruct)
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial copy constructor
+// CHECK-MESSAGES: :[[@LINE-6]]:44: note:
+
+#define STRUCT_WITH_COPY_ASSIGN(_base, _type) \
+  struct _type {                              \
+    _type &operator=(const _type &rhs) {      \
+      value = rhs.value;                      \
+      return *this;                           \
+    }                                         \
+    _base value;                              \
+  };
+
+STRUCT_WITH_COPY_ASSIGN(unsigned char, Hex8CopyAssign)
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial copy-assignment operator
+// CHECK-MESSAGES: :[[@LINE-9]]:40: note:
+
+// Use of braces
+struct UOB{
+  UOB(const UOB &Other):j{Other.j}{}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' to define a trivial copy constructor [modernize-use-equals-default]
+  // CHECK-FIXES: UOB(const UOB &Other)= default;
+  int j;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-delayed.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-delayed.cpp
new file mode 100644
index 0000000..953d88a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-delayed.cpp
@@ -0,0 +1,8 @@
+// RUN: clang-tidy %s -checks=-*,modernize-use-equals-default -- -std=c++11 -fdelayed-template-parsing -fexceptions | count 0
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+
+template <typename Ty>
+struct S {
+  S<Ty>& operator=(const S<Ty>&) { return *this; }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-macros.cpp
new file mode 100644
index 0000000..2277a86
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default-macros.cpp
@@ -0,0 +1,13 @@
+// RUN: %check_clang_tidy %s modernize-use-equals-default %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-equals-default.IgnoreMacros, value: 0}]}" \
+// RUN:   -- -std=c++11
+
+#define STRUCT_WITH_DEFAULT(_base, _type) \
+  struct _type {                          \
+    _type() {}                            \
+    _base value;                          \
+  };
+
+STRUCT_WITH_DEFAULT(unsigned char, InMacro)
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial default constructor
+// CHECK-MESSAGES: :[[@LINE-6]]:13: note:
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default.cpp
new file mode 100644
index 0000000..8fa15ff
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-default.cpp
@@ -0,0 +1,207 @@
+// RUN: %check_clang_tidy %s modernize-use-equals-default %t -- -- -std=c++11 -fno-delayed-template-parsing  -fexceptions
+
+// Out of line definition.
+class OL {
+public:
+  OL();
+  ~OL();
+};
+
+OL::OL() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default' to define a trivial default constructor [modernize-use-equals-default]
+// CHECK-FIXES: OL::OL() = default;
+OL::~OL() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default' to define a trivial destructor [modernize-use-equals-default]
+// CHECK-FIXES: OL::~OL() = default;
+
+// Inline definitions.
+class IL {
+public:
+  IL() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: IL() = default;
+  ~IL() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: ~IL() = default;
+};
+
+// Non-empty body.
+void f();
+class NE {
+public:
+  NE() { f(); }
+  ~NE() { f(); }
+};
+
+// Initializer or arguments.
+class IA {
+public:
+  // Constructor with initializer.
+  IA() : Field(5) {}
+  // Constructor with arguments.
+  IA(int Arg1, int Arg2) {}
+  int Field;
+};
+
+// Default member initializer
+class DMI {
+public:
+  DMI() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: DMI() = default;
+  int Field = 5;
+};
+
+// Class member
+class CM {
+public:
+  CM() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: CM() = default;
+  OL o;
+};
+
+// Private constructor/destructor.
+class Priv {
+  Priv() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: Priv() = default;
+  ~Priv() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: ~Priv() = default;
+};
+
+// struct.
+struct ST {
+  ST() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: ST() = default;
+  ~ST() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: ST() = default;
+};
+
+// Deleted constructor/destructor.
+class Del {
+public:
+  Del() = delete;
+  ~Del() = delete;
+};
+
+// Do not remove other keywords.
+class KW {
+public:
+  explicit KW() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use '= default'
+  // CHECK-FIXES: explicit KW() = default;
+  virtual ~KW() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use '= default'
+  // CHECK-FIXES: virtual ~KW() = default;
+};
+
+// Nested class.
+struct N {
+  struct NN {
+    NN() {}
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default'
+    // CHECK-FIXES: NN() = default;
+    ~NN() {}
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default'
+    // CHECK-FIXES: ~NN() = default;
+  };
+  int Int;
+};
+
+// Class template.
+template <class T>
+class Temp {
+public:
+  Temp() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: Temp() = default;
+  ~Temp() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: ~Temp() = default;
+};
+
+// Class template out of line with explicit instantiation.
+template <class T>
+class TempODef {
+public:
+  TempODef();
+  ~TempODef();
+};
+
+template <class T>
+TempODef<T>::TempODef() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use '= default'
+// CHECK-FIXES: TempODef<T>::TempODef() = default;
+template <class T>
+TempODef<T>::~TempODef() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use '= default'
+// CHECK-FIXES: TempODef<T>::~TempODef() = default;
+
+template class TempODef<int>;
+template class TempODef<double>;
+
+// Non user-provided constructor/destructor.
+struct Imp {
+  int Int;
+};
+void g() {
+  Imp *PtrImp = new Imp();
+  PtrImp->~Imp();
+  delete PtrImp;
+}
+
+// Already using default.
+struct IDef {
+  IDef() = default;
+  ~IDef() = default;
+};
+struct ODef {
+  ODef();
+  ~ODef();
+};
+ODef::ODef() = default;
+ODef::~ODef() = default;
+
+// Delegating constructor and overriden destructor.
+struct DC : KW {
+  DC() : KW() {}
+  ~DC() override {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: ~DC() override = default;
+};
+
+struct Comments {
+  Comments() {
+    // Don't erase comments inside the body.
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use '= default'
+  ~Comments() {
+    // Don't erase comments inside the body.
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use '= default'
+};
+
+// Try-catch.
+struct ITC {
+  ITC() try {} catch(...) {}
+  ~ITC() try {} catch(...) {}
+};
+
+struct OTC {
+  OTC();
+  ~OTC();
+};
+OTC::OTC() try {} catch(...) {}
+OTC::~OTC() try {} catch(...) {}
+
+#define STRUCT_WITH_DEFAULT(_base, _type) \
+  struct _type {                          \
+    _type() {}                            \
+    _base value;                          \
+  };
+
+STRUCT_WITH_DEFAULT(unsigned char, InMacro)
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-delete.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-delete.cpp
new file mode 100644
index 0000000..6ab2ae4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-equals-delete.cpp
@@ -0,0 +1,187 @@
+// RUN: %check_clang_tidy %s modernize-use-equals-delete %t
+
+struct PositivePrivate {
+private:
+  PositivePrivate();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: PositivePrivate() = delete;
+  PositivePrivate(const PositivePrivate &);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: PositivePrivate(const PositivePrivate &) = delete;
+  PositivePrivate &operator=(const PositivePrivate &);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: PositivePrivate &operator=(const PositivePrivate &) = delete;
+  PositivePrivate(PositivePrivate &&);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: PositivePrivate(PositivePrivate &&) = delete;
+  PositivePrivate &operator=(PositivePrivate &&);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: PositivePrivate &operator=(PositivePrivate &&) = delete;
+  ~PositivePrivate();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: ~PositivePrivate() = delete;
+};
+
+template<typename T>
+struct PositivePrivateTemplate {
+private:
+  PositivePrivateTemplate();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: PositivePrivateTemplate() = delete;
+  PositivePrivateTemplate(const PositivePrivateTemplate &);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: PositivePrivateTemplate(const PositivePrivateTemplate &) = delete;
+  PositivePrivateTemplate &operator=(const PositivePrivateTemplate &);
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: PositivePrivateTemplate &operator=(const PositivePrivateTemplate &) = delete;
+  PositivePrivateTemplate(PositivePrivateTemplate &&);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: PositivePrivateTemplate(PositivePrivateTemplate &&) = delete;
+  PositivePrivateTemplate &operator=(PositivePrivateTemplate &&);
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: PositivePrivateTemplate &operator=(PositivePrivateTemplate &&) = delete;
+  ~PositivePrivateTemplate();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: ~PositivePrivateTemplate() = delete;
+};
+
+template struct PositivePrivateTemplate<int>;
+template struct PositivePrivateTemplate<char>;
+
+struct NegativePublic {
+  NegativePublic(const NegativePublic &);
+};
+
+struct NegativeProtected {
+protected:
+  NegativeProtected(const NegativeProtected &);
+};
+
+struct PositiveInlineMember {
+  int foo() { return 0; }
+
+private:
+  PositiveInlineMember(const PositiveInlineMember &);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: PositiveInlineMember(const PositiveInlineMember &) = delete;
+};
+
+struct PositiveOutOfLineMember {
+  int foo();
+
+private:
+  PositiveOutOfLineMember(const PositiveOutOfLineMember &);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: PositiveOutOfLineMember(const PositiveOutOfLineMember &) = delete;
+};
+
+int PositiveOutOfLineMember::foo() { return 0; }
+
+struct PositiveAbstractMember {
+  virtual int foo() = 0;
+
+private:
+  PositiveAbstractMember(const PositiveAbstractMember &);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: PositiveAbstractMember(const PositiveAbstractMember &) = delete;
+};
+
+struct NegativeMemberNotImpl {
+  int foo();
+
+private:
+  NegativeMemberNotImpl(const NegativeMemberNotImpl &);
+};
+
+struct NegativeStaticMemberNotImpl {
+  static int foo();
+
+private:
+  NegativeStaticMemberNotImpl(const NegativeStaticMemberNotImpl &);
+};
+
+struct NegativeInline {
+private:
+  NegativeInline(const NegativeInline &) {}
+};
+
+struct NegativeOutOfLine {
+private:
+  NegativeOutOfLine(const NegativeOutOfLine &);
+};
+
+NegativeOutOfLine::NegativeOutOfLine(const NegativeOutOfLine &) {}
+
+struct NegativeConstructNotImpl {
+  NegativeConstructNotImpl();
+
+private:
+  NegativeConstructNotImpl(const NegativeConstructNotImpl &);
+};
+
+struct PositiveDefaultedConstruct {
+  PositiveDefaultedConstruct() = default;
+
+private:
+  PositiveDefaultedConstruct(const PositiveDefaultedConstruct &);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: PositiveDefaultedConstruct(const PositiveDefaultedConstruct &) = delete;
+};
+
+struct PositiveDeletedConstruct {
+  PositiveDeletedConstruct() = delete;
+
+private:
+  PositiveDeletedConstruct(const PositiveDeletedConstruct &);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= delete' to prohibit calling of a special member function [modernize-use-equals-delete]
+  // CHECK-FIXES: PositiveDeletedConstruct(const PositiveDeletedConstruct &) = delete;
+};
+
+struct NegativeDefaulted {
+private:
+  NegativeDefaulted(const NegativeDefaulted &) = default;
+};
+
+struct PrivateDeleted {
+private:
+  PrivateDeleted(const PrivateDeleted &) = delete;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: deleted member function should be public [modernize-use-equals-delete]
+};
+
+struct ProtectedDeleted {
+protected:
+  ProtectedDeleted(const ProtectedDeleted &) = delete;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: deleted member function should be public [modernize-use-equals-delete]
+};
+
+struct PublicDeleted {
+public:
+  PublicDeleted(const PublicDeleted &) = delete;
+};
+
+#define M1                                                         \
+  struct PrivateDeletedMacro {                                     \
+  private:                                                         \
+    PrivateDeletedMacro(const PrivateDeletedMacro &) = delete;     \
+  };                                                               \
+  struct ProtectedDeletedMacro {                                   \
+  protected:                                                       \
+    ProtectedDeletedMacro(const ProtectedDeletedMacro &) = delete; \
+  }
+
+M1;
+
+#define DISALLOW_COPY_AND_ASSIGN(name) \
+  name(const name &) = delete;         \
+  void operator=(const name &) = delete
+
+struct PrivateDeletedMacro2 {
+private:
+  DISALLOW_COPY_AND_ASSIGN(PrivateDeletedMacro2);
+};
+
+struct ProtectedDeletedMacro2 {
+protected:
+  DISALLOW_COPY_AND_ASSIGN(ProtectedDeletedMacro2);
+};
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept-macro.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept-macro.cpp
new file mode 100644
index 0000000..3948b66
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept-macro.cpp
@@ -0,0 +1,36 @@
+// RUN: %check_clang_tidy %s modernize-use-noexcept %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-noexcept.ReplacementString, value: 'NOEXCEPT'}]}" \
+// RUN:   -- -std=c++11 -fexceptions
+
+// Example definition of NOEXCEPT -- simplified test to see if noexcept is supported.
+#if (__has_feature(cxx_noexcept))
+#define NOEXCEPT noexcept
+#else
+#define NOEXCEPT throw()
+#endif
+
+void bar() throw() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'NOEXCEPT' instead [modernize-use-noexcept]
+// CHECK-FIXES: void bar() NOEXCEPT {}
+
+// Should not trigger a FixItHint, since macros only support noexcept, and this
+// case throws.
+class A {};
+class B {};
+void foobar() throw(A, B);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: dynamic exception specification 'throw(A, B)' is deprecated; consider removing it instead [modernize-use-noexcept]
+
+// Should not trigger a replacement.
+void foo() noexcept(true);
+
+struct Z {
+  void operator delete(void *ptr) throw();
+  void operator delete[](void *ptr) throw(int);
+  ~Z() throw(int) {}
+};
+// CHECK-MESSAGES: :[[@LINE-4]]:35: warning: dynamic exception specification 'throw()' is deprecated; consider using 'NOEXCEPT' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:37: warning: dynamic exception specification 'throw(int)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:8: warning: dynamic exception specification 'throw(int)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void operator delete(void *ptr) NOEXCEPT;
+// CHECK-FIXES: void operator delete[](void *ptr) throw(int);
+// CHECK-FIXES: ~Z() throw(int) {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept-opt.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept-opt.cpp
new file mode 100644
index 0000000..85a83c8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept-opt.cpp
@@ -0,0 +1,88 @@
+// RUN: %check_clang_tidy %s modernize-use-noexcept %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-noexcept.UseNoexceptFalse, value: 0}]}" \
+// RUN:   -- -std=c++11 -fexceptions
+
+class A {};
+class B {};
+
+void foo() throw();
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void foo() noexcept;
+
+void bar() throw(...);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw(...)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void bar() ;
+
+void k() throw(int(int));
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: dynamic exception specification 'throw(int(int))' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void k() ;
+
+void foobar() throw(A, B)
+{}
+// CHECK-MESSAGES: :[[@LINE-2]]:15: warning: dynamic exception specification 'throw(A, B)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void foobar()
+
+void baz(int = (throw A(), 0)) throw(A, B) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: dynamic exception specification 'throw(A, B)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void baz(int = (throw A(), 0)) {}
+
+void g(void (*fp)(void) throw());
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void g(void (*fp)(void) noexcept);
+
+void f(void (*fp)(void) throw(int)) throw(char);
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: dynamic exception specification 'throw(int)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:37: warning: dynamic exception specification 'throw(char)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void f(void (*fp)(void) ) ;
+
+#define THROW throw
+void h(void (*fp)(void) THROW(int)) THROW(char);
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: dynamic exception specification 'THROW(int)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:37: warning: dynamic exception specification 'THROW(char)' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void h(void (*fp)(void) ) ;
+
+void j() throw(int(int) throw(void(void) throw(int)));
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: dynamic exception specification 'throw(int(int) throw(void(void) throw(int)))' is deprecated; consider removing it instead [modernize-use-noexcept]
+// CHECK-FIXES: void j() ;
+
+class Y {
+  Y() throw() = default;
+};
+// CHECK-MESSAGES: :[[@LINE-2]]:7: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: Y() noexcept = default;
+
+struct Z {
+  void operator delete(void *ptr) throw();
+  void operator delete[](void *ptr) throw(int);
+  ~Z() throw(int) {}
+};
+// CHECK-MESSAGES: :[[@LINE-4]]:35: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:37: warning: dynamic exception specification 'throw(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:8: warning: dynamic exception specification 'throw(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void operator delete(void *ptr) noexcept;
+// CHECK-FIXES: void operator delete[](void *ptr) noexcept(false);
+// CHECK-FIXES: ~Z() noexcept(false) {}
+
+struct S {
+  void f() throw();
+};
+void f(void (S::*)() throw());
+// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:22: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void f() noexcept;
+// CHECK-FIXES: void f(void (S::*)() noexcept);
+
+typedef void (*fp)(void (*fp2)(int) throw());
+// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: typedef void (*fp)(void (*fp2)(int) noexcept);
+
+// Should not trigger a replacement.
+void titi() noexcept {}
+void toto() noexcept(true) {}
+
+// Should not trigger a replacement.
+void bad()
+#if !__has_feature(cxx_noexcept)
+    throw()
+#endif
+  ;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept.cpp
new file mode 100644
index 0000000..58c764a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-noexcept.cpp
@@ -0,0 +1,104 @@
+// RUN: %check_clang_tidy %s modernize-use-noexcept %t -- \
+// RUN:   -- -std=c++11 -fexceptions
+
+class A {};
+class B {};
+
+void foo() throw();
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void foo() noexcept;
+
+template <typename T>
+void foo() throw();
+void footest() { foo<int>(); foo<double>(); }
+// CHECK-MESSAGES: :[[@LINE-2]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void foo() noexcept;
+
+void bar() throw(...);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw(...)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void bar() noexcept(false);
+
+void k() throw(int(int));
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: dynamic exception specification 'throw(int(int))' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void k() noexcept(false);
+
+void foobar() throw(A, B)
+{}
+// CHECK-MESSAGES: :[[@LINE-2]]:15: warning: dynamic exception specification 'throw(A, B)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void foobar() noexcept(false)
+
+void baz(int = (throw A(), 0)) throw(A, B) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: dynamic exception specification 'throw(A, B)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void baz(int = (throw A(), 0)) noexcept(false) {}
+
+void g(void (*fp)(void) throw());
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void g(void (*fp)(void) noexcept);
+
+void f(void (*fp)(void) throw(int)) throw(char);
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: dynamic exception specification 'throw(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:37: warning: dynamic exception specification 'throw(char)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void f(void (*fp)(void) noexcept(false)) noexcept(false);
+
+#define THROW throw
+void h(void (*fp)(void) THROW(int)) THROW(char);
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: dynamic exception specification 'THROW(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:37: warning: dynamic exception specification 'THROW(char)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void h(void (*fp)(void) noexcept(false)) noexcept(false);
+
+void j() throw(int(int) throw(void(void) throw(int)));
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: dynamic exception specification 'throw(int(int) throw(void(void) throw(int)))' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void j() noexcept(false);
+
+class Y {
+  Y() throw() = default;
+};
+// CHECK-MESSAGES: :[[@LINE-2]]:7: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: Y() noexcept = default;
+
+struct Z {
+  void operator delete(void *ptr) throw();
+  void operator delete[](void *ptr) throw(int);
+  ~Z() throw(int) {}
+};
+// CHECK-MESSAGES: :[[@LINE-4]]:35: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:37: warning: dynamic exception specification 'throw(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:8: warning: dynamic exception specification 'throw(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void operator delete(void *ptr) noexcept;
+// CHECK-FIXES: void operator delete[](void *ptr) noexcept(false);
+// CHECK-FIXES: ~Z() noexcept(false) {}
+
+struct S {
+  void f() throw();
+};
+void f(void (S::*)() throw());
+// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:22: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void f() noexcept;
+// CHECK-FIXES: void f(void (S::*)() noexcept);
+
+template <typename T>
+struct ST {
+  void foo() throw();
+};
+template <typename T>
+void ft(void (ST<T>::*)() throw());
+// CHECK-MESSAGES: :[[@LINE-4]]:14: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:27: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void foo() noexcept;
+// CHECK-FIXES: void ft(void (ST<T>::*)() noexcept);
+
+typedef void (*fp)(void (*fp2)(int) throw());
+// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: typedef void (*fp)(void (*fp2)(int) noexcept);
+
+// Should not trigger a replacement.
+void titi() noexcept {}
+void toto() noexcept(true) {}
+
+// Should not trigger a replacement.
+void bad()
+#if !__has_feature(cxx_noexcept)
+    throw()
+#endif
+  ;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr-basic.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr-basic.cpp
new file mode 100644
index 0000000..7a953a7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr-basic.cpp
@@ -0,0 +1,361 @@
+// RUN: %check_clang_tidy %s modernize-use-nullptr %t -- -- \
+// RUN:   -std=c++98 -Wno-non-literal-null-conversion
+//
+// Some parts of the test (e.g. assignment of `const int` to `int *`) fail in
+// C++11, so we need to run the test in C++98 mode.
+
+const unsigned int g_null = 0;
+#define NULL 0
+
+void test_assignment() {
+  int *p1 = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr [modernize-use-nullptr]
+  // CHECK-FIXES: int *p1 = nullptr;
+  p1 = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr
+  // CHECK-FIXES: p1 = nullptr;
+
+  int *p2 = NULL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr
+  // CHECK-FIXES: int *p2 = nullptr;
+
+  p2 = p1;
+  // CHECK-FIXES: p2 = p1;
+
+  const int null = 0;
+  int *p3 = null;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr
+  // CHECK-FIXES: int *p3 = nullptr;
+
+  p3 = NULL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr
+  // CHECK-FIXES: p3 = nullptr;
+
+  int *p4 = p3;
+  // CHECK-FIXES: int *p4 = p3;
+
+  p4 = null;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr
+  // CHECK-FIXES: p4 = nullptr;
+
+  int i1 = 0;
+
+  int i2 = NULL;
+
+  int i3 = null;
+
+  int *p5, *p6, *p7;
+  p5 = p6 = p7 = NULL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+  // CHECK-FIXES: p5 = p6 = p7 = nullptr;
+}
+
+struct Foo {
+  Foo(int *p = NULL) : m_p1(p) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+  // CHECK-FIXES: Foo(int *p = nullptr) : m_p1(p) {}
+
+  void bar(int *p = 0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use nullptr
+  // CHECK-FIXES: void bar(int *p = nullptr) {}
+
+  void baz(int i = 0) {}
+
+  int *m_p1;
+  static int *m_p2;
+};
+
+int *Foo::m_p2 = NULL;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+// CHECK-FIXES: int *Foo::m_p2 = nullptr;
+
+template <typename T>
+struct Bar {
+  Bar(T *p) : m_p(p) {
+    m_p = static_cast<T*>(NULL);
+    // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr
+    // CHECK-FIXES: m_p = static_cast<T*>(nullptr);
+
+    m_p = static_cast<T*>(reinterpret_cast<int*>((void*)NULL));
+    // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr
+    // CHECK-FIXES: m_p = static_cast<T*>(nullptr);
+
+    m_p = static_cast<T*>(p ? p : static_cast<void*>(g_null));
+    // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: use nullptr
+    // CHECK-FIXES: m_p = static_cast<T*>(p ? p : static_cast<void*>(nullptr));
+
+    T *p2 = static_cast<T*>(reinterpret_cast<int*>((void*)NULL));
+    // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr
+    // CHECK-FIXES: T *p2 = static_cast<T*>(nullptr);
+
+    m_p = NULL;
+    // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use nullptr
+    // CHECK-FIXES: m_p = nullptr;
+
+    int i = static_cast<int>(0.f);
+    T *i2 = static_cast<int>(0.f);
+    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr
+    // CHECK-FIXES: T *i2 = nullptr;
+  }
+
+  T *m_p;
+};
+
+struct Baz {
+  Baz() : i(0) {}
+  int i;
+};
+
+void test_cxx_cases() {
+  Foo f(g_null);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+  // CHECK-FIXES: Foo f(nullptr);
+
+  f.bar(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+  // CHECK-FIXES: f.bar(nullptr);
+
+  f.baz(g_null);
+
+  f.m_p1 = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+  // CHECK-FIXES: f.m_p1 = nullptr;
+
+  Bar<int> b(g_null);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
+  // CHECK-FIXES: Bar<int> b(nullptr);
+
+  Baz b2;
+  int Baz::*memptr(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use nullptr
+  // CHECK-FIXES: int Baz::*memptr(nullptr);
+
+  memptr = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+  // CHECK-FIXES: memptr = nullptr;
+}
+
+void test_function_default_param1(void *p = 0);
+// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr
+// CHECK-FIXES: void test_function_default_param1(void *p = nullptr);
+
+void test_function_default_param2(void *p = NULL);
+// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr
+// CHECK-FIXES: void test_function_default_param2(void *p = nullptr);
+
+void test_function_default_param3(void *p = g_null);
+// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr
+// CHECK-FIXES: void test_function_default_param3(void *p = nullptr);
+
+void test_function(int *p) {}
+
+void test_function_no_ptr_param(int i) {}
+
+void test_function_call() {
+  test_function(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr
+  // CHECK-FIXES: test_function(nullptr);
+
+  test_function(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr
+  // CHECK-FIXES: test_function(nullptr);
+
+  test_function(g_null);
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr
+  // CHECK-FIXES: test_function(nullptr);
+
+  test_function_no_ptr_param(0);
+}
+
+char *test_function_return1() {
+  return 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr
+  // CHECK-FIXES: return nullptr;
+}
+
+void *test_function_return2() {
+  return NULL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr
+  // CHECK-FIXES: return nullptr;
+}
+
+long *test_function_return3() {
+  return g_null;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr
+  // CHECK-FIXES: return nullptr;
+}
+
+int test_function_return4() {
+  return 0;
+}
+
+int test_function_return5() {
+  return NULL;
+}
+
+int test_function_return6() {
+  return g_null;
+}
+
+int *test_function_return_cast1() {
+  return(int)0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+  // CHECK-FIXES: return nullptr;
+}
+
+int *test_function_return_cast2() {
+#define RET return
+  RET(int)0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use nullptr
+  // CHECK-FIXES: RET nullptr;
+#undef RET
+}
+
+// Test parentheses expressions resulting in a nullptr.
+int *test_parentheses_expression1() {
+  return(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr
+  // CHECK-FIXES: return(nullptr);
+}
+
+int *test_parentheses_expression2() {
+  return(int(0.f));
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr
+  // CHECK-FIXES: return(nullptr);
+}
+
+int *test_nested_parentheses_expression() {
+  return((((0))));
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr
+  // CHECK-FIXES: return((((nullptr))));
+}
+
+void *test_parentheses_explicit_cast() {
+  return(static_cast<void*>(0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr
+  // CHECK-FIXES: return(static_cast<void*>(nullptr));
+}
+
+void *test_parentheses_explicit_cast_sequence1() {
+  return(static_cast<void*>(static_cast<int*>((void*)NULL)));
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr
+  // CHECK-FIXES: return(static_cast<void*>(nullptr));
+}
+
+void *test_parentheses_explicit_cast_sequence2() {
+  return(static_cast<void*>(reinterpret_cast<int*>((float*)int(0.f))));
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr
+  // CHECK-FIXES: return(static_cast<void*>(nullptr));
+}
+
+// Test explicit cast expressions resulting in nullptr.
+struct Bam {
+  Bam(int *a) {}
+  Bam(float *a) {}
+  Bam operator=(int *a) { return Bam(a); }
+  Bam operator=(float *a) { return Bam(a); }
+};
+
+void ambiguous_function(int *a) {}
+void ambiguous_function(float *a) {}
+void const_ambiguous_function(const int *p) {}
+void const_ambiguous_function(const float *p) {}
+
+void test_explicit_cast_ambiguous1() {
+  ambiguous_function((int*)0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use nullptr
+  // CHECK-FIXES: ambiguous_function((int*)nullptr);
+}
+
+void test_explicit_cast_ambiguous2() {
+  ambiguous_function((int*)(0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use nullptr
+  // CHECK-FIXES: ambiguous_function((int*)nullptr);
+}
+
+void test_explicit_cast_ambiguous3() {
+  ambiguous_function(static_cast<int*>(reinterpret_cast<int*>((float*)0)));
+  // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: use nullptr
+  // CHECK-FIXES: ambiguous_function(static_cast<int*>(nullptr));
+}
+
+Bam test_explicit_cast_ambiguous4() {
+  return(((int*)(0)));
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr
+  // CHECK-FIXES: return(((int*)nullptr));
+}
+
+void test_explicit_cast_ambiguous5() {
+  // Test for ambiguous overloaded constructors.
+  Bam k((int*)(0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use nullptr
+  // CHECK-FIXES: Bam k((int*)nullptr);
+
+  // Test for ambiguous overloaded operators.
+  k = (int*)0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr
+  // CHECK-FIXES: k = (int*)nullptr;
+}
+
+void test_const_pointers_abiguous() {
+  const_ambiguous_function((int*)0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use nullptr
+  // CHECK-FIXES: const_ambiguous_function((int*)nullptr);
+}
+
+// Test where the implicit cast to null is surrounded by another implict cast
+// with possible explict casts in-between.
+void test_const_pointers() {
+  const int *const_p1 = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr
+  // CHECK-FIXES: const int *const_p1 = nullptr;
+  const int *const_p2 = NULL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr
+  // CHECK-FIXES: const int *const_p2 = nullptr;
+  const int *const_p3 = (int)0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr
+  // CHECK-FIXES: const int *const_p3 = nullptr;
+  const int *const_p4 = (int)0.0f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr
+  // CHECK-FIXES: const int *const_p4 = nullptr;
+  const int *const_p5 = (int*)0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use nullptr
+  // CHECK-FIXES: const int *const_p5 = (int*)nullptr;
+  int *t;
+  const int *const_p6 = static_cast<int*>(t ? t : static_cast<int*>(0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:69: warning: use nullptr
+  // CHECK-FIXES: const int *const_p6 = static_cast<int*>(t ? t : static_cast<int*>(nullptr));
+}
+
+void test_nested_implicit_cast_expr() {
+  int func0(void*, void*);
+  int func1(int, void*, void*);
+
+  (double)func1(0, 0, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use nullptr
+  // CHECK-MESSAGES: :[[@LINE-2]]:23: warning: use nullptr
+  // CHECK-FIXES: (double)func1(0, nullptr, nullptr);
+  (double)func1(func0(0, 0), 0, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use nullptr
+  // CHECK-MESSAGES: :[[@LINE-2]]:26: warning: use nullptr
+  // CHECK-MESSAGES: :[[@LINE-3]]:30: warning: use nullptr
+  // CHECK-MESSAGES: :[[@LINE-4]]:33: warning: use nullptr
+  // CHECK-FIXES: (double)func1(func0(nullptr, nullptr), nullptr, nullptr);
+}
+
+// FIXME: currently, the check doesn't work as it should with templates.
+template<typename T>
+class A {
+ public:
+  A(T *p = NULL) {}
+
+  void f() {
+    Ptr = NULL;
+  }
+  T *Ptr;
+};
+
+template<typename T>
+T *f2(T *a = NULL) {
+  return a ? a : NULL;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr.c b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr.c
new file mode 100644
index 0000000..c2ccbbd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr.c
@@ -0,0 +1,10 @@
+// RUN: clang-tidy %s -checks=-*,modernize-use-nullptr -- | count 0
+
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+
+#define NULL 0
+void f(void) {
+  char *str = NULL; // ok
+  (void)str;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr.cpp
new file mode 100644
index 0000000..878c114
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-nullptr.cpp
@@ -0,0 +1,305 @@
+// RUN: %check_clang_tidy %s modernize-use-nullptr %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-nullptr.NullMacros, value: 'MY_NULL,NULL'}]}" \
+// RUN:   -- -std=c++11
+
+#define NULL 0
+
+namespace std {
+
+typedef decltype(nullptr) nullptr_t;
+
+} // namespace std
+
+// Just to make sure make_null() could have side effects.
+void external();
+
+std::nullptr_t make_null() {
+  external();
+  return nullptr;
+}
+
+void func() {
+  void *CallTest = make_null();
+
+  int var = 1;
+  void *CommaTest = (var+=2, make_null());
+
+  int *CastTest = static_cast<int*>(make_null());
+}
+
+void dummy(int*) {}
+void side_effect() {}
+
+#define MACRO_EXPANSION_HAS_NULL \
+  void foo() { \
+    dummy(0); \
+    dummy(NULL); \
+    side_effect(); \
+  }
+
+MACRO_EXPANSION_HAS_NULL;
+#undef MACRO_EXPANSION_HAS_NULL
+
+
+void test_macro_expansion1() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy(NULL); \
+  side_effect();
+
+  MACRO_EXPANSION_HAS_NULL;
+
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+// Test macro expansion with cast sequence, PR15572.
+void test_macro_expansion2() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy((int*)0); \
+  side_effect();
+
+  MACRO_EXPANSION_HAS_NULL;
+
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+void test_macro_expansion3() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy(NULL); \
+  side_effect();
+
+#define OUTER_MACRO \
+  MACRO_EXPANSION_HAS_NULL; \
+  side_effect();
+
+  OUTER_MACRO;
+
+#undef OUTER_MACRO
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+void test_macro_expansion4() {
+#define MY_NULL NULL
+  int *p = MY_NULL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr [modernize-use-nullptr]
+  // CHECK-FIXES: int *p = nullptr;
+#undef MY_NULL
+}
+
+#define IS_EQ(x, y) if (x != y) return;
+void test_macro_args() {
+  int i = 0;
+  int *Ptr;
+
+  IS_EQ(static_cast<int*>(0), Ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr
+  // CHECK-FIXES: IS_EQ(static_cast<int*>(nullptr), Ptr);
+
+  IS_EQ(0, Ptr);    // literal
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+  // CHECK-FIXES: IS_EQ(nullptr, Ptr);
+
+  IS_EQ(NULL, Ptr); // macro
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+  // CHECK-FIXES: IS_EQ(nullptr, Ptr);
+
+  // These are ok since the null literal is not spelled within a macro.
+#define myassert(x) if (!(x)) return;
+  myassert(0 == Ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+  // CHECK-FIXES: myassert(nullptr == Ptr);
+
+  myassert(NULL == Ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+  // CHECK-FIXES: myassert(nullptr == Ptr);
+
+  // These are bad as the null literal is buried in a macro.
+#define BLAH(X) myassert(0 == (X));
+#define BLAH2(X) myassert(NULL == (X));
+  BLAH(Ptr);
+  BLAH2(Ptr);
+
+  // Same as above but testing extra macro expansion.
+#define EXPECT_NULL(X) IS_EQ(0, X);
+#define EXPECT_NULL2(X) IS_EQ(NULL, X);
+  EXPECT_NULL(Ptr);
+  EXPECT_NULL2(Ptr);
+
+  // Almost the same as above but now null literal is not in a macro so ok
+  // to transform.
+#define EQUALS_PTR(X) IS_EQ(X, Ptr);
+  EQUALS_PTR(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR(nullptr);
+  EQUALS_PTR(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR(nullptr);
+
+  // Same as above but testing extra macro expansion.
+#define EQUALS_PTR_I(X) EQUALS_PTR(X)
+  EQUALS_PTR_I(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR_I(nullptr);
+  EQUALS_PTR_I(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR_I(nullptr);
+
+  // Ok since null literal not within macro. However, now testing macro
+  // used as arg to another macro.
+#define decorate(EXPR) side_effect(); EXPR;
+  decorate(IS_EQ(NULL, Ptr));
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+  // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
+  decorate(IS_EQ(0, Ptr));
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+  // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
+
+  // This macro causes a NullToPointer cast to happen where 0 is assigned to z
+  // but the 0 literal cannot be replaced because it is also used as an
+  // integer in the comparison.
+#define INT_AND_PTR_USE(X) do { int *z = X; if (X == 4) break; } while(false)
+  INT_AND_PTR_USE(0);
+
+  // Both uses of X in this case result in NullToPointer casts so replacement
+  // is possible.
+#define PTR_AND_PTR_USE(X) do { int *z = X; if (X != z) break; } while(false)
+  PTR_AND_PTR_USE(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
+  // CHECK-FIXES: PTR_AND_PTR_USE(nullptr);
+  PTR_AND_PTR_USE(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
+  // CHECK-FIXES: PTR_AND_PTR_USE(nullptr);
+
+#define OPTIONAL_CODE(...) __VA_ARGS__
+#define NOT_NULL dummy(0)
+#define CALL(X) X
+  OPTIONAL_CODE(NOT_NULL);
+  CALL(NOT_NULL);
+
+#define ENTRY(X) {X}
+  struct A {
+    int *Ptr;
+  } a[2] = {ENTRY(0), {0}};
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
+  // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: use nullptr
+  // CHECK-FIXES: a[2] = {ENTRY(nullptr), {nullptr}};
+#undef ENTRY
+
+#define assert1(expr) (expr) ? 0 : 1
+#define assert2 assert1
+  int *p;
+  assert2(p == 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+  // CHECK-FIXES: assert2(p == nullptr);
+  assert2(p == NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+  // CHECK-FIXES: assert2(p == nullptr);
+#undef assert2
+#undef assert1
+
+#define ASSERT_EQ(a, b) a == b
+#define ASSERT_NULL(x) ASSERT_EQ(static_cast<void *>(NULL), x)
+  int *pp;
+  ASSERT_NULL(pp);
+  ASSERT_NULL(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use nullptr
+  // CHECK-FIXES: ASSERT_NULL(nullptr);
+#undef ASSERT_NULL
+#undef ASSERT_EQ
+}
+
+// One of the ancestor of the cast is a NestedNameSpecifierLoc.
+class NoDef;
+char function(NoDef *p);
+#define F(x) (sizeof(function(x)) == 1)
+template<class T, T t>
+class C {};
+C<bool, F(0)> c;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use nullptr
+// CHECK-FIXES: C<bool, F(nullptr)> c;
+#undef F
+
+// Test default argument expression.
+struct D {
+  explicit D(void *t, int *c = NULL) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use nullptr
+  // CHECK-FIXES: explicit D(void *t, int *c = nullptr) {}
+};
+
+void test_default_argument() {
+  D(nullptr);
+}
+
+// Test on two neighbour CXXDefaultArgExprs nodes.
+typedef unsigned long long uint64;
+struct ZZ {
+  explicit ZZ(uint64, const uint64* = NULL) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use nullptr
+// CHECK-FIXES: explicit ZZ(uint64, const uint64* = nullptr) {}
+  operator bool()  { return true; }
+};
+
+uint64 Hash(uint64 seed = 0) { return 0; }
+
+void f() {
+  bool a;
+  a = ZZ(Hash());
+}
+
+// Test on ignoring substituted template types.
+template<typename T>
+class TemplateClass {
+ public:
+  explicit TemplateClass(int a, T default_value = 0) {}
+
+  void h(T *default_value = 0) {}
+
+  void f(int* p = 0) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
+// CHECK-FIXES: void f(int* p = nullptr) {}
+};
+
+void IgnoreSubstTemplateType() {
+  TemplateClass<int*> a(1);
+}
+
+// Test on casting nullptr.
+struct G {
+  explicit G(bool, const char * = NULL) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use nullptr
+  // CHECK-FIXES: explicit G(bool, const char * = nullptr) {}
+};
+bool g(const char*);
+void test_cast_nullptr() {
+  G(g(nullptr));
+  G(g((nullptr)));
+  G(g(static_cast<char*>(nullptr)));
+  G(g(static_cast<const char*>(nullptr)));
+}
+
+// Test on recognizing multiple NULLs.
+class H {
+public:
+  H(bool);
+};
+
+#define T(expression) H(expression);
+bool h(int *, int *, int * = nullptr);
+void test_multiple_nulls() {
+  T(h(NULL, NULL));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr
+// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use nullptr
+// CHECK-FIXES: T(h(nullptr, nullptr));
+  T(h(NULL, nullptr));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr
+// CHECK-FIXES: T(h(nullptr, nullptr));
+  T(h(nullptr, NULL));
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+// CHECK-FIXES: T(h(nullptr, nullptr));
+  T(h(nullptr, nullptr));
+  T(h(NULL, NULL, NULL));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr
+// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use nullptr
+// CHECK-MESSAGES: :[[@LINE-3]]:19: warning: use nullptr
+// CHECK-FIXES: T(h(nullptr, nullptr, nullptr));
+}
+#undef T
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override-cxx98.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override-cxx98.cpp
new file mode 100644
index 0000000..bc162d6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override-cxx98.cpp
@@ -0,0 +1,19 @@
+// RUN: %check_clang_tidy %s modernize-use-override %t -- -- -std=c++98
+
+struct Base {
+  virtual ~Base() {}
+  virtual void a();
+  virtual void b();
+};
+
+struct SimpleCases : public Base {
+public:
+  virtual ~SimpleCases();
+  // CHECK-FIXES: {{^}}  virtual ~SimpleCases();
+
+  void a();
+  // CHECK-FIXES: {{^}}  void a();
+
+  virtual void b();
+  // CHECK-FIXES: {{^}}  virtual void b();
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override-ms.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override-ms.cpp
new file mode 100644
index 0000000..0cee917
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override-ms.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s modernize-use-override %t -- -- -fms-extensions -std=c++11
+
+// This test is designed to test ms-extension __declspec(dllexport) attributes.
+#define EXPORT __declspec(dllexport)
+
+class Base {
+  virtual EXPORT void a();
+};
+
+class EXPORT InheritedBase {
+  virtual void a();
+};
+
+class Derived : public Base {
+  virtual EXPORT void a();
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: prefer using 'override' or (rarely) 'final' instead of 'virtual' [modernize-use-override]
+  // CHECK-FIXES: {{^}}  EXPORT void a() override;
+};
+
+class EXPORT InheritedDerived : public InheritedBase {
+  virtual void a();
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using 'override' or (rarely) 'final' instead of 'virtual' [modernize-use-override]
+  // CHECK-FIXES: {{^}}  void a() override;
+};
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override.cpp
new file mode 100644
index 0000000..24aafe5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-override.cpp
@@ -0,0 +1,318 @@
+// RUN: %check_clang_tidy %s modernize-use-override %t -- -- -std=c++11 -fexceptions
+
+#define ABSTRACT = 0
+
+#define OVERRIDE override
+#define VIRTUAL virtual
+#define NOT_VIRTUAL
+#define NOT_OVERRIDE
+
+#define MUST_USE_RESULT __attribute__((warn_unused_result))
+#define UNUSED __attribute__((unused))
+
+struct MUST_USE_RESULT MustUseResultObject {};
+
+struct IntPair {
+  int First, Second;
+};
+
+struct Base {
+  virtual ~Base() {}
+  virtual void a();
+  virtual void b();
+  virtual void c();
+  virtual void d();
+  virtual void d2();
+  virtual void e() = 0;
+  virtual void f() = 0;
+  virtual void f2() const = 0;
+  virtual void g() = 0;
+
+  virtual void j() const;
+  virtual MustUseResultObject k();
+  virtual bool l() MUST_USE_RESULT UNUSED;
+  virtual bool n() MUST_USE_RESULT UNUSED;
+
+  virtual void m();
+  virtual void m2();
+  virtual void o() __attribute__((unused));
+
+  virtual void r() &;
+  virtual void rr() &&;
+
+  virtual void cv() const volatile;
+  virtual void cv2() const volatile;
+
+  virtual void ne() noexcept(false);
+  virtual void t() throw();
+
+  virtual void il(IntPair);
+};
+
+struct SimpleCases : public Base {
+public:
+  virtual ~SimpleCases();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: prefer using 'override' or (rarely) 'final' instead of 'virtual' [modernize-use-override]
+  // CHECK-FIXES: {{^}}  ~SimpleCases() override;
+
+  void a();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: annotate this
+  // CHECK-FIXES: {{^}}  void a() override;
+
+  void b() override;
+  // CHECK-MESSAGES-NOT: warning:
+  // CHECK-FIXES: {{^}}  void b() override;
+
+  virtual void c();
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void c() override;
+
+  virtual void d() override;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant since the function is already declared 'override'
+  // CHECK-FIXES: {{^}}  void d() override;
+
+  virtual void d2() final;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant since the function is already declared 'final'
+  // CHECK-FIXES: {{^}}  void d2() final;
+
+  virtual void e() = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void e() override = 0;
+
+  virtual void f()=0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void f() override =0;
+
+  virtual void f2() const=0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void f2() const override =0;
+
+  virtual void g() ABSTRACT;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void g() override ABSTRACT;
+
+  virtual void j() const;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void j() const override;
+
+  virtual MustUseResultObject k();  // Has an implicit attribute.
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: prefer using
+  // CHECK-FIXES: {{^}}  MustUseResultObject k() override;
+
+  virtual bool l() MUST_USE_RESULT UNUSED;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  bool l() override MUST_USE_RESULT UNUSED;
+
+  virtual bool n() UNUSED MUST_USE_RESULT;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  bool n() override UNUSED MUST_USE_RESULT;
+
+  void m() override final;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'override' is redundant since the function is already declared 'final'
+  // CHECK-FIXES: {{^}}  void m() final;
+
+  virtual void m2() override final;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' and 'override' are redundant since the function is already declared 'final'
+  // CHECK-FIXES: {{^}}  void m2() final;
+
+  virtual void o() __attribute__((unused));
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void o() override __attribute__((unused));
+
+  virtual void ne() noexcept(false);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void ne() noexcept(false) override;
+
+  virtual void t() throw();
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void t() throw() override;
+};
+
+// CHECK-MESSAGES-NOT: warning:
+
+void SimpleCases::c() {}
+// CHECK-FIXES: {{^}}void SimpleCases::c() {}
+
+SimpleCases::~SimpleCases() {}
+// CHECK-FIXES: {{^}}SimpleCases::~SimpleCases() {}
+
+struct DefaultedDestructor : public Base {
+  DefaultedDestructor() {}
+  virtual ~DefaultedDestructor() = default;
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: prefer using
+  // CHECK-FIXES: {{^}}  ~DefaultedDestructor() override = default;
+};
+
+struct FinalSpecified : public Base {
+public:
+  virtual ~FinalSpecified() final;
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: 'virtual' is redundant since the function is already declared 'final'
+  // CHECK-FIXES: {{^}}  ~FinalSpecified() final;
+
+  void b() final;
+  // CHECK-MESSAGES-NOT: warning:
+  // CHECK-FIXES: {{^}}  void b() final;
+
+  virtual void d() final;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant
+  // CHECK-FIXES: {{^}}  void d() final;
+
+  virtual void e() final = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant
+  // CHECK-FIXES: {{^}}  void e() final = 0;
+
+  virtual void j() const final;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant
+  // CHECK-FIXES: {{^}}  void j() const final;
+
+  virtual bool l() final MUST_USE_RESULT UNUSED;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant
+  // CHECK-FIXES: {{^}}  bool l() final MUST_USE_RESULT UNUSED;
+};
+
+struct InlineDefinitions : public Base {
+public:
+  virtual ~InlineDefinitions() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: prefer using
+  // CHECK-FIXES: {{^}}  ~InlineDefinitions() override {}
+
+  void a() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: annotate this
+  // CHECK-FIXES: {{^}}  void a() override {}
+
+  void b() override {}
+  // CHECK-MESSAGES-NOT: warning:
+  // CHECK-FIXES: {{^}}  void b() override {}
+
+  virtual void c()
+  {}
+  // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void c() override
+
+  virtual void d() override {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant
+  // CHECK-FIXES: {{^}}  void d() override {}
+
+  virtual void j() const
+  {}
+  // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void j() const override
+
+  virtual MustUseResultObject k() {}  // Has an implicit attribute.
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: prefer using
+  // CHECK-FIXES: {{^}}  MustUseResultObject k() override {}
+
+  virtual bool l() MUST_USE_RESULT UNUSED {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  bool l() override MUST_USE_RESULT UNUSED {}
+
+  virtual void r() &
+  {}
+  // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void r() & override
+
+  virtual void rr() &&
+  {}
+  // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void rr() && override
+
+  virtual void cv() const volatile
+  {}
+  // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void cv() const volatile override
+
+  virtual void cv2() const volatile // some comment
+  {}
+  // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void cv2() const volatile override // some comment
+};
+
+struct DefaultArguments : public Base {
+  // Tests for default arguments (with initializer lists).
+  // Make sure the override fix is placed after the argument list.
+  void il(IntPair p = {1, (2 + (3))}) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: annotate this
+  // CHECK-FIXES: {{^}}  void il(IntPair p = {1, (2 + (3))}) override {}
+};
+
+struct Macros : public Base {
+  // Tests for 'virtual' and 'override' being defined through macros. Basically
+  // give up for now.
+  NOT_VIRTUAL void a() NOT_OVERRIDE;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: annotate this
+  // CHECK-FIXES: {{^}}  NOT_VIRTUAL void a() override NOT_OVERRIDE;
+
+  VIRTUAL void b() NOT_OVERRIDE;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  VIRTUAL void b() override NOT_OVERRIDE;
+
+  NOT_VIRTUAL void c() OVERRIDE;
+  // CHECK-MESSAGES-NOT: warning:
+  // CHECK-FIXES: {{^}}  NOT_VIRTUAL void c() OVERRIDE;
+
+  VIRTUAL void d() OVERRIDE;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant
+  // CHECK-FIXES: {{^}}  VIRTUAL void d() OVERRIDE;
+
+#define FUNC(return_type, name) return_type name()
+  FUNC(void, e);
+  // CHECK-FIXES: {{^}}  FUNC(void, e);
+
+#define F virtual void f();
+  F
+  // CHECK-FIXES: {{^}}  F
+
+  VIRTUAL void g() OVERRIDE final;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' and 'override' are redundant
+  // CHECK-FIXES: {{^}}  VIRTUAL void g() final;
+};
+
+// Tests for templates.
+template <typename T> struct TemplateBase {
+  virtual void f(T t);
+};
+
+template <typename T> struct DerivedFromTemplate : public TemplateBase<T> {
+  virtual void f(T t);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void f(T t) override;
+};
+void f() { DerivedFromTemplate<int>().f(2); }
+
+template <class C>
+struct UnusedMemberInstantiation : public C {
+  virtual ~UnusedMemberInstantiation() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: prefer using
+  // CHECK-FIXES: {{^}}  ~UnusedMemberInstantiation() override {}
+};
+struct IntantiateWithoutUse : public UnusedMemberInstantiation<Base> {};
+
+struct Base2 {
+  virtual ~Base2() {}
+  virtual void a();
+};
+
+// The OverrideAttr isn't propagated to specializations in all cases. Make sure
+// we don't add "override" a second time.
+template <int I>
+struct MembersOfSpecializations : public Base2 {
+  void a() override;
+  // CHECK-MESSAGES-NOT: warning:
+  // CHECK-FIXES: {{^}}  void a() override;
+};
+template <> void MembersOfSpecializations<3>::a() {}
+void ff() { MembersOfSpecializations<3>().a(); };
+
+// In case try statement is used as a method body,
+// make sure that override fix is placed before try keyword.
+struct TryStmtAsBody : public Base {
+  void a() try
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: annotate this
+  // CHECK-FIXES: {{^}}  void a() override try
+  { b(); } catch(...) { c(); }
+
+  virtual void d() try
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void d() override try
+  { e(); } catch(...) { f(); }
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-transparent-functors.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-transparent-functors.cpp
new file mode 100644
index 0000000..b700f54
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-transparent-functors.cpp
@@ -0,0 +1,107 @@
+// RUN: %check_clang_tidy %s modernize-use-transparent-functors %t -- -- -std=c++14
+
+namespace std {
+template<class T>
+struct remove_reference;
+
+template <class T>
+constexpr T &&forward(typename std::remove_reference<T>::type &t);
+
+template <class T>
+constexpr T &&forward(typename std::remove_reference<T>::type &&t);
+
+template <typename T = void>
+struct plus {
+  constexpr T operator()(const T &Lhs, const T &Rhs) const;
+};
+
+template <>
+struct plus<void> {
+  template <typename T, typename U>
+  constexpr auto operator()(T &&Lhs, U &&Rhs) const ->
+    decltype(forward<T>(Lhs) + forward<U>(Rhs));
+};
+
+template <typename T = void>
+struct less {
+  constexpr bool operator()(const T &Lhs, const T &Rhs) const;
+};
+
+template <>
+struct less<void> {
+  template <typename T, typename U>
+  constexpr bool operator()(T &&Lhs, U &&Rhs) const;
+};
+
+template <typename T = void>
+struct logical_not {
+  constexpr bool operator()(const T &Arg) const;
+};
+
+template <>
+struct logical_not<void> {
+  template <typename T>
+  constexpr bool operator()(T &&Arg) const;
+};
+
+template <typename T>
+class allocator;
+
+template <
+    class Key,
+    class Compare = std::less<>,
+    class Allocator = std::allocator<Key>>
+class set {};
+
+template <
+    class Key,
+    class Compare = std::less<Key>,
+    class Allocator = std::allocator<Key>>
+class set2 {};
+
+template <class InputIt, class UnaryPredicate>
+InputIt find_if(InputIt first, InputIt last,
+                UnaryPredicate p);
+
+template <class RandomIt, class Compare>
+void sort(RandomIt first, RandomIt last, Compare comp);
+
+class iterator {};
+class string {};
+}
+
+int main() {
+  using std::set;
+  using std::less;
+  std::set<int, std::less<int>> s;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: prefer transparent functors 'less<>' [modernize-use-transparent-functors]
+  // CHECK-FIXES: {{^}}  std::set<int, std::less<>> s;{{$}}
+  set<int, std::less<int>> s2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: prefer transparent functors
+  // CHECK-FIXES: {{^}}  set<int, std::less<>> s2;{{$}}
+  set<int, less<int>> s3;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: prefer transparent functors
+  // CHECK-FIXES: {{^}}  set<int, less<>> s3;{{$}}
+  std::set<int, std::less<>> s4;
+  std::set<char *, std::less<std::string>> s5;
+  std::set<set<int, less<int>>, std::less<>> s6;
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: prefer transparent functors
+  // CHECK-FIXES: {{^}}  std::set<set<int, less<>>, std::less<>> s6;{{$}}
+  std::iterator begin, end;
+  sort(begin, end, std::less<int>());
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: prefer transparent functors
+  std::sort(begin, end, std::less<>());
+  find_if(begin, end, std::logical_not<bool>());
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: prefer transparent functors
+  std::find_if(begin, end, std::logical_not<>());
+  using my_set = std::set<int, std::less<int>>;
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: prefer transparent functors
+  // CHECK-FIXES: {{^}}  using my_set = std::set<int, std::less<>>;{{$}}
+  using my_set2 = std::set<char*, std::less<std::string>>;
+  using my_less = std::less<std::string>;
+  find_if(begin, end, my_less());
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: prefer transparent functors
+  std::set2<int> control;
+}
+
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-uncaught-exceptions.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-uncaught-exceptions.cpp
new file mode 100644
index 0000000..e6bae2b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-uncaught-exceptions.cpp
@@ -0,0 +1,79 @@
+// RUN: %check_clang_tidy %s modernize-use-uncaught-exceptions %t -- -- -std=c++1z
+#define MACRO std::uncaught_exception
+// CHECK-FIXES: #define MACRO std::uncaught_exception
+
+bool uncaught_exception() {
+  return 0;
+}
+
+namespace std {
+  bool uncaught_exception() {
+    return false;
+  }
+
+  int uncaught_exceptions() {
+    return 0;
+  }
+}
+
+template <typename T>
+bool doSomething(T t) { 
+  return t();
+  // CHECK-FIXES: return t();
+}
+
+template <bool (*T)()>
+bool doSomething2() { 
+  return T();
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+  // CHECK-FIXES: return T();
+}
+
+void no_warn() {
+
+  uncaught_exception();
+  // CHECK-FIXES: uncaught_exception();
+
+  doSomething(uncaught_exception);
+  // CHECK-FIXES: doSomething(uncaught_exception);
+}
+
+void warn() {
+
+  std::uncaught_exception();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+  // CHECK-FIXES: std::uncaught_exceptions();
+
+  using std::uncaught_exception;
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+  // CHECK-FIXES: using std::uncaught_exceptions;
+
+  uncaught_exception();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+  // CHECK-FIXES: uncaught_exceptions();
+
+  bool b{uncaught_exception()};
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+  // CHECK-FIXES: bool b{std::uncaught_exceptions() > 0};
+
+  MACRO();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+  // CHECK-FIXES: MACRO();
+
+  doSomething(std::uncaught_exception);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+  // CHECK-FIXES: doSomething(std::uncaught_exception);
+
+  doSomething(uncaught_exception);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+  // CHECK-FIXES: doSomething(uncaught_exception);
+
+  bool (*foo)();
+  foo = &uncaught_exception;
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+  // CHECK-FIXES: foo = &uncaught_exception;
+
+  doSomething2<uncaught_exception>();
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
+  // CHECK-FIXES: doSomething2<uncaught_exception>();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-using-macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-using-macros.cpp
new file mode 100644
index 0000000..5d88d1d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-using-macros.cpp
@@ -0,0 +1,23 @@
+// RUN: %check_clang_tidy %s modernize-use-using %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-using.IgnoreMacros, value: 0}]}" \
+// RUN:   -- -std=c++11
+
+#define CODE typedef int INT
+
+CODE;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: #define CODE typedef int INT
+// CHECK-FIXES: CODE;
+
+struct Foo;
+#define Bar Baz
+typedef Foo Bar;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: #define Bar Baz
+// CHECK-FIXES: using Baz = Foo;
+
+#define TYPEDEF typedef
+TYPEDEF Foo Bak;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: #define TYPEDEF typedef
+// CHECK-FIXES: TYPEDEF Foo Bak;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-using.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-using.cpp
new file mode 100644
index 0000000..e8f4958
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/modernize-use-using.cpp
@@ -0,0 +1,164 @@
+// RUN: %check_clang_tidy %s modernize-use-using %t
+
+typedef int Type;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' [modernize-use-using]
+// CHECK-FIXES: using Type = int;
+
+typedef long LL;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using LL = long;
+
+typedef int Bla;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Bla = int;
+
+typedef Bla Bla2;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Bla2 = Bla;
+
+typedef void (*type)(int, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using type = void (*)(int, int);
+
+typedef void (*type2)();
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using type2 = void (*)();
+
+class Class {
+  typedef long long Type;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
+  // CHECK-FIXES: using Type = long long;
+};
+
+typedef void (Class::*MyPtrType)(Bla) const;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using MyPtrType = void (Class::*)(Bla)[[ATTR:( __attribute__\(\(thiscall\)\))?]] const;
+
+class Iterable {
+public:
+  class Iterator {};
+};
+
+template <typename T>
+class Test {
+  typedef typename T::iterator Iter;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
+  // CHECK-FIXES: using Iter = typename T::iterator;
+};
+
+using balba = long long;
+
+union A {};
+
+typedef void (A::*PtrType)(int, int) const;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using PtrType = void (A::*)(int, int)[[ATTR]] const;
+
+typedef Class some_class;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using some_class = Class;
+
+typedef Class Cclass;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Cclass = Class;
+
+typedef Cclass cclass2;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using cclass2 = Cclass;
+
+class cclass {};
+
+typedef void (cclass::*MyPtrType3)(Bla);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using MyPtrType3 = void (cclass::*)(Bla)[[ATTR]];
+
+using my_class = int;
+
+typedef Test<my_class *> another;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using another = Test<my_class *>;
+
+typedef int* PInt;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using PInt = int *;
+
+typedef int bla1, bla2, bla3;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef int bla1, bla2, bla3;
+
+#define CODE typedef int INT
+
+CODE;
+// CHECK-FIXES: #define CODE typedef int INT
+// CHECK-FIXES: CODE;
+
+struct Foo;
+#define Bar Baz
+typedef Foo Bar;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: #define Bar Baz
+// CHECK-FIXES: using Baz = Foo;
+
+#define TYPEDEF typedef
+TYPEDEF Foo Bak;
+// CHECK-FIXES: #define TYPEDEF typedef
+// CHECK-FIXES: TYPEDEF Foo Bak;
+
+#define FOO Foo
+typedef FOO Bam;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: #define FOO Foo
+// CHECK-FIXES: using Bam = Foo;
+
+typedef struct Foo Bap;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Bap = struct Foo;
+
+struct Foo typedef Bap2;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Bap2 = struct Foo;
+
+Foo typedef Bap3;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Bap3 = Foo;
+
+typedef struct Unknown Baq;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Baq = struct Unknown;
+
+struct Unknown2 typedef Baw;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Baw = struct Unknown2;
+
+int typedef Bax;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Bax = int;
+
+typedef struct Q1 { int a; } S1;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef struct Q1 { int a; } S1;
+typedef struct { int b; } S2;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef struct { int b; } S2;
+struct Q2 { int c; } typedef S3;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: struct Q2 { int c; } typedef S3;
+struct { int d; } typedef S4;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: struct { int d; } typedef S4;
+
+namespace my_space {
+  class my_cclass {};
+  typedef my_cclass FuncType;
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using FuncType = my_cclass;
+}
+
+#define lol 4
+typedef unsigned Map[lol];
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef unsigned Map[lol];
+
+typedef void (*fun_type)();
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using fun_type = void (*)();
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/mpi-buffer-deref.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/mpi-buffer-deref.cpp
new file mode 100644
index 0000000..67304d2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/mpi-buffer-deref.cpp
@@ -0,0 +1,50 @@
+// RUN: %check_clang_tidy %s mpi-buffer-deref %t -- -- -I %S/Inputs/mpi-type-mismatch
+
+#include "mpimock.h"
+
+void negativeTests() {
+  char *buf;
+  MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer is insufficiently dereferenced: pointer->pointer [mpi-buffer-deref]
+
+  unsigned **buf2;
+  MPI_Send(buf2, 1, MPI_UNSIGNED, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer is insufficiently dereferenced: pointer->pointer
+
+  short buf3[1][1];
+  MPI_Send(buf3, 1, MPI_SHORT, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer is insufficiently dereferenced: array->array
+
+  long double _Complex *buf4[1];
+  MPI_Send(buf4, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer is insufficiently dereferenced: pointer->array
+
+  std::complex<float> *buf5[1][1];
+  MPI_Send(&buf5, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer is insufficiently dereferenced: pointer->array->array->pointer
+}
+
+void positiveTests() {
+  char buf;
+  MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+
+  unsigned *buf2;
+  MPI_Send(buf2, 1, MPI_UNSIGNED, 0, 0, MPI_COMM_WORLD);
+
+  short buf3[1][1];
+  MPI_Send(buf3[0], 1, MPI_SHORT, 0, 0, MPI_COMM_WORLD);
+
+  long double _Complex *buf4[1];
+  MPI_Send(*buf4, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+  long double _Complex buf5[1];
+  MPI_Send(buf5, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+  std::complex<float> *buf6[1][1];
+  MPI_Send(*buf6[0], 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+  // Referencing an array with '&' is valid, as this also points to the
+  // beginning of the array.
+  long double _Complex buf7[1];
+  MPI_Send(&buf7, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/mpi-type-mismatch.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/mpi-type-mismatch.cpp
new file mode 100644
index 0000000..5e230b8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/mpi-type-mismatch.cpp
@@ -0,0 +1,255 @@
+// RUN: %check_clang_tidy %s mpi-type-mismatch %t -- -- -I %S/Inputs/mpi-type-mismatch
+
+#include "mpimock.h"
+
+void charNegativeTest() {
+  int buf;
+  MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'int' does not match the MPI datatype 'MPI_CHAR'
+
+  short buf2;
+  MPI_Send(&buf2, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'short' does not match the MPI datatype 'MPI_CHAR'
+
+  long buf3;
+  MPI_Send(&buf3, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long' does not match the MPI datatype 'MPI_CHAR'
+
+  int8_t buf4;
+  MPI_Send(&buf4, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'int8_t' does not match the MPI datatype 'MPI_CHAR'
+
+  uint16_t buf5;
+  MPI_Send(&buf5, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_CHAR'
+
+  long double _Complex buf6;
+  MPI_Send(&buf6, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long double _Complex' does not match the MPI datatype 'MPI_CHAR'
+
+  std::complex<float> buf7;
+  MPI_Send(&buf7, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<float>' does not match the MPI datatype 'MPI_CHAR'
+}
+
+void intNegativeTest() {
+  unsigned char buf;
+  MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned char' does not match the MPI datatype 'MPI_INT'
+
+  unsigned buf2;
+  MPI_Send(&buf2, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned int' does not match the MPI datatype 'MPI_INT'
+
+  short buf3;
+  MPI_Send(&buf3, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'short' does not match the MPI datatype 'MPI_INT'
+
+  long buf4;
+  MPI_Send(&buf4, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long' does not match the MPI datatype 'MPI_INT'
+
+  int8_t buf5;
+  MPI_Send(&buf5, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'int8_t' does not match the MPI datatype 'MPI_INT'
+
+  uint16_t buf6;
+  MPI_Send(&buf6, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_INT'
+
+  long double _Complex buf7;
+  MPI_Send(&buf7, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long double _Complex' does not match the MPI datatype 'MPI_INT'
+
+  std::complex<float> buf8;
+  MPI_Send(&buf8, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<float>' does not match the MPI datatype 'MPI_INT'
+}
+
+void longNegativeTest() {
+  char buf;
+  MPI_Send(&buf, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'char' does not match the MPI datatype 'MPI_LONG'
+
+  unsigned buf2;
+  MPI_Send(&buf2, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned int' does not match the MPI datatype 'MPI_LONG'
+
+  unsigned short buf3;
+  MPI_Send(&buf3, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned short' does not match the MPI datatype 'MPI_LONG'
+
+  unsigned long buf4;
+  MPI_Send(&buf4, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned long' does not match the MPI datatype 'MPI_LONG'
+
+  int8_t buf5;
+  MPI_Send(&buf5, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'int8_t' does not match the MPI datatype 'MPI_LONG'
+
+  uint16_t buf6;
+  MPI_Send(&buf6, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_LONG'
+
+  long double _Complex buf7;
+  MPI_Send(&buf7, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long double _Complex' does not match the MPI datatype 'MPI_LONG'
+
+  std::complex<float> buf8;
+  MPI_Send(&buf8, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<float>' does not match the MPI datatype 'MPI_LONG'
+}
+
+void int8_tNegativeTest() {
+  char buf;
+  MPI_Send(&buf, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'char' does not match the MPI datatype 'MPI_INT8_T'
+
+  unsigned buf2;
+  MPI_Send(&buf2, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned int' does not match the MPI datatype 'MPI_INT8_T'
+
+  short buf3;
+  MPI_Send(&buf3, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'short' does not match the MPI datatype 'MPI_INT8_T'
+
+  unsigned long buf4;
+  MPI_Send(&buf4, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned long' does not match the MPI datatype 'MPI_INT8_T'
+
+  uint8_t buf5;
+  MPI_Send(&buf5, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint8_t' does not match the MPI datatype 'MPI_INT8_T'
+
+  uint16_t buf6;
+  MPI_Send(&buf6, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_INT8_T'
+
+  long double _Complex buf7;
+  MPI_Send(&buf7, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long double _Complex' does not match the MPI datatype 'MPI_INT8_T'
+
+  std::complex<float> buf8;
+  MPI_Send(&buf8, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<float>' does not match the MPI datatype 'MPI_INT8_T'
+}
+
+void complex_c_long_double_complexNegativeTest() {
+  char buf;
+  MPI_Send(&buf, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'char' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+  unsigned buf2;
+  MPI_Send(&buf2, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned int' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+  short buf3;
+  MPI_Send(&buf3, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'short' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+  unsigned long buf4;
+  MPI_Send(&buf4, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned long' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+  uint8_t buf5;
+  MPI_Send(&buf5, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint8_t' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+  uint16_t buf6;
+  MPI_Send(&buf6, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+  double _Complex buf7;
+  MPI_Send(&buf7, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'double _Complex' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+  std::complex<float> buf8;
+  MPI_Send(&buf8, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<float>' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+}
+
+void complex_cxx_float_complexNegativeTest() {
+  char buf;
+  MPI_Send(&buf, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'char' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+  unsigned buf2;
+  MPI_Send(&buf2, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned int' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+  short buf3;
+  MPI_Send(&buf3, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'short' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+  unsigned long buf4;
+  MPI_Send(&buf4, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned long' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+  uint8_t buf5;
+  MPI_Send(&buf5, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint8_t' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+  uint16_t buf6;
+  MPI_Send(&buf6, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+  double _Complex buf7;
+  MPI_Send(&buf7, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'double _Complex' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+  std::complex<double> buf8;
+  MPI_Send(&buf8, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<double>' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+}
+
+void skippedTypesTests() {
+  // typedefs, user defined MPI and nullptr types are skipped
+  typedef char CHAR;
+  CHAR buf;
+  MPI_Send(&buf, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+  typedef unsigned UNSIGNED;
+  UNSIGNED buf2;
+  MPI_Send(&buf2, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+#define _MPI_LONG MPI_LONG
+  int buf3;
+  MPI_Send(&buf3, 1, _MPI_LONG, 0, 0, MPI_COMM_WORLD);
+
+#define _MPI_CXX_FLOAT_COMPLEX MPI_CXX_FLOAT_COMPLEX
+  short buf4;
+  MPI_Send(&buf4, 1, _MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+  MPI_Send(NULL, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+}
+
+void positiveTests() {
+  char buf;
+  MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+
+  int buf2;
+  MPI_Send(&buf2, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+
+  long buf3;
+  MPI_Send(&buf3, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+
+  int8_t buf4;
+  MPI_Send(&buf4, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+
+  long double _Complex buf5;
+  MPI_Send(&buf5, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+  std::complex<float> buf6;
+  MPI_Send(&buf6, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+  uint8_t buf7;
+  MPI_Send(&buf7, 1, MPI_UINT8_T, 0, 0, MPI_COMM_WORLD);
+
+  uint16_t buf8;
+  MPI_Send(&buf8, 1, MPI_UINT16_T, 0, 0, MPI_COMM_WORLD);
+
+  // On some systems like PPC or ARM, 'char' is unsigned by default which is why
+  // distinct signedness for the buffer and MPI type is tolerated.
+  unsigned char buf9;
+  MPI_Send(&buf9, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nolint.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nolint.cpp
new file mode 100644
index 0000000..893e819
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nolint.cpp
@@ -0,0 +1,49 @@
+// RUN: %check_clang_tidy %s google-explicit-constructor,clang-diagnostic-unused-variable,clang-analyzer-core.UndefinedBinaryOperatorResult %t -- -extra-arg=-Wunused-variable -- -I%S/Inputs/nolint
+
+#include "trigger_warning.h"
+void I(int& Out) {
+  int In;
+  A1(In, Out);
+}
+// CHECK-MESSAGES-NOT: trigger_warning.h:{{.*}} warning
+// CHECK-MESSAGES-NOT: :[[@LINE-4]]:{{.*}} note
+
+class A { A(int i); };
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
+
+class B { B(int i); }; // NOLINT
+
+class C { C(int i); }; // NOLINT(for-some-other-check)
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
+
+class C1 { C1(int i); }; // NOLINT(*)
+
+class C2 { C2(int i); }; // NOLINT(not-closed-bracket-is-treated-as-skip-all
+
+class C3 { C3(int i); }; // NOLINT(google-explicit-constructor)
+
+class C4 { C4(int i); }; // NOLINT(some-check, google-explicit-constructor)
+
+class C5 { C5(int i); }; // NOLINT without-brackets-skip-all, another-check
+
+void f() {
+  int i;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: unused variable 'i' [clang-diagnostic-unused-variable]
+  int j; // NOLINT
+}
+
+#define MACRO(X) class X { X(int i); };
+MACRO(D)
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: single-argument constructors must be marked explicit
+MACRO(E) // NOLINT
+
+#define MACRO_NOARG class F { F(int i); };
+MACRO_NOARG // NOLINT
+
+#define MACRO_NOLINT class G { G(int i); }; // NOLINT
+MACRO_NOLINT
+
+#define DOUBLE_MACRO MACRO(H) // NOLINT
+DOUBLE_MACRO
+
+// CHECK-MESSAGES: Suppressed 12 warnings (12 NOLINT)
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nolintnextline.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nolintnextline.cpp
new file mode 100644
index 0000000..a97928a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nolintnextline.cpp
@@ -0,0 +1,49 @@
+class A { A(int i); };
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
+
+// NOLINTNEXTLINE
+class B { B(int i); };
+
+// NOLINTNEXTLINE(for-some-other-check)
+class C { C(int i); };
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
+
+// NOLINTNEXTLINE(*)
+class C1 { C1(int i); };
+
+// NOLINTNEXTLINE(not-closed-bracket-is-treated-as-skip-all
+class C2 { C2(int i); };
+
+// NOLINTNEXTLINE(google-explicit-constructor)
+class C3 { C3(int i); };
+
+// NOLINTNEXTLINE(some-check, google-explicit-constructor)
+class C4 { C4(int i); };
+
+// NOLINTNEXTLINE without-brackets-skip-all, another-check
+class C5 { C5(int i); };
+
+
+// NOLINTNEXTLINE
+
+class D { D(int i); };
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
+
+// NOLINTNEXTLINE
+//
+class E { E(int i); };
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
+
+#define MACRO(X) class X { X(int i); };
+MACRO(F)
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: single-argument constructors must be marked explicit
+// NOLINTNEXTLINE
+MACRO(G)
+
+#define MACRO_NOARG class H { H(int i); };
+// NOLINTNEXTLINE
+MACRO_NOARG
+
+// CHECK-MESSAGES: Suppressed 8 warnings (8 NOLINT)
+
+// RUN: %check_clang_tidy %s google-explicit-constructor %t --
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nonstandard-file-extension.test b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nonstandard-file-extension.test
new file mode 100644
index 0000000..4cb4d11
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/nonstandard-file-extension.test
@@ -0,0 +1,6 @@
+// RUN: %check_clang_tidy -assume-filename=const-cast.cpp %s cppcoreguidelines-pro-type-const-cast %t
+
+const int *i;
+int *j;
+void f() { j = const_cast<int *>(i); }
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use const_cast [cppcoreguidelines-pro-type-const-cast]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-arc-and-properties.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-arc-and-properties.m
new file mode 100644
index 0000000..7fbd796
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-arc-and-properties.m
@@ -0,0 +1,21 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-semicolon %t
+
+// This test checks if Objective-C 2.0 (@properties) and
+// Automatic Reference Counting (ARC) are enabled for .m files
+// checked via check_clang_tidy.py.
+
+#if !__has_feature(objc_arc)
+#error Objective-C ARC not enabled as expected
+#endif
+
+@interface Foo
+@property (nonatomic, assign) int shouldDoStuff;
+- (void)nop;
+@end
+
+void fail(Foo *f)
+{
+  if(f.shouldDoStuff); [f nop];
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: potentially unintended semicolon [bugprone-suspicious-semicolon]
+  // CHECK-FIXES: if(f.shouldDoStuff) [f nop];
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-avoid-nserror-init.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-avoid-nserror-init.m
new file mode 100644
index 0000000..7794077
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-avoid-nserror-init.m
@@ -0,0 +1,12 @@
+// RUN: %check_clang_tidy %s objc-avoid-nserror-init %t
+@interface NSError
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+@implementation foo
+- (void)bar {
+    NSError *error = [[NSError alloc] init];
+    // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use errorWithDomain:code:userInfo: or initWithDomain:code:userInfo: to create a new NSError [objc-avoid-nserror-init]
+}
+@end
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-avoid-spinlock.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-avoid-spinlock.m
new file mode 100644
index 0000000..f9f05cb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-avoid-spinlock.m
@@ -0,0 +1,15 @@
+// RUN: %check_clang_tidy %s objc-avoid-spinlock %t
+
+typedef int OSSpinLock;
+
+@implementation Foo
+- (void)f {
+    int i = 1;
+    OSSpinlockLock(&i);
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [objc-avoid-spinlock]
+    OSSpinlockTry(&i);
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [objc-avoid-spinlock]
+    OSSpinlockUnlock(&i);
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [objc-avoid-spinlock]
+}
+@end
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-forbidden-subclassing-custom.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-forbidden-subclassing-custom.m
new file mode 100644
index 0000000..59e6a88
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-forbidden-subclassing-custom.m
@@ -0,0 +1,39 @@
+// RUN: %check_clang_tidy %s objc-forbidden-subclassing %t \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: objc-forbidden-subclassing.ClassNames, value: "Foo;Quux"}]}' \
+// RUN: --
+
+@interface UIImagePickerController
+@end
+
+// Make sure custom config options replace (not add to) the default list.
+@interface Waldo : UIImagePickerController
+// CHECK-MESSAGES-NOT: :[[@LINE-1]]:12: warning: Objective-C interface 'Waldo' subclasses 'UIImagePickerController', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
+
+@interface Foo
+@end
+
+@interface Bar : Foo
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Objective-C interface 'Bar' subclasses 'Foo', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
+
+// Check subclasses of subclasses.
+@interface Baz : Bar
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Objective-C interface 'Baz' subclasses 'Foo', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
+
+@interface Quux
+@end
+
+// Check that more than one forbidden superclass can be specified.
+@interface Xyzzy : Quux
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Objective-C interface 'Xyzzy' subclasses 'Quux', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
+
+@interface Plugh
+@end
+
+@interface Corge : Plugh
+// CHECK-MESSAGES-NOT: :[[@LINE-1]]:12: warning: Objective-C interface 'Corge' subclasses 'Plugh', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-forbidden-subclassing.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-forbidden-subclassing.m
new file mode 100644
index 0000000..3ad38bf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-forbidden-subclassing.m
@@ -0,0 +1,21 @@
+// RUN: %check_clang_tidy %s objc-forbidden-subclassing %t
+
+@interface UIImagePickerController
+@end
+
+@interface Foo : UIImagePickerController
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Objective-C interface 'Foo' subclasses 'UIImagePickerController', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
+
+// Check subclasses of subclasses.
+@interface Bar : Foo
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Objective-C interface 'Bar' subclasses 'UIImagePickerController', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
+
+@interface Baz
+@end
+
+// Make sure innocent subclasses aren't caught by the check.
+@interface Blech : Baz
+// CHECK-MESSAGES-NOT: :[[@LINE-1]]:12: warning: Objective-C interface 'Blech' subclasses 'Baz', which is not intended to be subclassed [objc-forbidden-subclassing]
+@end
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-no-arc-or-properties.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-no-arc-or-properties.m
new file mode 100644
index 0000000..c1e73ed
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-no-arc-or-properties.m
@@ -0,0 +1,29 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-semicolon %t -- -- -fno-objc-arc -fobjc-abi-version=1
+
+// This test ensures check_clang_tidy.py allows disabling Objective-C ARC and
+// Objective-C 2.0 via passing arguments after -- on the command line.
+//
+// (We could include a test which doesn't pass any arguments after --
+// to check if ARC and ObjC 2.0 are disabled by default, but that test
+// could change behavior based on the default Objective-C runtime for
+// the platform, which would make this test flaky.)
+
+#if __has_feature(objc_arc)
+#error Objective-C ARC unexpectedly enabled even with -fno-objc-arc
+#endif
+
+#ifdef __OBJC2__
+#error Objective-C 2.0 unexpectedly enabled even with -fobjc-abi-version=1
+#endif
+
+@interface Foo
+- (int)shouldDoStuff;
+- (void)nop;
+@end
+
+void fail(Foo *f)
+{
+  if([f shouldDoStuff]); [f nop];
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: potentially unintended semicolon [bugprone-suspicious-semicolon]
+  // CHECK-FIXES: if([f shouldDoStuff]) [f nop];
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration-additional.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration-additional.m
new file mode 100644
index 0000000..bf836fa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration-additional.m
@@ -0,0 +1,15 @@
+// RUN: %check_clang_tidy %s objc-property-declaration %t \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: objc-property-declaration.Acronyms, value: "ABC;TGIF"}]}' \
+// RUN: --
+@class NSString;
+
+@interface Foo
+@property(assign, nonatomic) int AbcNotRealPrefix;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'AbcNotRealPrefix' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+// CHECK-FIXES: @property(assign, nonatomic) int abcNotRealPrefix;
+@property(assign, nonatomic) int ABCCustomPrefix;
+@property(strong, nonatomic) NSString *ABC_custom_prefix;
+// CHECK-MESSAGES: :[[@LINE-1]]:40: warning: property name 'ABC_custom_prefix' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+@property(assign, nonatomic) int GIFShouldIncludeStandardAcronym;
+@end
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration-custom.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration-custom.m
new file mode 100644
index 0000000..68374ec
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration-custom.m
@@ -0,0 +1,18 @@
+// RUN: %check_clang_tidy %s objc-property-declaration %t \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: objc-property-declaration.Acronyms, value: "ABC;TGIF"}, \
+// RUN:   {key: objc-property-declaration.IncludeDefaultAcronyms, value: 0}]}' \
+// RUN: --
+@class NSString;
+
+@interface Foo
+@property(assign, nonatomic) int AbcNotRealPrefix;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'AbcNotRealPrefix' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+// CHECK-FIXES: @property(assign, nonatomic) int abcNotRealPrefix;
+@property(assign, nonatomic) int ABCCustomPrefix;
+@property(strong, nonatomic) NSString *ABC_custom_prefix;
+// CHECK-MESSAGES: :[[@LINE-1]]:40: warning: property name 'ABC_custom_prefix' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+@property(assign, nonatomic) int GIFIgnoreStandardAcronym;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'GIFIgnoreStandardAcronym' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+@property(strong, nonatomic) NSString *TGIF;
+@end
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration.m
new file mode 100644
index 0000000..7f70784
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/objc-property-declaration.m
@@ -0,0 +1,46 @@
+// RUN: %check_clang_tidy %s objc-property-declaration %t
+@class NSData;
+@class NSString;
+@class UIViewController;
+
+@interface Foo
+@property(assign, nonatomic) int NotCamelCase;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'NotCamelCase' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+// CHECK-FIXES: @property(assign, nonatomic) int notCamelCase;
+@property(assign, nonatomic) int camelCase;
+@property(strong, nonatomic) NSString *URLString;
+@property(strong, nonatomic) NSString *bundleID;
+@property(strong, nonatomic) NSData *RGBABytes;
+@property(strong, nonatomic) UIViewController *notificationsVC;
+@property(strong, nonatomic) NSString *URL_string;
+// CHECK-MESSAGES: :[[@LINE-1]]:40: warning: property name 'URL_string' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+@property(strong, nonatomic) NSString *supportURLsCamelCase;
+@property(strong, nonatomic) NSString *supportURLCamelCase;
+@property(strong, nonatomic) NSString *VCsPluralToAdd;
+@property(assign, nonatomic) int centerX;
+@property(assign, nonatomic) int enable2GBackgroundFetch;
+@property(assign, nonatomic) int shouldUseCFPreferences;
+@property(assign, nonatomic) int enableGLAcceleration;
+@property(assign, nonatomic) int ID;
+@property(assign, nonatomic) int hasADog;
+@end
+
+@interface Foo (Bar)
+@property(assign, nonatomic) int abc_NotCamelCase;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'abc_NotCamelCase' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+@property(assign, nonatomic) int abCD_camelCase;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'abCD_camelCase' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+// CHECK-FIXES: @property(assign, nonatomic) int abcd_camelCase;
+@property(assign, nonatomic) int abCD_NotCamelCase;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'abCD_NotCamelCase' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+// CHECK-FIXES: @property(assign, nonatomic) int abcd_notCamelCase;
+@property(assign, nonatomic) int wrongFormat_;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'wrongFormat_' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+@property(strong, nonatomic) NSString *URLStr;
+@property(assign, nonatomic) int abc_camelCase;
+@end
+
+@interface Foo ()
+@property(assign, nonatomic) int abc_inClassExtension;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: property name 'abc_inClassExtension' not using lowerCamelCase style or not prefixed in a category, according to the Apple Coding Guidelines [objc-property-declaration]
+@end
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/overlapping.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/overlapping.cpp
new file mode 100644
index 0000000..f970a13
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/overlapping.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-tidy -checks=-*,llvm-include-order -header-filter=.* %s \
+// RUN:   -- -isystem %S/Inputs/Headers -I %S/Inputs/overlapping | \
+// RUN:   not grep "note: this fix will not be applied because it overlaps with another fix"
+
+#include <s.h>
+#include "o.h"
+
+// Test that clang-tidy takes into account in which file we are doing the
+// replacements to determine if they overlap or not. In the file "o.h" there is
+// a similar error at the same file offset, but they do not overlap.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-faster-string-find.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-faster-string-find.cpp
new file mode 100644
index 0000000..b36e323
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-faster-string-find.cpp
@@ -0,0 +1,110 @@
+// RUN: %check_clang_tidy %s performance-faster-string-find %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:             [{key: performance-faster-string-find.StringLikeClasses, \
+// RUN:               value: 'std::basic_string; ::llvm::StringRef;'}]}" --
+
+namespace std {
+template <typename Char>
+struct basic_string {
+  int find(const Char *, int = 0) const;
+  int find(const Char *, int, int) const;
+  int rfind(const Char *) const;
+  int find_first_of(const Char *) const;
+  int find_first_not_of(const Char *) const;
+  int find_last_of(const Char *) const;
+  int find_last_not_of(const Char *) const;
+};
+
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+}  // namespace std
+
+namespace llvm {
+struct StringRef {
+  int find(const char *) const;
+};
+}  // namespace llvm
+
+struct NotStringRef {
+  int find(const char *);
+};
+
+void StringFind() {
+  std::string Str;
+
+  Str.find("a");
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'find' called with a string literal consisting of a single character; consider using the more effective overload accepting a character [performance-faster-string-find]
+  // CHECK-FIXES: Str.find('a');
+
+  // Works with the pos argument.
+  Str.find("a", 1);
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'find' called with a string literal
+  // CHECK-FIXES: Str.find('a', 1);
+
+  // Doens't work with strings smaller or larger than 1 char.
+  Str.find("");
+  Str.find("ab");
+
+  // Doesn't do anything with the 3 argument overload.
+  Str.find("a", 1, 1);
+
+  // Other methods that can also be replaced
+  Str.rfind("a");
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: 'rfind' called with a string literal
+  // CHECK-FIXES: Str.rfind('a');
+  Str.find_first_of("a");
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: 'find_first_of' called with a string
+  // CHECK-FIXES: Str.find_first_of('a');
+  Str.find_first_not_of("a");
+  // CHECK-MESSAGES: [[@LINE-1]]:25: warning: 'find_first_not_of' called with a
+  // CHECK-FIXES: Str.find_first_not_of('a');
+  Str.find_last_of("a");
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'find_last_of' called with a string
+  // CHECK-FIXES: Str.find_last_of('a');
+  Str.find_last_not_of("a");
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: 'find_last_not_of' called with a
+  // CHECK-FIXES: Str.find_last_not_of('a');
+
+  // std::wstring should work.
+  std::wstring WStr;
+  WStr.find(L"n");
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: 'find' called with a string literal
+  // CHECK-FIXES: Str.find(L'n');
+  // Even with unicode that fits in one wide char.
+  WStr.find(L"\x3A9");
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: 'find' called with a string literal
+  // CHECK-FIXES: Str.find(L'\x3A9');
+
+  // Also with other types, but only if it was specified in the options.
+  llvm::StringRef sr;
+  sr.find("x");
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: 'find' called with a string literal
+  // CHECK-FIXES: sr.find('x');
+  NotStringRef nsr;
+  nsr.find("x");
+}
+
+
+template <typename T>
+int FindTemplateDependant(T value) {
+  return value.find("A");
+}
+template <typename T>
+int FindTemplateNotDependant(T pos) {
+  return std::string().find("A", pos);
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: 'find' called with a string literal
+  // CHECK-FIXES: return std::string().find('A', pos);
+}
+
+int FindStr() {
+  return FindTemplateDependant(std::string()) + FindTemplateNotDependant(1);
+}
+
+#define STR_MACRO(str) str.find("A")
+#define POS_MACRO(pos) std::string().find("A",pos)
+
+int Macros() {
+  return STR_MACRO(std::string()) + POS_MACRO(1);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'find' called with a string literal
+  // CHECK-MESSAGES: [[@LINE-2]]:37: warning: 'find' called with a string literal
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-for-range-copy-warn-on-all-auto-copies.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-for-range-copy-warn-on-all-auto-copies.cpp
new file mode 100644
index 0000000..75655a6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-for-range-copy-warn-on-all-auto-copies.cpp
@@ -0,0 +1,39 @@
+// RUN: %check_clang_tidy %s performance-for-range-copy %t -config="{CheckOptions: [{key: "performance-for-range-copy.WarnOnAllAutoCopies", value: 1}]}" -- -std=c++11
+
+template <typename T>
+struct Iterator {
+  void operator++() {}
+  const T& operator*() {
+    static T* TT = new T();
+    return *TT;
+  }
+  bool operator!=(const Iterator &) { return false; }
+};
+template <typename T>
+struct View {
+  T begin() { return T(); }
+  T begin() const { return T(); }
+  T end() { return T(); }
+  T end() const { return T(); }
+};
+
+struct S {
+  S();
+  S(const S &);
+  ~S();
+  S &operator=(const S &);
+};
+
+void NegativeLoopVariableNotAuto() {
+  for (S S1 : View<Iterator<S>>()) {
+    S* S2 = &S1;
+  }
+}
+
+void PositiveTriggeredForAutoLoopVariable() {
+  for (auto S1 : View<Iterator<S>>()) {
+    // CHECK-MESSAGES: [[@LINE-1]]:13: warning: the loop variable's type is not a reference type; this creates a copy in each iteration; consider making this a reference [performance-for-range-copy]
+    // CHECK-FIXES: for (const auto& S1 : View<Iterator<S>>()) {
+    S* S2 = &S1;
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-for-range-copy.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-for-range-copy.cpp
new file mode 100644
index 0000000..1c77996
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-for-range-copy.cpp
@@ -0,0 +1,262 @@
+// RUN: %check_clang_tidy %s performance-for-range-copy %t -- -- -std=c++11 -fno-delayed-template-parsing
+
+namespace std {
+
+template <typename _Tp>
+struct remove_reference { typedef _Tp type; };
+
+template <typename _Tp>
+constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) {
+  return static_cast<typename std::remove_reference<_Tp>::type &&>(__t);
+}
+
+} // std
+
+template <typename T>
+struct Iterator {
+  void operator++() {}
+  const T& operator*() {
+    static T* TT = new T();
+    return *TT;
+  }
+  bool operator!=(const Iterator &) { return false; }
+  typedef const T& const_reference;
+};
+template <typename T>
+struct View {
+  T begin() { return T(); }
+  T begin() const { return T(); }
+  T end() { return T(); }
+  T end() const { return T(); }
+  typedef typename T::const_reference const_reference;
+};
+
+struct ConstructorConvertible {
+};
+
+struct S {
+  S();
+  S(const S &);
+  S(const ConstructorConvertible&) {}
+  ~S();
+  S &operator=(const S &);
+};
+
+struct Convertible {
+  operator S() const {
+    return S();
+  }
+};
+
+void negativeConstReference() {
+  for (const S &S1 : View<Iterator<S>>()) {
+  }
+}
+
+void negativeUserDefinedConversion() {
+  Convertible C[0];
+  for (const S &S1 : C) {
+  }
+}
+
+void negativeImplicitConstructorConversion() {
+  ConstructorConvertible C[0];
+  for (const S &S1 : C) {
+  }
+}
+
+template <typename T>
+void uninstantiated() {
+  for (const S S1 : View<Iterator<S>>()) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: the loop variable's type is not a reference type; this creates a copy in each iteration; consider making this a reference [performance-for-range-copy]
+  // CHECK-FIXES: {{^}}  for (const S& S1 : View<Iterator<S>>()) {}
+
+  // Don't warn on dependent types.
+  for (const T t1 : View<Iterator<T>>()) {
+  }
+}
+
+template <typename T>
+void instantiated() {
+  for (const S S2 : View<Iterator<S>>()) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: the loop variable's type is {{.*}}
+  // CHECK-FIXES: {{^}}  for (const S& S2 : View<Iterator<S>>()) {}
+
+  for (const T T2 : View<Iterator<T>>()) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: the loop variable's type is {{.*}}
+  // CHECK-FIXES: {{^}}  for (const T& T2 : View<Iterator<T>>()) {}
+}
+
+template <typename T>
+void instantiatedNegativeTypedefConstReference() {
+  for (typename T::const_reference T2 : T()) {
+    S S1 = T2;
+  }
+}
+
+void f() {
+  instantiated<int>();
+  instantiated<S>();
+  instantiatedNegativeTypedefConstReference<View<Iterator<S>>>();
+}
+
+struct Mutable {
+  Mutable() {}
+  Mutable(const Mutable &) = default;
+  Mutable(const Mutable &, const Mutable &) {}
+  void setBool(bool B) {}
+  bool constMethod() const {
+    return true;
+  }
+  Mutable& operator[](int I) {
+    return *this;
+  }
+  bool operator==(const Mutable &Other) const {
+    return true;
+  }
+  ~Mutable() {}
+};
+
+struct Point {
+  ~Point() {}
+  int x, y;
+};
+
+Mutable& operator<<(Mutable &Out, bool B) {
+  Out.setBool(B);
+  return Out;
+}
+
+bool operator!=(const Mutable& M1, const Mutable& M2) {
+  return false;
+}
+
+void use(const Mutable &M);
+void use(int I);
+void useTwice(const Mutable &M1, const Mutable &M2);
+void useByValue(Mutable M);
+void useByConstValue(const Mutable M);
+void mutate(Mutable *M);
+void mutate(Mutable &M);
+void onceConstOnceMutated(const Mutable &M1, Mutable &M2);
+
+void negativeVariableIsMutated() {
+  for (auto M : View<Iterator<Mutable>>()) {
+    mutate(M);
+  }
+  for (auto M : View<Iterator<Mutable>>()) {
+    mutate(&M);
+  }
+  for (auto M : View<Iterator<Mutable>>()) {
+    M.setBool(true);
+  }
+}
+
+void negativeOnceConstOnceMutated() {
+  for (auto M : View<Iterator<Mutable>>()) {
+    onceConstOnceMutated(M, M);
+  }
+}
+
+void negativeVarIsMoved() {
+  for (auto M : View<Iterator<Mutable>>()) {
+    auto Moved = std::move(M);
+  }
+}
+
+void negativeNonConstOperatorIsInvoked() {
+  for (auto NonConstOperatorInvokee : View<Iterator<Mutable>>()) {
+    auto& N = NonConstOperatorInvokee[0];
+  }
+}
+
+void negativeNonConstNonMemberOperatorInvoked() {
+  for (auto NonConstOperatorInvokee : View<Iterator<Mutable>>()) {
+    NonConstOperatorInvokee << true;
+  }
+}
+
+void negativeConstCheapToCopy() {
+  for (const int I : View<Iterator<int>>()) {
+  }
+}
+
+void negativeConstCheapToCopyTypedef() {
+  typedef const int ConstInt;
+  for (ConstInt C  : View<Iterator<ConstInt>>()) {
+  }
+}
+
+void negativeCheapToCopy() {
+  for (int I : View<Iterator<int>>()) {
+    use(I);
+  }
+}
+
+void negativeCheapToCopyTypedef() {
+  typedef int Int;
+  for (Int I : View<Iterator<Int>>()) {
+    use(I);
+  }
+}
+
+void positiveOnlyConstMethodInvoked() {
+  for (auto M : View<Iterator<Mutable>>()) {
+    // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+    // CHECK-FIXES: for (const auto& M : View<Iterator<Mutable>>()) {
+    M.constMethod();
+  }
+}
+
+void positiveOnlyUsedAsConstArguments() {
+  for (auto UsedAsConst : View<Iterator<Mutable>>()) {
+    // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+    // CHECK-FIXES: for (const auto& UsedAsConst : View<Iterator<Mutable>>()) {
+    use(UsedAsConst);
+    useTwice(UsedAsConst, UsedAsConst);
+    useByValue(UsedAsConst);
+    useByConstValue(UsedAsConst);
+  }
+}
+
+void positiveOnlyAccessedFieldAsConst() {
+  for (auto UsedAsConst : View<Iterator<Point>>()) {
+    // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+    // CHECK-FIXES: for (const auto& UsedAsConst : View<Iterator<Point>>()) {
+    use(UsedAsConst.x);
+    use(UsedAsConst.y);
+  }
+}
+
+void positiveOnlyUsedInCopyConstructor() {
+  for (auto A : View<Iterator<Mutable>>()) {
+    // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+    // CHECK-FIXES: for (const auto& A : View<Iterator<Mutable>>()) {
+    Mutable Copy = A;
+    Mutable Copy2(A);
+  }
+}
+
+void positiveTwoConstConstructorArgs() {
+  for (auto A : View<Iterator<Mutable>>()) {
+    // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+    // CHECK-FIXES: for (const auto& A : View<Iterator<Mutable>>()) {
+    Mutable Copy(A, A);
+  }
+}
+
+void PositiveConstMemberOperatorInvoked() {
+  for (auto ConstOperatorInvokee : View<Iterator<Mutable>>()) {
+    // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+    // CHECK-FIXES: for (const auto& ConstOperatorInvokee : View<Iterator<Mutable>>()) {
+    bool result = ConstOperatorInvokee == Mutable();
+  }
+}
+
+void PositiveConstNonMemberOperatorInvoked() {
+  for (auto ConstOperatorInvokee : View<Iterator<Mutable>>()) {
+    // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+    // CHECK-FIXES: for (const auto& ConstOperatorInvokee : View<Iterator<Mutable>>()) {
+    bool result = ConstOperatorInvokee != Mutable();
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-implicit-conversion-in-loop.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-implicit-conversion-in-loop.cpp
new file mode 100644
index 0000000..72f9e52
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-implicit-conversion-in-loop.cpp
@@ -0,0 +1,197 @@
+// RUN: %check_clang_tidy %s performance-implicit-conversion-in-loop %t
+
+// ---------- Classes used in the tests ----------
+
+// Iterator returning by value.
+template <typename T>
+struct Iterator {
+  void operator++();
+  T operator*();
+  bool operator!=(const Iterator& other);
+};
+
+// Iterator returning by reference.
+template <typename T>
+struct RefIterator {
+  void operator++();
+  T& operator*();
+  bool operator!=(const RefIterator& other);
+};
+
+// The template argument is an iterator type, and a view is an object you can
+// run a for loop on.
+template <typename T>
+struct View {
+  T begin();
+  T end();
+};
+
+// With this class, the implicit conversion is a call to the (implicit)
+// constructor of the class.
+template <typename T>
+class ImplicitWrapper {
+ public:
+  // Implicit!
+  ImplicitWrapper(const T& t);
+};
+
+// With this class, the implicit conversion is a call to the conversion
+// operators of SimpleClass and ComplexClass.
+template <typename T>
+class OperatorWrapper {
+ public:
+  OperatorWrapper() = delete;
+};
+
+struct SimpleClass {
+  int foo;
+  operator OperatorWrapper<SimpleClass>();
+};
+
+// The materialize expression is not the same when the class has a destructor,
+// so we make sure we cover that case too.
+class ComplexClass {
+ public:
+  ComplexClass();
+  ~ComplexClass();
+  operator OperatorWrapper<ComplexClass>();
+};
+
+typedef View<Iterator<SimpleClass>> SimpleView;
+typedef View<RefIterator<SimpleClass>> SimpleRefView;
+typedef View<Iterator<ComplexClass>> ComplexView;
+typedef View<RefIterator<ComplexClass>> ComplexRefView;
+
+// ---------- The test themselves ----------
+// For each test we do, in the same order, const ref, non const ref, const
+// value, non const value.
+
+void SimpleClassIterator() {
+  for (const SimpleClass& foo : SimpleView()) {}
+  // This line does not compile because a temporary cannot be assigned to a non
+  // const reference.
+  // for (SimpleClass& foo : SimpleView()) {}
+  for (const SimpleClass foo : SimpleView()) {}
+  for (SimpleClass foo : SimpleView()) {}
+}
+
+void SimpleClassRefIterator() {
+  for (const SimpleClass& foo : SimpleRefView()) {}
+  for (SimpleClass& foo : SimpleRefView()) {}
+  for (const SimpleClass foo : SimpleRefView()) {}
+  for (SimpleClass foo : SimpleRefView()) {}
+}
+
+void ComplexClassIterator() {
+  for (const ComplexClass& foo : ComplexView()) {}
+  // for (ComplexClass& foo : ComplexView()) {}
+  for (const ComplexClass foo : ComplexView()) {}
+  for (ComplexClass foo : ComplexView()) {}
+}
+
+void ComplexClassRefIterator() {
+  for (const ComplexClass& foo : ComplexRefView()) {}
+  for (ComplexClass& foo : ComplexRefView()) {}
+  for (const ComplexClass foo : ComplexRefView()) {}
+  for (ComplexClass foo : ComplexRefView()) {}
+}
+
+void ImplicitSimpleClassIterator() {
+  for (const ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the loop variable 'foo' is different from the one returned by the iterator and generates an implicit conversion; you can either change the type to the matching one ('const SimpleClass &' but 'const auto&' is always a valid option) or remove the reference to make it explicit that you are creating a new value [performance-implicit-conversion-in-loop]
+  // for (ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}
+  for (const ImplicitWrapper<SimpleClass> foo : SimpleView()) {}
+  for (ImplicitWrapper<SimpleClass> foo : SimpleView()) {}
+}
+
+void ImplicitSimpleClassRefIterator() {
+  for (const ImplicitWrapper<SimpleClass>& foo : SimpleRefView()) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
+  // for (ImplicitWrapper<SimpleClass>& foo : SimpleRefView()) {}
+  for (const ImplicitWrapper<SimpleClass> foo : SimpleRefView()) {}
+  for (ImplicitWrapper<SimpleClass> foo : SimpleRefView()) {}
+}
+
+void ImplicitSimpleClassArray() {
+  SimpleClass array[5];
+  for (const ImplicitWrapper<SimpleClass>& foo : array) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
+  // for (ImplicitWrapper<SimpleClass>& foo : array) {}
+  for (const ImplicitWrapper<SimpleClass> foo : array) {}
+  for (ImplicitWrapper<SimpleClass> foo : array) {}
+}
+
+void ImplicitComplexClassIterator() {
+  for (const ImplicitWrapper<ComplexClass>& foo : ComplexView()) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
+  // for (ImplicitWrapper<ComplexClass>& foo : ComplexView()) {}
+  for (const ImplicitWrapper<ComplexClass> foo : ComplexView()) {}
+  for (ImplicitWrapper<ComplexClass> foo : ComplexView()) {}
+}
+
+void ImplicitComplexClassRefIterator() {
+  ComplexClass array[5];
+  for (const ImplicitWrapper<ComplexClass>& foo : array) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
+  // for (ImplicitWrapper<ComplexClass>& foo : array) {}
+  for (const ImplicitWrapper<ComplexClass> foo : array) {}
+  for (ImplicitWrapper<ComplexClass> foo : array) {}
+}
+
+void ImplicitComplexClassArray() {
+  for (const ImplicitWrapper<ComplexClass>& foo : ComplexRefView()) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
+  // for (ImplicitWrapper<ComplexClass>& foo : ComplexRefView()) {}
+  for (const ImplicitWrapper<ComplexClass> foo : ComplexRefView()) {}
+  for (ImplicitWrapper<ComplexClass> foo : ComplexRefView()) {}
+}
+
+void OperatorSimpleClassIterator() {
+  for (const OperatorWrapper<SimpleClass>& foo : SimpleView()) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
+  // for (OperatorWrapper<SimpleClass>& foo : SimpleView()) {}
+  for (const OperatorWrapper<SimpleClass> foo : SimpleView()) {}
+  for (OperatorWrapper<SimpleClass> foo : SimpleView()) {}
+}
+
+void OperatorSimpleClassRefIterator() {
+  for (const OperatorWrapper<SimpleClass>& foo : SimpleRefView()) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
+  // for (OperatorWrapper<SimpleClass>& foo : SimpleRefView()) {}
+  for (const OperatorWrapper<SimpleClass> foo : SimpleRefView()) {}
+  for (OperatorWrapper<SimpleClass> foo : SimpleRefView()) {}
+}
+
+void OperatorSimpleClassArray() {
+  SimpleClass array[5];
+  for (const OperatorWrapper<SimpleClass>& foo : array) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
+  // for (OperatorWrapper<SimpleClass>& foo : array) {}
+  for (const OperatorWrapper<SimpleClass> foo : array) {}
+  for (OperatorWrapper<SimpleClass> foo : array) {}
+}
+
+void OperatorComplexClassIterator() {
+  for (const OperatorWrapper<ComplexClass>& foo : ComplexView()) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
+  // for (OperatorWrapper<ComplexClass>& foo : ComplexView()) {}
+  for (const OperatorWrapper<ComplexClass> foo : ComplexView()) {}
+  for (OperatorWrapper<ComplexClass> foo : ComplexView()) {}
+}
+
+void OperatorComplexClassRefIterator() {
+  for (const OperatorWrapper<ComplexClass>& foo : ComplexRefView()) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
+  // for (OperatorWrapper<ComplexClass>& foo : ComplexRefView()) {}
+  for (const OperatorWrapper<ComplexClass> foo : ComplexRefView()) {}
+  for (OperatorWrapper<ComplexClass> foo : ComplexRefView()) {}
+}
+
+void OperatorComplexClassArray() {
+  ComplexClass array[5];
+  for (const OperatorWrapper<ComplexClass>& foo : array) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
+  // for (OperatorWrapper<ComplexClass>& foo : array) {}
+  for (const OperatorWrapper<ComplexClass> foo : array) {}
+  for (OperatorWrapper<ComplexClass> foo : array) {}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-algorithm.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-algorithm.cpp
new file mode 100644
index 0000000..19a6701
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-algorithm.cpp
@@ -0,0 +1,166 @@
+// RUN: %check_clang_tidy %s performance-inefficient-algorithm %t
+
+namespace std {
+template <typename T> struct less {
+  bool operator()(const T &lhs, const T &rhs) { return lhs < rhs; }
+};
+
+template <typename T> struct greater {
+  bool operator()(const T &lhs, const T &rhs) { return lhs > rhs; }
+};
+
+struct iterator_type {};
+
+template <typename K, typename Cmp = less<K>> struct set {
+  typedef iterator_type iterator;
+  iterator find(const K &k);
+  unsigned count(const K &k);
+
+  iterator begin();
+  iterator end();
+  iterator begin() const;
+  iterator end() const;
+};
+
+struct other_iterator_type {};
+
+template <typename K, typename V, typename Cmp = less<K>> struct map {
+  typedef other_iterator_type iterator;
+  iterator find(const K &k);
+  unsigned count(const K &k);
+
+  iterator begin();
+  iterator end();
+  iterator begin() const;
+  iterator end() const;
+};
+
+template <typename K, typename V> struct multimap : map<K, V> {};
+template <typename K> struct unordered_set : set<K> {};
+template <typename K, typename V> struct unordered_map : map<K, V> {};
+template <typename K> struct unordered_multiset : set<K> {};
+template <typename K, typename V> struct unordered_multimap : map<K, V> {};
+
+template <typename K, typename Cmp = less<K>> struct multiset : set<K, Cmp> {};
+
+template <typename FwIt, typename K>
+FwIt find(FwIt, FwIt end, const K &) { return end; }
+
+template <typename FwIt, typename K, typename Cmp>
+FwIt find(FwIt, FwIt end, const K &, Cmp) { return end; }
+
+template <typename FwIt, typename Pred>
+FwIt find_if(FwIt, FwIt end, Pred) { return end; }
+
+template <typename FwIt, typename K>
+unsigned count(FwIt, FwIt, const K &) { return 0; }
+
+template <typename FwIt, typename K>
+FwIt lower_bound(FwIt, FwIt end, const K &) { return end; }
+
+template <typename FwIt, typename K, typename Ord>
+FwIt lower_bound(FwIt, FwIt end, const K &, Ord) { return end; }
+}
+
+#define FIND_IN_SET(x) find(x.begin(), x.end(), 10)
+// CHECK-FIXES: #define FIND_IN_SET(x) find(x.begin(), x.end(), 10)
+
+template <typename T> void f(const T &t) {
+  std::set<int> s;
+  find(s.begin(), s.end(), 46);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+  // CHECK-FIXES: {{^  }}s.find(46);{{$}}
+
+  find(t.begin(), t.end(), 46);
+  // CHECK-FIXES: {{^  }}find(t.begin(), t.end(), 46);{{$}}
+}
+
+int main() {
+  std::set<int> s;
+  auto it = std::find(s.begin(), s.end(), 43);
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: this STL algorithm call should be replaced with a container method [performance-inefficient-algorithm]
+  // CHECK-FIXES: {{^  }}auto it = s.find(43);{{$}}
+  auto c = count(s.begin(), s.end(), 43);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: this STL algorithm call should be
+  // CHECK-FIXES: {{^  }}auto c = s.count(43);{{$}}
+
+#define SECOND(x, y, z) y
+  SECOND(q,std::count(s.begin(), s.end(), 22),w);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: this STL algorithm call should be
+  // CHECK-FIXES: {{^  }}SECOND(q,s.count(22),w);{{$}}
+
+  it = find_if(s.begin(), s.end(), [](int) { return false; });
+
+  std::multiset<int> ms;
+  find(ms.begin(), ms.end(), 46);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+  // CHECK-FIXES: {{^  }}ms.find(46);{{$}}
+
+  const std::multiset<int> &msref = ms;
+  find(msref.begin(), msref.end(), 46);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+  // CHECK-FIXES: {{^  }}msref.find(46);{{$}}
+
+  std::multiset<int> *msptr = &ms;
+  find(msptr->begin(), msptr->end(), 46);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+  // CHECK-FIXES: {{^  }}msptr->find(46);{{$}}
+
+  it = std::find(s.begin(), s.end(), 43, std::greater<int>());
+  // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: different comparers used in the algorithm and the container [performance-inefficient-algorithm]
+
+  FIND_IN_SET(s);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+  // CHECK-FIXES: {{^  }}FIND_IN_SET(s);{{$}}
+
+  f(s);
+
+  std::unordered_set<int> us;
+  lower_bound(us.begin(), us.end(), 10);
+  // CHECK-FIXES: {{^  }}lower_bound(us.begin(), us.end(), 10);{{$}}
+  find(us.begin(), us.end(), 10);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+  // CHECK-FIXES: {{^  }}us.find(10);{{$}}
+
+  std::unordered_multiset<int> ums;
+  find(ums.begin(), ums.end(), 10);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+  // CHECK-FIXES: {{^  }}ums.find(10);{{$}}
+
+  std::map<int, int> intmap;
+  find(intmap.begin(), intmap.end(), 46);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+  // CHECK-FIXES: {{^  }}find(intmap.begin(), intmap.end(), 46);{{$}}
+
+  std::multimap<int, int> intmmap;
+  find(intmmap.begin(), intmmap.end(), 46);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+  // CHECK-FIXES: {{^  }}find(intmmap.begin(), intmmap.end(), 46);{{$}}
+
+  std::unordered_map<int, int> umap;
+  find(umap.begin(), umap.end(), 46);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+  // CHECK-FIXES: {{^  }}find(umap.begin(), umap.end(), 46);{{$}}
+
+  std::unordered_multimap<int, int> ummap;
+  find(ummap.begin(), ummap.end(), 46);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+  // CHECK-FIXES: {{^  }}find(ummap.begin(), ummap.end(), 46);{{$}}
+}
+
+struct Value {
+  int value;
+};
+
+struct Ordering {
+  bool operator()(const Value &lhs, const Value &rhs) const {
+    return lhs.value < rhs.value;
+  }
+  bool operator()(int lhs, const Value &rhs) const { return lhs < rhs.value; }
+};
+
+void g(std::set<Value, Ordering> container, int value) {
+  lower_bound(container.begin(), container.end(), value, Ordering());
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be
+  // CHECK-FIXES: {{^  }}lower_bound(container.begin(), container.end(), value, Ordering());{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-string-concatenation.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-string-concatenation.cpp
new file mode 100644
index 0000000..1dbd56b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-string-concatenation.cpp
@@ -0,0 +1,48 @@
+// RUN: %check_clang_tidy %s performance-inefficient-string-concatenation %t
+
+namespace std {
+template <typename T>
+class basic_string {
+public:
+  basic_string() {}
+  ~basic_string() {}
+  basic_string<T> *operator+=(const basic_string<T> &) {}
+  friend basic_string<T> operator+(const basic_string<T> &, const basic_string<T> &) {}
+};
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+}
+
+void f(std::string) {}
+std::string g(std::string) {}
+
+int main() {
+  std::string mystr1, mystr2;
+  std::wstring mywstr1, mywstr2;
+  auto myautostr1 = mystr1;
+  auto myautostr2 = mystr2;
+
+  for (int i = 0; i < 10; ++i) {
+    f(mystr1 + mystr2 + mystr1);
+    // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: string concatenation results in allocation of unnecessary temporary strings; consider using 'operator+=' or 'string::append()' instead
+    mystr1 = mystr1 + mystr2;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: string concatenation
+    mystr1 = mystr2 + mystr2 + mystr2;
+    // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: string concatenation
+    mystr1 = mystr2 + mystr1;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: string concatenation
+    mywstr1 = mywstr2 + mywstr1;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: string concatenation
+    mywstr1 = mywstr2 + mywstr2 + mywstr2;
+    // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: string concatenation
+    myautostr1 = myautostr1 + myautostr2;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: string concatenation
+
+    mywstr1 = mywstr2 + mywstr2;
+    mystr1 = mystr2 + mystr2;
+    mystr1 += mystr2;
+    f(mystr2 + mystr1);
+    mystr1 = g(mystr1);
+  }
+  return 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-vector-operation.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-vector-operation.cpp
new file mode 100644
index 0000000..a04f66e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-inefficient-vector-operation.cpp
@@ -0,0 +1,277 @@
+// RUN: %check_clang_tidy %s performance-inefficient-vector-operation %t -- -format-style=llvm -- --std=c++11
+
+namespace std {
+
+typedef int size_t;
+
+template<class E> class initializer_list {
+public:
+  using value_type = E;
+  using reference = E&;
+  using const_reference = const E&;
+  using size_type = size_t;
+  using iterator = const E*;
+  using const_iterator = const E*;
+  initializer_list();
+  size_t size() const; // number of elements
+  const E* begin() const; // first element
+  const E* end() const; // one past the last element
+};
+
+// initializer list range access
+template<class E> const E* begin(initializer_list<E> il);
+template<class E> const E* end(initializer_list<E> il);
+
+template <class T>
+class vector {
+ public:
+  typedef T* iterator;
+  typedef const T* const_iterator;
+  typedef T& reference;
+  typedef const T& const_reference;
+  typedef size_t size_type;
+
+  explicit vector();
+  explicit vector(size_type n);
+
+  void push_back(const T& val);
+
+  template <class... Args> void emplace_back(Args &&... args);
+
+  void reserve(size_t n);
+  void resize(size_t n);
+
+  size_t size();
+  const_reference operator[] (size_type) const;
+  reference operator[] (size_type);
+
+  const_iterator begin() const;
+  const_iterator end() const;
+};
+} // namespace std
+
+class Foo {
+ public:
+  explicit Foo(int);
+};
+
+class Bar {
+ public:
+  Bar(int);
+};
+
+int Op(int);
+
+void f(std::vector<int>& t) {
+  {
+    std::vector<int> v0;
+    // CHECK-FIXES: v0.reserve(10);
+    for (int i = 0; i < 10; ++i)
+      v0.push_back(i);
+      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called inside a loop; consider pre-allocating the vector capacity before the loop
+  }
+  {
+    std::vector<int> v1;
+    // CHECK-FIXES: v1.reserve(10);
+    for (int i = 0; i < 10; i++)
+      v1.push_back(i);
+      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+  }
+  {
+    std::vector<int> v2;
+    // CHECK-FIXES: v2.reserve(10);
+    for (int i = 0; i < 10; ++i)
+      v2.push_back(0);
+      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+  }
+  {
+    std::vector<int> v3;
+    // CHECK-FIXES: v3.reserve(5);
+    for (int i = 0; i < 5; ++i) {
+      v3.push_back(i);
+      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+    }
+    // CHECK-FIXES-NOT: v3.reserve(10);
+    for (int i = 0; i < 10; ++i) {
+      // No fix for this loop as we encounter the prior loops.
+      v3.push_back(i);
+    }
+  }
+  {
+    std::vector<int> v4;
+    std::vector<int> v5;
+    v5.reserve(3);
+    // CHECK-FIXES: v4.reserve(10);
+    for (int i = 0; i < 10; ++i)
+      v4.push_back(i);
+      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+  }
+  {
+    std::vector<int> v6;
+    // CHECK-FIXES: v6.reserve(t.size());
+    for (std::size_t i = 0; i < t.size(); ++i) {
+      v6.push_back(t[i]);
+      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+    }
+  }
+  {
+    std::vector<int> v7;
+    // CHECK-FIXES: v7.reserve(t.size() - 1);
+    for (std::size_t i = 0; i < t.size() - 1; ++i) {
+      v7.push_back(t[i]);
+    } // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+  }
+  {
+    std::vector<int> v8;
+    // CHECK-FIXES: v8.reserve(t.size());
+    for (const auto &e : t) {
+      v8.push_back(e);
+      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+    }
+  }
+  {
+    std::vector<int> v9;
+    // CHECK-FIXES: v9.reserve(t.size());
+    for (const auto &e : t) {
+      v9.push_back(Op(e));
+      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+    }
+  }
+  {
+    std::vector<Foo> v10;
+    // CHECK-FIXES: v10.reserve(t.size());
+    for (const auto &e : t) {
+      v10.push_back(Foo(e));
+      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+    }
+  }
+  {
+    std::vector<Bar> v11;
+    // CHECK-FIXES: v11.reserve(t.size());
+    for (const auto &e : t) {
+      v11.push_back(e);
+      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+    }
+  }
+  {
+    std::vector<Foo> v12;
+    // CHECK-FIXES: v12.reserve(t.size());
+    for (const auto &e : t) {
+      v12.emplace_back(e);
+      // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'emplace_back' is called
+    }
+  }
+
+  // ---- Non-fixed Cases ----
+  {
+    std::vector<int> z0;
+    z0.reserve(20);
+    // CHECK-FIXES-NOT: z0.reserve(10);
+    // There is a "reserve" call already.
+    for (int i = 0; i < 10; ++i) {
+      z0.push_back(i);
+    }
+  }
+  {
+    std::vector<int> z1;
+    z1.reserve(5);
+    // CHECK-FIXES-NOT: z1.reserve(10);
+    // There is a "reserve" call already.
+    for (int i = 0; i < 10; ++i) {
+      z1.push_back(i);
+    }
+  }
+  {
+    std::vector<int> z2;
+    z2.resize(5);
+    // CHECK-FIXES-NOT: z2.reserve(10);
+    // There is a ref usage of v before the loop.
+    for (int i = 0; i < 10; ++i) {
+      z2.push_back(i);
+    }
+  }
+  {
+    std::vector<int> z3;
+    z3.push_back(0);
+    // CHECK-FIXES-NOT: z3.reserve(10);
+    // There is a ref usage of v before the loop.
+    for (int i = 0; i < 10; ++i) {
+      z3.push_back(i);
+    }
+  }
+  {
+    std::vector<int> z4;
+    f(z4);
+    // CHECK-FIXES-NOT: z4.reserve(10);
+    // There is a ref usage of z4 before the loop.
+    for (int i = 0; i < 10; ++i) {
+      z4.push_back(i);
+    }
+  }
+  {
+    std::vector<int> z5(20);
+    // CHECK-FIXES-NOT: z5.reserve(10);
+    // z5 is not constructed with default constructor.
+    for (int i = 0; i < 10; ++i) {
+      z5.push_back(i);
+    }
+  }
+  {
+    std::vector<int> z6;
+    // CHECK-FIXES-NOT: z6.reserve(10);
+    // For-loop is not started with 0.
+    for (int i = 1; i < 10; ++i) {
+      z6.push_back(i);
+    }
+  }
+  {
+    std::vector<int> z7;
+    // CHECK-FIXES-NOT: z7.reserve(t.size());
+    // z7 isn't referenced in for-loop body.
+    for (std::size_t i = 0; i < t.size(); ++i) {
+      t.push_back(i);
+    }
+  }
+  {
+    std::vector<int> z8;
+    int k;
+    // CHECK-FIXES-NOT: z8.reserve(10);
+    // For-loop isn't a fixable loop.
+    for (std::size_t i = 0; k < 10; ++i) {
+      z8.push_back(t[i]);
+    }
+  }
+  {
+    std::vector<int> z9;
+    // CHECK-FIXES-NOT: z9.reserve(i + 1);
+    // The loop end expression refers to the loop variable i.
+    for (int i = 0; i < i + 1; i++)
+      z9.push_back(i);
+  }
+  {
+    std::vector<int> z10;
+    int k;
+    // CHECK-FIXES-NOT: z10.reserve(10);
+    // For-loop isn't a fixable loop.
+    for (std::size_t i = 0; i < 10; ++k) {
+      z10.push_back(t[i]);
+    }
+  }
+  {
+    std::vector<int> z11;
+    // initializer_list should not trigger the check.
+    for (int e : {1, 2, 3, 4, 5}) {
+      z11.push_back(e);
+    }
+  }
+  {
+    std::vector<int> z12;
+    std::vector<int>* z13 = &t;
+    // We only support detecting the range init expression which references
+    // container directly.
+    // Complex range init expressions like `*z13` is not supported.
+    for (const auto &e : *z13) {
+      z12.push_back(e);
+    }
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-const-arg-trivially-copyable.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-const-arg-trivially-copyable.cpp
new file mode 100644
index 0000000..ea0c2fc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-const-arg-trivially-copyable.cpp
@@ -0,0 +1,98 @@
+// RUN: %check_clang_tidy %s performance-move-const-arg %t \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: performance-move-const-arg.CheckTriviallyCopyableMove, value: 0}]}' \
+// RUN: -- -std=c++14
+
+namespace std {
+
+template <typename> struct remove_reference;
+template <typename _Tp> struct remove_reference { typedef _Tp type; };
+template <typename _Tp> struct remove_reference<_Tp &> { typedef _Tp type; };
+template <typename _Tp> struct remove_reference<_Tp &&> { typedef _Tp type; };
+
+template <typename _Tp>
+constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) {
+  return static_cast<typename std::remove_reference<_Tp>::type &&>(__t);
+}
+
+template <typename _Tp>
+constexpr _Tp &&
+forward(typename remove_reference<_Tp>::type &__t) noexcept {
+  return static_cast<_Tp &&>(__t);
+}
+
+} // namespace std
+
+class NoMoveSemantics {
+ public:
+  NoMoveSemantics();
+  NoMoveSemantics(const NoMoveSemantics &);
+
+  NoMoveSemantics &operator=(const NoMoveSemantics &);
+};
+
+void callByConstRef(const NoMoveSemantics &);
+void callByConstRef(int i, const NoMoveSemantics &);
+
+void moveToConstReferencePositives() {
+  NoMoveSemantics obj;
+
+  // Basic case. It is here just to have a single "detected and fixed" case.
+  callByConstRef(std::move(obj));
+  // CHECK-MESSAGES: :[[@LINE-1]]:18:  warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
+  // CHECK-FIXES: callByConstRef(obj);
+}
+
+struct TriviallyCopyable {
+  int i;
+};
+
+void f(TriviallyCopyable) {}
+
+void g() {
+  TriviallyCopyable obj;
+  f(std::move(obj));
+}
+
+class MoveSemantics {
+ public:
+  MoveSemantics();
+  MoveSemantics(MoveSemantics &&);
+
+  MoveSemantics &operator=(MoveSemantics &&);
+};
+
+void fmovable(MoveSemantics);
+
+void lambda1() {
+  auto f = [](MoveSemantics m) {
+    fmovable(std::move(m));
+  };
+  f(MoveSemantics());
+}
+
+template<class T> struct function {};
+
+template<typename Result, typename... Args>
+class function<Result(Args...)> {
+public:
+  function() = default;
+  void operator()(Args... args) const {
+    fmovable(std::forward<Args>(args)...);
+  }
+};
+
+void functionInvocation() {
+  function<void(MoveSemantics)> callback;
+  MoveSemantics m;
+  callback(std::move(m));
+}
+
+void lambda2() {
+  function<void(MoveSemantics)> callback;
+
+  auto f = [callback = std::move(callback)](MoveSemantics m) mutable {
+    callback(std::move(m));
+  };
+  f(MoveSemantics());
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-const-arg.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-const-arg.cpp
new file mode 100644
index 0000000..06ed6e0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-const-arg.cpp
@@ -0,0 +1,248 @@
+// RUN: %check_clang_tidy %s performance-move-const-arg %t
+
+namespace std {
+template <typename>
+struct remove_reference;
+
+template <typename _Tp>
+struct remove_reference {
+  typedef _Tp type;
+};
+
+template <typename _Tp>
+struct remove_reference<_Tp &> {
+  typedef _Tp type;
+};
+
+template <typename _Tp>
+struct remove_reference<_Tp &&> {
+  typedef _Tp type;
+};
+
+template <typename _Tp>
+constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) {
+  return static_cast<typename std::remove_reference<_Tp>::type &&>(__t);
+}
+
+template <typename _Tp>
+constexpr _Tp &&
+forward(typename remove_reference<_Tp>::type &__t) noexcept {
+  return static_cast<_Tp &&>(__t);
+}
+
+} // namespace std
+
+class A {
+public:
+  A() {}
+  A(const A &rhs) {}
+  A(A &&rhs) {}
+};
+
+struct TriviallyCopyable {
+  int i;
+};
+
+void f(TriviallyCopyable) {}
+
+void g() {
+  TriviallyCopyable obj;
+  f(std::move(obj));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: std::move of the variable 'obj' of the trivially-copyable type 'TriviallyCopyable' has no effect; remove std::move() [performance-move-const-arg]
+  // CHECK-FIXES: f(obj);
+}
+
+int f1() {
+  return std::move(42);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the expression of the trivially-copyable type 'int' has no effect; remove std::move() [performance-move-const-arg]
+  // CHECK-FIXES: return 42;
+}
+
+int f2(int x2) {
+  return std::move(x2);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the variable 'x2' of the trivially-copyable type 'int'
+  // CHECK-FIXES: return x2;
+}
+
+int *f3(int *x3) {
+  return std::move(x3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the variable 'x3' of the trivially-copyable type 'int *'
+  // CHECK-FIXES: return x3;
+}
+
+A f4(A x4) { return std::move(x4); }
+
+A f5(const A x5) {
+  return std::move(x5);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the const variable 'x5' has no effect; remove std::move() or make the variable non-const [performance-move-const-arg]
+  // CHECK-FIXES: return x5;
+}
+
+template <typename T>
+T f6(const T x6) {
+  return std::move(x6);
+}
+
+void f7() { int a = f6(10); }
+
+#define M1(x) x
+void f8() {
+  const A a;
+  M1(A b = std::move(a);)
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: std::move of the const variable 'a' has no effect; remove std::move() or make the variable non-const
+  // CHECK-FIXES: M1(A b = a;)
+}
+
+#define M2(x) std::move(x)
+int f9() { return M2(1); }
+
+template <typename T>
+T f10(const int x10) {
+  return std::move(x10);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the const variable 'x10' of the trivially-copyable type 'const int' has no effect; remove std::move() [performance-move-const-arg]
+  // CHECK-FIXES: return x10;
+}
+void f11() {
+  f10<int>(1);
+  f10<double>(1);
+}
+
+class NoMoveSemantics {
+public:
+  NoMoveSemantics();
+  NoMoveSemantics(const NoMoveSemantics &);
+
+  NoMoveSemantics &operator=(const NoMoveSemantics &);
+};
+
+void callByConstRef(const NoMoveSemantics &);
+void callByConstRef(int i, const NoMoveSemantics &);
+
+void moveToConstReferencePositives() {
+  NoMoveSemantics obj;
+
+  // Basic case.
+  callByConstRef(std::move(obj));
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: passing result of std::move() as
+  // CHECK-FIXES: callByConstRef(obj);
+
+  // Also works for second argument.
+  callByConstRef(1, std::move(obj));
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: passing result of std::move() as
+  // CHECK-FIXES: callByConstRef(1, obj);
+
+  // Works if std::move() applied to a temporary.
+  callByConstRef(std::move(NoMoveSemantics()));
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: passing result of std::move() as
+  // CHECK-FIXES: callByConstRef(NoMoveSemantics());
+
+  // Works if calling a copy constructor.
+  NoMoveSemantics other(std::move(obj));
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: passing result of std::move() as
+  // CHECK-FIXES: NoMoveSemantics other(obj);
+
+  // Works if calling assignment operator.
+  other = std::move(obj);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: passing result of std::move() as
+  // CHECK-FIXES: other = obj;
+}
+
+class MoveSemantics {
+public:
+  MoveSemantics();
+  MoveSemantics(MoveSemantics &&);
+
+  MoveSemantics &operator=(MoveSemantics &&);
+};
+
+void callByValue(MoveSemantics);
+
+void callByRValueRef(MoveSemantics &&);
+
+template <class T>
+void templateFunction(T obj) {
+  T other = std::move(obj);
+}
+
+#define M3(T, obj)            \
+  do {                        \
+    T other = std::move(obj); \
+  } while (true)
+
+#define CALL(func) (func)()
+
+void moveToConstReferenceNegatives() {
+  // No warning when actual move takes place.
+  MoveSemantics move_semantics;
+  callByValue(std::move(move_semantics));
+  callByRValueRef(std::move(move_semantics));
+  MoveSemantics other(std::move(move_semantics));
+  other = std::move(move_semantics);
+
+  // No warning if std::move() not used.
+  NoMoveSemantics no_move_semantics;
+  callByConstRef(no_move_semantics);
+
+  // No warning if instantiating a template.
+  templateFunction(no_move_semantics);
+
+  // No warning inside of macro expansions.
+  M3(NoMoveSemantics, no_move_semantics);
+
+  // No warning inside of macro expansion, even if the macro expansion is inside
+  // a lambda that is, in turn, an argument to a macro.
+  CALL([no_move_semantics] { M3(NoMoveSemantics, no_move_semantics); });
+
+  auto lambda = [] {};
+  auto lambda2 = std::move(lambda);
+}
+
+class MoveOnly {
+public:
+  MoveOnly(const MoveOnly &other) = delete;
+  MoveOnly &operator=(const MoveOnly &other) = delete;
+  MoveOnly(MoveOnly &&other) = default;
+  MoveOnly &operator=(MoveOnly &&other) = default;
+};
+template <class T>
+void Q(T);
+void moveOnlyNegatives(MoveOnly val) {
+  Q(std::move(val));
+}
+
+void fmovable(MoveSemantics);
+
+void lambda1() {
+  auto f = [](MoveSemantics m) {
+    fmovable(std::move(m));
+  };
+  f(MoveSemantics());
+}
+
+template<class T> struct function {};
+
+template<typename Result, typename... Args>
+class function<Result(Args...)> {
+public:
+  function() = default;
+  void operator()(Args... args) const {
+    fmovable(std::forward<Args>(args)...);
+  }
+};
+
+void functionInvocation() {
+  function<void(MoveSemantics)> callback;
+  MoveSemantics m;
+  callback(std::move(m));
+}
+
+void lambda2() {
+  function<void(MoveSemantics)> callback;
+
+  auto f = [callback = std::move(callback)](MoveSemantics m) mutable {
+    // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: std::move of the variable 'callback' of the trivially-copyable type 'function<void (MoveSemantics)>' has no effect; remove std::move()
+    // CHECK-FIXES: auto f = [callback = callback](MoveSemantics m) mutable {
+    callback(std::move(m));
+  };
+  f(MoveSemantics());
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-constructor-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-constructor-init.cpp
new file mode 100644
index 0000000..c9ed346
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-move-constructor-init.cpp
@@ -0,0 +1,154 @@
+// RUN: %check_clang_tidy %s performance-move-constructor-init,modernize-pass-by-value %t -- \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: modernize-pass-by-value.ValuesOnly, value: 1}]}' \
+// RUN: -- -std=c++11 -isystem %S/Inputs/Headers
+
+#include <s.h>
+
+// CHECK-FIXES: #include <utility>
+
+template <class T> struct remove_reference      {typedef T type;};
+template <class T> struct remove_reference<T&>  {typedef T type;};
+template <class T> struct remove_reference<T&&> {typedef T type;};
+
+template <typename T>
+typename remove_reference<T>::type&& move(T&& arg) {
+  return static_cast<typename remove_reference<T>::type&&>(arg);
+}
+
+struct C {
+  C() = default;
+  C(const C&) = default;
+};
+
+struct B {
+  B() {}
+  B(const B&) {}
+  B(B &&) {}
+};
+
+struct D : B {
+  D() : B() {}
+  D(const D &RHS) : B(RHS) {}
+  // CHECK-MESSAGES: :[[@LINE+3]]:16: warning: move constructor initializes base class by calling a copy constructor [performance-move-constructor-init]
+  // CHECK-MESSAGES: 26:3: note: copy constructor being called
+  // CHECK-MESSAGES: 27:3: note: candidate move constructor here
+  D(D &&RHS) : B(RHS) {}
+};
+
+struct E : B {
+  E() : B() {}
+  E(const E &RHS) : B(RHS) {}
+  E(E &&RHS) : B(move(RHS)) {} // ok
+};
+
+struct F {
+  C M;
+
+  F(F &&) : M(C()) {} // ok
+};
+
+struct G {
+  G() = default;
+  G(const G&) = default;
+  G(G&&) = delete;
+};
+
+struct H : G {
+  H() = default;
+  H(const H&) = default;
+  H(H &&RHS) : G(RHS) {} // ok
+};
+
+struct I {
+  I(const I &) = default; // suppresses move constructor creation
+};
+
+struct J : I {
+  J(J &&RHS) : I(RHS) {} // ok
+};
+
+struct K {}; // Has implicit copy and move constructors, is trivially copyable
+struct L : K {
+  L(L &&RHS) : K(RHS) {} // ok
+};
+
+struct M {
+  B Mem;
+  // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: move constructor initializes class member by calling a copy constructor [performance-move-constructor-init]
+  M(M &&RHS) : Mem(RHS.Mem) {}
+};
+
+struct N {
+  B Mem;
+  N(N &&RHS) : Mem(move(RHS.Mem)) {}
+};
+
+struct O {
+  O(O&& other) : b(other.b) {} // ok
+  const B b;
+};
+
+struct P {
+  P(O&& other) : b(other.b) {} // ok
+  B b;
+};
+
+struct Movable {
+  Movable(Movable &&) = default;
+  Movable(const Movable &) = default;
+  Movable &operator=(const Movable &) = default;
+  ~Movable() {}
+};
+
+struct TriviallyCopyable {
+  TriviallyCopyable() = default;
+  TriviallyCopyable(TriviallyCopyable &&) = default;
+  TriviallyCopyable(const TriviallyCopyable &) = default;
+};
+
+struct Positive {
+  Positive(Movable M) : M_(M) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: pass by value and use std::move [modernize-pass-by-value]
+  // CHECK-FIXES: Positive(Movable M) : M_(std::move(M)) {}
+  Movable M_;
+};
+
+struct NegativeMultipleInitializerReferences {
+  NegativeMultipleInitializerReferences(Movable M) : M_(M), n_(M) {}
+  Movable M_;
+  Movable n_;
+};
+
+struct NegativeReferencedInConstructorBody {
+  NegativeReferencedInConstructorBody(Movable M) : M_(M) { M_ = M; }
+  Movable M_;
+};
+
+struct NegativeParamTriviallyCopyable {
+  NegativeParamTriviallyCopyable(TriviallyCopyable T) : T_(T) {}
+  NegativeParamTriviallyCopyable(int I) : I_(I) {}
+
+  TriviallyCopyable T_;
+  int I_;
+};
+
+struct NegativeNotPassedByValue {
+  // This const ref constructor isn't warned about because the ValuesOnly option is set.
+  NegativeNotPassedByValue(const Movable &M) : M_(M) {}
+  NegativeNotPassedByValue(const Movable M) : M_(M) {}
+  NegativeNotPassedByValue(Movable &M) : M_(M) {}
+  NegativeNotPassedByValue(Movable *M) : M_(*M) {}
+  NegativeNotPassedByValue(const Movable *M) : M_(*M) {}
+  Movable M_;
+};
+
+struct Immovable {
+  Immovable(const Immovable &) = default;
+  Immovable(Immovable &&) = delete;
+};
+
+struct NegativeImmovableParameter {
+  NegativeImmovableParameter(Immovable I) : I_(I) {}
+  Immovable I_;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-noexcept-move-constructor.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-noexcept-move-constructor.cpp
new file mode 100644
index 0000000..70d7065
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-noexcept-move-constructor.cpp
@@ -0,0 +1,54 @@
+// RUN: %check_clang_tidy %s performance-noexcept-move-constructor %t
+
+class A {
+  A(A &&);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]
+  A &operator=(A &&);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should
+};
+
+struct B {
+  static constexpr bool kFalse = false;
+  B(B &&) noexcept(kFalse);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]
+};
+
+class OK {};
+
+void f() {
+  OK a;
+  a = OK();
+}
+
+class OK1 {
+public:
+  OK1();
+  OK1(const OK1 &);
+  OK1(OK1 &&) noexcept;
+  OK1 &operator=(OK1 &&) noexcept;
+  void f();
+  void g() noexcept;
+};
+
+class OK2 {
+  static constexpr bool kTrue = true;
+
+public:
+  OK2(OK2 &&) noexcept(true) {}
+  OK2 &operator=(OK2 &&) noexcept(kTrue) { return *this; }
+};
+
+struct OK3 {
+  OK3(OK3 &&) noexcept(false) {}
+  OK3 &operator=(OK3 &&) = delete;
+};
+
+struct OK4 {
+  OK4(OK4 &&) noexcept = default;
+  OK4 &operator=(OK4 &&) noexcept = default;
+};
+
+struct OK5 {
+  OK5(OK5 &&) noexcept(true) = default;
+  OK5 &operator=(OK5 &&) noexcept(true) = default;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-type-promotion-in-math-fn.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-type-promotion-in-math-fn.cpp
new file mode 100644
index 0000000..b2da7cc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-type-promotion-in-math-fn.cpp
@@ -0,0 +1,316 @@
+// RUN: %check_clang_tidy %s performance-type-promotion-in-math-fn %t
+
+// CHECK-FIXES: #include <cmath>
+
+double acos(double);
+double acosh(double);
+double asin(double);
+double asinh(double);
+double atan2(double, double);
+double atan(double);
+double atanh(double);
+double cbrt(double);
+double ceil(double);
+double copysign(double, double);
+double cos(double);
+double cosh(double);
+double erfc(double);
+double erf(double);
+double exp2(double);
+double exp(double);
+double expm1(double);
+double fabs(double);
+double fdim(double, double);
+double floor(double);
+double fma(double, double, double);
+double fmax(double, double);
+double fmin(double, double);
+double fmod(double, double);
+double frexp(double, int *);
+double hypot(double, double);
+double ilogb(double);
+double ldexp(double, double);
+double lgamma(double);
+long long llrint(double);
+double log10(double);
+double log1p(double);
+double log2(double);
+double logb(double);
+double log(double);
+long lrint(double);
+double modf(double);
+double nearbyint(double);
+double nextafter(double, double);
+double nexttoward(double, long double);
+double pow(double, double);
+double remainder(double, double);
+double remquo(double, double, int *);
+double rint(double);
+double round(double);
+double scalbln(double, long);
+double scalbn(double, int);
+double sin(double);
+double sinh(double);
+double sqrt(double);
+double tan(double);
+double tanh(double);
+double tgamma(double);
+double trunc(double);
+long long llround(double);
+long lround(double);
+
+void check_all_fns() {
+  float a, b, c;
+  int i;
+  long l;
+  int *int_ptr;
+
+  acos(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'acos' promotes float to double [performance-type-promotion-in-math-fn]
+  // CHECK-FIXES: {{^}}  std::acos(a);{{$}}
+  acosh(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'acosh'
+  // CHECK-FIXES: {{^}}  std::acosh(a);{{$}}
+  asin(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'asin'
+  // CHECK-FIXES: {{^}}  std::asin(a);{{$}}
+  asinh(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'asinh'
+  // CHECK-FIXES: {{^}}  std::asinh(a);{{$}}
+  atan2(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'atan2'
+  // CHECK-FIXES: {{^}}  std::atan2(a, b);{{$}}
+  atan(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'atan'
+  // CHECK-FIXES: {{^}}  std::atan(a);{{$}}
+  atanh(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'atanh'
+  // CHECK-FIXES: {{^}}  std::atanh(a);{{$}}
+  cbrt(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'cbrt'
+  // CHECK-FIXES: {{^}}  std::cbrt(a);{{$}}
+  ceil(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'ceil'
+  // CHECK-FIXES: {{^}}  std::ceil(a);{{$}}
+  copysign(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'copysign'
+  // CHECK-FIXES: {{^}}  std::copysign(a, b);{{$}}
+  cos(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'cos'
+  // CHECK-FIXES: {{^}}  std::cos(a);{{$}}
+  cosh(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'cosh'
+  // CHECK-FIXES: {{^}}  std::cosh(a);{{$}}
+  erf(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'erf'
+  // CHECK-FIXES: {{^}}  std::erf(a);{{$}}
+  erfc(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'erfc'
+  // CHECK-FIXES: {{^}}  std::erfc(a);{{$}}
+  exp2(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'exp2'
+  // CHECK-FIXES: {{^}}  std::exp2(a);{{$}}
+  exp(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'exp'
+  // CHECK-FIXES: {{^}}  std::exp(a);{{$}}
+  expm1(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'expm1'
+  // CHECK-FIXES: {{^}}  std::expm1(a);{{$}}
+  fabs(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fabs'
+  // CHECK-FIXES: {{^}}  std::fabs(a);{{$}}
+  fdim(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fdim'
+  // CHECK-FIXES: {{^}}  std::fdim(a, b);{{$}}
+  floor(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'floor'
+  // CHECK-FIXES: {{^}}  std::floor(a);{{$}}
+  fma(a, b, c);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fma'
+  // CHECK-FIXES: {{^}}  std::fma(a, b, c);{{$}}
+  fmax(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fmax'
+  // CHECK-FIXES: {{^}}  std::fmax(a, b);{{$}}
+  fmin(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fmin'
+  // CHECK-FIXES: {{^}}  std::fmin(a, b);{{$}}
+  fmod(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'fmod'
+  // CHECK-FIXES: {{^}}  std::fmod(a, b);{{$}}
+  frexp(a, int_ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'frexp'
+  // CHECK-FIXES: {{^}}  std::frexp(a, int_ptr);{{$}}
+  hypot(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'hypot'
+  // CHECK-FIXES: {{^}}  std::hypot(a, b);{{$}}
+  ilogb(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'ilogb'
+  // CHECK-FIXES: {{^}}  std::ilogb(a);{{$}}
+  ldexp(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'ldexp'
+  // CHECK-FIXES: {{^}}  std::ldexp(a, b);{{$}}
+  lgamma(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'lgamma'
+  // CHECK-FIXES: {{^}}  std::lgamma(a);{{$}}
+  llrint(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'llrint'
+  // CHECK-FIXES: {{^}}  std::llrint(a);{{$}}
+  llround(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'llround'
+  // CHECK-FIXES: {{^}}  std::llround(a);{{$}}
+  log10(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log10'
+  // CHECK-FIXES: {{^}}  std::log10(a);{{$}}
+  log1p(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log1p'
+  // CHECK-FIXES: {{^}}  std::log1p(a);{{$}}
+  log2(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log2'
+  // CHECK-FIXES: {{^}}  std::log2(a);{{$}}
+  log(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'log'
+  // CHECK-FIXES: {{^}}  std::log(a);{{$}}
+  logb(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'logb'
+  // CHECK-FIXES: {{^}}  std::logb(a);{{$}}
+  lrint(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'lrint'
+  // CHECK-FIXES: {{^}}  std::lrint(a);{{$}}
+  lround(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'lround'
+  // CHECK-FIXES: {{^}}  std::lround(a);{{$}}
+  nearbyint(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nearbyint'
+  // CHECK-FIXES: {{^}}  std::nearbyint(a);{{$}}
+  nextafter(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nextafter'
+  // CHECK-FIXES: {{^}}  std::nextafter(a, b);{{$}}
+  nexttoward(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
+  // CHECK-FIXES: {{^}}  std::nexttoward(a, b);{{$}}
+  pow(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'pow'
+  // CHECK-FIXES: {{^}}  std::pow(a, b);{{$}}
+  remainder(a, b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'remainder'
+  // CHECK-FIXES: {{^}}  std::remainder(a, b);{{$}}
+  remquo(a, b, int_ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'remquo'
+  // CHECK-FIXES: {{^}}  std::remquo(a, b, int_ptr);{{$}}
+  rint(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'rint'
+  // CHECK-FIXES: {{^}}  std::rint(a);{{$}}
+  round(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'round'
+  // CHECK-FIXES: {{^}}  std::round(a);{{$}}
+  scalbln(a, l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbln'
+  // CHECK-FIXES: {{^}}  std::scalbln(a, l);{{$}}
+  scalbn(a, i);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbn'
+  // CHECK-FIXES: {{^}}  std::scalbn(a, i);{{$}}
+  sin(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'sin'
+  // CHECK-FIXES: {{^}}  std::sin(a);{{$}}
+  sinh(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'sinh'
+  // CHECK-FIXES: {{^}}  std::sinh(a);{{$}}
+  sqrt(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'sqrt'
+  // CHECK-FIXES: {{^}}  std::sqrt(a);{{$}}
+  tan(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'tan'
+  // CHECK-FIXES: {{^}}  std::tan(a);{{$}}
+  tanh(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'tanh'
+  // CHECK-FIXES: {{^}}  std::tanh(a);{{$}}
+  tgamma(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'tgamma'
+  // CHECK-FIXES: {{^}}  std::tgamma(a);{{$}}
+  trunc(a);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'trunc'
+  // CHECK-FIXES: {{^}}  std::trunc(a);{{$}}
+}
+
+// nexttoward/nexttowardf are weird -- the second param is always long double.
+// So we warn if the first arg is a float, regardless of what the second arg is.
+void check_nexttoward() {
+  nexttoward(0.f, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
+  // CHECK-FIXES: {{^}}  std::nexttoward(0.f, 0);{{$}}
+  nexttoward(0.f, 0l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
+  // CHECK-FIXES: {{^}}  std::nexttoward(0.f, 0l);{{$}}
+  nexttoward(0.f, 0.f);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
+  // CHECK-FIXES: {{^}}  std::nexttoward(0.f, 0.f);{{$}}
+  nexttoward(0.f, 0.);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'nexttoward'
+  // CHECK-FIXES: {{^}}  std::nexttoward(0.f, 0.);{{$}}
+
+  // No warnings for these.
+  nexttoward(0., 0);
+  nexttoward(0., 0.f);
+  nexttoward(0., 0.);
+}
+
+// The second parameter to scalbn and scalbnf is an int, so we don't care what
+// type you pass as that argument; we warn iff the first argument is a float.
+void check_scalbn() {
+  scalbn(0.f, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbn'
+  // CHECK-FIXES: {{^}}  std::scalbn(0.f, 0);{{$}}
+  scalbn(0.f, static_cast<char>(0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbn'
+  // CHECK-FIXES: {{^}}  std::scalbn(0.f, static_cast<char>(0));{{$}}
+
+  // No warnings for these.
+  scalbn(0., 0);
+  scalbn(0., static_cast<char>(0));
+}
+
+// scalbln/scalblnf are like scalbn/scalbnf except their second arg is a long.
+// Again, doesn't matter what we pass for the second arg; we warn iff the first
+// arg is a float.
+void check_scalbln() {
+  scalbln(0.f, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbln'
+  // CHECK-FIXES: {{^}}  std::scalbln(0.f, 0);{{$}}
+  scalbln(0.f, 0l);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: call to 'scalbln'
+  // CHECK-FIXES: {{^}}  std::scalbln(0.f, 0l);{{$}}
+
+  // No warnings for these.
+  scalbln(0., 0);
+  scalbln(0., 0l);
+}
+
+float cosf(float);
+double foo(double);         // not a math.h function
+float cos(float);           // not a math.h function (wrong signature)
+double cos(double, double); // not a math.h function (wrong signature)
+
+namespace std {
+void cos(float);
+} // namespace std
+
+void check_no_warnings() {
+  foo(0.); // no warning because not a math.h function.
+
+  sin(0);        // no warning because arg is an int
+  cos(0.);       // no warning because arg is a double
+  std::cos(0.f); // no warning because not ::cos.
+  cosf(0.f);     // no warning; we expect this to take a float
+  cos(0.f);      // does not match the expected signature of ::cos
+  cos(0.f, 0.f); // does not match the expected signature of ::cos
+
+  // No warnings because all args are not floats.
+  remainder(0., 0.f);
+  remainder(0.f, 0.);
+  remainder(0, 0.f);
+  remainder(0.f, 0);
+  fma(0.f, 0.f, 0);
+  fma(0.f, 0.f, 0.);
+  fma(0.f, 0., 0.f);
+  fma(0., 0.f, 0.f);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-copy-initialization.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-copy-initialization.cpp
new file mode 100644
index 0000000..50dcfd8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-copy-initialization.cpp
@@ -0,0 +1,389 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-copy-initialization %t
+
+struct ExpensiveToCopyType {
+  ExpensiveToCopyType();
+  virtual ~ExpensiveToCopyType();
+  const ExpensiveToCopyType &reference() const;
+  void nonConstMethod();
+  bool constMethod() const;
+};
+
+struct TrivialToCopyType {
+  const TrivialToCopyType &reference() const;
+};
+
+struct WeirdCopyCtorType {
+  WeirdCopyCtorType();
+  WeirdCopyCtorType(const WeirdCopyCtorType &w, bool oh_yes = true);
+
+  void nonConstMethod();
+  bool constMethod() const;
+};
+
+ExpensiveToCopyType global_expensive_to_copy_type;
+
+const ExpensiveToCopyType &ExpensiveTypeReference();
+const TrivialToCopyType &TrivialTypeReference();
+
+void mutate(ExpensiveToCopyType &);
+void mutate(ExpensiveToCopyType *);
+void useAsConstPointer(const ExpensiveToCopyType *);
+void useAsConstReference(const ExpensiveToCopyType &);
+void useByValue(ExpensiveToCopyType);
+
+void PositiveFunctionCall() {
+  const auto AutoAssigned = ExpensiveTypeReference();
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned' is copy-constructed from a const reference; consider making it a const reference [performance-unnecessary-copy-initialization]
+  // CHECK-FIXES: const auto& AutoAssigned = ExpensiveTypeReference();
+  const auto AutoCopyConstructed(ExpensiveTypeReference());
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
+  // CHECK-FIXES: const auto& AutoCopyConstructed(ExpensiveTypeReference());
+  const ExpensiveToCopyType VarAssigned = ExpensiveTypeReference();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
+  // CHECK-FIXES:   const ExpensiveToCopyType& VarAssigned = ExpensiveTypeReference();
+  const ExpensiveToCopyType VarCopyConstructed(ExpensiveTypeReference());
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
+  // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(ExpensiveTypeReference());
+}
+
+void PositiveMethodCallConstReferenceParam(const ExpensiveToCopyType &Obj) {
+  const auto AutoAssigned = Obj.reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
+  // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
+  const auto AutoCopyConstructed(Obj.reference());
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
+  // CHECK-FIXES: const auto& AutoCopyConstructed(Obj.reference());
+  const ExpensiveToCopyType VarAssigned = Obj.reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
+  // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj.reference();
+  const ExpensiveToCopyType VarCopyConstructed(Obj.reference());
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
+  // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj.reference());
+}
+
+void PositiveMethodCallConstParam(const ExpensiveToCopyType Obj) {
+  const auto AutoAssigned = Obj.reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
+  // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
+  const auto AutoCopyConstructed(Obj.reference());
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
+  // CHECK-FIXES: const auto& AutoCopyConstructed(Obj.reference());
+  const ExpensiveToCopyType VarAssigned = Obj.reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
+  // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj.reference();
+  const ExpensiveToCopyType VarCopyConstructed(Obj.reference());
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
+  // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj.reference());
+}
+
+void PositiveMethodCallConstPointerParam(const ExpensiveToCopyType *const Obj) {
+  const auto AutoAssigned = Obj->reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
+  // CHECK-FIXES: const auto& AutoAssigned = Obj->reference();
+  const auto AutoCopyConstructed(Obj->reference());
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
+  // CHECK-FIXES: const auto& AutoCopyConstructed(Obj->reference());
+  const ExpensiveToCopyType VarAssigned = Obj->reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
+  // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj->reference();
+  const ExpensiveToCopyType VarCopyConstructed(Obj->reference());
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
+  // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj->reference());
+}
+
+void PositiveLocalConstValue() {
+  const ExpensiveToCopyType Obj;
+  const auto UnnecessaryCopy = Obj.reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'
+  // CHECK-FIXES: const auto& UnnecessaryCopy = Obj.reference();
+}
+
+void PositiveLocalConstRef() {
+  const ExpensiveToCopyType Obj;
+  const ExpensiveToCopyType &ConstReference = Obj.reference();
+  const auto UnnecessaryCopy = ConstReference.reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'
+  // CHECK-FIXES: const auto& UnnecessaryCopy = ConstReference.reference();
+}
+
+void PositiveLocalConstPointer() {
+  const ExpensiveToCopyType Obj;
+  const ExpensiveToCopyType *const ConstPointer = &Obj;
+  const auto UnnecessaryCopy = ConstPointer->reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'
+  // CHECK-FIXES: const auto& UnnecessaryCopy = ConstPointer->reference();
+}
+
+void NegativeFunctionCallTrivialType() {
+  const auto AutoAssigned = TrivialTypeReference();
+  const auto AutoCopyConstructed(TrivialTypeReference());
+  const TrivialToCopyType VarAssigned = TrivialTypeReference();
+  const TrivialToCopyType VarCopyConstructed(TrivialTypeReference());
+}
+
+void NegativeStaticLocalVar(const ExpensiveToCopyType &Obj) {
+  static const auto StaticVar = Obj.reference();
+}
+
+void PositiveFunctionCallExpensiveTypeNonConstVariable() {
+  auto AutoAssigned = ExpensiveTypeReference();
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'AutoAssigned' is copy-constructed from a const reference but is only used as const reference; consider making it a const reference [performance-unnecessary-copy-initialization]
+  // CHECK-FIXES: const auto& AutoAssigned = ExpensiveTypeReference();
+  auto AutoCopyConstructed(ExpensiveTypeReference());
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'AutoCopyConstructed'
+  // CHECK-FIXES: const auto& AutoCopyConstructed(ExpensiveTypeReference());
+  ExpensiveToCopyType VarAssigned = ExpensiveTypeReference();
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: the variable 'VarAssigned'
+  // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = ExpensiveTypeReference();
+  ExpensiveToCopyType VarCopyConstructed(ExpensiveTypeReference());
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: the variable 'VarCopyConstructed'
+  // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(ExpensiveTypeReference());
+}
+
+void positiveNonConstVarInCodeBlock(const ExpensiveToCopyType &Obj) {
+  {
+    auto Assigned = Obj.reference();
+    // CHECK-MESSAGES: [[@LINE-1]]:10: warning: the variable 'Assigned'
+    // CHECK-FIXES: const auto& Assigned = Obj.reference();
+    Assigned.reference();
+    useAsConstReference(Assigned);
+    useByValue(Assigned);
+  }
+}
+
+void negativeNonConstVarWithNonConstUse(const ExpensiveToCopyType &Obj) {
+  {
+    auto NonConstInvoked = Obj.reference();
+    // CHECK-FIXES: auto NonConstInvoked = Obj.reference();
+    NonConstInvoked.nonConstMethod();
+  }
+  {
+    auto Reassigned = Obj.reference();
+    // CHECK-FIXES: auto Reassigned = Obj.reference();
+    Reassigned = ExpensiveToCopyType();
+  }
+  {
+    auto MutatedByReference = Obj.reference();
+    // CHECK-FIXES: auto MutatedByReference = Obj.reference();
+    mutate(MutatedByReference);
+  }
+  {
+    auto MutatedByPointer = Obj.reference();
+    // CHECK-FIXES: auto MutatedByPointer = Obj.reference();
+    mutate(&MutatedByPointer);
+  }
+}
+
+void PositiveMethodCallNonConstRefNotModified(ExpensiveToCopyType &Obj) {
+  const auto AutoAssigned = Obj.reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
+  // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
+}
+
+void NegativeMethodCallNonConstRefIsModified(ExpensiveToCopyType &Obj) {
+  const auto AutoAssigned = Obj.reference();
+  const auto AutoCopyConstructed(Obj.reference());
+  const ExpensiveToCopyType VarAssigned = Obj.reference();
+  const ExpensiveToCopyType VarCopyConstructed(Obj.reference());
+  mutate(&Obj);
+}
+
+void PositiveMethodCallNonConstNotModified(ExpensiveToCopyType Obj) {
+  const auto AutoAssigned = Obj.reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
+  // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
+}
+
+void NegativeMethodCallNonConstValueArgumentIsModified(ExpensiveToCopyType Obj) {
+  Obj.nonConstMethod();
+  const auto AutoAssigned = Obj.reference();
+}
+
+void PositiveMethodCallNonConstPointerNotModified(ExpensiveToCopyType *const Obj) {
+  const auto AutoAssigned = Obj->reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
+  // CHECK-FIXES: const auto& AutoAssigned = Obj->reference();
+  Obj->constMethod();
+}
+
+void NegativeMethodCallNonConstPointerIsModified(ExpensiveToCopyType *const Obj) {
+  const auto AutoAssigned = Obj->reference();
+  const auto AutoCopyConstructed(Obj->reference());
+  const ExpensiveToCopyType VarAssigned = Obj->reference();
+  const ExpensiveToCopyType VarCopyConstructed(Obj->reference());
+  mutate(Obj);
+}
+
+void PositiveLocalVarIsNotModified() {
+  ExpensiveToCopyType LocalVar;
+  const auto AutoAssigned = LocalVar.reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
+  // CHECK-FIXES: const auto& AutoAssigned = LocalVar.reference();
+}
+
+void NegativeLocalVarIsModified() {
+  ExpensiveToCopyType Obj;
+  const auto AutoAssigned = Obj.reference();
+  Obj = AutoAssigned;
+}
+
+struct NegativeConstructor {
+  NegativeConstructor(const ExpensiveToCopyType &Obj) : Obj(Obj) {}
+  ExpensiveToCopyType Obj;
+};
+
+#define UNNECESSARY_COPY_INIT_IN_MACRO_BODY(TYPE)                              \
+  void functionWith##TYPE(const TYPE &T) {                                     \
+    auto AssignedInMacro = T.reference();                                      \
+  }                                                                            \
+// Ensure fix is not applied.
+// CHECK-FIXES: auto AssignedInMacro = T.reference();
+
+UNNECESSARY_COPY_INIT_IN_MACRO_BODY(ExpensiveToCopyType)
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: the variable 'AssignedInMacro' is copy-constructed
+
+#define UNNECESSARY_COPY_INIT_IN_MACRO_ARGUMENT(ARGUMENT) ARGUMENT
+
+void PositiveMacroArgument(const ExpensiveToCopyType &Obj) {
+  UNNECESSARY_COPY_INIT_IN_MACRO_ARGUMENT(auto CopyInMacroArg = Obj.reference());
+  // CHECK-MESSAGES: [[@LINE-1]]:48: warning: the variable 'CopyInMacroArg' is copy-constructed
+  // Ensure fix is not applied.
+  // CHECK-FIXES: auto CopyInMacroArg = Obj.reference()
+}
+
+void PositiveLocalCopyConstMethodInvoked() {
+  ExpensiveToCopyType orig;
+  ExpensiveToCopyType copy_1 = orig;
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_1' of the variable 'orig' is never modified; consider avoiding the copy [performance-unnecessary-copy-initialization]
+  // CHECK-FIXES: const ExpensiveToCopyType& copy_1 = orig;
+  copy_1.constMethod();
+  orig.constMethod();
+}
+
+void PositiveLocalCopyUsingExplicitCopyCtor() {
+  ExpensiveToCopyType orig;
+  ExpensiveToCopyType copy_2(orig);
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_2'
+  // CHECK-FIXES: const ExpensiveToCopyType& copy_2(orig);
+  copy_2.constMethod();
+  orig.constMethod();
+}
+
+void PositiveLocalCopyCopyIsArgument(const ExpensiveToCopyType &orig) {
+  ExpensiveToCopyType copy_3 = orig;
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_3'
+  // CHECK-FIXES: const ExpensiveToCopyType& copy_3 = orig;
+  copy_3.constMethod();
+}
+
+void PositiveLocalCopyUsedAsConstRef() {
+  ExpensiveToCopyType orig;
+  ExpensiveToCopyType copy_4 = orig;
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_4'
+  // CHECK-FIXES: const ExpensiveToCopyType& copy_4 = orig;
+  useAsConstReference(orig);
+}
+
+void PositiveLocalCopyTwice() {
+  ExpensiveToCopyType orig;
+  ExpensiveToCopyType copy_5 = orig;
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_5'
+  // CHECK-FIXES: const ExpensiveToCopyType& copy_5 = orig;
+  ExpensiveToCopyType copy_6 = copy_5;
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_6'
+  // CHECK-FIXES: const ExpensiveToCopyType& copy_6 = copy_5;
+  copy_5.constMethod();
+  copy_6.constMethod();
+  orig.constMethod();
+}
+
+
+void PositiveLocalCopyWeirdCopy() {
+  WeirdCopyCtorType orig;
+  WeirdCopyCtorType weird_1(orig);
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: local copy 'weird_1'
+  // CHECK-FIXES: const WeirdCopyCtorType& weird_1(orig);
+  weird_1.constMethod();
+
+  WeirdCopyCtorType weird_2 = orig;
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: local copy 'weird_2'
+  // CHECK-FIXES: const WeirdCopyCtorType& weird_2 = orig;
+  weird_2.constMethod();
+}
+
+void NegativeLocalCopySimpleTypes() {
+  int i1 = 0;
+  int i2 = i1;
+}
+
+void NegativeLocalCopyCopyIsModified() {
+  ExpensiveToCopyType orig;
+  ExpensiveToCopyType neg_copy_1 = orig;
+  neg_copy_1.nonConstMethod();
+}
+
+void NegativeLocalCopyOriginalIsModified() {
+  ExpensiveToCopyType orig;
+  ExpensiveToCopyType neg_copy_2 = orig;
+  orig.nonConstMethod();
+}
+
+void NegativeLocalCopyUsedAsRefArg() {
+  ExpensiveToCopyType orig;
+  ExpensiveToCopyType neg_copy_3 = orig;
+  mutate(neg_copy_3);
+}
+
+void NegativeLocalCopyUsedAsPointerArg() {
+  ExpensiveToCopyType orig;
+  ExpensiveToCopyType neg_copy_4 = orig;
+  mutate(&neg_copy_4);
+}
+
+void NegativeLocalCopyCopyFromGlobal() {
+  ExpensiveToCopyType neg_copy_5 = global_expensive_to_copy_type;
+}
+
+void NegativeLocalCopyCopyToStatic() {
+  ExpensiveToCopyType orig;
+  static ExpensiveToCopyType neg_copy_6 = orig;
+}
+
+void NegativeLocalCopyNonConstInForLoop() {
+  ExpensiveToCopyType orig;
+  for (ExpensiveToCopyType neg_copy_7 = orig; orig.constMethod();
+       orig.nonConstMethod()) {
+    orig.constMethod();
+  }
+}
+
+void NegativeLocalCopyWeirdNonCopy() {
+  WeirdCopyCtorType orig;
+  WeirdCopyCtorType neg_weird_1(orig, false);
+  WeirdCopyCtorType neg_weird_2(orig, true);
+}
+void WarningOnlyMultiDeclStmt() {
+  ExpensiveToCopyType orig;
+  ExpensiveToCopyType copy = orig, copy2;
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy' of the variable 'orig' is never modified; consider avoiding the copy [performance-unnecessary-copy-initialization]
+  // CHECK-FIXES: ExpensiveToCopyType copy = orig, copy2;
+}
+
+class Element {};
+class Container {
+public:
+  class Iterator {
+  public:
+    void operator++();
+    Element operator*();
+    bool operator!=(const Iterator &);
+    WeirdCopyCtorType c;
+  };
+  const Iterator &begin() const;
+  const Iterator &end() const;
+};
+
+void implicitVarFalsePositive() {
+  for (const Element &E : Container()) {
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-arc.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-arc.m
new file mode 100644
index 0000000..0a9ea06
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-arc.m
@@ -0,0 +1,16 @@
+// RUN: clang-tidy %s -checks=-*,performance-unnecessary-value-param -- \
+// RUN:   -xobjective-c -fobjc-abi-version=2 -fobjc-arc | count 0
+
+#if !__has_feature(objc_arc)
+#error Objective-C ARC not enabled as expected
+#endif
+
+// Passing an Objective-C ARC-managed object to a C function should
+// not raise performance-unnecessary-value-param.
+void foo(id object) { }
+
+// Same for explcitly non-ARC-managed Objective-C objects.
+void bar(__unsafe_unretained id object) { }
+
+// Same for Objective-c classes.
+void baz(Class c) { }
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-arc.mm b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-arc.mm
new file mode 100644
index 0000000..4ed0506
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-arc.mm
@@ -0,0 +1,16 @@
+// RUN: clang-tidy %s -checks=-*,performance-unnecessary-value-param -- \
+// RUN:   -xobjective-c++ -fobjc-abi-version=2 -fobjc-arc | count 0
+
+#if !__has_feature(objc_arc)
+#error Objective-C ARC not enabled as expected
+#endif
+
+// Passing an Objective-C ARC-managed object to a C function should
+// not raise performance-unnecessary-value-param.
+void foo(id object) { }
+
+// Same for explcitly non-ARC-managed Objective-C objects.
+void bar(__unsafe_unretained id object) { }
+
+// Same for Objective-c classes.
+void baz(Class c) { }
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-delayed.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-delayed.cpp
new file mode 100644
index 0000000..623bf8b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-delayed.cpp
@@ -0,0 +1,181 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -- -fdelayed-template-parsing
+
+struct ExpensiveToCopyType {
+  const ExpensiveToCopyType & constReference() const {
+    return *this;
+  }
+  void nonConstMethod();
+  virtual ~ExpensiveToCopyType();
+};
+
+void mutate(ExpensiveToCopyType &);
+void mutate(ExpensiveToCopyType *);
+void useAsConstReference(const ExpensiveToCopyType &);
+void useByValue(ExpensiveToCopyType);
+
+// This class simulates std::pair<>. It is trivially copy constructible
+// and trivially destructible, but not trivially copy assignable.
+class SomewhatTrivial {
+ public:
+  SomewhatTrivial();
+  SomewhatTrivial(const SomewhatTrivial&) = default;
+  ~SomewhatTrivial() = default;
+  SomewhatTrivial& operator=(const SomewhatTrivial&);
+};
+
+void positiveExpensiveConstValue(const ExpensiveToCopyType Obj);
+// CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj);
+void positiveExpensiveConstValue(const ExpensiveToCopyType Obj) {
+  // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'Obj' is copied for each invocation; consider making it a reference [performance-unnecessary-value-param]
+  // CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj) {
+}
+
+void positiveExpensiveValue(ExpensiveToCopyType Obj);
+// CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj);
+void positiveExpensiveValue(ExpensiveToCopyType Obj) {
+  // CHECK-MESSAGES: [[@LINE-1]]:49: warning: the parameter 'Obj' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
+  // CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj) {
+  Obj.constReference();
+  useAsConstReference(Obj);
+  auto Copy = Obj;
+  useByValue(Obj);
+}
+
+void positiveWithComment(const ExpensiveToCopyType /* important */ S);
+// CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S);
+void positiveWithComment(const ExpensiveToCopyType /* important */ S) {
+  // CHECK-MESSAGES: [[@LINE-1]]:68: warning: the const qualified
+  // CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S) {
+}
+
+void positiveUnnamedParam(const ExpensiveToCopyType) {
+  // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter #1
+  // CHECK-FIXES: void positiveUnnamedParam(const ExpensiveToCopyType&) {
+}
+
+void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy);
+// CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy);
+void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy) {
+  // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter 'ConstCopy'
+  // CHECK-MESSAGES: [[@LINE-2]]:120: warning: the parameter 'Copy'
+  // CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy) {
+}
+
+struct PositiveConstValueConstructor {
+  PositiveConstValueConstructor(const ExpensiveToCopyType ConstCopy) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:59: warning: the const qualified parameter 'ConstCopy'
+  // CHECK-FIXES: PositiveConstValueConstructor(const ExpensiveToCopyType& ConstCopy) {}
+};
+
+template <typename T> void templateWithNonTemplatizedParameter(const ExpensiveToCopyType S, T V) {
+  // CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'S'
+  // CHECK-FIXES: template <typename T> void templateWithNonTemplatizedParameter(const ExpensiveToCopyType& S, T V) {
+}
+
+void instantiated() {
+  templateWithNonTemplatizedParameter(ExpensiveToCopyType(), ExpensiveToCopyType());
+  templateWithNonTemplatizedParameter(ExpensiveToCopyType(), 5);
+}
+
+template <typename T> void negativeTemplateType(const T V) {
+}
+
+void negativeArray(const ExpensiveToCopyType[]) {
+}
+
+void negativePointer(ExpensiveToCopyType* Obj) {
+}
+
+void negativeConstPointer(const ExpensiveToCopyType* Obj) {
+}
+
+void negativeConstReference(const ExpensiveToCopyType& Obj) {
+}
+
+void negativeReference(ExpensiveToCopyType& Obj) {
+}
+
+void negativeUniversalReference(ExpensiveToCopyType&& Obj) {
+}
+
+void negativeSomewhatTrivialConstValue(const SomewhatTrivial Somewhat) {
+}
+
+void negativeSomewhatTrivialValue(SomewhatTrivial Somewhat) {
+}
+
+void negativeConstBuiltIn(const int I) {
+}
+
+void negativeValueBuiltIn(int I) {
+}
+
+void negativeValueIsMutatedByReference(ExpensiveToCopyType Obj) {
+  mutate(Obj);
+}
+
+void negativeValueIsMutatatedByPointer(ExpensiveToCopyType Obj) {
+  mutate(&Obj);
+}
+
+void negativeValueIsReassigned(ExpensiveToCopyType Obj) {
+  Obj = ExpensiveToCopyType();
+}
+
+void negativeValueNonConstMethodIsCalled(ExpensiveToCopyType Obj) {
+  Obj.nonConstMethod();
+}
+
+struct PositiveValueUnusedConstructor {
+  PositiveValueUnusedConstructor(ExpensiveToCopyType Copy) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
+  // CHECK-FIXES: PositiveValueUnusedConstructor(const ExpensiveToCopyType& Copy) {}
+};
+
+struct PositiveValueCopiedConstructor {
+  PositiveValueCopiedConstructor(ExpensiveToCopyType Copy) : Field(Copy) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
+  // CHECK-FIXES: PositiveValueCopiedConstructor(const ExpensiveToCopyType& Copy) : Field(Copy) {}
+  ExpensiveToCopyType Field;
+};
+
+template <typename T>
+struct Container {
+  typedef const T & const_reference;
+};
+
+void NegativeTypedefParam(const Container<ExpensiveToCopyType>::const_reference Param) {
+}
+
+#define UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY()         \
+  void inMacro(const ExpensiveToCopyType T) {           \
+  }                                                     \
+// Ensure fix is not applied.
+// CHECK-FIXES: void inMacro(const ExpensiveToCopyType T) {
+
+UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY()
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: the const qualified parameter 'T'
+
+#define UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(ARGUMENT)     \
+  ARGUMENT
+
+UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(void inMacroArgument(const ExpensiveToCopyType InMacroArg) {})
+// CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'InMacroArg'
+// CHECK-FIXES: void inMacroArgument(const ExpensiveToCopyType InMacroArg) {}
+
+struct VirtualMethod {
+  virtual ~VirtualMethod() {}
+  virtual void handle(ExpensiveToCopyType T) const = 0;
+};
+
+struct NegativeOverriddenMethod : public VirtualMethod {
+  void handle(ExpensiveToCopyType Overridden) const {
+    // CHECK-FIXES: handle(ExpensiveToCopyType Overridden) const {
+  }
+};
+
+struct NegativeDeletedMethod {
+  ~NegativeDeletedMethod() {}
+  NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;
+  // CHECK-FIXES: NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-header.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-header.cpp
new file mode 100644
index 0000000..9e4c246
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-header.cpp
@@ -0,0 +1,20 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: cp %S/Inputs/performance-unnecessary-value-param/header.h %t/header.h
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t/temp -- -- -std=c++11 -I %t
+// RUN: diff %t/header.h %S/Inputs/performance-unnecessary-value-param/header-fixed.h
+
+#include "header.h"
+
+
+
+int f1(int n, ABC v1, ABC v2) {
+  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: the parameter 'v1' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
+  // CHECK-MESSAGES: [[@LINE-2]]:27: warning: the parameter 'v2' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
+  // CHECK-FIXES: int f1(int n, const ABC& v1, const ABC& v2) {
+  return v1.get(n) + v2.get(n);
+}
+int f2(int n, ABC v2) {
+  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: the parameter 'v2' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
+  // CHECK-FIXES: int f2(int n, const ABC& v2) {
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
new file mode 100644
index 0000000..cd8c4da
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
@@ -0,0 +1,9 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -fix-errors -- --std=c++11
+
+// Ensure that incomplete types result in an error from the frontend and not a
+// clang-tidy diagnostic about IncompleteType being expensive to copy.
+struct IncompleteType;
+void NegativeForIncompleteType(IncompleteType I) {
+  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 'IncompleteType' [clang-diagnostic-error]
+}
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param.cpp
new file mode 100644
index 0000000..dcf82df
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -0,0 +1,361 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
+
+// CHECK-FIXES: #include <utility>
+
+struct ExpensiveToCopyType {
+  const ExpensiveToCopyType & constReference() const {
+    return *this;
+  }
+  void nonConstMethod();
+  virtual ~ExpensiveToCopyType();
+};
+
+void mutate(ExpensiveToCopyType &);
+void mutate(ExpensiveToCopyType *);
+void useAsConstReference(const ExpensiveToCopyType &);
+void useByValue(ExpensiveToCopyType);
+
+// This class simulates std::pair<>. It is trivially copy constructible
+// and trivially destructible, but not trivially copy assignable.
+class SomewhatTrivial {
+ public:
+  SomewhatTrivial();
+  SomewhatTrivial(const SomewhatTrivial&) = default;
+  ~SomewhatTrivial() = default;
+  SomewhatTrivial& operator=(const SomewhatTrivial&);
+};
+
+struct MoveOnlyType {
+  MoveOnlyType(const MoveOnlyType &) = delete;
+  MoveOnlyType(MoveOnlyType &&) = default;
+  ~MoveOnlyType();
+  void constMethod() const;
+};
+
+struct ExpensiveMovableType {
+  ExpensiveMovableType();
+  ExpensiveMovableType(ExpensiveMovableType &&);
+  ExpensiveMovableType(const ExpensiveMovableType &) = default;
+  ExpensiveMovableType &operator=(const ExpensiveMovableType &) = default;
+  ExpensiveMovableType &operator=(ExpensiveMovableType &&);
+  ~ExpensiveMovableType();
+};
+
+void positiveExpensiveConstValue(const ExpensiveToCopyType Obj);
+// CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj);
+void positiveExpensiveConstValue(const ExpensiveToCopyType Obj) {
+  // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'Obj' is copied for each invocation; consider making it a reference [performance-unnecessary-value-param]
+  // CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj) {
+}
+
+void positiveExpensiveValue(ExpensiveToCopyType Obj);
+// CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj);
+void positiveExpensiveValue(ExpensiveToCopyType Obj) {
+  // CHECK-MESSAGES: [[@LINE-1]]:49: warning: the parameter 'Obj' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
+  // CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj) {
+  Obj.constReference();
+  useAsConstReference(Obj);
+  auto Copy = Obj;
+  useByValue(Obj);
+}
+
+void positiveWithComment(const ExpensiveToCopyType /* important */ S);
+// CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S);
+void positiveWithComment(const ExpensiveToCopyType /* important */ S) {
+  // CHECK-MESSAGES: [[@LINE-1]]:68: warning: the const qualified
+  // CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S) {
+}
+
+void positiveUnnamedParam(const ExpensiveToCopyType) {
+  // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter #1
+  // CHECK-FIXES: void positiveUnnamedParam(const ExpensiveToCopyType&) {
+}
+
+void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy);
+// CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy);
+void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy) {
+  // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter 'ConstCopy'
+  // CHECK-MESSAGES: [[@LINE-2]]:120: warning: the parameter 'Copy'
+  // CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy) {
+}
+
+struct PositiveConstValueConstructor {
+  PositiveConstValueConstructor(const ExpensiveToCopyType ConstCopy) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:59: warning: the const qualified parameter 'ConstCopy'
+  // CHECK-FIXES: PositiveConstValueConstructor(const ExpensiveToCopyType& ConstCopy) {}
+};
+
+template <typename T> void templateWithNonTemplatizedParameter(const ExpensiveToCopyType S, T V) {
+  // CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'S'
+  // CHECK-FIXES: template <typename T> void templateWithNonTemplatizedParameter(const ExpensiveToCopyType& S, T V) {
+}
+
+void instantiated() {
+  templateWithNonTemplatizedParameter(ExpensiveToCopyType(), ExpensiveToCopyType());
+  templateWithNonTemplatizedParameter(ExpensiveToCopyType(), 5);
+}
+
+template <typename T> void negativeTemplateType(const T V) {
+}
+
+void negativeArray(const ExpensiveToCopyType[]) {
+}
+
+void negativePointer(ExpensiveToCopyType* Obj) {
+}
+
+void negativeConstPointer(const ExpensiveToCopyType* Obj) {
+}
+
+void negativeConstReference(const ExpensiveToCopyType& Obj) {
+}
+
+void negativeReference(ExpensiveToCopyType& Obj) {
+}
+
+void negativeUniversalReference(ExpensiveToCopyType&& Obj) {
+}
+
+void negativeSomewhatTrivialConstValue(const SomewhatTrivial Somewhat) {
+}
+
+void negativeSomewhatTrivialValue(SomewhatTrivial Somewhat) {
+}
+
+void negativeConstBuiltIn(const int I) {
+}
+
+void negativeValueBuiltIn(int I) {
+}
+
+void negativeValueIsMutatedByReference(ExpensiveToCopyType Obj) {
+  mutate(Obj);
+}
+
+void negativeValueIsMutatatedByPointer(ExpensiveToCopyType Obj) {
+  mutate(&Obj);
+}
+
+void negativeValueIsReassigned(ExpensiveToCopyType Obj) {
+  Obj = ExpensiveToCopyType();
+}
+
+void negativeValueNonConstMethodIsCalled(ExpensiveToCopyType Obj) {
+  Obj.nonConstMethod();
+}
+
+struct PositiveValueUnusedConstructor {
+  PositiveValueUnusedConstructor(ExpensiveToCopyType Copy) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
+  // CHECK-FIXES: PositiveValueUnusedConstructor(const ExpensiveToCopyType& Copy) {}
+};
+
+struct PositiveValueCopiedConstructor {
+  PositiveValueCopiedConstructor(ExpensiveToCopyType Copy) : Field(Copy) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
+  // CHECK-FIXES: PositiveValueCopiedConstructor(const ExpensiveToCopyType& Copy) : Field(Copy) {}
+  ExpensiveToCopyType Field;
+};
+
+struct PositiveValueMovableConstructor {
+  PositiveValueMovableConstructor(ExpensiveMovableType Copy) : Field(Copy) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:70: warning: parameter 'Copy'
+  // CHECK-FIXES: PositiveValueMovableConstructor(ExpensiveMovableType Copy) : Field(std::move(Copy)) {}
+  ExpensiveMovableType Field;
+};
+
+struct NegativeValueMovedConstructor {
+  NegativeValueMovedConstructor(ExpensiveMovableType Copy) : Field(static_cast<ExpensiveMovableType &&>(Copy)) {}
+  ExpensiveMovableType Field;
+};
+
+template <typename T>
+struct Container {
+  typedef const T & const_reference;
+};
+
+void NegativeTypedefParam(const Container<ExpensiveToCopyType>::const_reference Param) {
+}
+
+#define UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY()         \
+  void inMacro(const ExpensiveToCopyType T) {           \
+  }                                                     \
+// Ensure fix is not applied.
+// CHECK-FIXES: void inMacro(const ExpensiveToCopyType T) {
+
+UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY()
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: the const qualified parameter 'T'
+
+#define UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(ARGUMENT)     \
+  ARGUMENT
+
+UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(void inMacroArgument(const ExpensiveToCopyType InMacroArg) {})
+// CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'InMacroArg'
+// CHECK-FIXES: void inMacroArgument(const ExpensiveToCopyType InMacroArg) {}
+
+struct VirtualMethod {
+  virtual ~VirtualMethod() {}
+  virtual void handle(ExpensiveToCopyType T) const = 0;
+};
+
+struct NegativeOverriddenMethod : public VirtualMethod {
+  void handle(ExpensiveToCopyType Overridden) const {
+    // CHECK-FIXES: handle(ExpensiveToCopyType Overridden) const {
+  }
+};
+
+struct VirtualMethodWarningOnly {
+  virtual void methodWithExpensiveValueParam(ExpensiveToCopyType T) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'T' is copied
+  // CHECK-FIXES: virtual void methodWithExpensiveValueParam(ExpensiveToCopyType T) {}
+  virtual ~VirtualMethodWarningOnly() {}
+};
+
+struct PositiveNonVirualMethod {
+  void method(const ExpensiveToCopyType T) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:41: warning: the const qualified parameter 'T' is copied
+  // CHECK-FIXES: void method(const ExpensiveToCopyType& T) {}
+};
+
+struct NegativeDeletedMethod {
+  ~NegativeDeletedMethod() {}
+  NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;
+  // CHECK-FIXES: NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;
+};
+
+void NegativeMoveOnlyTypePassedByValue(MoveOnlyType M) {
+  M.constMethod();
+}
+
+void PositiveMoveOnCopyConstruction(ExpensiveMovableType E) {
+  auto F = E;
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: parameter 'E' is passed by value and only copied once; consider moving it to avoid unnecessary copies [performance-unnecessary-value-param]
+  // CHECK-FIXES: auto F = std::move(E);
+}
+
+void PositiveConstRefNotMoveSinceReferencedMultipleTimes(ExpensiveMovableType E) {
+  // CHECK-MESSAGES: [[@LINE-1]]:79: warning: the parameter 'E' is copied
+  // CHECK-FIXES: void PositiveConstRefNotMoveSinceReferencedMultipleTimes(const ExpensiveMovableType& E) {
+  auto F = E;
+  auto G = E;
+}
+
+void PositiveMoveOnCopyAssignment(ExpensiveMovableType E) {
+  ExpensiveMovableType F;
+  F = E;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: parameter 'E' is passed by value
+  // CHECK-FIXES: F = std::move(E);
+}
+
+struct NotCopyAssigned {
+  NotCopyAssigned &operator=(const ExpensiveMovableType &);
+};
+
+void PositiveNoMoveForNonCopyAssigmentOperator(ExpensiveMovableType E) {
+  // CHECK-MESSAGES: [[@LINE-1]]:69: warning: the parameter 'E' is copied
+  // CHECK-FIXES: void PositiveNoMoveForNonCopyAssigmentOperator(const ExpensiveMovableType& E) {
+  NotCopyAssigned N;
+  N = E;
+}
+
+// The argument could be moved but is not since copy statement is inside a loop.
+void PositiveNoMoveInsideLoop(ExpensiveMovableType E) {
+  // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the parameter 'E' is copied
+  // CHECK-FIXES: void PositiveNoMoveInsideLoop(const ExpensiveMovableType& E) {
+  for (;;) {
+    auto F = E;
+  }
+}
+
+void PositiveConstRefNotMoveConstructible(ExpensiveToCopyType T) {
+  // CHECK-MESSAGES: [[@LINE-1]]:63: warning: the parameter 'T' is copied
+  // CHECK-FIXES: void PositiveConstRefNotMoveConstructible(const ExpensiveToCopyType& T) {
+  auto U = T;
+}
+
+void PositiveConstRefNotMoveAssignable(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveConstRefNotMoveAssignable(const ExpensiveToCopyType& A) {
+  ExpensiveToCopyType B;
+  B = A;
+}
+
+// Case where parameter in declaration is already const-qualified but not in
+// implementation. Make sure a second 'const' is not added to the declaration.
+void PositiveConstDeclaration(const ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveConstDeclaration(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) {
+}
+
+void PositiveNonConstDeclaration(ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
+  // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A) {
+}
+
+void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:75: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+}
+
+void ReferenceFunctionOutsideOfCallExpr() {
+  void (*ptr)(ExpensiveToCopyType) = &PositiveOnlyMessageAsReferencedInCompilationUnit;
+}
+
+void PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveMessageAndFixAsFunctionIsCalled(const ExpensiveToCopyType& A) {
+}
+
+void ReferenceFunctionByCallingIt() {
+  PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType());
+}
+
+// Virtual method overrides of dependent types cannot be recognized unless they
+// are marked as override or final. Test that check is not triggered on methods
+// marked with override or final.
+template <typename T>
+struct NegativeDependentTypeInterface {
+  virtual void Method(ExpensiveToCopyType E) = 0;
+};
+
+template <typename T>
+struct NegativeOverrideImpl : public NegativeDependentTypeInterface<T> {
+  void Method(ExpensiveToCopyType E) override {}
+};
+
+template <typename T>
+struct NegativeFinalImpl : public NegativeDependentTypeInterface<T> {
+  void Method(ExpensiveToCopyType E) final {}
+};
+
+struct PositiveConstructor {
+  PositiveConstructor(ExpensiveToCopyType E) : E(E) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:43: warning: the parameter 'E' is copied
+  // CHECK-FIXES: PositiveConstructor(const ExpensiveToCopyType& E) : E(E) {}
+
+  ExpensiveToCopyType E;
+};
+
+struct NegativeUsingConstructor : public PositiveConstructor {
+  using PositiveConstructor::PositiveConstructor;
+};
+
+void fun() {
+  ExpensiveToCopyType E;
+  NegativeUsingConstructor S(E);
+}
+
+template<typename T>
+void templateFunction(T) {
+}
+
+template<>
+void templateFunction<ExpensiveToCopyType>(ExpensiveToCopyType E) {
+  // CHECK-MESSAGES: [[@LINE-1]]:64: warning: the parameter 'E' is copied
+  // CHECK-FIXES: void templateFunction<ExpensiveToCopyType>(ExpensiveToCopyType E) {
+  E.constReference();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/portability-simd-intrinsics-ppc.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/portability-simd-intrinsics-ppc.cpp
new file mode 100644
index 0000000..be0ef76
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/portability-simd-intrinsics-ppc.cpp
@@ -0,0 +1,13 @@
+// RUN: %check_clang_tidy %s portability-simd-intrinsics %t -- \
+// RUN:  -config='{CheckOptions: [ \
+// RUN:    {key: portability-simd-intrinsics.Suggest, value: 1} \
+// RUN:  ]}' -- -target ppc64le -maltivec -std=c++11
+
+vector int vec_add(vector int, vector int);
+
+void PPC() {
+  vector int i0, i1;
+
+  vec_add(i0, i1);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'vec_add' can be replaced by operator+ on std::experimental::simd objects [portability-simd-intrinsics]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/portability-simd-intrinsics-x86.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/portability-simd-intrinsics-x86.cpp
new file mode 100644
index 0000000..1fb2289
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/portability-simd-intrinsics-x86.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s portability-simd-intrinsics %t -- \
+// RUN:  -config='{CheckOptions: [ \
+// RUN:    {key: portability-simd-intrinsics.Suggest, value: 1} \
+// RUN:  ]}' -- -target x86_64 -std=c++11
+
+typedef long long __m128i __attribute__((vector_size(16)));
+typedef double __m256 __attribute__((vector_size(32)));
+
+__m128i _mm_add_epi32(__m128i, __m128i);
+__m256 _mm256_load_pd(double const *);
+void _mm256_store_pd(double *, __m256);
+
+int _mm_add_fake(int, int);
+
+void X86() {
+  __m128i i0, i1;
+  __m256 d0;
+
+  _mm_add_epi32(i0, i1);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: '_mm_add_epi32' can be replaced by operator+ on std::experimental::simd objects [portability-simd-intrinsics]
+  d0 = _mm256_load_pd(0);
+  _mm256_store_pd(0, d0);
+
+  _mm_add_fake(0, 1);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/pr37091.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/pr37091.cpp
new file mode 100644
index 0000000..e56115a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/pr37091.cpp
@@ -0,0 +1,10 @@
+// REQUIRES: shell
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+
+// This is a reproducer for PR37091.
+//
+// Verify that no temporary files are left behind by the clang-tidy invocation.
+
+// RUN: env TMPDIR=%t TEMP=%t TMP=%t clang-tidy %s -- --target=mips64
+// RUN: rmdir %t
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/read_file_config.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/read_file_config.cpp
new file mode 100644
index 0000000..3635c21
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/read_file_config.cpp
@@ -0,0 +1,12 @@
+// RUN: mkdir -p %T/read-file-config/
+// RUN: cp %s %T/read-file-config/test.cpp
+// RUN: echo 'Checks: "-*,modernize-use-nullptr"' > %T/read-file-config/.clang-tidy
+// RUN: echo '[{"command": "cc -c -o test.o test.cpp", "directory": "%/T/read-file-config", "file": "%/T/read-file-config/test.cpp"}]' > %T/read-file-config/compile_commands.json
+// RUN: clang-tidy %T/read-file-config/test.cpp | not grep "warning: .*\[clang-analyzer-deadcode.DeadStores\]$"
+// RUN: clang-tidy -checks="-*,clang-analyzer-*" %T/read-file-config/test.cpp | grep "warning: .*\[clang-analyzer-deadcode.DeadStores\]$"
+
+void f() {
+  int x;
+  x = 1;
+  x = 2;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-avoid-const-params-in-decls.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-avoid-const-params-in-decls.cpp
new file mode 100644
index 0000000..c2c12a4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-avoid-const-params-in-decls.cpp
@@ -0,0 +1,133 @@
+// RUN: %check_clang_tidy %s readability-avoid-const-params-in-decls %t
+
+using alias_type = bool;
+using alias_const_type = const bool;
+
+
+void F1(const int i);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is const-qualified in the function declaration; const-qualification of parameters only has an effect in function definitions [readability-avoid-const-params-in-decls]
+// CHECK-FIXES: void F1(int i);
+
+void F2(const int *const i);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is const-qualified
+// CHECK-FIXES: void F2(const int *i);
+
+void F3(int const i);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is const-qualified
+// CHECK-FIXES: void F3(int i);
+
+void F4(alias_type const i);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is const-qualified
+// CHECK-FIXES: void F4(alias_type i);
+
+void F5(const int);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 1 is const-qualified
+// CHECK-FIXES: void F5(int);
+
+void F6(const int *const);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 1 is const-qualified
+// CHECK-FIXES: void F6(const int *);
+
+void F7(int, const int);
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: parameter 2 is const-qualified
+// CHECK-FIXES: void F7(int, int);
+
+void F8(const int, const int);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 1 is const-qualified
+// CHECK-MESSAGES: :[[@LINE-2]]:20: warning: parameter 2 is const-qualified
+// CHECK-FIXES: void F8(int, int);
+
+void F9(const int long_name);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'long_name'
+// CHECK-FIXES: void F9(int long_name);
+
+void F10(const int *const *const long_name);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: parameter 'long_name'
+// CHECK-FIXES: void F10(const int *const *long_name);
+
+void F11(const unsigned int /*v*/);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: parameter 1
+// CHECK-FIXES: void F11(unsigned int /*v*/);
+
+void F12(const bool b = true);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: parameter 'b'
+// CHECK-FIXES: void F12(bool b = true);
+
+template<class T>
+int F13(const bool b = true);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'b'
+// CHECK-FIXES: int F13(bool b = true);
+int f13 = F13<int>();
+
+struct Foo {
+  Foo(const int i);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: parameter 'i'
+  // CHECK-FIXES: Foo(int i);
+
+  void operator()(const int i);
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: parameter 'i'
+  // CHECK-FIXES: void operator()(int i);
+};
+
+template <class T>
+struct FooT {
+  FooT(const int i);
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: parameter 'i'
+  // CHECK-FIXES: FooT(int i);
+
+  void operator()(const int i);
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: parameter 'i'
+  // CHECK-FIXES: void operator()(int i);
+};
+FooT<int> f(1);
+
+// Do not match on definitions
+void NF1(const int i) {}
+void NF2(const int *const i) {}
+void NF3(int const i) {}
+void NF4(alias_type const i) {}
+void NF5(const int) {}
+void NF6(const int *const) {}
+void NF7(int, const int) {}
+void NF8(const int, const int) {}
+template <class T>
+int NF9(const int, const int) { return 0; }
+int nf9 = NF9<int>(1, 2);
+
+// Do not match on inline member functions
+struct Bar {
+  Bar(const int i) {}
+
+  void operator()(const int i) {}
+};
+
+// Do not match on inline member functions of a templated class
+template <class T>
+struct BarT {
+  BarT(const int i) {}
+
+  void operator()(const int i) {}
+};
+BarT<int> b(1);
+
+// Do not match on other stuff
+void NF(const alias_type& i);
+void NF(const int &i);
+void NF(const int *i);
+void NF(alias_const_type i);
+void NF(const alias_type&);
+void NF(const int&);
+void NF(const int*);
+void NF(const int* const*);
+void NF(alias_const_type);
+
+// Regression test for when the 'const' token is not in the code.
+#define CONCAT(a, b) a##b
+void ConstNotVisible(CONCAT(cons, t) int i);
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: parameter 'i'
+// We warn, but we can't give a fix
+// CHECK-FIXES: void ConstNotVisible(CONCAT(cons, t) int i);
+
+// Regression test. We should not warn (or crash) on lambda expressions
+auto lambda_with_name = [](const int n) {};
+auto lambda_without_name = [](const int) {};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-assert-failure.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-assert-failure.cpp
new file mode 100644
index 0000000..7d619c0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-assert-failure.cpp
@@ -0,0 +1,12 @@
+// RUN: not clang-tidy -checks='-*,readability-braces-around-statements' %s --
+
+// Note: this test expects no assert failure happened in clang-tidy.
+
+int test_failure() {
+  if (std::rand()) {
+  }
+}
+
+void test_failure2() {
+  for (a b c;;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-few-lines.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-few-lines.cpp
new file mode 100644
index 0000000..00d253a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-few-lines.cpp
@@ -0,0 +1,30 @@
+// RUN: %check_clang_tidy %s readability-braces-around-statements %t -- -config="{CheckOptions: [{key: readability-braces-around-statements.ShortStatementLines, value: 4}]}" --
+
+void do_something(const char *) {}
+
+bool cond(const char *) {
+  return false;
+}
+
+void test() {
+  if (cond("if1") /*comment*/) do_something("same-line");
+
+  if (cond("if2"))
+    do_something("single-line");
+
+  if (cond("if3") /*comment*/)
+    // some comment
+    do_something("three"
+                 "lines");
+
+  if (cond("if4") /*comment*/)
+    // some comment
+    do_something("many"
+                 "many"
+                 "many"
+                 "many"
+                 "lines");
+  // CHECK-MESSAGES: :[[@LINE-7]]:31: warning: statement should be inside braces
+  // CHECK-FIXES: if (cond("if4") /*comment*/) {
+  // CHECK-FIXES: }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-format.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-format.cpp
new file mode 100644
index 0000000..81f832d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-format.cpp
@@ -0,0 +1,33 @@
+// RUN: %check_clang_tidy %s readability-braces-around-statements %t -- -format-style="{IndentWidth: 3}" --
+
+void do_something(const char *) {}
+
+bool cond(const char *) {
+  return false;
+}
+
+void test() {
+  if (cond("if0") /*comment*/) do_something("same-line");
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: statement should be inside braces
+  // CHECK-FIXES: {{^}}   if (cond("if0") /*comment*/) {{{$}}
+  // CHECK-FIXES-NEXT: {{^}}      do_something("same-line");{{$}}
+  // CHECK-FIXES-NEXT: {{^}}   }{{$}}
+
+  if (1) while (2) if (3) for (;;) do ; while(false) /**/;/**/
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: statement should be inside braces
+  // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: statement should be inside braces
+  // CHECK-MESSAGES: :[[@LINE-3]]:26: warning: statement should be inside braces
+  // CHECK-MESSAGES: :[[@LINE-4]]:35: warning: statement should be inside braces
+  // CHECK-MESSAGES: :[[@LINE-5]]:38: warning: statement should be inside braces
+  // CHECK-FIXES:      {{^}}  if (1) {{{$}}
+  // CHECK-FIXES-NEXT: {{^}}     while (2) {
+  // CHECK-FIXES-NEXT: {{^}}        if (3) {
+  // CHECK-FIXES-NEXT: {{^}}           for (;;) {
+  // CHECK-FIXES-NEXT: {{^}}              do {
+  // CHECK-FIXES-NEXT: {{^}}                 ;
+  // CHECK-FIXES-NEXT: {{^}}              } while (false) /**/; /**/
+  // CHECK-FIXES-NEXT: {{^}}           }
+  // CHECK-FIXES-NEXT: {{^}}        }
+  // CHECK-FIXES-NEXT: {{^}}     }
+  // CHECK-FIXES-NEXT: {{^}}  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-same-line.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-same-line.cpp
new file mode 100644
index 0000000..504043f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-same-line.cpp
@@ -0,0 +1,36 @@
+// RUN: %check_clang_tidy %s readability-braces-around-statements %t -- -config="{CheckOptions: [{key: readability-braces-around-statements.ShortStatementLines, value: 1}]}" --
+
+void do_something(const char *) {}
+
+bool cond(const char *) {
+  return false;
+}
+
+void test() {
+  if (cond("if1") /*comment*/) do_something("same-line");
+
+  if (cond("if2"))
+    do_something("single-line");
+  // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: statement should be inside braces
+  // CHECK-FIXES: if (cond("if2")) {
+  // CHECK-FIXES: }
+
+  if (cond("if3") /*comment*/)
+    // some comment
+    do_something("three"
+                 "lines");
+  // CHECK-MESSAGES: :[[@LINE-4]]:31: warning: statement should be inside braces
+  // CHECK-FIXES: if (cond("if3") /*comment*/) {
+  // CHECK-FIXES: }
+
+  if (cond("if4") /*comment*/)
+    // some comment
+    do_something("many"
+                 "many"
+                 "many"
+                 "many"
+                 "lines");
+  // CHECK-MESSAGES: :[[@LINE-7]]:31: warning: statement should be inside braces
+  // CHECK-FIXES: if (cond("if4") /*comment*/) {
+  // CHECK-FIXES: }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-single-line.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-single-line.cpp
new file mode 100644
index 0000000..3edbd4b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements-single-line.cpp
@@ -0,0 +1,33 @@
+// RUN: %check_clang_tidy %s readability-braces-around-statements %t -- -config="{CheckOptions: [{key: readability-braces-around-statements.ShortStatementLines, value: 2}]}" --
+
+void do_something(const char *) {}
+
+bool cond(const char *) {
+  return false;
+}
+
+void test() {
+  if (cond("if1") /*comment*/) do_something("same-line");
+
+  if (cond("if2"))
+    do_something("single-line");
+
+  if (cond("if3") /*comment*/)
+    // some comment
+    do_something("three"
+                 "lines");
+  // CHECK-MESSAGES: :[[@LINE-4]]:31: warning: statement should be inside braces
+  // CHECK-FIXES: if (cond("if3") /*comment*/) {
+  // CHECK-FIXES: }
+
+  if (cond("if4") /*comment*/)
+    // some comment
+    do_something("many"
+                 "many"
+                 "many"
+                 "many"
+                 "lines");
+  // CHECK-MESSAGES: :[[@LINE-7]]:31: warning: statement should be inside braces
+  // CHECK-FIXES: if (cond("if4") /*comment*/) {
+  // CHECK-FIXES: }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements.cpp
new file mode 100644
index 0000000..8dc5bf1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-braces-around-statements.cpp
@@ -0,0 +1,206 @@
+// RUN: %check_clang_tidy %s readability-braces-around-statements %t
+
+void do_something(const char *) {}
+
+bool cond(const char *) {
+  return false;
+}
+
+#define EMPTY_MACRO
+#define EMPTY_MACRO_FUN()
+
+void test() {
+  if (cond("if0") /*comment*/) do_something("same-line");
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: statement should be inside braces
+  // CHECK-FIXES:   if (cond("if0") /*comment*/) { do_something("same-line");
+  // CHECK-FIXES: }
+
+  if (cond("if0.1"))
+    do_something("single-line");
+  // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: statement should be inside braces
+  // CHECK-FIXES: if (cond("if0.1")) {
+  // CHECK-FIXES: }
+
+  if (cond("if1") /*comment*/)
+    // some comment
+    do_something("if1");
+  // CHECK-MESSAGES: :[[@LINE-3]]:31: warning: statement should be inside braces
+  // CHECK-FIXES: if (cond("if1") /*comment*/) {
+  // CHECK-FIXES: }
+  if (cond("if2")) {
+    do_something("if2");
+  }
+  if (cond("if3"))
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: statement should be inside braces
+  // CHECK-FIXES: if (cond("if3")) {
+  // CHECK-FIXES: }
+
+  if (cond("if-else1"))
+    do_something("if-else1");
+  // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: statement should be inside braces
+  // CHECK-FIXES: if (cond("if-else1")) {
+  // CHECK-FIXES: } else {
+  else
+    do_something("if-else1 else");
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: statement should be inside braces
+  // CHECK-FIXES: }
+  if (cond("if-else2")) {
+    do_something("if-else2");
+  } else {
+    do_something("if-else2 else");
+  }
+
+  if (cond("if-else if-else1"))
+    do_something("if");
+  // CHECK-MESSAGES: :[[@LINE-2]]:32: warning: statement should be inside braces
+  // CHECK-FIXES: } else if (cond("else if1")) {
+  else if (cond("else if1"))
+    do_something("else if");
+  // CHECK-MESSAGES: :[[@LINE-2]]:29: warning: statement should be inside braces
+  else
+    do_something("else");
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: statement should be inside braces
+  // CHECK-FIXES: }
+  if (cond("if-else if-else2")) {
+    do_something("if");
+  } else if (cond("else if2")) {
+    do_something("else if");
+  } else {
+    do_something("else");
+  }
+
+  for (;;)
+    do_something("for");
+  // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: statement should be inside braces
+  // CHECK-FIXES: for (;;) {
+  // CHECK-FIXES: }
+  for (;;) {
+    do_something("for");
+  }
+  for (;;)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: statement should be inside braces
+  // CHECK-FIXES: for (;;) {
+  // CHECK-FIXES: }
+
+  int arr[4] = {1, 2, 3, 4};
+  for (int a : arr)
+    do_something("for-range");
+  // CHECK-MESSAGES: :[[@LINE-2]]:20: warning: statement should be inside braces
+  // CHECK-FIXES: for (int a : arr) {
+  // CHECK-FIXES: }
+  for (int a : arr) {
+    do_something("for-range");
+  }
+  for (int a : arr)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:20: warning: statement should be inside braces
+  // CHECK-FIXES: for (int a : arr) {
+  // CHECK-FIXES: }
+
+  while (cond("while1"))
+    do_something("while");
+  // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: statement should be inside braces
+  // CHECK-FIXES: while (cond("while1")) {
+  // CHECK-FIXES: }
+  while (cond("while2")) {
+    do_something("while");
+  }
+  while (false)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: statement should be inside braces
+  // CHECK-FIXES: while (false) {
+  // CHECK-FIXES: }
+
+  do
+    do_something("do1");
+  while (cond("do1"));
+  // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: statement should be inside braces
+  // CHECK-FIXES: do {
+  // CHECK-FIXES: } while (cond("do1"));
+  do {
+    do_something("do2");
+  } while (cond("do2"));
+
+  do
+    ;
+  while (false);
+  // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: statement should be inside braces
+  // CHECK-FIXES: do {
+  // CHECK-FIXES: } while (false);
+
+  if (cond("ifif1"))
+    // comment
+    if (cond("ifif2"))
+      // comment
+      /*comment*/ ; // comment
+  // CHECK-MESSAGES: :[[@LINE-5]]:21: warning: statement should be inside braces
+  // CHECK-MESSAGES: :[[@LINE-4]]:23: warning: statement should be inside braces
+  // CHECK-FIXES: if (cond("ifif1")) {
+  // CHECK-FIXES: if (cond("ifif2")) {
+  // CHECK-FIXES: }
+  // CHECK-FIXES-NEXT: }
+
+  if (cond("ifif3"))
+    // comment
+    if (cond("ifif4")) {
+      // comment
+      /*comment*/; // comment
+    }
+  // CHECK-MESSAGES: :[[@LINE-6]]:21: warning: statement should be inside braces
+  // CHECK-FIXES: if (cond("ifif3")) {
+  // CHECK-FIXES: }
+
+  if (cond("ifif5"))
+    ; /* multi-line
+        comment */
+  // CHECK-MESSAGES: :[[@LINE-3]]:21: warning: statement should be inside braces
+  // CHECK-FIXES: if (cond("ifif5")) {
+  // CHECK-FIXES: }/* multi-line
+
+  if (1) while (2) if (3) for (;;) do ; while(false) /**/;/**/
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: statement should be inside braces
+  // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: statement should be inside braces
+  // CHECK-MESSAGES: :[[@LINE-3]]:26: warning: statement should be inside braces
+  // CHECK-MESSAGES: :[[@LINE-4]]:35: warning: statement should be inside braces
+  // CHECK-MESSAGES: :[[@LINE-5]]:38: warning: statement should be inside braces
+  // CHECK-FIXES: if (1) { while (2) { if (3) { for (;;) { do { ; } while(false) /**/;/**/
+  // CHECK-FIXES-NEXT: }
+  // CHECK-FIXES-NEXT: }
+  // CHECK-FIXES-NEXT: }
+  // CHECK-FIXES-NEXT: }
+}
+
+void f(const char *p) {
+  if (!p)
+    f("\
+");
+} // end of f
+// CHECK-MESSAGES: :[[@LINE-4]]:10: warning: statement should be inside braces
+// CHECK-FIXES:      {{^}}  if (!p) {{{$}}
+// CHECK-FIXES-NEXT: {{^}}    f("\{{$}}
+// CHECK-FIXES-NEXT: {{^}}");{{$}}
+// CHECK-FIXES-NEXT: {{^}}}{{$}}
+// CHECK-FIXES-NEXT: {{^}}} // end of f{{$}}
+
+#define M(x) x
+
+int test_macros(bool b) {
+  if (b) {
+    return 1;
+  } else
+    M(return 2);
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: statement should be inside braces
+  // CHECK-FIXES: } else {
+  // CHECK-FIXES-NEXT:   M(return 2);
+  // CHECK-FIXES-NEXT: }
+  M(
+    for (;;)
+      ;
+  );
+  // CHECK-MESSAGES: :[[@LINE-3]]:13: warning: statement should be inside braces
+  // CHECK-FIXES: {{^}}    for (;;) {{{$}}
+  // CHECK-FIXES-NEXT: {{^      ;$}}
+  // CHECK-FIXES-NEXT: {{^}$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-container-size-empty.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-container-size-empty.cpp
new file mode 100644
index 0000000..3c3c9a6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-container-size-empty.cpp
@@ -0,0 +1,439 @@
+// RUN: %check_clang_tidy %s readability-container-size-empty %t
+
+namespace std {
+template <typename T> struct vector {
+  vector();
+  bool operator==(const vector<T>& other) const;
+  bool operator!=(const vector<T>& other) const;
+  unsigned long size() const;
+  bool empty() const;
+};
+
+template <typename T> struct basic_string {
+  basic_string();
+  bool operator==(const basic_string<T>& other) const;
+  bool operator!=(const basic_string<T>& other) const;
+  bool operator==(const char *) const;
+  bool operator!=(const char *) const;
+  basic_string<T> operator+(const basic_string<T>& other) const;
+  unsigned long size() const;
+  bool empty() const;
+};
+
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+
+inline namespace __v2 {
+template <typename T> struct set {
+  set();
+  bool operator==(const set<T>& other) const;
+  bool operator!=(const set<T>& other) const;
+  unsigned long size() const;
+  bool empty() const;
+};
+}
+
+}
+
+template <typename T>
+class TemplatedContainer {
+public:
+  bool operator==(const TemplatedContainer<T>& other) const;
+  bool operator!=(const TemplatedContainer<T>& other) const;
+  int size() const;
+  bool empty() const;
+};
+
+template <typename T>
+class PrivateEmpty {
+public:
+  bool operator==(const PrivateEmpty<T>& other) const;
+  bool operator!=(const PrivateEmpty<T>& other) const;
+  int size() const;
+private:
+  bool empty() const;
+};
+
+struct BoolSize {
+  bool size() const;
+  bool empty() const;
+};
+
+struct EnumSize {
+  enum E { one };
+  enum E size() const;
+  bool empty() const;
+};
+
+class Container {
+public:
+  bool operator==(const Container& other) const;
+  int size() const;
+  bool empty() const;
+};
+
+class Derived : public Container {
+};
+
+class Container2 {
+public:
+  int size() const;
+  bool empty() const { return size() == 0; }
+};
+
+class Container3 {
+public:
+  int size() const;
+  bool empty() const;
+};
+
+bool Container3::empty() const { return this->size() == 0; }
+
+class Container4 {
+public:
+  bool operator==(const Container4& rhs) const;
+  int size() const;
+  bool empty() const { return *this == Container4(); }
+};
+
+std::string s_func() {
+  return std::string();
+}
+
+int main() {
+  std::set<int> intSet;
+  std::string str;
+  std::string str2;
+  std::wstring wstr;
+  str.size() + 0;
+  str.size() - 0;
+  0 + str.size();
+  0 - str.size();
+  if (intSet.size() == 0)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
+  // CHECK-FIXES: {{^  }}if (intSet.empty()){{$}}
+  // CHECK-MESSAGES: :32:8: note: method 'set<int>'::empty() defined here
+  if (intSet == std::set<int>())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness
+  // CHECK-FIXES: {{^  }}if (intSet.empty()){{$}}
+  // CHECK-MESSAGES: :32:8: note: method 'set<int>'::empty() defined here
+  if (s_func() == "")
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (s_func().empty()){{$}}
+  if (str.size() == 0)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (str.empty()){{$}}
+  if ((str + str2).size() == 0)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if ((str + str2).empty()){{$}}
+  if (str == "")
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (str.empty()){{$}}
+  if (str + str2 == "")
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if ((str + str2).empty()){{$}}
+  if (wstr.size() == 0)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (wstr.empty()){{$}}
+  if (wstr == "")
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (wstr.empty()){{$}}
+  std::vector<int> vect;
+  if (vect.size() == 0)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (vect.empty()){{$}}
+  if (vect == std::vector<int>())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (vect.empty()){{$}}
+  if (vect.size() != 0)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!vect.empty()){{$}}
+  if (vect != std::vector<int>())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!vect.empty()){{$}}
+  if (0 == vect.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (vect.empty()){{$}}
+  if (0 != vect.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!vect.empty()){{$}}
+  if (std::vector<int>() == vect)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (vect.empty()){{$}}
+  if (std::vector<int>() != vect)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!vect.empty()){{$}}
+  if (vect.size() > 0)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!vect.empty()){{$}}
+  if (0 < vect.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!vect.empty()){{$}}
+  if (vect.size() < 1)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (vect.empty()){{$}}
+  if (1 > vect.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (vect.empty()){{$}}
+  if (vect.size() >= 1)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!vect.empty()){{$}}
+  if (1 <= vect.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!vect.empty()){{$}}
+  if (vect.size() > 1) // no warning
+    ;
+  if (1 < vect.size()) // no warning
+    ;
+  if (vect.size() <= 1) // no warning
+    ;
+  if (1 >= vect.size()) // no warning
+    ;
+  if (!vect.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (vect.empty()){{$}}
+  if (vect.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!vect.empty()){{$}}
+
+  if (vect.empty())
+    ;
+
+  const std::vector<int> vect2;
+  if (vect2.size() != 0)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!vect2.empty()){{$}}
+
+  std::vector<int> *vect3 = new std::vector<int>();
+  if (vect3->size() == 0)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (vect3->empty()){{$}}
+  if ((*vect3).size() == 0)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if ((*vect3).empty()){{$}}
+  if ((*vect3) == std::vector<int>())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (vect3->empty()){{$}}
+  if (*vect3 == std::vector<int>())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (vect3->empty()){{$}}
+
+  delete vect3;
+
+  const std::vector<int> &vect4 = vect2;
+  if (vect4.size() == 0)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (vect4.empty()){{$}}
+  if (vect4 == std::vector<int>())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (vect4.empty()){{$}}
+
+  TemplatedContainer<void> templated_container;
+  if (templated_container.size() == 0)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (templated_container.empty()){{$}}
+  if (templated_container == TemplatedContainer<void>())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (templated_container.empty()){{$}}
+  if (templated_container.size() != 0)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!templated_container.empty()){{$}}
+  if (templated_container != TemplatedContainer<void>())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!templated_container.empty()){{$}}
+  if (0 == templated_container.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (templated_container.empty()){{$}}
+  if (TemplatedContainer<void>() == templated_container)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (templated_container.empty()){{$}}
+  if (0 != templated_container.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!templated_container.empty()){{$}}
+  if (TemplatedContainer<void>() != templated_container)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!templated_container.empty()){{$}}
+  if (templated_container.size() > 0)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!templated_container.empty()){{$}}
+  if (0 < templated_container.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!templated_container.empty()){{$}}
+  if (templated_container.size() < 1)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (templated_container.empty()){{$}}
+  if (1 > templated_container.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (templated_container.empty()){{$}}
+  if (templated_container.size() >= 1)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!templated_container.empty()){{$}}
+  if (1 <= templated_container.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!templated_container.empty()){{$}}
+  if (templated_container.size() > 1) // no warning
+    ;
+  if (1 < templated_container.size()) // no warning
+    ;
+  if (templated_container.size() <= 1) // no warning
+    ;
+  if (1 >= templated_container.size()) // no warning
+    ;
+  if (!templated_container.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (templated_container.empty()){{$}}
+  if (templated_container.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!templated_container.empty()){{$}}
+
+  if (templated_container.empty())
+    ;
+
+  // No warnings expected.
+  PrivateEmpty<void> private_empty;
+  if (private_empty.size() == 0)
+    ;
+  if (private_empty == PrivateEmpty<void>())
+    ;
+  if (private_empty.size() != 0)
+    ;
+  if (private_empty != PrivateEmpty<void>())
+    ;
+  if (0 == private_empty.size())
+    ;
+  if (PrivateEmpty<void>() == private_empty)
+    ;
+  if (0 != private_empty.size())
+    ;
+  if (PrivateEmpty<void>() != private_empty)
+    ;
+  if (private_empty.size() > 0)
+    ;
+  if (0 < private_empty.size())
+    ;
+  if (private_empty.size() < 1)
+    ;
+  if (1 > private_empty.size())
+    ;
+  if (private_empty.size() >= 1)
+    ;
+  if (1 <= private_empty.size())
+    ;
+  if (private_empty.size() > 1)
+    ;
+  if (1 < private_empty.size())
+    ;
+  if (private_empty.size() <= 1)
+    ;
+  if (1 >= private_empty.size())
+    ;
+  if (!private_empty.size())
+    ;
+  if (private_empty.size())
+    ;
+
+  // Types with weird size() return type.
+  BoolSize bs;
+  if (bs.size() == 0)
+    ;
+  EnumSize es;
+  if (es.size() == 0)
+    ;
+
+  Derived derived;
+  if (derived.size() == 0)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (derived.empty()){{$}}
+  if (derived == Derived())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (derived.empty()){{$}}
+}
+
+#define CHECKSIZE(x) if (x.size())
+// CHECK-FIXES: #define CHECKSIZE(x) if (x.size())
+
+template <typename T> void f() {
+  std::vector<T> v;
+  if (v.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
+  // CHECK-FIXES: {{^  }}if (!v.empty()){{$}}
+  if (v == std::vector<T>())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of comparing to an empty object [readability-container-size-empty]
+  // CHECK-FIXES: {{^  }}if (v.empty()){{$}}
+  // CHECK-FIXES-NEXT: ;
+  CHECKSIZE(v);
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: the 'empty' method should be used
+  // CHECK-MESSAGES: CHECKSIZE(v);
+
+  TemplatedContainer<T> templated_container;
+  if (templated_container.size())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!templated_container.empty()){{$}}
+  if (templated_container != TemplatedContainer<T>())
+    ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
+  // CHECK-FIXES: {{^  }}if (!templated_container.empty()){{$}}
+  // CHECK-FIXES-NEXT: ;
+  CHECKSIZE(templated_container);
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: the 'empty' method should be used
+  // CHECK-MESSAGES: CHECKSIZE(templated_container);
+}
+
+void g() {
+  f<int>();
+  f<double>();
+  f<char *>();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-delete-null-pointer.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-delete-null-pointer.cpp
new file mode 100644
index 0000000..b46e52a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-delete-null-pointer.cpp
@@ -0,0 +1,86 @@
+// RUN: %check_clang_tidy %s readability-delete-null-pointer %t
+
+#define NULL 0
+
+void f() {
+  int *p = 0;
+
+  // #1
+  if (p) { // #2
+    delete p;
+  } // #3
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: 'if' statement is unnecessary; deleting null pointer has no effect [readability-delete-null-pointer]
+
+  // CHECK-FIXES: {{^  }}// #1
+  // CHECK-FIXES-NEXT: {{^  }}// #2
+  // CHECK-FIXES-NEXT: delete p;
+  // CHECK-FIXES-NEXT: {{^  }}// #3
+
+  int *p2 = new int[3];
+  // #4
+  if (p2) // #5
+    delete[] p2;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: 'if' statement is unnecessary;
+
+  // CHECK-FIXES: // #4
+  // CHECK-FIXES-NEXT: {{^  }}// #5
+  // CHECK-FIXES-NEXT: delete[] p2;
+
+  int *p3 = 0;
+  if (NULL != p3) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'if' statement is unnecessary;
+    delete p3;
+  }
+  // CHECK-FIXES-NOT: if (NULL != p3) {
+  // CHECK-FIXES: delete p3;
+
+  int *p4 = nullptr;
+  if (p4 != nullptr) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'if' statement is unnecessary;
+    delete p4;
+  }
+  // CHECK-FIXES-NOT: if (p4 != nullptr) {
+  // CHECK-FIXES: delete p4;
+
+  char *c;
+  if (c != 0) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'if' statement is unnecessary;
+    delete c;
+  }
+  // CHECK-FIXES-NOT: if (c != 0) {
+  // CHECK-FIXES: delete c;
+
+  char *c2;
+  if (c2) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'if' statement is unnecessary;
+    // CHECK-FIXES: } else {
+    // CHECK-FIXES: c2 = c;
+    delete c2;
+  } else {
+    c2 = c;
+  }
+  struct A {
+    void foo() {
+      if (mp) // #6
+        delete mp;
+      // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: 'if' statement is unnecessary; deleting null pointer has no effect [readability-delete-null-pointer]
+      // CHECK-FIXES: {{^      }}// #6
+      // CHECK-FIXES-NEXT: delete mp;
+    }
+    int *mp;
+  };
+}
+
+void g() {
+  int *p5, *p6;
+  if (p5)
+    delete p6;
+
+  if (p5 && p6)
+    delete p5;
+
+  if (p6) {
+    int x = 5;
+    delete p6;
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-deleted-default.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-deleted-default.cpp
new file mode 100644
index 0000000..bf27e00
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-deleted-default.cpp
@@ -0,0 +1,127 @@
+// RUN: %check_clang_tidy %s readability-deleted-default %t -- -- -std=c++11 -fno-ms-compatibility
+
+class NoDefault {
+public:
+  NoDefault() = delete;
+  NoDefault(NoDefault &&Other) = delete;
+  NoDefault(const NoDefault &Other) = delete;
+};
+
+class MissingEverything {
+public:
+  MissingEverything() = default;
+  // CHECK-MESSAGES: warning: default constructor is explicitly defaulted but implicitly deleted, probably because a non-static data member or a base class is lacking a default constructor; definition can either be removed or explicitly deleted [readability-deleted-default]
+  MissingEverything(MissingEverything &&Other) = default;
+  // CHECK-MESSAGES: warning: move constructor is explicitly defaulted but implicitly deleted, probably because a non-static data member or a base class is neither copyable nor movable; definition can either be removed or explicitly deleted [readability-deleted-default]
+  MissingEverything(const MissingEverything &Other) = default;
+  // CHECK-MESSAGES: warning: copy constructor is explicitly defaulted but implicitly deleted, probably because a non-static data member or a base class is not copyable; definition can either be removed or explicitly deleted [readability-deleted-default]
+  MissingEverything &operator=(MissingEverything &&Other) = default;
+  // CHECK-MESSAGES: warning: move assignment operator is explicitly defaulted but implicitly deleted, probably because a base class or a non-static data member is not assignable, e.g. because the latter is marked 'const'; definition can either be removed or explicitly deleted [readability-deleted-default]
+  MissingEverything &operator=(const MissingEverything &Other) = default;
+  // CHECK-MESSAGES: warning: copy assignment operator is explicitly defaulted but implicitly deleted, probably because a base class or a non-static data member is not assignable, e.g. because the latter is marked 'const'; definition can either be removed or explicitly deleted [readability-deleted-default]
+
+private:
+  NoDefault ND;
+};
+
+class NotAssignable {
+public:
+  NotAssignable(NotAssignable &&Other) = default;
+  NotAssignable(const NotAssignable &Other) = default;
+  NotAssignable &operator=(NotAssignable &&Other) = default;
+  // CHECK-MESSAGES: warning: move assignment operator is explicitly defaulted but implicitly deleted
+  NotAssignable &operator=(const NotAssignable &Other) = default;
+  // CHECK-MESSAGES: warning: copy assignment operator is explicitly defaulted but implicitly deleted
+
+private:
+  const int I = 0;
+};
+
+class Movable {
+public:
+  Movable() = default;
+  Movable(Movable &&Other) = default;
+  Movable(const Movable &Other) = delete;
+  Movable &operator=(Movable &&Other) = default;
+  Movable &operator=(const Movable &Other) = delete;
+};
+
+class NotCopyable {
+public:
+  NotCopyable(NotCopyable &&Other) = default;
+  NotCopyable(const NotCopyable &Other) = default;
+  // CHECK-MESSAGES: warning: copy constructor is explicitly defaulted but implicitly deleted
+  NotCopyable &operator=(NotCopyable &&Other) = default;
+  NotCopyable &operator=(const NotCopyable &Other) = default;
+  // CHECK-MESSAGES: warning: copy assignment operator is explicitly defaulted but implicitly deleted
+private:
+  Movable M;
+};
+
+template <typename T> class Templated {
+public:
+  // No warning here, it is a templated class.
+  Templated() = default;
+  Templated(Templated &&Other) = default;
+  Templated(const Templated &Other) = default;
+  Templated &operator=(Templated &&Other) = default;
+  Templated &operator=(const Templated &Other) = default;
+
+  class InnerTemplated {
+  public:
+    // This class is not in itself templated, but we still don't have warning.
+    InnerTemplated() = default;
+    InnerTemplated(InnerTemplated &&Other) = default;
+    InnerTemplated(const InnerTemplated &Other) = default;
+    InnerTemplated &operator=(InnerTemplated &&Other) = default;
+    InnerTemplated &operator=(const InnerTemplated &Other) = default;
+
+  private:
+    T TVar;
+  };
+
+  class InnerNotTemplated {
+  public:
+    // This one could technically have warnings, but currently doesn't.
+    InnerNotTemplated() = default;
+    InnerNotTemplated(InnerNotTemplated &&Other) = default;
+    InnerNotTemplated(const InnerNotTemplated &Other) = default;
+    InnerNotTemplated &operator=(InnerNotTemplated &&Other) = default;
+    InnerNotTemplated &operator=(const InnerNotTemplated &Other) = default;
+
+  private:
+    int I;
+  };
+
+private:
+  const T TVar{};
+};
+
+int FunctionWithInnerClass() {
+  class InnerNotAssignable {
+  public:
+    InnerNotAssignable &operator=(InnerNotAssignable &&Other) = default;
+    // CHECK-MESSAGES: warning: move assignment operator is explicitly defaulted but implicitly deleted
+  private:
+    const int I = 0;
+  };
+  return 1;
+};
+
+template <typename T>
+int TemplateFunctionWithInnerClass() {
+  class InnerNotAssignable {
+  public:
+    InnerNotAssignable &operator=(InnerNotAssignable &&Other) = default;
+  private:
+    const T TVar{};
+  };
+  return 1;
+};
+
+void Foo() {
+  Templated<const int> V1;
+  Templated<int>::InnerTemplated V2;
+  Templated<float>::InnerNotTemplated V3;
+  TemplateFunctionWithInnerClass<int>();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-else-after-return.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-else-after-return.cpp
new file mode 100644
index 0000000..7e95092
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-else-after-return.cpp
@@ -0,0 +1,107 @@
+// RUN: %check_clang_tidy %s readability-else-after-return %t -- -- -std=c++11 -fexceptions
+
+namespace std {
+struct string {
+  string(const char *);
+  ~string();
+};
+} // namespace std
+
+struct my_exception {
+  my_exception(const std::string &s);
+};
+
+void f(int a) {
+  if (a > 0)
+    return;
+  else // comment-0
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'else' after 'return'
+  // CHECK-FIXES: {{^}}  // comment-0
+    return;
+
+  if (a > 0) {
+    return;
+  } else { // comment-1
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return'
+  // CHECK-FIXES: {{^}}  } // comment-1
+    return;
+  }
+
+  if (a > 0) {
+    f(0);
+    if (a > 10)
+      return;
+  } else {
+    return;
+  }
+
+  if (a > 0)
+    f(0);
+  else if (a > 10)
+    return;
+  else // comment-2
+  // CHECK-FIXES-NOT: {{^}}  // comment-2
+    f(0);
+
+  if (a > 0)
+    if (a < 10)
+      return;
+    else // comment-3
+    // CHECK-FIXES-NOT: {{^}}    // comment-3
+      f(0);
+  else
+    if (a > 10)
+      return;
+    else // comment-4
+    // CHECK-FIXES-NOT: {{^}}    // comment-4
+      f(0);
+
+  if (a > 0) {
+    if (a < 10)
+      return;
+    else // comment-5
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return'
+    // CHECK-FIXES: {{^}}    // comment-5
+      f(0);
+  } else {
+    if (a > 10)
+      return;
+    else // comment-6
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return'
+    // CHECK-FIXES: {{^}}    // comment-6
+      f(0);
+  }
+}
+
+void foo() {
+  for (unsigned x = 0; x < 42; ++x) {
+    if (x) {
+      continue;
+    } else { // comment-7
+    // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use 'else' after 'continue'
+    // CHECK-FIXES: {{^}}    } // comment-7
+      x++;
+    }
+    if (x) {
+      break;
+    } else { // comment-8
+    // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use 'else' after 'break'
+    // CHECK-FIXES: {{^}}    } // comment-8
+      x++;
+    }
+    if (x) {
+      throw 42;
+    } else { // comment-9
+    // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use 'else' after 'throw'
+    // CHECK-FIXES: {{^}}    } // comment-9
+      x++;
+    }
+    if (x) {
+      throw my_exception("foo");
+    } else { // comment-10
+    // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use 'else' after 'throw'
+    // CHECK-FIXES: {{^}}    } // comment-10
+      x++;
+    }
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-function-size-variables-c++17.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-function-size-variables-c++17.cpp
new file mode 100644
index 0000000..8af0d96
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-function-size-variables-c++17.cpp
@@ -0,0 +1,21 @@
+// RUN: %check_clang_tidy %s readability-function-size %t -- -config='{CheckOptions: [{key: readability-function-size.LineThreshold, value: 0}, {key: readability-function-size.StatementThreshold, value: 0}, {key: readability-function-size.BranchThreshold, value: 0}, {key: readability-function-size.ParameterThreshold, value: 5}, {key: readability-function-size.NestingThreshold, value: 2}, {key: readability-function-size.VariableThreshold, value: 1}]}' -- -std=c++17
+
+void structured_bindings() {
+  int a[2] = {1, 2};
+  auto [x, y] = a;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'structured_bindings' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 2 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 3 variables (threshold 1)
+
+#define SWAP(x, y) ({auto& [x0, x1] = x;  __typeof__(x) t = {x0, x1}; auto& [y0, y1] = y; auto& [t0, t1] = t; x0 = y0; x1 = y1; y0 = t0; y1 = t1; })
+void variables_13() {
+  int a[2] = {1, 2};
+  int b[2] = {3, 4};
+  SWAP(a, b);
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:6: warning: function 'variables_13' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 4 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 11 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-8]]:6: note: 2 variables (threshold 1)
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-function-size.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-function-size.cpp
new file mode 100644
index 0000000..efb41a1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-function-size.cpp
@@ -0,0 +1,301 @@
+// RUN: %check_clang_tidy %s readability-function-size %t -- -config='{CheckOptions: [{key: readability-function-size.LineThreshold, value: 0}, {key: readability-function-size.StatementThreshold, value: 0}, {key: readability-function-size.BranchThreshold, value: 0}, {key: readability-function-size.ParameterThreshold, value: 5}, {key: readability-function-size.NestingThreshold, value: 2}, {key: readability-function-size.VariableThreshold, value: 1}]}' -- -std=c++11
+
+// Bad formatting is intentional, don't run clang-format over the whole file!
+
+void foo1() {
+}
+
+void foo2() {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'foo2' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-2]]:6: note: 1 statements (threshold 0)
+
+void foo3() {
+;
+
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'foo3' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 1 statements (threshold 0)
+
+void foo4(int i) { if (i) {} else; {}
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:6: warning: function 'foo4' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-3]]:6: note: 1 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 3 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 1 branches (threshold 0)
+
+void foo5(int i) {for(;i;)while(i)
+do;while(i);
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:6: warning: function 'foo5' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 7 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 3 branches (threshold 0)
+
+template <typename T> T foo6(T i) {return i;
+}
+int x = foo6(0);
+// CHECK-MESSAGES: :[[@LINE-3]]:25: warning: function 'foo6' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-4]]:25: note: 1 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:25: note: 1 statements (threshold 0)
+
+void foo7(int p1, int p2, int p3, int p4, int p5, int p6) {;}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'foo7' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-2]]:6: note: 1 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-3]]:6: note: 6 parameters (threshold 5)
+
+void bar1() { [](){;;;;;;;;;;;if(1){}}();
+
+
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'bar1' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 14 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 1 branches (threshold 0)
+
+void bar2() { class A { void barx() {;;} }; }
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'bar2' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-2]]:6: note: 3 statements (threshold 0)
+//
+// CHECK-MESSAGES: :[[@LINE-4]]:30: warning: function 'barx' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-5]]:30: note: 2 statements (threshold 0)
+
+#define macro() {int x; {int y; {int z;}}}
+
+void baz0() { // 1
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'baz0' exceeds recommended size/complexity
+  // CHECK-MESSAGES: :[[@LINE-2]]:6: note: 28 lines including whitespace and comments (threshold 0)
+  // CHECK-MESSAGES: :[[@LINE-3]]:6: note: 9 statements (threshold 0)
+  int a;
+  { // 2
+    int b;
+    { // 3
+// CHECK-MESSAGES: :[[@LINE-1]]:5: note: nesting level 3 starts here (threshold 2)
+      int c;
+      { // 4
+        int d;
+      }
+    }
+  }
+  { // 2
+    int e;
+  }
+  { // 2
+    { // 3
+// CHECK-MESSAGES: :[[@LINE-1]]:5: note: nesting level 3 starts here (threshold 2)
+      int j;
+    }
+  }
+  macro()
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: note: nesting level 3 starts here (threshold 2)
+  // CHECK-MESSAGES: :[[@LINE-28]]:25: note: expanded from macro 'macro'
+  // CHECK-MESSAGES: :[[@LINE-27]]:6: note: 9 variables (threshold 1)
+}
+
+// check that nested if's are not reported. this was broken initially
+void nesting_if() { // 1
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'nesting_if' exceeds recommended size/complexity
+  // CHECK-MESSAGES: :[[@LINE-2]]:6: note: 23 lines including whitespace and comments (threshold 0)
+  // CHECK-MESSAGES: :[[@LINE-3]]:6: note: 18 statements (threshold 0)
+  // CHECK-MESSAGES: :[[@LINE-4]]:6: note: 6 branches (threshold 0)
+  if (true) { // 2
+     int j;
+  } else if (true) { // 2
+     int j;
+     if (true) { // 3
+       // CHECK-MESSAGES: :[[@LINE-1]]:16: note: nesting level 3 starts here (threshold 2)
+       int j;
+     }
+  } else if (true) { // 2
+     int j;
+     if (true) { // 3
+       // CHECK-MESSAGES: :[[@LINE-1]]:16: note: nesting level 3 starts here (threshold 2)
+       int j;
+     }
+  } else if (true) { // 2
+     int j;
+  }
+  // CHECK-MESSAGES: :[[@LINE-22]]:6: note: 6 variables (threshold 1)
+}
+
+// however this should warn
+void bad_if_nesting() { // 1
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'bad_if_nesting' exceeds recommended size/complexity
+// CHECK-MESSAGES: :[[@LINE-2]]:6: note: 23 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-3]]:6: note: 12 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 4 branches (threshold 0)
+  if (true) {    // 2
+    int j;
+  } else { // 2
+    if (true) { // 3
+      // CHECK-MESSAGES: :[[@LINE-1]]:15: note: nesting level 3 starts here (threshold 2)
+      int j;
+    } else { // 3
+      // CHECK-MESSAGES: :[[@LINE-1]]:12: note: nesting level 3 starts here (threshold 2)
+      if (true) { // 4
+        int j;
+      } else { // 4
+        if (true) { // 5
+          int j;
+        }
+      }
+    }
+  }
+  // CHECK-MESSAGES: :[[@LINE-22]]:6: note: 4 variables (threshold 1)
+}
+
+void variables_0() {
+  int i;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:6: warning: function 'variables_0' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 1 statements (threshold 0)
+void variables_1(int i) {
+  int j;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:6: warning: function 'variables_1' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 1 statements (threshold 0)
+void variables_2(int i, int j) {
+  ;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:6: warning: function 'variables_2' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 1 statements (threshold 0)
+void variables_3() {
+  int i[2];
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:6: warning: function 'variables_3' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 1 statements (threshold 0)
+void variables_4() {
+  int i;
+  int j;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'variables_4' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 2 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 2 variables (threshold 1)
+void variables_5() {
+  int i, j;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:6: warning: function 'variables_5' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 1 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 2 variables (threshold 1)
+void variables_6() {
+  for (int i;;)
+    for (int j;;)
+      ;
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:6: warning: function 'variables_6' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 4 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 5 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-8]]:6: note: 2 branches (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-9]]:6: note: 2 variables (threshold 1)
+void variables_7() {
+  if (int a = 1)
+    if (int b = 2)
+      ;
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:6: warning: function 'variables_7' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 4 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 7 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-8]]:6: note: 2 branches (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-9]]:6: note: 2 variables (threshold 1)
+void variables_8() {
+  int a[2];
+  for (auto i : a)
+    for (auto j : a)
+      ;
+}
+// CHECK-MESSAGES: :[[@LINE-6]]:6: warning: function 'variables_8' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 5 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-8]]:6: note: 8 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-9]]:6: note: 2 branches (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-10]]:6: note: 3 variables (threshold 1)
+void variables_9() {
+  int a, b;
+  struct A {
+    A(int c, int d) {
+      int e, f;
+    }
+  };
+}
+// CHECK-MESSAGES: :[[@LINE-8]]:6: warning: function 'variables_9' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-9]]:6: note: 7 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-10]]:6: note: 3 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-11]]:6: note: 2 variables (threshold 1)
+// CHECK-MESSAGES: :[[@LINE-9]]:5: warning: function 'A' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-10]]:5: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-11]]:5: note: 1 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-12]]:5: note: 2 variables (threshold 1)
+void variables_10() {
+  int a, b;
+  struct A {
+    int c;
+    int d;
+  };
+}
+// CHECK-MESSAGES: :[[@LINE-7]]:6: warning: function 'variables_10' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-8]]:6: note: 6 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-9]]:6: note: 2 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-10]]:6: note: 2 variables (threshold 1)
+void variables_11() {
+  struct S {
+    void bar() {
+      int a, b;
+    }
+  };
+}
+// CHECK-MESSAGES: :[[@LINE-7]]:6: warning: function 'variables_11' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-8]]:6: note: 6 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:10: warning: function 'bar' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-8]]:10: note: 2 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-9]]:10: note: 2 variables (threshold 1)
+void variables_12() {
+  int v;
+  auto test = [](int a, int b) -> void {};
+  test({}, {});
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:6: warning: function 'variables_12' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 4 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 3 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-8]]:6: note: 2 variables (threshold 1)
+void variables_13() {
+  int v;
+  auto test = []() -> void {
+    int a;
+    int b;
+  };
+  test();
+}
+// CHECK-MESSAGES: :[[@LINE-8]]:6: warning: function 'variables_13' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-9]]:6: note: 7 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-10]]:6: note: 5 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-11]]:6: note: 2 variables (threshold 1)
+void variables_14() {
+  (void)({int a = 12; a; });
+  (void)({int a = 12; a; });
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'variables_14' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 6 statements (threshold 0)
+#define SWAP(x, y) ({__typeof__(x) temp = x; x = y; y = temp; })
+void variables_15() {
+  int a = 10, b = 12;
+  SWAP(a, b);
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'variables_15' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 5 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 2 variables (threshold 1)
+#define vardecl(type, name) type name;
+void variables_16() {
+  vardecl(int, a);
+  vardecl(int, b);
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:6: warning: function 'variables_16' exceeds recommended size/complexity thresholds [readability-function-size]
+// CHECK-MESSAGES: :[[@LINE-5]]:6: note: 3 lines including whitespace and comments (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-6]]:6: note: 4 statements (threshold 0)
+// CHECK-MESSAGES: :[[@LINE-7]]:6: note: 2 variables (threshold 1)
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-identifier-naming-objc.m b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-identifier-naming-objc.m
new file mode 100644
index 0000000..ab123c2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-identifier-naming-objc.m
@@ -0,0 +1,12 @@
+// RUN: %check_clang_tidy %s readability-identifier-naming %t \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: readability-identifier-naming.ObjcIvarPrefix, value: '_'}]}' \
+// RUN: --
+
+@interface Foo {
+    int _bar;
+    int barWithoutPrefix;
+    // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for objc ivar 'barWithoutPrefix' [readability-identifier-naming]
+    // CHECK-FIXES: int _barWithoutPrefix;
+}
+@end 
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-identifier-naming.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-identifier-naming.cpp
new file mode 100644
index 0000000..436e844
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-identifier-naming.cpp
@@ -0,0 +1,476 @@
+// Remove UNSUPPORTED for powerpc64le when the problem introduced by
+// r288563 is resolved.
+// UNSUPPORTED: powerpc64le
+// RUN: %check_clang_tidy %s readability-identifier-naming %t -- \
+// RUN:   -config='{CheckOptions: [ \
+// RUN:     {key: readability-identifier-naming.AbstractClassCase, value: CamelCase}, \
+// RUN:     {key: readability-identifier-naming.AbstractClassPrefix, value: 'A'}, \
+// RUN:     {key: readability-identifier-naming.ClassCase, value: CamelCase}, \
+// RUN:     {key: readability-identifier-naming.ClassPrefix, value: 'C'}, \
+// RUN:     {key: readability-identifier-naming.ClassConstantCase, value: CamelCase}, \
+// RUN:     {key: readability-identifier-naming.ClassConstantPrefix, value: 'k'}, \
+// RUN:     {key: readability-identifier-naming.ClassMemberCase, value: CamelCase}, \
+// RUN:     {key: readability-identifier-naming.ClassMethodCase, value: camelBack}, \
+// RUN:     {key: readability-identifier-naming.ConstantCase, value: UPPER_CASE}, \
+// RUN:     {key: readability-identifier-naming.ConstantSuffix, value: '_CST'}, \
+// RUN:     {key: readability-identifier-naming.ConstexprFunctionCase, value: lower_case}, \
+// RUN:     {key: readability-identifier-naming.ConstexprMethodCase, value: lower_case}, \
+// RUN:     {key: readability-identifier-naming.ConstexprVariableCase, value: lower_case}, \
+// RUN:     {key: readability-identifier-naming.EnumCase, value: CamelCase}, \
+// RUN:     {key: readability-identifier-naming.EnumPrefix, value: 'E'}, \
+// RUN:     {key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE}, \
+// RUN:     {key: readability-identifier-naming.FunctionCase, value: camelBack}, \
+// RUN:     {key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE}, \
+// RUN:     {key: readability-identifier-naming.GlobalFunctionCase, value: CamelCase}, \
+// RUN:     {key: readability-identifier-naming.GlobalVariableCase, value: lower_case}, \
+// RUN:     {key: readability-identifier-naming.GlobalVariablePrefix, value: 'g_'}, \
+// RUN:     {key: readability-identifier-naming.InlineNamespaceCase, value: lower_case}, \
+// RUN:     {key: readability-identifier-naming.LocalConstantCase, value: CamelCase}, \
+// RUN:     {key: readability-identifier-naming.LocalConstantPrefix, value: 'k'}, \
+// RUN:     {key: readability-identifier-naming.LocalVariableCase, value: lower_case}, \
+// RUN:     {key: readability-identifier-naming.MemberCase, value: CamelCase}, \
+// RUN:     {key: readability-identifier-naming.MemberPrefix, value: 'm_'}, \
+// RUN:     {key: readability-identifier-naming.ConstantMemberCase, value: lower_case}, \
+// RUN:     {key: readability-identifier-naming.PrivateMemberPrefix, value: '__'}, \
+// RUN:     {key: readability-identifier-naming.ProtectedMemberPrefix, value: '_'}, \
+// RUN:     {key: readability-identifier-naming.PublicMemberCase, value: lower_case}, \
+// RUN:     {key: readability-identifier-naming.MethodCase, value: camelBack}, \
+// RUN:     {key: readability-identifier-naming.PrivateMethodPrefix, value: '__'}, \
+// RUN:     {key: readability-identifier-naming.ProtectedMethodPrefix, value: '_'}, \
+// RUN:     {key: readability-identifier-naming.NamespaceCase, value: lower_case}, \
+// RUN:     {key: readability-identifier-naming.ParameterCase, value: camelBack}, \
+// RUN:     {key: readability-identifier-naming.ParameterPrefix, value: 'a_'}, \
+// RUN:     {key: readability-identifier-naming.ConstantParameterCase, value: camelBack}, \
+// RUN:     {key: readability-identifier-naming.ConstantParameterPrefix, value: 'i_'}, \
+// RUN:     {key: readability-identifier-naming.ParameterPackCase, value: camelBack}, \
+// RUN:     {key: readability-identifier-naming.PureFunctionCase, value: lower_case}, \
+// RUN:     {key: readability-identifier-naming.PureMethodCase, value: camelBack}, \
+// RUN:     {key: readability-identifier-naming.StaticConstantCase, value: UPPER_CASE}, \
+// RUN:     {key: readability-identifier-naming.StaticVariableCase, value: camelBack}, \
+// RUN:     {key: readability-identifier-naming.StaticVariablePrefix, value: 's_'}, \
+// RUN:     {key: readability-identifier-naming.StructCase, value: lower_case}, \
+// RUN:     {key: readability-identifier-naming.TemplateParameterCase, value: UPPER_CASE}, \
+// RUN:     {key: readability-identifier-naming.TemplateTemplateParameterCase, value: CamelCase}, \
+// RUN:     {key: readability-identifier-naming.TemplateUsingCase, value: lower_case}, \
+// RUN:     {key: readability-identifier-naming.TemplateUsingPrefix, value: 'u_'}, \
+// RUN:     {key: readability-identifier-naming.TypeTemplateParameterCase, value: camelBack}, \
+// RUN:     {key: readability-identifier-naming.TypeTemplateParameterSuffix, value: '_t'}, \
+// RUN:     {key: readability-identifier-naming.TypedefCase, value: lower_case}, \
+// RUN:     {key: readability-identifier-naming.TypedefSuffix, value: '_t'}, \
+// RUN:     {key: readability-identifier-naming.UnionCase, value: CamelCase}, \
+// RUN:     {key: readability-identifier-naming.UnionPrefix, value: 'U'}, \
+// RUN:     {key: readability-identifier-naming.UsingCase, value: lower_case}, \
+// RUN:     {key: readability-identifier-naming.ValueTemplateParameterCase, value: camelBack}, \
+// RUN:     {key: readability-identifier-naming.VariableCase, value: lower_case}, \
+// RUN:     {key: readability-identifier-naming.VirtualMethodCase, value: Camel_Snake_Case}, \
+// RUN:     {key: readability-identifier-naming.VirtualMethodPrefix, value: 'v_'}, \
+// RUN:     {key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE}, \
+// RUN:     {key: readability-identifier-naming.TypeAliasCase, value: camel_Snake_Back}, \
+// RUN:     {key: readability-identifier-naming.TypeAliasSuffix, value: '_t'}, \
+// RUN:     {key: readability-identifier-naming.IgnoreFailedSplit, value: 0} \
+// RUN:   ]}' -- -std=c++11 -fno-delayed-template-parsing \
+// RUN:   -I%S/Inputs/readability-identifier-naming \
+// RUN:   -isystem %S/Inputs/readability-identifier-naming/system
+
+// clang-format off
+
+#include <system-header.h>
+#include "user-header.h"
+// NO warnings or fixes expected from declarations within header files without
+// the -header-filter= option
+
+namespace FOO_NS {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: invalid case style for namespace 'FOO_NS' [readability-identifier-naming]
+// CHECK-FIXES: {{^}}namespace foo_ns {{{$}}
+inline namespace InlineNamespace {
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: invalid case style for inline namespace 'InlineNamespace'
+// CHECK-FIXES: {{^}}inline namespace inline_namespace {{{$}}
+
+SYSTEM_NS::structure g_s1;
+// NO warnings or fixes expected as SYSTEM_NS and structure are declared in a header file
+
+USER_NS::object g_s2;
+// NO warnings or fixes expected as USER_NS and object are declared in a header file
+
+SYSTEM_MACRO(var1);
+// NO warnings or fixes expected as var1 is from macro expansion
+
+USER_MACRO(var2);
+// NO warnings or fixes expected as var2 is declared in a macro expansion
+
+#define BLA int FOO_bar
+BLA;
+// NO warnings or fixes expected as FOO_bar is from macro expansion
+
+int global0;
+#define USE_NUMBERED_GLOBAL(number) auto use_global##number = global##number
+USE_NUMBERED_GLOBAL(0);
+// NO warnings or fixes expected as global0 is pieced together in a macro
+// expansion.
+
+int global1;
+#define USE_NUMBERED_BAL(prefix, number) \
+  auto use_##prefix##bal##number = prefix##bal##number
+USE_NUMBERED_BAL(glo, 1);
+// NO warnings or fixes expected as global1 is pieced together in a macro
+// expansion.
+
+int global2;
+#define USE_RECONSTRUCTED(glo, bal) auto use_##glo##bal = glo##bal
+USE_RECONSTRUCTED(glo, bal2);
+// NO warnings or fixes expected as global2 is pieced together in a macro
+// expansion.
+
+int global;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'global'
+// CHECK-FIXES: {{^}}int g_global;{{$}}
+#define USE_IN_MACRO(m) auto use_##m = m
+USE_IN_MACRO(global);
+
+int global3;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'global3'
+// CHECK-FIXES: {{^}}int g_global3;{{$}}
+#define ADD_TO_SELF(m) (m) + (m)
+int g_twice_global3 = ADD_TO_SELF(global3);
+// CHECK-FIXES: {{^}}int g_twice_global3 = ADD_TO_SELF(g_global3);{{$}}
+
+enum my_enumeration {
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for enum 'my_enumeration'
+// CHECK-FIXES: {{^}}enum EMyEnumeration {{{$}}
+    MyConstant = 1,
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for enum constant 'MyConstant'
+// CHECK-FIXES: {{^}}    MY_CONSTANT = 1,{{$}}
+    your_CONST = 1,
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for enum constant 'your_CONST'
+// CHECK-FIXES: {{^}}    YOUR_CONST = 1,{{$}}
+    THIS_ConstValue = 1,
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for enum constant 'THIS_ConstValue'
+// CHECK-FIXES: {{^}}    THIS_CONST_VALUE = 1,{{$}}
+};
+
+constexpr int ConstExpr_variable = MyConstant;
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for constexpr variable 'ConstExpr_variable'
+// CHECK-FIXES: {{^}}constexpr int const_expr_variable = MY_CONSTANT;{{$}}
+
+class my_class {
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for class 'my_class'
+// CHECK-FIXES: {{^}}class CMyClass {{{$}}
+public:
+    my_class();
+// CHECK-FIXES: {{^}}    CMyClass();{{$}}
+
+    my_class(void*) : my_class() {}
+// CHECK-FIXES: {{^}}    CMyClass(void*) : CMyClass() {}{{$}}
+
+    ~
+      my_class();
+// (space in destructor token test, we could check trigraph but they will be deprecated)
+// CHECK-FIXES: {{^}}    ~{{$}}
+// CHECK-FIXES: {{^}}      CMyClass();{{$}}
+
+private:
+  const int MEMBER_one_1 = ConstExpr_variable;
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: invalid case style for constant member 'MEMBER_one_1'
+// CHECK-FIXES: {{^}}  const int member_one_1 = const_expr_variable;{{$}}
+  int member2 = 2;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for private member 'member2'
+// CHECK-FIXES: {{^}}  int __member2 = 2;{{$}}
+  int _memberWithExtraUnderscores_ = 42;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for private member '_memberWithExtraUnderscores_'
+// CHECK-FIXES: {{^}}  int __memberWithExtraUnderscores = 42;{{$}}
+
+private:
+    int private_member = 3;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for private member 'private_member'
+// CHECK-FIXES: {{^}}    int __private_member = 3;{{$}}
+
+protected:
+    int ProtMember;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for protected member 'ProtMember'
+// CHECK-FIXES: {{^}}    int _ProtMember;{{$}}
+
+public:
+    int PubMem;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for public member 'PubMem'
+// CHECK-FIXES: {{^}}    int pub_mem;{{$}}
+
+    static const int classConstant;
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: invalid case style for class constant 'classConstant'
+// CHECK-FIXES: {{^}}    static const int kClassConstant;{{$}}
+    static int ClassMember_2;
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: invalid case style for class member 'ClassMember_2'
+// CHECK-FIXES: {{^}}    static int ClassMember2;{{$}}
+};
+class my_class;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for class 'my_class'
+// CHECK-FIXES: {{^}}class CMyClass;{{$}}
+
+class my_forward_declared_class; // No warning should be triggered.
+
+const int my_class::classConstant = 4;
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: invalid case style for class constant 'classConstant'
+// CHECK-FIXES: {{^}}const int CMyClass::kClassConstant = 4;{{$}}
+
+int my_class::ClassMember_2 = 5;
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for class member 'ClassMember_2'
+// CHECK-FIXES: {{^}}int CMyClass::ClassMember2 = 5;{{$}}
+
+class my_derived_class : public virtual my_class {};
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for class 'my_derived_class'
+// CHECK-FIXES: {{^}}class CMyDerivedClass : public virtual CMyClass {};{{$}}
+
+class CMyWellNamedClass {};
+// No warning expected as this class is well named.
+
+template <typename t_t>
+class CMyWellNamedClass2 : public my_class {
+  // CHECK-FIXES: {{^}}class CMyWellNamedClass2 : public CMyClass {{{$}}
+  t_t my_Bad_Member;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for private member 'my_Bad_Member'
+  // CHECK-FIXES: {{^}}  t_t __my_Bad_Member;{{$}}
+  int my_Other_Bad_Member = 42;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for private member 'my_Other_Bad_Member'
+  // CHECK-FIXES: {{^}}  int __my_Other_Bad_Member = 42;{{$}}
+public:
+  CMyWellNamedClass2() = default;
+  CMyWellNamedClass2(CMyWellNamedClass2 const&) = default;
+  CMyWellNamedClass2(CMyWellNamedClass2 &&) = default;
+  CMyWellNamedClass2(t_t a_v, void *a_p) : my_class(a_p), my_Bad_Member(a_v) {}
+  // CHECK-FIXES: {{^}}  CMyWellNamedClass2(t_t a_v, void *a_p) : CMyClass(a_p), __my_Bad_Member(a_v) {}{{$}}
+
+  CMyWellNamedClass2(t_t a_v) : my_class(), my_Bad_Member(a_v), my_Other_Bad_Member(11) {}
+  // CHECK-FIXES: {{^}}  CMyWellNamedClass2(t_t a_v) : CMyClass(), __my_Bad_Member(a_v), __my_Other_Bad_Member(11) {}{{$}}
+};
+void InstantiateClassMethods() {
+  // Ensure we trigger the instantiation of each constructor
+  CMyWellNamedClass2<int> x;
+  CMyWellNamedClass2<int> x2 = x;
+  CMyWellNamedClass2<int> x3 = static_cast<CMyWellNamedClass2<int>&&>(x2);
+  CMyWellNamedClass2<int> x4(42);
+  CMyWellNamedClass2<int> x5(42, nullptr);
+}
+
+template<typename T>
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: invalid case style for type template parameter 'T'
+// CHECK-FIXES: {{^}}template<typename t_t>{{$}}
+class my_templated_class : CMyWellNamedClass {};
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for class 'my_templated_class'
+// CHECK-FIXES: {{^}}class CMyTemplatedClass : CMyWellNamedClass {};{{$}}
+
+template<typename T>
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: invalid case style for type template parameter 'T'
+// CHECK-FIXES: {{^}}template<typename t_t>{{$}}
+class my_other_templated_class : my_templated_class<  my_class>, private my_derived_class {};
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for class 'my_other_templated_class'
+// CHECK-FIXES: {{^}}class CMyOtherTemplatedClass : CMyTemplatedClass<  CMyClass>, private CMyDerivedClass {};{{$}}
+
+template<typename t_t>
+using mysuper_tpl_t = my_other_templated_class  <:: FOO_NS  ::my_class>;
+// CHECK-FIXES: {{^}}using mysuper_tpl_t = CMyOtherTemplatedClass  <:: foo_ns  ::CMyClass>;{{$}}
+
+const int global_Constant = 6;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: invalid case style for global constant 'global_Constant'
+// CHECK-FIXES: {{^}}const int GLOBAL_CONSTANT = 6;{{$}}
+int Global_variable = 7;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'Global_variable'
+// CHECK-FIXES: {{^}}int g_global_variable = 7;{{$}}
+
+void global_function(int PARAMETER_1, int const CONST_parameter) {
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global function 'global_function'
+// CHECK-MESSAGES: :[[@LINE-2]]:26: warning: invalid case style for parameter 'PARAMETER_1'
+// CHECK-MESSAGES: :[[@LINE-3]]:49: warning: invalid case style for constant parameter 'CONST_parameter'
+// CHECK-FIXES: {{^}}void GlobalFunction(int a_parameter1, int const i_constParameter) {{{$}}
+    static const int THIS_static_ConsTant = 4;
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: invalid case style for static constant 'THIS_static_ConsTant'
+// CHECK-FIXES: {{^}}    static const int THIS_STATIC_CONS_TANT = 4;{{$}}
+    static int THIS_static_variable;
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: invalid case style for static variable 'THIS_static_variable'
+// CHECK-FIXES: {{^}}    static int s_thisStaticVariable;{{$}}
+    int const local_Constant = 3;
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for local constant 'local_Constant'
+// CHECK-FIXES: {{^}}    int const kLocalConstant = 3;{{$}}
+    int LOCAL_VARIABLE;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for local variable 'LOCAL_VARIABLE'
+// CHECK-FIXES: {{^}}    int local_variable;{{$}}
+
+    int LOCAL_Array__[] = {0, 1, 2};
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for local variable 'LOCAL_Array__'
+// CHECK-FIXES: {{^}}    int local_array[] = {0, 1, 2};{{$}}
+
+    for (auto _ : LOCAL_Array__) {
+    }
+}
+
+template<typename ... TYPE_parameters>
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: invalid case style for type template parameter 'TYPE_parameters'
+// CHECK-FIXES: {{^}}template<typename ... typeParameters_t>{{$}}
+void Global_Fun(TYPE_parameters... PARAMETER_PACK) {
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global function 'Global_Fun'
+// CHECK-MESSAGES: :[[@LINE-2]]:36: warning: invalid case style for parameter pack 'PARAMETER_PACK'
+// CHECK-FIXES: {{^}}void GlobalFun(typeParameters_t... parameterPack) {{{$}}
+    global_function(1, 2);
+// CHECK-FIXES: {{^}}    GlobalFunction(1, 2);{{$}}
+    FOO_bar = Global_variable;
+// CHECK-FIXES: {{^}}    FOO_bar = g_global_variable;{{$}}
+// NO fix expected for FOO_bar declared in macro expansion
+}
+
+template<template<typename> class TPL_parameter, int COUNT_params, typename ... TYPE_parameters>
+// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: invalid case style for template template parameter 'TPL_parameter'
+// CHECK-MESSAGES: :[[@LINE-2]]:54: warning: invalid case style for value template parameter 'COUNT_params'
+// CHECK-MESSAGES: :[[@LINE-3]]:81: warning: invalid case style for type template parameter 'TYPE_parameters'
+// CHECK-FIXES: {{^}}template<template<typename> class TplParameter, int countParams, typename ... typeParameters_t>{{$}}
+class test_CLASS {
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for class 'test_CLASS'
+// CHECK-FIXES: {{^}}class CTestClass {{{$}}
+};
+
+class abstract_class {
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for abstract class 'abstract_class'
+// CHECK-FIXES: {{^}}class AAbstractClass {{{$}}
+    virtual ~abstract_class() = 0;
+// CHECK-FIXES: {{^}}    virtual ~AAbstractClass() = 0;{{$}}
+    virtual void VIRTUAL_METHOD();
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: invalid case style for virtual method 'VIRTUAL_METHOD'
+// CHECK-FIXES: {{^}}    virtual void v_Virtual_Method();{{$}}
+    void non_Virtual_METHOD() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for private method 'non_Virtual_METHOD'
+// CHECK-FIXES: {{^}}    void __non_Virtual_METHOD() {}{{$}}
+
+public:
+    static void CLASS_METHOD() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: invalid case style for class method 'CLASS_METHOD'
+// CHECK-FIXES: {{^}}    static void classMethod() {}{{$}}
+
+    constexpr int CST_expr_Method() { return 2; }
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: invalid case style for constexpr method 'CST_expr_Method'
+// CHECK-FIXES: {{^}}    constexpr int cst_expr_method() { return 2; }{{$}}
+
+private:
+    void PRIVate_Method();
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for private method 'PRIVate_Method'
+// CHECK-FIXES: {{^}}    void __PRIVate_Method();{{$}}
+protected:
+    void protected_Method();
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for protected method 'protected_Method'
+// CHECK-FIXES: {{^}}    void _protected_Method();{{$}}
+public:
+    void public_Method();
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for method 'public_Method'
+// CHECK-FIXES: {{^}}    void publicMethod();{{$}}
+};
+
+constexpr int CE_function() { return 3; }
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for constexpr function 'CE_function'
+// CHECK-FIXES: {{^}}constexpr int ce_function() { return 3; }{{$}}
+
+struct THIS___Structure {
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for struct 'THIS___Structure'
+// CHECK-FIXES: {{^}}struct this_structure {{{$}}
+    THIS___Structure();
+// CHECK-FIXES: {{^}}    this_structure();{{$}}
+
+  union __MyUnion_is_wonderful__ {};
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for union '__MyUnion_is_wonderful__'
+// CHECK-FIXES: {{^}}  union UMyUnionIsWonderful {};{{$}}
+};
+
+typedef THIS___Structure struct_type;
+// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: invalid case style for typedef 'struct_type'
+// CHECK-FIXES: {{^}}typedef this_structure struct_type_t;{{$}}
+
+struct_type GlobalTypedefTestFunction(struct_type a_argument1) {
+// CHECK-FIXES: {{^}}struct_type_t GlobalTypedefTestFunction(struct_type_t a_argument1) {
+    struct_type typedef_test_1;
+// CHECK-FIXES: {{^}}    struct_type_t typedef_test_1;
+}
+
+using my_struct_type = THIS___Structure;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for type alias 'my_struct_type'
+// CHECK-FIXES: {{^}}using my_Struct_Type_t = this_structure;{{$}}
+
+template<typename t_t>
+using SomeOtherTemplate = my_other_templated_class  <:: FOO_NS  ::my_class>;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for type alias 'SomeOtherTemplate'
+// CHECK-FIXES: {{^}}using some_Other_Template_t = CMyOtherTemplatedClass  <:: foo_ns  ::CMyClass>;{{$}}
+
+static void static_Function() {
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: invalid case style for function 'static_Function'
+// CHECK-FIXES: {{^}}static void staticFunction() {{{$}}
+
+  ::FOO_NS::InlineNamespace::abstract_class::CLASS_METHOD();
+// CHECK-FIXES: {{^}}  ::foo_ns::inline_namespace::AAbstractClass::classMethod();{{$}}
+  ::FOO_NS::InlineNamespace::static_Function();
+// CHECK-FIXES: {{^}}  ::foo_ns::inline_namespace::staticFunction();{{$}}
+
+  using ::FOO_NS::InlineNamespace::CE_function;
+// CHECK-FIXES: {{^}}  using ::foo_ns::inline_namespace::ce_function;{{$}}
+
+  unsigned MY_LOCAL_array[] = {1,2,3};
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: invalid case style for local variable 'MY_LOCAL_array'
+// CHECK-FIXES: {{^}}  unsigned my_local_array[] = {1,2,3};{{$}}
+
+  unsigned const MyConstLocal_array[] = {1,2,3};
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: invalid case style for local constant 'MyConstLocal_array'
+// CHECK-FIXES: {{^}}  unsigned const kMyConstLocalArray[] = {1,2,3};{{$}}
+
+  static unsigned MY_STATIC_array[] = {1,2,3};
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: invalid case style for static variable 'MY_STATIC_array'
+// CHECK-FIXES: {{^}}  static unsigned s_myStaticArray[] = {1,2,3};{{$}}
+
+  static unsigned const MyConstStatic_array[] = {1,2,3};
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: invalid case style for static constant 'MyConstStatic_array'
+// CHECK-FIXES: {{^}}  static unsigned const MY_CONST_STATIC_ARRAY[] = {1,2,3};{{$}}
+
+  char MY_LOCAL_string[] = "123";
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for local variable 'MY_LOCAL_string'
+// CHECK-FIXES: {{^}}  char my_local_string[] = "123";{{$}}
+
+  char const MyConstLocal_string[] = "123";
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: invalid case style for local constant 'MyConstLocal_string'
+// CHECK-FIXES: {{^}}  char const kMyConstLocalString[] = "123";{{$}}
+
+  static char MY_STATIC_string[] = "123";
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for static variable 'MY_STATIC_string'
+// CHECK-FIXES: {{^}}  static char s_myStaticString[] = "123";{{$}}
+
+  static char const MyConstStatic_string[] = "123";
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: invalid case style for static constant 'MyConstStatic_string'
+// CHECK-FIXES: {{^}}  static char const MY_CONST_STATIC_STRING[] = "123";{{$}}
+}
+
+#define MY_TEST_Macro(X) X()
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for macro definition 'MY_TEST_Macro'
+// CHECK-FIXES: {{^}}#define MY_TEST_MACRO(X) X()
+
+void MY_TEST_Macro(function) {}
+// CHECK-FIXES: {{^}}void MY_TEST_MACRO(function) {}
+}
+}
+
+template <typename t_t> struct a {
+  typename t_t::template b<> c;
+
+  char const MY_ConstMember_string[4] = "123";
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: invalid case style for constant member 'MY_ConstMember_string'
+// CHECK-FIXES: {{^}}  char const my_const_member_string[4] = "123";{{$}}
+
+  static char const MyConstClass_string[];
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: invalid case style for class constant 'MyConstClass_string'
+// CHECK-FIXES: {{^}}  static char const kMyConstClassString[];{{$}}
+};
+
+template<typename t_t>
+char const a<t_t>::MyConstClass_string[] = "123";
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: invalid case style for class constant 'MyConstClass_string'
+// CHECK-FIXES: {{^}}char const a<t_t>::kMyConstClassString[] = "123";{{$}}
+
+template <template <typename> class A> struct b { A<int> c; };
+
+unsigned MY_GLOBAL_array[] = {1,2,3};
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for global variable 'MY_GLOBAL_array'
+// CHECK-FIXES: {{^}}unsigned g_my_global_array[] = {1,2,3};{{$}}
+
+unsigned const MyConstGlobal_array[] = {1,2,3};
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: invalid case style for global constant 'MyConstGlobal_array'
+// CHECK-FIXES: {{^}}unsigned const MY_CONST_GLOBAL_ARRAY[] = {1,2,3};{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion-allow-in-conditions.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion-allow-in-conditions.cpp
new file mode 100644
index 0000000..c50b798
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion-allow-in-conditions.cpp
@@ -0,0 +1,72 @@
+// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: readability-implicit-bool-conversion.AllowIntegerConditions, value: 1}, \
+// RUN:   {key: readability-implicit-bool-conversion.AllowPointerConditions, value: 1}]}' \
+// RUN: -- -std=c++11
+
+template<typename T>
+void functionTaking(T);
+
+int functionReturningInt();
+int* functionReturningPointer();
+
+struct Struct {
+  int member;
+  unsigned bitfield : 1;
+};
+
+
+void regularImplicitConversionIntegerToBoolIsNotIgnored() {
+  int integer = 0;
+  functionTaking<bool>(integer);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool [readability-implicit-bool-conversion]
+  // CHECK-FIXES: functionTaking<bool>(integer != 0);
+}
+
+void implicitConversionIntegerToBoolInConditionalsIsAllowed() {
+  Struct s = {};
+  if (s.member) {}
+  if (!s.member) {}
+  if (s.bitfield) {}
+  if (!s.bitfield) {}
+  if (functionReturningInt()) {}
+  if (!functionReturningInt()) {}
+  if (functionReturningInt() && functionReturningPointer()) {}
+  if (!functionReturningInt() && !functionReturningPointer()) {}
+  for (; functionReturningInt(); ) {}
+  for (; functionReturningPointer(); ) {}
+  for (; functionReturningInt() && !functionReturningPointer() || (!functionReturningInt() && functionReturningPointer()); ) {}
+  while (functionReturningInt()) {}
+  while (functionReturningPointer()) {}
+  while (functionReturningInt() && !functionReturningPointer() || (!functionReturningInt() && functionReturningPointer())) {}
+  int value1 = functionReturningInt() ? 1 : 2;
+  int value2 = !functionReturningInt() ? 1 : 2;
+  int value3 = (functionReturningInt() && functionReturningPointer() || !functionReturningInt()) ? 1 : 2;
+  int value4 = functionReturningInt() ?: value3;
+  int *p1 = functionReturningPointer() ?: &value3;
+}
+
+void regularImplicitConversionPointerToBoolIsNotIgnored() {
+  int* pointer = nullptr;
+  functionTaking<bool>(pointer);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int *' -> bool
+  // CHECK-FIXES: functionTaking<bool>(pointer != nullptr);
+
+  int Struct::* memberPointer = &Struct::member;
+  functionTaking<bool>(memberPointer);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int Struct::*' -> bool
+  // CHECK-FIXES: functionTaking<bool>(memberPointer != nullptr);
+}
+
+void implicitConversionPointerToBoolInConditionalsIsAllowed() {
+  if (functionReturningPointer()) {}
+  if (not functionReturningPointer()) {}
+  int value1 = functionReturningPointer() ? 1 : 2;
+  int value2 = (not functionReturningPointer()) ? 1 : 2;
+
+  int Struct::* memberPointer = &Struct::member;
+  if (memberPointer) {}
+  if (memberPointer) {}
+  int value3 = memberPointer ? 1 : 2;
+  int value4 = (not memberPointer) ? 1 : 2;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion-cxx98.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion-cxx98.cpp
new file mode 100644
index 0000000..587f7e2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion-cxx98.cpp
@@ -0,0 +1,45 @@
+// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t -- -- -std=c++98
+
+// We need NULL macro, but some buildbots don't like including <cstddef> header
+// This is a portable way of getting it to work
+#undef NULL
+#define NULL 0L
+
+template<typename T>
+void functionTaking(T);
+
+struct Struct {
+  int member;
+};
+
+void useOldNullMacroInReplacements() {
+  int* pointer = NULL;
+  functionTaking<bool>(pointer);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int *' -> bool [readability-implicit-bool-conversion]
+  // CHECK-FIXES: functionTaking<bool>(pointer != 0);
+
+  int Struct::* memberPointer = NULL;
+  functionTaking<bool>(!memberPointer);
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion 'int Struct::*' -> bool
+  // CHECK-FIXES: functionTaking<bool>(memberPointer == 0);
+}
+
+void fixFalseLiteralConvertingToNullPointer() {
+  functionTaking<int*>(false);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'int *'
+  // CHECK-FIXES: functionTaking<int*>(0);
+
+  int* pointer = NULL;
+  if (pointer == false) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: implicit conversion bool -> 'int *'
+  // CHECK-FIXES: if (pointer == 0) {}
+
+  functionTaking<int Struct::*>(false);
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion bool -> 'int Struct::*'
+  // CHECK-FIXES: functionTaking<int Struct::*>(0);
+
+  int Struct::* memberPointer = NULL;
+  if (memberPointer != false) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'int Struct::*'
+  // CHECK-FIXES: if (memberPointer != 0) {}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion.cpp
new file mode 100644
index 0000000..0bdd670
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-implicit-bool-conversion.cpp
@@ -0,0 +1,439 @@
+// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t
+
+// We need NULL macro, but some buildbots don't like including <cstddef> header
+// This is a portable way of getting it to work
+#undef NULL
+#define NULL 0L
+
+template<typename T>
+void functionTaking(T);
+
+struct Struct {
+  int member;
+};
+
+
+////////// Implicit conversion from bool.
+
+void implicitConversionFromBoolSimpleCases() {
+  bool boolean = true;
+
+  functionTaking<bool>(boolean);
+
+  functionTaking<int>(boolean);
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit conversion bool -> 'int' [readability-implicit-bool-conversion]
+  // CHECK-FIXES: functionTaking<int>(static_cast<int>(boolean));
+
+  functionTaking<unsigned long>(boolean);
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion bool -> 'unsigned long'
+  // CHECK-FIXES: functionTaking<unsigned long>(static_cast<unsigned long>(boolean));
+
+  functionTaking<char>(boolean);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'char'
+  // CHECK-FIXES: functionTaking<char>(static_cast<char>(boolean));
+
+  functionTaking<float>(boolean);
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion bool -> 'float'
+  // CHECK-FIXES: functionTaking<float>(static_cast<float>(boolean));
+
+  functionTaking<double>(boolean);
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit conversion bool -> 'double'
+  // CHECK-FIXES: functionTaking<double>(static_cast<double>(boolean));
+}
+
+float implicitConversionFromBoolInReturnValue() {
+  bool boolean = false;
+  return boolean;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion bool -> 'float'
+  // CHECK-FIXES: return static_cast<float>(boolean);
+}
+
+void implicitConversionFromBoolInSingleBoolExpressions(bool b1, bool b2) {
+  bool boolean = true;
+  boolean = b1 ^ b2;
+  boolean = b1 && b2;
+  boolean |= !b1 || !b2;
+  boolean &= b1;
+  boolean = b1 == true;
+  boolean = b2 != false;
+
+  int integer = boolean - 3;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit conversion bool -> 'int'
+  // CHECK-FIXES: int integer = static_cast<int>(boolean) - 3;
+
+  float floating = boolean / 0.3f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit conversion bool -> 'float'
+  // CHECK-FIXES: float floating = static_cast<float>(boolean) / 0.3f;
+
+  char character = boolean;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit conversion bool -> 'char'
+  // CHECK-FIXES: char character = static_cast<char>(boolean);
+}
+
+void implicitConversionFromBoollInComplexBoolExpressions() {
+  bool boolean = true;
+  bool anotherBoolean = false;
+
+  int integer = boolean && anotherBoolean;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit conversion bool -> 'int'
+  // CHECK-FIXES: int integer = static_cast<int>(boolean && anotherBoolean);
+
+  unsigned long unsignedLong = (! boolean) + 4ul;
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit conversion bool -> 'unsigned long'
+  // CHECK-FIXES: unsigned long unsignedLong = static_cast<unsigned long>(! boolean) + 4ul;
+
+  float floating = (boolean || anotherBoolean) * 0.3f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit conversion bool -> 'float'
+  // CHECK-FIXES: float floating = static_cast<float>(boolean || anotherBoolean) * 0.3f;
+
+  double doubleFloating = (boolean && (anotherBoolean || boolean)) * 0.3;
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: implicit conversion bool -> 'double'
+  // CHECK-FIXES: double doubleFloating = static_cast<double>(boolean && (anotherBoolean || boolean)) * 0.3;
+}
+
+void implicitConversionFromBoolLiterals() {
+  functionTaking<int>(true);
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit conversion bool -> 'int'
+  // CHECK-FIXES: functionTaking<int>(1);
+
+  functionTaking<unsigned long>(false);
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion bool -> 'unsigned long'
+  // CHECK-FIXES: functionTaking<unsigned long>(0u);
+
+  functionTaking<signed char>(true);
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: implicit conversion bool -> 'signed char'
+  // CHECK-FIXES: functionTaking<signed char>(1);
+
+  functionTaking<float>(false);
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion bool -> 'float'
+  // CHECK-FIXES: functionTaking<float>(0.0f);
+
+  functionTaking<double>(true);
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit conversion bool -> 'double'
+  // CHECK-FIXES: functionTaking<double>(1.0);
+}
+
+void implicitConversionFromBoolInComparisons() {
+  bool boolean = true;
+  int integer = 0;
+
+  functionTaking<bool>(boolean == integer);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'int'
+  // CHECK-FIXES: functionTaking<bool>(static_cast<int>(boolean) == integer);
+
+  functionTaking<bool>(integer != boolean);
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: implicit conversion bool -> 'int'
+  // CHECK-FIXES: functionTaking<bool>(integer != static_cast<int>(boolean));
+}
+
+void ignoreBoolComparisons() {
+  bool boolean = true;
+  bool anotherBoolean = false;
+
+  functionTaking<bool>(boolean == anotherBoolean);
+  functionTaking<bool>(boolean != anotherBoolean);
+}
+
+void ignoreExplicitCastsFromBool() {
+  bool boolean = true;
+
+  int integer = static_cast<int>(boolean) + 3;
+  float floating = static_cast<float>(boolean) * 0.3f;
+  char character = static_cast<char>(boolean);
+}
+
+void ignoreImplicitConversionFromBoolInMacroExpansions() {
+  bool boolean = true;
+
+  #define CAST_FROM_BOOL_IN_MACRO_BODY boolean + 3
+  int integerFromMacroBody = CAST_FROM_BOOL_IN_MACRO_BODY;
+
+  #define CAST_FROM_BOOL_IN_MACRO_ARGUMENT(x) x + 3
+  int integerFromMacroArgument = CAST_FROM_BOOL_IN_MACRO_ARGUMENT(boolean);
+}
+
+namespace ignoreImplicitConversionFromBoolInTemplateInstantiations {
+
+template<typename T>
+void templateFunction() {
+  bool boolean = true;
+  T uknownType = boolean + 3;
+}
+
+void useOfTemplateFunction() {
+  templateFunction<int>();
+}
+
+} // namespace ignoreImplicitConversionFromBoolInTemplateInstantiations
+
+////////// Implicit conversions to bool.
+
+void implicitConversionToBoolSimpleCases() {
+  int integer = 10;
+  functionTaking<bool>(integer);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: functionTaking<bool>(integer != 0);
+
+  unsigned long unsignedLong = 10;
+  functionTaking<bool>(unsignedLong);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'unsigned long' -> bool
+  // CHECK-FIXES: functionTaking<bool>(unsignedLong != 0u);
+
+  float floating = 0.0f;
+  functionTaking<bool>(floating);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: functionTaking<bool>(floating != 0.0f);
+
+  double doubleFloating = 1.0f;
+  functionTaking<bool>(doubleFloating);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'double' -> bool
+  // CHECK-FIXES: functionTaking<bool>(doubleFloating != 0.0);
+
+  signed char character = 'a';
+  functionTaking<bool>(character);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'signed char' -> bool
+  // CHECK-FIXES: functionTaking<bool>(character != 0);
+
+  int* pointer = nullptr;
+  functionTaking<bool>(pointer);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int *' -> bool
+  // CHECK-FIXES: functionTaking<bool>(pointer != nullptr);
+
+  auto pointerToMember = &Struct::member;
+  functionTaking<bool>(pointerToMember);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int Struct::*' -> bool
+  // CHECK-FIXES: functionTaking<bool>(pointerToMember != nullptr);
+}
+
+void implicitConversionToBoolInSingleExpressions() {
+  int integer = 10;
+  bool boolComingFromInt = integer;
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: bool boolComingFromInt = integer != 0;
+
+  float floating = 10.0f;
+  bool boolComingFromFloat = floating;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: bool boolComingFromFloat = floating != 0.0f;
+
+  signed char character = 'a';
+  bool boolComingFromChar = character;
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: implicit conversion 'signed char' -> bool
+  // CHECK-FIXES: bool boolComingFromChar = character != 0;
+
+  int* pointer = nullptr;
+  bool boolComingFromPointer = pointer;
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit conversion 'int *' -> bool
+  // CHECK-FIXES: bool boolComingFromPointer = pointer != nullptr;
+}
+
+void implicitConversionToBoolInComplexExpressions() {
+  bool boolean = true;
+
+  int integer = 10;
+  int anotherInteger = 20;
+  bool boolComingFromInteger = integer + anotherInteger;
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: bool boolComingFromInteger = (integer + anotherInteger) != 0;
+
+  float floating = 0.2f;
+  bool boolComingFromFloating = floating - 0.3f || boolean;
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: bool boolComingFromFloating = ((floating - 0.3f) != 0.0f) || boolean;
+
+  double doubleFloating = 0.3;
+  bool boolComingFromDoubleFloating = (doubleFloating - 0.4) && boolean;
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit conversion 'double' -> bool
+  // CHECK-FIXES: bool boolComingFromDoubleFloating = ((doubleFloating - 0.4) != 0.0) && boolean;
+}
+
+void implicitConversionInNegationExpressions() {
+  int integer = 10;
+  bool boolComingFromNegatedInt = !integer;
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: bool boolComingFromNegatedInt = integer == 0;
+
+  float floating = 10.0f;
+  bool boolComingFromNegatedFloat = ! floating;
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: bool boolComingFromNegatedFloat = floating == 0.0f;
+
+  signed char character = 'a';
+  bool boolComingFromNegatedChar = (! character);
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit conversion 'signed char' -> bool
+  // CHECK-FIXES: bool boolComingFromNegatedChar = (character == 0);
+
+  int* pointer = nullptr;
+  bool boolComingFromNegatedPointer = not pointer;
+  // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: implicit conversion 'int *' -> bool
+  // CHECK-FIXES: bool boolComingFromNegatedPointer = pointer == nullptr;
+}
+
+void implicitConversionToBoolInControlStatements() {
+  int integer = 10;
+  if (integer) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: if (integer != 0) {}
+
+  long int longInteger = 0.2f;
+  for (;longInteger;) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: implicit conversion 'long' -> bool
+  // CHECK-FIXES: for (;longInteger != 0;) {}
+
+  float floating = 0.3f;
+  while (floating) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: while (floating != 0.0f) {}
+
+  double doubleFloating = 0.4;
+  do {} while (doubleFloating);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: implicit conversion 'double' -> bool
+  // CHECK-FIXES: do {} while (doubleFloating != 0.0);
+}
+
+bool implicitConversionToBoolInReturnValue() {
+  float floating = 1.0f;
+  return floating;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: return floating != 0.0f;
+}
+
+void implicitConversionToBoolFromLiterals() {
+  functionTaking<bool>(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: functionTaking<bool>(false);
+
+  functionTaking<bool>(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: functionTaking<bool>(true);
+
+  functionTaking<bool>(2ul);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'unsigned long' -> bool
+  // CHECK-FIXES: functionTaking<bool>(true);
+
+
+  functionTaking<bool>(0.0f);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: functionTaking<bool>(false);
+
+  functionTaking<bool>(1.0f);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: functionTaking<bool>(true);
+
+  functionTaking<bool>(2.0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'double' -> bool
+  // CHECK-FIXES: functionTaking<bool>(true);
+
+
+  functionTaking<bool>('\0');
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'char' -> bool
+  // CHECK-FIXES: functionTaking<bool>(false);
+
+  functionTaking<bool>('a');
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'char' -> bool
+  // CHECK-FIXES: functionTaking<bool>(true);
+
+
+  functionTaking<bool>("");
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'const char *' -> bool
+  // CHECK-FIXES: functionTaking<bool>(true);
+
+  functionTaking<bool>("abc");
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'const char *' -> bool
+  // CHECK-FIXES: functionTaking<bool>(true);
+
+  functionTaking<bool>(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'long' -> bool
+  // CHECK-FIXES: functionTaking<bool>(false);
+}
+
+void implicitConversionToBoolFromUnaryMinusAndZeroLiterals() {
+  functionTaking<bool>(-0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: functionTaking<bool>((-0) != 0);
+
+  functionTaking<bool>(-0.0f);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: functionTaking<bool>((-0.0f) != 0.0f);
+
+  functionTaking<bool>(-0.0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'double' -> bool
+  // CHECK-FIXES: functionTaking<bool>((-0.0) != 0.0);
+}
+
+void implicitConversionToBoolInWithOverloadedOperators() {
+  struct UserStruct {
+    int operator()(int x) { return x; }
+    int operator+(int y) { return y; }
+  };
+
+  UserStruct s;
+
+  functionTaking<bool>(s(0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: functionTaking<bool>(s(0) != 0);
+
+  functionTaking<bool>(s + 2);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: functionTaking<bool>((s + 2) != 0);
+}
+
+int functionReturningInt();
+int* functionReturningPointer();
+
+void ignoreImplicitConversionToBoolWhenDeclaringVariableInControlStatements() {
+  if (int integer = functionReturningInt()) {}
+
+  while (int* pointer = functionReturningPointer()) {}
+}
+
+void ignoreExplicitCastsToBool() {
+  int integer = 10;
+  bool boolComingFromInt = static_cast<bool>(integer);
+
+  float floating = 10.0f;
+  bool boolComingFromFloat = static_cast<bool>(floating);
+
+  char character = 'a';
+  bool boolComingFromChar = static_cast<bool>(character);
+
+  int* pointer = nullptr;
+  bool booleanComingFromPointer = static_cast<bool>(pointer);
+}
+
+void ignoreImplicitConversionToBoolInMacroExpansions() {
+  int integer = 3;
+
+  #define CAST_TO_BOOL_IN_MACRO_BODY integer && false
+  bool boolFromMacroBody = CAST_TO_BOOL_IN_MACRO_BODY;
+
+  #define CAST_TO_BOOL_IN_MACRO_ARGUMENT(x) x || true
+  bool boolFromMacroArgument = CAST_TO_BOOL_IN_MACRO_ARGUMENT(integer);
+}
+
+namespace ignoreImplicitConversionToBoolInTemplateInstantiations {
+
+template<typename T>
+void templateFunction() {
+  T unknownType = 0;
+  bool boolean = unknownType;
+}
+
+void useOfTemplateFunction() {
+  templateFunction<int>();
+}
+
+} // namespace ignoreImplicitConversionToBoolInTemplateInstantiations
+
+namespace ignoreUserDefinedConversionOperator {
+
+struct StructWithUserConversion {
+  operator bool();
+};
+
+void useOfUserConversion() {
+  StructWithUserConversion structure;
+  functionTaking<bool>(structure);
+}
+
+} // namespace ignoreUserDefinedConversionOperator
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name-macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name-macros.cpp
new file mode 100644
index 0000000..c06bbfb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name-macros.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s readability-inconsistent-declaration-parameter-name %t -- \
+// RUN:   -config="{CheckOptions: [{key: readability-inconsistent-declaration-parameter-name.IgnoreMacros, value: 0}]}" \
+// RUN:   -- -std=c++11
+
+#define MACRO() \
+  void f(int x);
+
+struct S {
+  MACRO();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: function 'S::f' has a definition with different parameter names
+};
+
+void S::f(int y) {
+}
+
+//////////////////////////////////////////////////////
+
+#define DECLARE_FUNCTION_WITH_PARAM_NAME(function_name, param_name) \
+  void function_name(int param_name)
+
+// CHECK-MESSAGES: :[[@LINE+1]]:34: warning: function 'macroFunction' has 1 other declaration with different parameter names [readability-inconsistent-declaration-parameter-name]
+DECLARE_FUNCTION_WITH_PARAM_NAME(macroFunction, a);
+// CHECK-MESSAGES: :[[@LINE+2]]:34: note: the 1st inconsistent declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:34: note: differing parameters are named here: ('b'), in the other declaration: ('a')
+DECLARE_FUNCTION_WITH_PARAM_NAME(macroFunction, b);
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name-strict.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name-strict.cpp
new file mode 100644
index 0000000..90ac45f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name-strict.cpp
@@ -0,0 +1,11 @@
+// RUN: %check_clang_tidy %s readability-inconsistent-declaration-parameter-name %t -- \
+// RUN:   -config="{CheckOptions: [{key: readability-inconsistent-declaration-parameter-name.Strict, value: 1}]}" \
+// RUN:   -- -std=c++11
+
+void inconsistentFunction(int a, int b, int c);
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'inconsistentFunction' has 1 other declaration with different parameter names
+void inconsistentFunction(int prefixA, int b, int cSuffix);
+// CHECK-MESSAGES: :[[@LINE-1]]:6: note: the 1st inconsistent declaration seen here
+// CHECK-MESSAGES: :[[@LINE-2]]:6: note: differing parameters are named here: ('prefixA', 'cSuffix'), in the other declaration: ('a', 'c')
+void inconsistentFunction(int a, int b, int c);
+void inconsistentFunction(int /*c*/, int /*c*/, int /*c*/);
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name.cpp
new file mode 100644
index 0000000..c98258b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-inconsistent-declaration-parameter-name.cpp
@@ -0,0 +1,193 @@
+// RUN: %check_clang_tidy %s readability-inconsistent-declaration-parameter-name %t -- -- -std=c++11 -fno-delayed-template-parsing
+
+void consistentFunction(int a, int b, int c);
+void consistentFunction(int a, int b, int c);
+void consistentFunction(int prefixA, int b, int cSuffix);
+void consistentFunction(int a, int b, int c);
+void consistentFunction(int a, int b, int /*c*/);
+void consistentFunction(int /*c*/, int /*c*/, int /*c*/);
+
+//////////////////////////////////////////////////////
+
+// CHECK-MESSAGES: :[[@LINE+1]]:6: warning: function 'inconsistentFunction' has 2 other declarations with different parameter names [readability-inconsistent-declaration-parameter-name]
+void inconsistentFunction(int a, int b, int c);
+// CHECK-MESSAGES: :[[@LINE+2]]:6: note: the 1st inconsistent declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('d', 'e', 'f'), in the other declaration: ('a', 'b', 'c')
+void inconsistentFunction(int d, int e, int f);
+// CHECK-MESSAGES: :[[@LINE+2]]:6: note: the 2nd inconsistent declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('x', 'y', 'z'), in the other declaration: ('a', 'b', 'c')
+void inconsistentFunction(int x, int y, int z);
+
+//////////////////////////////////////////////////////
+
+// CHECK-MESSAGES: :[[@LINE+4]]:6: warning: function 'inconsistentFunctionWithVisibleDefinition' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]
+// CHECK-MESSAGES: :[[@LINE+9]]:6: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+2]]:6: note: differing parameters are named here: ('a'), in definition: ('c')
+// CHECK-FIXES: void inconsistentFunctionWithVisibleDefinition(int c);
+void inconsistentFunctionWithVisibleDefinition(int a);
+// CHECK-MESSAGES: :[[@LINE+4]]:6: warning: function 'inconsistentFunctionWithVisibleDefinition' has a definition
+// CHECK-MESSAGES: :[[@LINE+4]]:6: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+2]]:6: note: differing parameters are named here: ('b'), in definition: ('c')
+// CHECK-FIXES: void inconsistentFunctionWithVisibleDefinition(int c);
+void inconsistentFunctionWithVisibleDefinition(int b);
+void inconsistentFunctionWithVisibleDefinition(int c) { c; }
+
+// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function 'inconsidentFunctionWithUnreferencedParameterInDefinition' has a definition
+// CHECK-MESSAGES: :[[@LINE+3]]:6: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('a'), in definition: ('b')
+void inconsidentFunctionWithUnreferencedParameterInDefinition(int a);
+void inconsidentFunctionWithUnreferencedParameterInDefinition(int b) {}
+
+//////////////////////////////////////////////////////
+
+struct Struct {
+// CHECK-MESSAGES: :[[@LINE+4]]:8: warning: function 'Struct::inconsistentFunction' has a definition
+// CHECK-MESSAGES: :[[@LINE+6]]:14: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+2]]:8: note: differing parameters are named here: ('a'), in definition: ('b')
+// CHECK-FIXES: void inconsistentFunction(int b);
+  void inconsistentFunction(int a);
+};
+
+void Struct::inconsistentFunction(int b) { b = 0; }
+
+//////////////////////////////////////////////////////
+
+struct SpecialFunctions {
+// CHECK-MESSAGES: :[[@LINE+4]]:3: warning: function 'SpecialFunctions::SpecialFunctions' has a definition
+// CHECK-MESSAGES: :[[@LINE+12]]:19: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+2]]:3: note: differing parameters are named here: ('a'), in definition: ('b')
+// CHECK-FIXES: SpecialFunctions(int b);
+  SpecialFunctions(int a);
+
+// CHECK-MESSAGES: :[[@LINE+4]]:21: warning: function 'SpecialFunctions::operator=' has a definition
+// CHECK-MESSAGES: :[[@LINE+8]]:37: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+2]]:21: note: differing parameters are named here: ('a'), in definition: ('b')
+// CHECK-FIXES: SpecialFunctions& operator=(const SpecialFunctions& b);
+  SpecialFunctions& operator=(const SpecialFunctions& a);
+};
+
+SpecialFunctions::SpecialFunctions(int b) { b; }
+
+SpecialFunctions& SpecialFunctions::operator=(const SpecialFunctions& b) { b; return *this; }
+
+//////////////////////////////////////////////////////
+
+// CHECK-MESSAGES: :[[@LINE+5]]:6: warning: function 'templateFunctionWithSeparateDeclarationAndDefinition' has a definition
+// CHECK-MESSAGES: :[[@LINE+7]]:6: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+3]]:6: note: differing parameters are named here: ('a'), in definition: ('b')
+// CHECK-FIXES: void templateFunctionWithSeparateDeclarationAndDefinition(T b);
+template<typename T>
+void templateFunctionWithSeparateDeclarationAndDefinition(T a);
+
+template<typename T>
+void templateFunctionWithSeparateDeclarationAndDefinition(T b) { b; }
+
+//////////////////////////////////////////////////////
+
+template<typename T>
+void templateFunctionWithSpecializations(T a) { a; }
+
+template<>
+// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'templateFunctionWithSpecializations<int>' has a primary template declaration with different parameter names [readability-inconsistent-declaration-parameter-name]
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: the primary template declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('b'), in primary template declaration: ('a')
+void templateFunctionWithSpecializations(int b) { b; }
+
+template<>
+// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'templateFunctionWithSpecializations<float>' has a primary template
+// CHECK-MESSAGES: :[[@LINE-10]]:6: note: the primary template declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('c'), in primary template declaration: ('a')
+void templateFunctionWithSpecializations(float c) { c; }
+
+//////////////////////////////////////////////////////
+
+template<typename T>
+void templateFunctionWithoutDefinitionButWithSpecialization(T a);
+
+template<>
+// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'templateFunctionWithoutDefinitionButWithSpecialization<int>' has a primary template
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: the primary template declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('b'), in primary template declaration: ('a')
+void templateFunctionWithoutDefinitionButWithSpecialization(int b) { b; }
+
+//////////////////////////////////////////////////////
+
+template<typename T>
+void templateFunctionWithSeparateSpecializationDeclarationAndDefinition(T a);
+
+template<>
+// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'templateFunctionWithSeparateSpecializationDeclarationAndDefinition<int>' has a primary template
+// CHECK-MESSAGES: :[[@LINE-4]]:6: note: the primary template declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('b'), in primary template declaration: ('a')
+void templateFunctionWithSeparateSpecializationDeclarationAndDefinition(int b);
+
+template<>
+// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'templateFunctionWithSeparateSpecializationDeclarationAndDefinition<int>' has a primary template
+// CHECK-MESSAGES: :[[@LINE-10]]:6: note: the primary template declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('c'), in primary template declaration: ('a')
+void templateFunctionWithSeparateSpecializationDeclarationAndDefinition(int c) { c; }
+
+//////////////////////////////////////////////////////
+
+template<typename T>
+class ClassTemplate
+{
+public:
+// CHECK-MESSAGES: :[[@LINE+4]]:10: warning: function 'ClassTemplate::functionInClassTemplateWithSeparateDeclarationAndDefinition' has a definition
+// CHECK-MESSAGES: :[[@LINE+7]]:24: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+2]]:10: note: differing parameters are named here: ('a'), in definition: ('b')
+// CHECK-FIXES: void functionInClassTemplateWithSeparateDeclarationAndDefinition(int b);
+    void functionInClassTemplateWithSeparateDeclarationAndDefinition(int a);
+};
+
+template<typename T>
+void ClassTemplate<T>::functionInClassTemplateWithSeparateDeclarationAndDefinition(int b) { b; }
+
+//////////////////////////////////////////////////////
+
+class Class
+{
+public:
+    template<typename T>
+// CHECK-MESSAGES: :[[@LINE+4]]:8: warning: function 'Class::memberFunctionTemplateWithSeparateDeclarationAndDefinition' has a definition
+// CHECK-MESSAGES: :[[@LINE+12]]:13: note: the definition seen here
+// CHECK-MESSAGES: :[[@LINE+2]]:8: note: differing parameters are named here: ('a'), in definition: ('b')
+// CHECK-FIXES: void memberFunctionTemplateWithSeparateDeclarationAndDefinition(T b);
+  void memberFunctionTemplateWithSeparateDeclarationAndDefinition(T a);
+
+  template<typename T>
+  void memberFunctionTemplateWithSpecializations(T a) { a; }
+};
+
+//////////////////////////////////////////////////////
+
+template<typename T>
+void Class::memberFunctionTemplateWithSeparateDeclarationAndDefinition(T b) { b; }
+
+//////////////////////////////////////////////////////
+
+template<>
+// CHECK-MESSAGES: :[[@LINE+3]]:13: warning: function template specialization 'Class::memberFunctionTemplateWithSpecializations<int>' has a primary template
+// CHECK-MESSAGES: :[[@LINE-12]]:8: note: the primary template declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:13: note: differing parameters are named here: ('b'), in primary template declaration: ('a')
+void Class::memberFunctionTemplateWithSpecializations(int b) { b; }
+
+template<>
+// CHECK-MESSAGES: :[[@LINE+3]]:13: warning: function template specialization 'Class::memberFunctionTemplateWithSpecializations<float>' has a primary template
+// CHECK-MESSAGES: :[[@LINE-18]]:8: note: the primary template declaration seen here
+// CHECK-MESSAGES: :[[@LINE+1]]:13: note: differing parameters are named here: ('c'), in primary template declaration: ('a')
+void Class::memberFunctionTemplateWithSpecializations(float c) { c; }
+
+//////////////////////////////////////////////////////
+
+// This resulted in a warning by default.
+#define MACRO() \
+  void f(int x);
+
+struct S {
+  MACRO();
+};
+
+void S::f(int y)
+{
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-misleading-indentation.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-misleading-indentation.cpp
new file mode 100644
index 0000000..59d5f40
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-misleading-indentation.cpp
@@ -0,0 +1,111 @@
+// RUN: %check_clang_tidy %s readability-misleading-indentation %t
+
+void foo1();
+void foo2();
+
+#define BLOCK \
+  if (cond1)  \
+    foo1();   \
+    foo2();
+
+int main()
+{
+  bool cond1 = true;
+  bool cond2 = true;
+
+  if (cond1)
+    if (cond2)
+      foo1();
+  else
+    foo2();
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: different indentation for 'if' and corresponding 'else' [readability-misleading-indentation]
+
+  if (cond1) {
+    if (cond2)
+      foo1();
+  }
+  else
+    foo2();
+
+  if (cond1)
+    if (cond2)
+      foo1();
+    else
+      foo2();
+
+  if (cond2)
+    foo1();
+    foo2();
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: misleading indentation: statement is indented too deeply [readability-misleading-indentation]
+    // CHECK-MESSAGES: :[[@LINE-4]]:3: note: did you mean this line to be inside this 'if'
+    foo2(); // No redundant warning.
+
+  if (cond1)
+  {
+    foo1();
+  }
+    foo2();
+
+  if (cond1)
+    foo1();
+  foo2();
+
+  if (cond2)
+    if (cond1) foo1(); else foo2();
+
+  if (cond1) {
+  } else {
+  }
+
+  if (cond1) {
+  }
+  else {
+  }
+
+  if (cond1)
+  {
+  }
+  else
+  {
+  }
+
+  if (cond1)
+    {
+    }
+  else
+    {
+    }
+
+  if(cond1) {
+  }
+  else if (cond2) {
+  }
+  else {
+  }
+
+  if(cond1) {
+  }
+  else if (cond2) {
+  }
+       else {
+  }
+  // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: different indentation for 'if' and corresponding 'else' [readability-misleading-indentation]
+  
+  if (cond1) {
+    if (cond1) {
+    }
+    else if (cond2) {
+    }
+    else {
+    }
+    if (cond1) {
+    } else if (cond2) {
+    } else if (!cond2) {
+    } else {
+    }
+  }
+  else if (cond2) {
+  }
+
+  BLOCK
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-misplaced-array-index.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-misplaced-array-index.cpp
new file mode 100644
index 0000000..43dd458
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-misplaced-array-index.cpp
@@ -0,0 +1,34 @@
+// RUN: %check_clang_tidy %s readability-misplaced-array-index %t
+
+#define ABC  "abc"
+
+struct XY { int *X; int *Y; };
+
+void dostuff(int);
+
+void unusualSyntax(int *P1, struct XY *P2) {
+  10[P1] = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: confusing array subscript expression, usually the index is inside the []
+  // CHECK-FIXES: P1[10] = 0;
+
+  10[P2->X] = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: confusing array subscript expression
+  // CHECK-FIXES: P2->X[10] = 0;
+
+  dostuff(1["abc"]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: confusing array subscript expression
+  // CHECK-FIXES:  dostuff("abc"[1]);
+
+  dostuff(1[ABC]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: confusing array subscript expression
+  // CHECK-FIXES:  dostuff(ABC[1]);
+
+  dostuff(0[0 + ABC]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: confusing array subscript expression
+  // CHECK-FIXES:  dostuff(0[0 + ABC]);
+  // No fixit. Probably the code should be ABC[0]
+}
+
+void normalSyntax(int *X) {
+  X[10] = 0;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-named-parameter.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-named-parameter.cpp
new file mode 100644
index 0000000..af2c195
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-named-parameter.cpp
@@ -0,0 +1,133 @@
+// RUN: %check_clang_tidy %s readability-named-parameter %t
+
+void Method(char *) { /* */ }
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: all parameters should be named in a function
+// CHECK-FIXES: void Method(char * /*unused*/) { /* */ }
+void Method2(char *) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: all parameters should be named in a function
+// CHECK-FIXES: void Method2(char * /*unused*/) {}
+void Method3(char *, void *) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: all parameters should be named in a function
+// CHECK-FIXES: void Method3(char * /*unused*/, void * /*unused*/) {}
+void Method4(char *, int /*unused*/) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: all parameters should be named in a function
+// CHECK-FIXES: void Method4(char * /*unused*/, int /*unused*/) {}
+void operator delete[](void *) throw() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: all parameters should be named in a function
+// CHECK-FIXES: void operator delete[](void * /*unused*/) throw() {}
+int Method5(int) { return 0; }
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: all parameters should be named in a function
+// CHECK-FIXES: int Method5(int /*unused*/) { return 0; }
+void Method6(void (*)(void *)) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: all parameters should be named in a function
+// CHECK-FIXES: void Method6(void (* /*unused*/)(void *)) {}
+template <typename T> void Method7(T) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: all parameters should be named in a function
+// CHECK-FIXES: template <typename T> void Method7(T /*unused*/) {}
+
+// Don't warn in macros.
+#define M void MethodM(int) {}
+M
+
+void operator delete(void *x) throw() {}
+void Method7(char * /*x*/) {}
+void Method8(char *x) {}
+typedef void (*TypeM)(int x);
+void operator delete[](void *x) throw();
+void operator delete[](void * /*x*/) throw();
+
+struct X {
+  X operator++(int) {}
+  X operator--(int) {}
+
+  X(X&) = delete;
+  X &operator=(X&) = default;
+
+  const int &i;
+};
+
+void (*Func1)(void *);
+void Func2(void (*func)(void *)) {}
+template <void Func(void *)> void Func3() {}
+
+template <typename T>
+struct Y {
+  void foo(T) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: all parameters should be named in a function
+// CHECK-FIXES: void foo(T /*unused*/) {}
+};
+
+Y<int> y;
+Y<float> z;
+
+struct Base {
+  virtual void foo(bool notThisOne);
+  virtual void foo(int argname);
+};
+
+struct Derived : public Base {
+  void foo(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: all parameters should be named in a function
+// CHECK-FIXES: void foo(int /*argname*/);
+};
+
+void FDef(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: all parameters should be named in a function
+// CHECK-FIXES: void FDef(int /*n*/);
+void FDef(int n) {}
+
+void FDef2(int, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: all parameters should be named in a function
+// CHECK-FIXES: void FDef2(int /*n*/, int /*unused*/);
+void FDef2(int n, int) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: all parameters should be named in a function
+// CHECK-FIXES: void FDef2(int n, int /*unused*/) {}
+
+void FNoDef(int);
+
+class Z {};
+
+Z &operator++(Z&) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: all parameters should be named in a function
+// CHECK-FIXES: Z &operator++(Z& /*unused*/) {}
+
+Z &operator++(Z&, int) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: all parameters should be named in a function
+// CHECK-FIXES: Z &operator++(Z& /*unused*/, int) {}
+
+Z &operator--(Z&) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: all parameters should be named in a function
+// CHECK-FIXES: Z &operator--(Z& /*unused*/) {}
+
+Z &operator--(Z&, int) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: all parameters should be named in a function
+// CHECK-FIXES: Z &operator--(Z& /*unused*/, int) {}
+
+namespace testing {
+namespace internal {
+class IgnoredValue {
+ public:
+  template <typename T>
+  IgnoredValue(const T& /* ignored */) {}
+};
+}
+typedef internal::IgnoredValue Unused;
+}
+
+using ::testing::Unused;
+
+void MockFunction(Unused, int q, Unused) {
+  ++q;
+  ++q;
+  ++q;
+}
+
+namespace std {
+typedef decltype(nullptr) nullptr_t;
+}
+
+void f(std::nullptr_t) {}
+
+typedef void (F)(int);
+F f;
+void f(int x) {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-non-const-parameter.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-non-const-parameter.cpp
new file mode 100644
index 0000000..6cd1f91
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-non-const-parameter.cpp
@@ -0,0 +1,289 @@
+// RUN: %check_clang_tidy %s readability-non-const-parameter %t
+
+// Currently the checker only warns about pointer arguments.
+//
+// It can be defined both that the data is const and that the pointer is const,
+// the checker only checks if the data can be const-specified.
+//
+// It does not warn about pointers to records or function pointers.
+
+// Some external function where first argument is nonconst and second is const.
+char *strcpy1(char *dest, const char *src);
+unsigned my_strcpy(char *buf, const char *s);
+unsigned my_strlen(const char *buf);
+
+// CHECK-MESSAGES: :[[@LINE+1]]:29: warning: pointer parameter 'last' can be pointer to const [readability-non-const-parameter]
+void warn1(int *first, int *last) {
+  // CHECK-FIXES: {{^}}void warn1(int *first, const int *last) {{{$}}
+  *first = 0;
+  if (first < last) {
+  } // <- last can be const
+}
+
+// TODO: warning should be written here
+void warn2(char *p) {
+  char buf[10];
+  strcpy1(buf, p);
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:19: warning: pointer parameter 'p' can be
+void assign1(int *p) {
+  // CHECK-FIXES: {{^}}void assign1(const int *p) {{{$}}
+  const int *q;
+  q = p;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:19: warning: pointer parameter 'p' can be
+void assign2(int *p) {
+  // CHECK-FIXES: {{^}}void assign2(const int *p) {{{$}}
+  const int *q;
+  q = p + 1;
+}
+
+void assign3(int *p) {
+  *p = 0;
+}
+
+void assign4(int *p) {
+  *p += 2;
+}
+
+void assign5(char *p) {
+  p[0] = 0;
+}
+
+void assign6(int *p) {
+  int *q;
+  q = p++;
+}
+
+void assign7(char *p) {
+  char *a, *b;
+  a = b = p;
+}
+
+void assign8(char *a, char *b) {
+  char *x;
+  x = (a ? a : b);
+}
+
+void assign9(unsigned char *str, const unsigned int i) {
+  unsigned char *p;
+  for (p = str + i; *p;) {
+  }
+}
+
+void assign10(int *buf) {
+  int i, *p;
+  for (i = 0, p = buf; i < 10; i++, p++) {
+    *p = 1;
+  }
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:17: warning: pointer parameter 'p' can be
+void init1(int *p) {
+  // CHECK-FIXES: {{^}}void init1(const int *p) {{{$}}
+  const int *q = p;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:17: warning: pointer parameter 'p' can be
+void init2(int *p) {
+  // CHECK-FIXES: {{^}}void init2(const int *p) {{{$}}
+  const int *q = p + 1;
+}
+
+void init3(int *p) {
+  int *q = p;
+}
+
+void init4(float *p) {
+  int *q = (int *)p;
+}
+
+void init5(int *p) {
+  int *i = p ? p : 0;
+}
+
+void init6(int *p) {
+  int *a[] = {p, p, 0};
+}
+
+void init7(int *p, int x) {
+  for (int *q = p + x - 1; 0; q++)
+    ;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:18: warning: pointer parameter 'p' can be
+int return1(int *p) {
+  // CHECK-FIXES: {{^}}int return1(const int *p) {{{$}}
+  return *p;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:25: warning: pointer parameter 'p' can be
+const int *return2(int *p) {
+  // CHECK-FIXES: {{^}}const int *return2(const int *p) {{{$}}
+  return p;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:25: warning: pointer parameter 'p' can be
+const int *return3(int *p) {
+  // CHECK-FIXES: {{^}}const int *return3(const int *p) {{{$}}
+  return p + 1;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:27: warning: pointer parameter 'p' can be
+const char *return4(char *p) {
+  // CHECK-FIXES: {{^}}const char *return4(const char *p) {{{$}}
+  return p ? p : "";
+}
+
+char *return5(char *s) {
+  return s;
+}
+
+char *return6(char *s) {
+  return s + 1;
+}
+
+char *return7(char *a, char *b) {
+  return a ? a : b;
+}
+
+char return8(int *p) {
+  return ++(*p);
+}
+
+void dontwarn1(int *p) {
+  ++(*p);
+}
+
+void dontwarn2(int *p) {
+  (*p)++;
+}
+
+int dontwarn3(_Atomic(int) * p) {
+  return *p;
+}
+
+void callFunction1(char *p) {
+  strcpy1(p, "abc");
+}
+
+void callFunction2(char *p) {
+  strcpy1(&p[0], "abc");
+}
+
+void callFunction3(char *p) {
+  strcpy1(p + 2, "abc");
+}
+
+char *callFunction4(char *p) {
+  return strcpy1(p, "abc");
+}
+
+unsigned callFunction5(char *buf) {
+  unsigned len = my_strlen(buf);
+  return len + my_strcpy(buf, "abc");
+}
+
+void f6(int **p);
+void callFunction6(int *p) { f6(&p); }
+
+typedef union { void *v; } t;
+void f7(t obj);
+void callFunction7(int *p) {
+  f7((t){p});
+}
+
+void f8(int &x);
+void callFunction8(int *p) {
+  f8(*p);
+}
+
+// Don't warn about nonconst function pointers that can be const.
+void functionpointer(double f(double), int x) {
+  f(x);
+}
+
+// TODO: This is a false positive.
+// CHECK-MESSAGES: :[[@LINE+1]]:27: warning: pointer parameter 'p' can be
+int functionpointer2(int *p) {
+  return *p;
+}
+void use_functionpointer2() {
+  int (*fp)(int *) = functionpointer2; // <- the parameter 'p' can't be const
+}
+
+// Don't warn about nonconst record pointers that can be const.
+struct XY {
+  int *x;
+  int *y;
+};
+void recordpointer(struct XY *xy) {
+  *(xy->x) = 0;
+}
+
+class C {
+public:
+  C(int *p) : p(p) {}
+
+private:
+  int *p;
+};
+
+class C2 {
+public:
+  // CHECK-MESSAGES: :[[@LINE+1]]:11: warning: pointer parameter 'p' can be
+  C2(int *p) : p(p) {}
+  // CHECK-FIXES: {{^}}  C2(const int *p) : p(p) {}{{$}}
+
+private:
+  const int *p;
+};
+
+void tempObject(int *p) {
+  C c(p);
+}
+
+// avoid fp for const pointer array
+void constPointerArray(const char *remapped[][2]) {
+  const char *name = remapped[0][0];
+}
+
+class Warn {
+public:
+  // CHECK-MESSAGES: :[[@LINE+1]]:21: warning: pointer parameter 'p' can be
+  void doStuff(int *p) {
+    // CHECK-FIXES: {{^}}  void doStuff(const int *p) {{{$}}
+    x = *p;
+  }
+
+private:
+  int x;
+};
+
+class Base {
+public:
+  // Ensure there is no false positive for this method. It is virtual.
+  virtual void doStuff(int *p) {
+    int x = *p;
+  }
+};
+
+class Derived : public Base {
+public:
+  // Ensure there is no false positive for this method. It overrides a method.
+  void doStuff(int *p) override {
+    int x = *p;
+  }
+};
+
+extern char foo(char *s); // 1
+// CHECK-FIXES: {{^}}extern char foo(const char *s); // 1{{$}}
+// CHECK-MESSAGES: :[[@LINE+1]]:16: warning: pointer parameter 's' can be
+char foo(char *s) {
+  // CHECK-FIXES: {{^}}char foo(const char *s) {{{$}}
+  return *s;
+}
+char foo(char *s); // 2
+// CHECK-FIXES: {{^}}char foo(const char *s); // 2{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-control-flow.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-control-flow.cpp
new file mode 100644
index 0000000..0352e3a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-control-flow.cpp
@@ -0,0 +1,224 @@
+// RUN: %check_clang_tidy %s readability-redundant-control-flow %t
+
+void g(int i);
+void j();
+
+void f() {
+  return;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement at the end of a function with a void return type [readability-redundant-control-flow]
+// CHECK-FIXES: {{^}}void f() {{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void g() {
+  f();
+  return;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement
+// CHECK-FIXES: {{^  }}f();{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void g(int i) {
+  if (i < 0) {
+    return;
+  }
+  if (i < 10) {
+    f();
+  }
+}
+
+int h() {
+  return 1;
+}
+
+void j() {
+}
+
+void k() {
+  for (int i = 0; i < 10; ++i) {
+    continue;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement at the end of loop statement
+// CHECK-FIXES: {{^}}  for (int i = 0; i < 10; ++i) {{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void k2() {
+  int v[10] = { 0 };
+  for (auto i : v) {
+    continue;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: {{^}}  for (auto i : v) {{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void m() {
+  int i = 0;
+  do {
+    ++i;
+    continue;
+  } while (i < 10);
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: {{^  do {$}}
+// CHECK-FIXES-NEXT: {{^}}    ++i;{{$}}
+// CHECK-FIXES-NEXT: {{^ *}}} while (i < 10);{{$}}
+
+void p() {
+  int i = 0;
+  while (i < 10) {
+    ++i;
+    continue;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: {{^}}  while (i < 10) {{{$}}
+// CHECK-FIXES-NEXT: {{^}}    ++i;{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void im_not_dead(int i) {
+  if (i > 0) {
+    return;
+  }
+  g();
+}
+
+void im_still_not_dead(int i) {
+  for (int j = 0; j < 10; ++j) {
+    if (i < 10) {
+      continue;
+    }
+    g();
+  }
+}
+
+void im_dead(int i) {
+  if (i > 0) {
+    return;
+    g();
+  }
+  g();
+}
+
+void im_still_dead(int i) {
+  for (int j = 0; j < 10; ++j) {
+    if (i < 10) {
+      continue;
+      g();
+    }
+    g();
+  }
+}
+
+void void_return() {
+  return g();
+}
+
+void nested_return_unmolested() {
+  g();
+  {
+    g();
+    return;
+  }
+}
+
+void nested_continue_unmolested() {
+  for (int i = 0; i < 10; ++i) {
+    if (i < 5) {
+      continue;
+    }
+  }
+}
+
+#define MACRO_RETURN_UNMOLESTED(fn_)  \
+  (fn_)();                            \
+  return
+
+#define MACRO_CONTINUE_UNMOLESTED(x_) \
+  do {                                \
+    for (int i = 0; i < (x_); ++i) {  \
+      continue;                       \
+    }                                 \
+  } while (false)
+
+void macro_return() {
+  MACRO_RETURN_UNMOLESTED(g);
+}
+
+void macro_continue() {
+  MACRO_CONTINUE_UNMOLESTED(10);
+}
+
+#define MACRO_RETURN_ARG(stmt_) \
+  stmt_
+
+#define MACRO_CONTINUE_ARG(stmt_)   \
+  do {                              \
+    for (int i = 0; i < 10; ++i) {  \
+      stmt_;                        \
+    }                               \
+  } while (false)
+
+void macro_arg_return() {
+  MACRO_RETURN_ARG(return);
+}
+
+void macro_arg_continue() {
+  MACRO_CONTINUE_ARG(continue);
+}
+
+template <typename T>
+void template_return(T check) {
+  if (check < T(0)) {
+    return;
+  }
+  return;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement
+// CHECK-FIXES: {{^}}  if (check < T(0)) {{{$}}
+// CHECK-FIXES-NEXT: {{^    return;$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+template <>
+void template_return(int check) {
+  if (check < 0) {
+    return;
+  }
+  return;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement
+// CHECK-FIXES: {{^}}  if (check < 0) {{{$}}
+// CHECK-FIXES-NEXT: {{^    return;$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+template <typename T>
+void template_loop(T end) {
+  for (T i = 0; i < end; ++i) {
+    continue;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: {{^}}  for (T i = 0; i < end; ++i) {{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+template <>
+void template_loop(int end) {
+  for (int i = 0; i < end; ++i) {
+    continue;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: {{^}}  for (int i = 0; i < end; ++i) {{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void call_templates() {
+  template_return(10);
+  template_return(10.0f);
+  template_return(10.0);
+  template_loop(10);
+  template_loop(10L);
+  template_loop(10U);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-declaration-ignore-macros.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-declaration-ignore-macros.cpp
new file mode 100644
index 0000000..2dc8618
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-declaration-ignore-macros.cpp
@@ -0,0 +1,22 @@
+// RUN: %check_clang_tidy %s readability-redundant-declaration %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:             [{key: readability-redundant-declaration.IgnoreMacros, \
+// RUN:               value: 1}]}" \
+// RUN:   -- -std=c++11
+
+extern int Xyz;
+extern int Xyz; // Xyz
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'Xyz' declaration [readability-redundant-declaration]
+// CHECK-FIXES: {{^}}// Xyz{{$}}
+
+namespace macros {
+#define DECLARE(x) extern int x
+#define DEFINE(x) extern int x; int x = 42
+DECLARE(test);
+DEFINE(test);
+// CHECK-FIXES: {{^}}#define DECLARE(x) extern int x{{$}}
+// CHECK-FIXES: {{^}}#define DEFINE(x) extern int x; int x = 42{{$}}
+// CHECK-FIXES: {{^}}DECLARE(test);{{$}}
+// CHECK-FIXES: {{^}}DEFINE(test);{{$}}
+
+} // namespace macros
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-declaration.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-declaration.cpp
new file mode 100644
index 0000000..83d1b5b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-declaration.cpp
@@ -0,0 +1,70 @@
+// RUN: %check_clang_tidy %s readability-redundant-declaration %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:             [{key: readability-redundant-declaration.IgnoreMacros, \
+// RUN:               value: 0}]}" \
+// RUN:   -- -std=c++11
+
+extern int Xyz;
+extern int Xyz; // Xyz
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'Xyz' declaration [readability-redundant-declaration]
+// CHECK-FIXES: {{^}}// Xyz{{$}}
+int Xyz = 123;
+
+extern int A;
+extern int A, B;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'A' declaration
+// CHECK-FIXES: {{^}}extern int A, B;{{$}}
+
+extern int Buf[10];
+extern int Buf[10]; // Buf[10]
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'Buf' declaration
+// CHECK-FIXES: {{^}}// Buf[10]{{$}}
+
+static int f();
+static int f(); // f
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'f' declaration
+// CHECK-FIXES: {{^}}// f{{$}}
+static int f() {}
+
+// Original check crashed for the code below.
+namespace std {
+typedef decltype(sizeof(0)) size_t;
+}
+void *operator new(std::size_t) __attribute__((__externally_visible__));
+void *operator new[](std::size_t) __attribute__((__externally_visible__));
+
+// Don't warn about static member definition.
+struct C {
+  static int I;
+};
+int C::I;
+
+template <class T>
+struct C2 {
+  C2();
+};
+
+template <class T>
+C2<T>::C2() = default;
+
+void best_friend();
+
+struct Friendly {
+  friend void best_friend();
+  friend void enemy();
+};
+
+void enemy();
+
+namespace macros {
+#define DECLARE(x) extern int x
+#define DEFINE(x) extern int x; int x = 42
+DECLARE(test);
+DEFINE(test);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant 'test' declaration
+// CHECK-FIXES: {{^}}#define DECLARE(x) extern int x{{$}}
+// CHECK-FIXES: {{^}}#define DEFINE(x) extern int x; int x = 42{{$}}
+// CHECK-FIXES: {{^}}DECLARE(test);{{$}}
+// CHECK-FIXES: {{^}}DEFINE(test);{{$}}
+
+} // namespace macros
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-function-ptr-dereference.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-function-ptr-dereference.cpp
new file mode 100644
index 0000000..2b34ce1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-function-ptr-dereference.cpp
@@ -0,0 +1,45 @@
+// RUN: %check_clang_tidy %s readability-redundant-function-ptr-dereference %t
+
+void f(int i);
+
+void positive() {
+  void (*p)(int) = f;
+
+  (**p)(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: redundant repeated dereference of function pointer [readability-redundant-function-ptr-dereference]
+  // CHECK-FIXES: (*p)(1);
+  (*****p)(2);
+  // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: redundant repeated
+  // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: redundant repeated
+  // CHECK-MESSAGES: :[[@LINE-3]]:6: warning: redundant repeated
+  // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: redundant repeated
+  // CHECK-FIXES: (*p)(2);
+}
+
+template<typename T>
+void invoke(const T& fn) {
+  fn(0); // 1
+  (*fn)(0); // 2
+  // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: redundant repeated
+  // CHECK-FIXES: fn(0); // 1
+  // CHECK-FIXES: (fn)(0); // 2
+  // FIXME: Remove unnecessary parentheses.
+}
+
+void f1(int);
+void f2(double);
+void f3(char);
+
+void instantiate() {
+  invoke(f1);
+  invoke(f2);
+  invoke(f3);
+  invoke([](unsigned) {});
+}
+
+void negative() {
+  void (*q)(int) = &f;
+
+  q(1);
+  (*q)(2);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-member-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-member-init.cpp
new file mode 100644
index 0000000..90b52fd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-member-init.cpp
@@ -0,0 +1,219 @@
+// RUN: %check_clang_tidy %s readability-redundant-member-init %t
+
+struct S {
+  S() = default;
+  S(int i) : i(i) {}
+  int i = 1;
+};
+
+struct T {
+  T(int i = 1) : i(i) {}
+  int i;
+};
+
+struct U {
+  int i;
+};
+
+union V {
+  int i;
+  double f;
+};
+
+// Initializer calls default constructor
+struct F1 {
+  F1() : f() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 'f' is redundant
+  // CHECK-FIXES: F1()  {}
+  S f;
+};
+
+// Initializer calls default constructor with default argument
+struct F2 {
+  F2() : f() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 'f' is redundant
+  // CHECK-FIXES: F2()  {}
+  T f;
+};
+
+// Multiple redundant initializers for same constructor
+struct F3 {
+  F3() : f(), g(1), h() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 'f' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: initializer for member 'h' is redundant
+  // CHECK-FIXES: F3() :  g(1) {}
+  S f, g, h;
+};
+
+// Templated class independent type
+template <class V>
+struct F4 {
+  F4() : f() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 'f' is redundant
+  // CHECK-FIXES: F4()  {}
+  S f;
+};
+F4<int> f4i;
+F4<S> f4s;
+
+// Base class
+struct F5 : S {
+  F5() : S() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for base class 'S' is redundant
+  // CHECK-FIXES: F5()  {}
+};
+
+// Constructor call requires cleanup
+struct Cleanup {
+  ~Cleanup() {}
+};
+
+struct UsesCleanup {
+  UsesCleanup(const Cleanup &c = Cleanup()) {}
+};
+
+struct F6 {
+  F6() : uc() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 'uc' is redundant
+  // CHECK-FIXES: F6()  {}
+  UsesCleanup uc;
+};
+
+// Multiple inheritance
+struct F7 : S, T {
+  F7() : S(), T() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for base class 'S' is redundant
+  // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: initializer for base class 'T' is redundant
+  // CHECK-FIXES: F7()  {}
+};
+
+namespace Foo {
+inline namespace Bar {
+template <int N>
+struct Template {
+  Template() = default;
+  int i = N;
+};
+}
+}
+
+enum { N_THINGS = 5 };
+
+struct F8 : Foo::Template<N_THINGS> {
+  F8() : Template() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for base class 'Foo::Template<N_THINGS>' is redundant
+  // CHECK-FIXES: F8()  {}
+};
+
+// Anonymous struct
+struct F9 {
+  F9() : s1() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 's1' is redundant
+  // CHECK-FIXES: F9()  {}
+  struct {
+    S s1;
+    S s2;
+  };
+};
+
+// Initializer not written
+struct NF1 {
+  NF1() {}
+  S f;
+};
+
+// Initializer doesn't call default constructor
+struct NF2 {
+  NF2() : f(1) {}
+  S f;
+};
+
+// Initializer calls default constructor without using default argument
+struct NF3 {
+  NF3() : f(1) {}
+  T f;
+};
+
+// Initializer calls default constructor without using default argument
+struct NF4 {
+  NF4() : f(2) {}
+  T f;
+};
+
+// Initializer is zero-initialization
+struct NF5 {
+  NF5() : i() {}
+  int i;
+};
+
+// Initializer is direct-initialization
+struct NF6 {
+  NF6() : i(1) {}
+  int i;
+};
+
+// Initializer is aggregate initialization of struct
+struct NF7 {
+  NF7() : f{} {}
+  U f;
+};
+
+// Initializer is zero-initialization of struct
+struct NF7b {
+  NF7b() : f() {}
+  U f;
+};
+
+// Initializer is aggregate initialization of array
+struct NF8 {
+  NF8() : f{} {}
+  int f[2];
+};
+
+struct NF9 {
+  NF9() : f{} {}
+  S f[2];
+};
+
+// Initializing member of union
+union NF10 {
+  NF10() : s() {}
+  int i;
+  S s;
+};
+
+// Templated class dependent type
+template <class V>
+struct NF11 {
+  NF11() : f() {}
+  V f;
+};
+NF11<int> nf11i;
+NF11<S> nf11s;
+
+// Delegating constructor
+class NF12 {
+  NF12() = default;
+  NF12(int) : NF12() {}
+};
+
+// Const member
+struct NF13 {
+  NF13() : f() {}
+  const S f;
+};
+
+// Union member
+struct NF14 {
+  NF14() : f() {}
+  V f;
+};
+
+// Anonymous union member
+struct NF15 {
+  NF15() : s1() {}
+  union {
+    S s1;
+    S s2;
+  };
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-smartptr-get.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-smartptr-get.cpp
new file mode 100644
index 0000000..685a57c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-smartptr-get.cpp
@@ -0,0 +1,196 @@
+// RUN: %check_clang_tidy %s readability-redundant-smartptr-get %t
+
+#define NULL __null
+
+namespace std {
+
+template <typename T>
+struct unique_ptr {
+  T& operator*() const;
+  T* operator->() const;
+  T* get() const;
+  explicit operator bool() const noexcept;
+};
+
+template <typename T>
+struct shared_ptr {
+  T& operator*() const;
+  T* operator->() const;
+  T* get() const;
+  explicit operator bool() const noexcept;
+};
+
+}  // namespace std
+
+struct Bar {
+  void Do();
+  void ConstDo() const;
+};
+struct BarPtr {
+  Bar* operator->();
+  Bar& operator*();
+  Bar* get();
+  explicit operator bool() const;
+};
+struct int_ptr {
+  int* get();
+  int* operator->();
+  int& operator*();
+};
+
+struct Fail1 {
+  Bar* get();
+};
+struct Fail2 {
+  Bar* get();
+  int* operator->();
+  int& operator*();
+};
+
+struct PointerWithOverloadedGet {
+  int* get();
+  template <typename T>
+  T* get();
+  int* operator->();
+  int& operator*();
+};
+
+void Positive() {
+  BarPtr u;
+  // CHECK-FIXES: BarPtr u;
+  BarPtr().get()->Do();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant get() call on smart pointer [readability-redundant-smartptr-get]
+  // CHECK-MESSAGES: BarPtr().get()->Do();
+  // CHECK-FIXES: BarPtr()->Do();
+
+  u.get()->ConstDo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant get() call
+  // CHECK-MESSAGES: u.get()->ConstDo();
+  // CHECK-FIXES: u->ConstDo();
+
+  Bar& b = *BarPtr().get();
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant get() call
+  // CHECK-MESSAGES: Bar& b = *BarPtr().get();
+  // CHECK-FIXES: Bar& b = *BarPtr();
+
+  Bar& b2 = *std::unique_ptr<Bar>().get();
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant get() call
+  // CHECK-MESSAGES: Bar& b2 = *std::unique_ptr<Bar>().get();
+  // CHECK-FIXES: Bar& b2 = *std::unique_ptr<Bar>();
+
+  (*BarPtr().get()).ConstDo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call
+  // CHECK-MESSAGES: (*BarPtr().get()).ConstDo();
+  // CHECK-FIXES: (*BarPtr()).ConstDo();
+
+  (*std::unique_ptr<Bar>().get()).ConstDo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call
+  // CHECK-MESSAGES: (*std::unique_ptr<Bar>().get()).ConstDo();
+  // CHECK-FIXES: (*std::unique_ptr<Bar>()).ConstDo();
+
+  std::unique_ptr<Bar>* up;
+  (*up->get()).Do();
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call
+  // CHECK-MESSAGES: (*up->get()).Do();
+  // CHECK-FIXES: (**up).Do();
+
+  int_ptr ip;
+  int i = *ip.get();
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant get() call
+  // CHECK-MESSAGES: int i = *ip.get();
+  // CHECK-FIXES: int i = *ip;
+
+  auto ip2 = ip;
+  i = *ip2.get();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+  // CHECK-MESSAGES: i = *ip2.get();
+  // CHECK-FIXES: i = *ip2;
+
+  std::unique_ptr<int> uu;
+  std::shared_ptr<double> *ss;
+  bool bb = uu.get() == nullptr;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant get() call
+  // CHECK-MESSAGES: uu.get() == nullptr;
+  // CHECK-FIXES: bool bb = uu == nullptr;
+
+  if (up->get());
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call
+  // CHECK-MESSAGES: if (up->get());
+  // CHECK-FIXES: if (*up);
+  if ((uu.get()));
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+  // CHECK-MESSAGES: if ((uu.get()));
+  // CHECK-FIXES: if ((uu));
+  bb = !ss->get();
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant get() call
+  // CHECK-MESSAGES: bb = !ss->get();
+  // CHECK-FIXES: bb = !*ss;
+  bb = u.get() ? true : false;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+  // CHECK-MESSAGES: bb = u.get() ? true : false;
+  // CHECK-FIXES: bb = u ? true : false;
+
+  bb = nullptr != ss->get();
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: redundant get() call
+  // CHECK-MESSAGES: nullptr != ss->get();
+  // CHECK-FIXES: bb = nullptr != *ss;
+
+  i = *PointerWithOverloadedGet().get();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+  // CHECK-MESSAGES: i = *PointerWithOverloadedGet().get();
+  // CHECK-FIXES: i = *PointerWithOverloadedGet();
+
+  bb = std::unique_ptr<int>().get() == NULL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+  // CHECK-MESSAGES: bb = std::unique_ptr<int>().get() == NULL;
+  // CHECK-FIXES: bb = std::unique_ptr<int>() == NULL;
+  bb = ss->get() == NULL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+  // CHECK-MESSAGES: bb = ss->get() == NULL;
+  // CHECK-FIXES: bb = *ss == NULL;
+
+  std::unique_ptr<int> x, y;
+  if (x.get() == nullptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call
+  // CHECK-MESSAGES: if (x.get() == nullptr);
+  // CHECK-FIXES: if (x == nullptr);
+  if (nullptr == y.get());
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: redundant get() call
+  // CHECK-MESSAGES: if (nullptr == y.get());
+  // CHECK-FIXES: if (nullptr == y);
+  if (x.get() == NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call
+  // CHECK-MESSAGES: if (x.get() == NULL);
+  // CHECK-FIXES: if (x == NULL);
+  if (NULL == x.get());
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: redundant get() call
+  // CHECK-MESSAGES: if (NULL == x.get());
+  // CHECK-FIXES: if (NULL == x);
+}
+
+void Negative() {
+  struct NegPtr {
+    int* get();
+    int* operator->() {
+      return &*this->get();
+    }
+    int& operator*() {
+      return *get();
+    }
+  };
+
+  long l = *PointerWithOverloadedGet().get<long>();
+
+  std::unique_ptr<Bar>* u;
+  u->get()->Do();
+
+  Fail1().get()->Do();
+  Fail2().get()->Do();
+  const Bar& b = *Fail1().get();
+  (*Fail2().get()).Do();
+
+  int_ptr ip;
+  bool bb = ip.get() == nullptr;
+  bb = !ip.get();
+  bb = ip.get() ? true : false;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-cstr-msvc.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-cstr-msvc.cpp
new file mode 100644
index 0000000..a6b6b20
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-cstr-msvc.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s readability-redundant-string-cstr %t
+
+namespace std {
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T, typename A>
+struct basic_string {
+  basic_string();
+  // MSVC headers define two constructors instead of using optional arguments.
+  basic_string(const C *p);
+  basic_string(const C *p, const A &a);
+  const C *c_str() const;
+  const C *data() const;
+};
+typedef basic_string<char, std::char_traits<char>, std::allocator<char>> string;
+}
+namespace llvm {
+struct StringRef {
+  StringRef(const char *p);
+  StringRef(const std::string &);
+};
+}
+
+void f1(const std::string &s) {
+  f1(s.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}f1(s);{{$}}
+  f1(s.data());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'data' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}f1(s);{{$}}
+}
+void f2(const llvm::StringRef r) {
+  std::string s;
+  f2(s.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}std::string s;{{$}}
+  // CHECK-FIXES-NEXT: {{^  }}f2(s);{{$}}
+}
+void f3(const llvm::StringRef &r) {
+  std::string s;
+  f3(s.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}std::string s;{{$}}
+  // CHECK-FIXES-NEXT: {{^  }}f3(s);{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-cstr.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-cstr.cpp
new file mode 100644
index 0000000..976a54f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-cstr.cpp
@@ -0,0 +1,207 @@
+// RUN: %check_clang_tidy %s readability-redundant-string-cstr %t -- -- -std=c++11
+
+typedef unsigned __INT16_TYPE__ char16;
+typedef unsigned __INT32_TYPE__ char32;
+typedef __SIZE_TYPE__ size;
+
+namespace std {
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T, typename A>
+struct basic_string {
+  typedef basic_string<C, T, A> _Type;
+  basic_string();
+  basic_string(const C *p, const A &a = A());
+
+  const C *c_str() const;
+  const C *data() const;
+
+  _Type& append(const C *s);
+  _Type& append(const C *s, size n);
+  _Type& assign(const C *s);
+  _Type& assign(const C *s, size n);
+
+  int compare(const _Type&) const;
+  int compare(const C* s) const;
+  int compare(size pos, size len, const _Type&) const;
+  int compare(size pos, size len, const C* s) const;
+
+  size find(const _Type& str, size pos = 0) const;
+  size find(const C* s, size pos = 0) const;
+  size find(const C* s, size pos, size n) const;
+
+  _Type& insert(size pos, const _Type& str);
+  _Type& insert(size pos, const C* s);
+  _Type& insert(size pos, const C* s, size n);
+
+  _Type& operator+=(const _Type& str);
+  _Type& operator+=(const C* s);
+  _Type& operator=(const _Type& str);
+  _Type& operator=(const C* s);
+};
+
+typedef basic_string<char, std::char_traits<char>, std::allocator<char>> string;
+typedef basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>> wstring;
+typedef basic_string<char16, std::char_traits<char16>, std::allocator<char16>> u16string;
+typedef basic_string<char32, std::char_traits<char32>, std::allocator<char32>> u32string;
+}
+
+std::string operator+(const std::string&, const std::string&);
+std::string operator+(const std::string&, const char*);
+std::string operator+(const char*, const std::string&);
+
+bool operator==(const std::string&, const std::string&);
+bool operator==(const std::string&, const char*);
+bool operator==(const char*, const std::string&);
+
+namespace llvm {
+struct StringRef {
+  StringRef(const char *p);
+  StringRef(const std::string &);
+};
+}
+
+// Tests for std::string.
+
+void f1(const std::string &s) {
+  f1(s.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}f1(s);{{$}}
+  f1(s.data());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'data' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}f1(s);{{$}}
+}
+void f2(const llvm::StringRef r) {
+  std::string s;
+  f2(s.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}std::string s;{{$}}
+  // CHECK-FIXES-NEXT: {{^  }}f2(s);{{$}}
+}
+void f3(const llvm::StringRef &r) {
+  std::string s;
+  f3(s.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}std::string s;{{$}}
+  // CHECK-FIXES-NEXT: {{^  }}f3(s);{{$}}
+}
+void f4(const std::string &s) {
+  const std::string* ptr = &s;
+  f1(ptr->c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}f1(*ptr);{{$}}
+}
+void f5(const std::string &s) {
+  std::string tmp;
+  tmp.append(s.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}tmp.append(s);{{$}}
+  tmp.assign(s.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}tmp.assign(s);{{$}}
+
+  if (tmp.compare(s.c_str()) == 0) return;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}if (tmp.compare(s) == 0) return;{{$}}
+
+  if (tmp.compare(1, 2, s.c_str()) == 0) return;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}if (tmp.compare(1, 2, s) == 0) return;{{$}}
+
+  if (tmp.find(s.c_str()) == 0) return;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}if (tmp.find(s) == 0) return;{{$}}
+
+  if (tmp.find(s.c_str(), 2) == 0) return;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}if (tmp.find(s, 2) == 0) return;{{$}}
+
+  if (tmp.find(s.c_str(), 2) == 0) return;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}if (tmp.find(s, 2) == 0) return;{{$}}
+
+  tmp.insert(1, s.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}tmp.insert(1, s);{{$}}
+
+  tmp = s.c_str();
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}tmp = s;{{$}}
+
+  tmp += s.c_str();
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}tmp += s;{{$}}
+
+  if (tmp == s.c_str()) return;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}if (tmp == s) return;{{$}}
+
+  tmp = s + s.c_str();
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}tmp = s + s;{{$}}
+
+  tmp = s.c_str() + s;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant call {{.*}}
+  // CHECK-FIXES: {{^  }}tmp = s + s;{{$}}
+}
+void f6(const std::string &s) {
+  std::string tmp;
+  tmp.append(s.c_str(), 2);
+  tmp.assign(s.c_str(), 2);
+
+  if (tmp.compare(s) == 0) return;
+  if (tmp.compare(1, 2, s) == 0) return;
+
+  tmp = s;
+  tmp += s;
+
+  if (tmp == s)
+    return;
+
+  tmp = s + s;
+
+  if (tmp.find(s.c_str(), 2, 4) == 0) return;
+
+  tmp.insert(1, s);
+  tmp.insert(1, s.c_str(), 2);
+}
+
+// Tests for std::wstring.
+
+void g1(const std::wstring &s) {
+  g1(s.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}g1(s);{{$}}
+}
+
+// Tests for std::u16string.
+
+void h1(const std::u16string &s) {
+  h1(s.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}h1(s);{{$}}
+}
+
+// Tests for std::u32string.
+
+void k1(const std::u32string &s) {
+  k1(s.c_str());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant call to 'c_str' [readability-redundant-string-cstr]
+  // CHECK-FIXES: {{^  }}k1(s);{{$}}
+}
+
+// Tests on similar classes that aren't good candidates for this checker.
+
+struct NotAString {
+  NotAString();
+  NotAString(const NotAString&);
+  const char *c_str() const;
+};
+
+void dummy(const char*) {}
+
+void invalid(const NotAString &s) {
+  dummy(s.c_str());
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-init-msvc.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-init-msvc.cpp
new file mode 100644
index 0000000..0299519
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-init-msvc.cpp
@@ -0,0 +1,61 @@
+// RUN: %check_clang_tidy %s readability-redundant-string-init %t
+
+namespace std {
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C>>
+struct basic_string {
+  basic_string();
+  basic_string(const basic_string&);
+  // MSVC headers define two constructors instead of using optional arguments.
+  basic_string(const C *);
+  basic_string(const C *, const A &);
+  ~basic_string();
+};
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+}
+
+void f() {
+  std::string a = "";
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization [readability-redundant-string-init]
+  // CHECK-FIXES: std::string a;
+  std::string b("");
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+  // CHECK-FIXES: std::string b;
+  std::string c = R"()";
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+  // CHECK-FIXES: std::string c;
+  std::string d(R"()");
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+  // CHECK-FIXES: std::string d;
+
+  std::string u = "u";
+  std::string w("w");
+  std::string x = R"(x)";
+  std::string y(R"(y)");
+  std::string z;
+}
+
+void g() {
+  std::wstring a = L"";
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+  // CHECK-FIXES: std::wstring a;
+  std::wstring b(L"");
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+  // CHECK-FIXES: std::wstring b;
+  std::wstring c = LR"()";
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+  // CHECK-FIXES: std::wstring c;
+  std::wstring d(LR"()");
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+  // CHECK-FIXES: std::wstring d;
+
+  std::wstring u = L"u";
+  std::wstring w(L"w");
+  std::wstring x = LR"(x)";
+  std::wstring y(LR"(y)");
+  std::wstring z;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-init.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-init.cpp
new file mode 100644
index 0000000..4455ad4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-redundant-string-init.cpp
@@ -0,0 +1,140 @@
+// RUN: %check_clang_tidy %s readability-redundant-string-init %t
+
+namespace std {
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C>>
+struct basic_string {
+  basic_string();
+  basic_string(const basic_string&);
+  basic_string(const C *, const A &a = A());
+  ~basic_string();
+};
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+}
+
+void f() {
+  std::string a = "";
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization [readability-redundant-string-init]
+  // CHECK-FIXES: std::string a;
+  std::string b("");
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+  // CHECK-FIXES: std::string b;
+  std::string c = R"()";
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+  // CHECK-FIXES: std::string c;
+  std::string d(R"()");
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+  // CHECK-FIXES: std::string d;
+
+  std::string u = "u";
+  std::string w("w");
+  std::string x = R"(x)";
+  std::string y(R"(y)");
+  std::string z;
+}
+
+void g() {
+  std::wstring a = L"";
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+  // CHECK-FIXES: std::wstring a;
+  std::wstring b(L"");
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+  // CHECK-FIXES: std::wstring b;
+  std::wstring c = LR"()";
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+  // CHECK-FIXES: std::wstring c;
+  std::wstring d(LR"()");
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant string initialization
+  // CHECK-FIXES: std::wstring d;
+
+  std::wstring u = L"u";
+  std::wstring w(L"w");
+  std::wstring x = LR"(x)";
+  std::wstring y(LR"(y)");
+  std::wstring z;
+}
+
+template <typename T>
+void templ() {
+  std::string s = "";
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+  // CHECK-FIXES: std::string s;
+}
+
+#define M(x) x
+#define N { std::string s = ""; }
+// CHECK-FIXES: #define N { std::string s = ""; }
+
+void h() {
+  templ<int>();
+  templ<double>();
+
+  M({ std::string s = ""; })
+  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: redundant string initialization
+  // CHECK-FIXES: M({ std::string s; })
+
+  N
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: redundant string initialization
+  // CHECK-FIXES: N
+  N
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: redundant string initialization
+  // CHECK-FIXES: N
+}
+
+typedef std::string MyString;
+#define STRING MyString
+#define DECL_STRING(name, val) STRING name = val
+
+void i() {
+  MyString a = "";
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant string initialization
+  // CHECK-FIXES: MyString a;
+  STRING b = "";
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: redundant string initialization
+  // CHECK-FIXES: STRING b;
+  MyString c = "" "" "";
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant string initialization
+  // CHECK-FIXES: MyString c;
+  STRING d = "" "" "";
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: redundant string initialization
+  // CHECK-FIXES: STRING d;
+  DECL_STRING(e, "");
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+
+  MyString f = "u";
+  STRING g = "u";
+  DECL_STRING(h, "u");
+}
+
+#define EMPTY_STR ""
+void j() {
+  std::string a(EMPTY_STR);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+  // CHECK-FIXES: std::string a;
+  std::string b = (EMPTY_STR);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+  // CHECK-FIXES: std::string b;
+
+  std::string c(EMPTY_STR "u" EMPTY_STR);
+}
+
+void k() {
+  std::string a = "", b = "", c = "";
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+  // CHECK-MESSAGES: [[@LINE-2]]:23: warning: redundant string initialization
+  // CHECK-MESSAGES: [[@LINE-3]]:31: warning: redundant string initialization
+  // CHECK-FIXES: std::string a, b, c;
+
+  std::string d = "u", e = "u", f = "u";
+}
+
+// These cases should not generate warnings.
+extern void Param1(std::string param = "");
+extern void Param2(const std::string& param = "");
+void Param3(std::string param = "") {}
+void Param4(STRING param = "") {}
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr-chained-conditional-assignment.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr-chained-conditional-assignment.cpp
new file mode 100644
index 0000000..65b86c3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr-chained-conditional-assignment.cpp
@@ -0,0 +1,34 @@
+// RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t -- -config="{CheckOptions: [{key: "readability-simplify-boolean-expr.ChainedConditionalAssignment", value: 1}]}" --
+
+void chained_conditional_compound_assignment(int i) {
+  bool b;
+  if (i < 0) {
+    b = true;
+  } else if (i < 10) {
+    b = false;
+  } else if (i > 20) {
+    b = true;
+  } else {
+    b = false;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: redundant boolean literal in conditional assignment [readability-simplify-boolean-expr]
+  // CHECK-FIXES:      {{^}}  } else if (i < 10) {{{$}}
+  // CHECK-FIXES-NEXT: {{^}}    b = false;{{$}}
+  // CHECK-FIXES-NEXT: {{^}}  } else b = i > 20;{{$}}
+}
+
+void chained_conditional_assignment(int i) {
+  bool b;
+  if (i < 0)
+    b = true;
+  else if (i < 10)
+    b = false;
+  else if (i > 20)
+    b = true;
+  else
+    b = false;
+  // CHECK-MESSAGES: :[[@LINE-3]]:9: warning: {{.*}} in conditional assignment
+  // CHECK-FIXES:      {{^}}  else if (i < 10)
+  // CHECK-FIXES-NEXT: {{^}}    b = false;
+  // CHECK-FIXES-NEXT: {{^}}  else b = i > 20;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr-chained-conditional-return.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr-chained-conditional-return.cpp
new file mode 100644
index 0000000..fb8759c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr-chained-conditional-return.cpp
@@ -0,0 +1,94 @@
+// RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t -- -config="{CheckOptions: [{key: "readability-simplify-boolean-expr.ChainedConditionalReturn", value: 1}]}" --
+
+bool chained_conditional_compound_return(int i) {
+  if (i < 0) {
+    return true;
+  } else if (i < 10) {
+    return false;
+  } else if (i > 20) {
+    return true;
+  } else {
+    return false;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:12: warning: redundant boolean literal in conditional return statement [readability-simplify-boolean-expr]
+  // CHECK-FIXES:      {{^}}  } else if (i < 10) {{{$}}
+  // CHECK-FIXES-NEXT: {{^}}    return false;{{$}}
+  // CHECK-FIXES-NEXT: {{^}}  } else return i > 20;{{$}}
+}
+
+bool chained_conditional_return(int i) {
+  if (i < 0)
+    return true;
+  else if (i < 10)
+    return false;
+  else if (i > 20)
+    return true;
+  else
+    return false;
+  // CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return statement
+  // CHECK-FIXES:      {{^}}  else if (i < 10)
+  // CHECK-FIXES-NEXT: {{^}}    return false;
+  // CHECK-FIXES-NEXT: {{^}}  else return i > 20;
+}
+
+bool chained_simple_if_return(int i) {
+  if (i < 5)
+    return true;
+  if (i > 10)
+    return true;
+  return false;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool chained_simple_if_return(int i) {{{$}}
+// CHECK-FIXES: {{^}}  if (i < 5){{$}}
+// CHECK-FIXES: {{^    return true;$}}
+// CHECK-FIXES: {{^  return i > 10;$}}
+// CHECK-FIXES: {{^}$}}
+
+bool chained_simple_if_return_negated(int i) {
+  if (i < 5)
+    return false;
+  if (i > 10)
+    return false;
+  return true;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool chained_simple_if_return_negated(int i) {{{$}}
+// CHECK-FIXES: {{^}}  if (i < 5){{$}}
+// CHECK-FIXES: {{^    return false;$}}
+// CHECK-FIXES: {{^  return i <= 10;$}}
+// CHECK-FIXES: {{^}$}}
+
+bool complex_chained_if_return_return(int i) {
+  if (i < 5) {
+    return true;
+  }
+  if (i > 10) {
+    return true;
+  }
+  return false;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool complex_chained_if_return_return(int i) {{{$}}
+// CHECK-FIXES: {{^}}  if (i < 5) {{{$}}
+// CHECK-FIXES: {{^}}    return true;{{$}}
+// CHECK-FIXES: {{^}}  }{{$}}
+// CHECK-FIXES: {{^  return i > 10;$}}
+// CHECK-FIXES: {{^}$}}
+
+bool complex_chained_if_return_return_negated(int i) {
+  if (i < 5) {
+    return false;
+  }
+  if (i > 10) {
+    return false;
+  }
+  return true;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool complex_chained_if_return_return_negated(int i) {{{$}}
+// CHECK-FIXES: {{^}}  if (i < 5) {{{$}}
+// CHECK-FIXES: {{^}}    return false;{{$}}
+// CHECK-FIXES: {{^}}  }{{$}}
+// CHECK-FIXES: {{^  return i <= 10;$}}
+// CHECK-FIXES: {{^}$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr.cpp
new file mode 100644
index 0000000..cd93c5d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-bool-expr.cpp
@@ -0,0 +1,950 @@
+// RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t
+
+bool a1 = false;
+
+//=-=-=-=-=-=-= operator ==
+bool aa = false == a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant boolean literal supplied to boolean operator [readability-simplify-boolean-expr]
+// CHECK-FIXES: {{^bool aa = !a1;$}}
+bool ab = true == a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool ab = a1;$}}
+bool a2 = a1 == false;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a2 = !a1;$}}
+bool a3 = a1 == true;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a3 = a1;$}}
+
+//=-=-=-=-=-=-= operator !=
+bool n1 = a1 != false;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool n1 = a1;$}}
+bool n2 = a1 != true;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool n2 = !a1;$}}
+bool n3 = false != a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool n3 = a1;$}}
+bool n4 = true != a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool n4 = !a1;$}}
+
+//=-=-=-=-=-=-= operator ||
+bool a4 = a1 || false;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a4 = a1;$}}
+bool a5 = a1 || true;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a5 = true;$}}
+bool a6 = false || a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a6 = a1;$}}
+bool a7 = true || a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a7 = true;$}}
+
+//=-=-=-=-=-=-= operator &&
+bool a8 = a1 && false;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a8 = false;$}}
+bool a9 = a1 && true;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a9 = a1;$}}
+bool ac = false && a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool ac = false;$}}
+bool ad = true && a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool ad = a1;$}}
+
+void if_with_bool_literal_condition() {
+  int i = 0;
+  if (false) {
+    i = 1;
+  } else {
+    i = 2;
+  }
+  i = 3;
+  // CHECK-MESSAGES: :[[@LINE-6]]:7: warning: {{.*}} in if statement condition
+  // CHECK-FIXES:      {{^  int i = 0;$}}
+  // CHECK-FIXES-NEXT: {{^  {$}}
+  // CHECK-FIXES-NEXT: {{^    i = 2;$}}
+  // CHECK-FIXES-NEXT: {{^  }$}}
+  // CHECK-FIXES-NEXT: {{^  i = 3;$}}
+
+  i = 4;
+  if (true) {
+    i = 5;
+  } else {
+    i = 6;
+  }
+  i = 7;
+  // CHECK-MESSAGES: :[[@LINE-6]]:7: warning: {{.*}} in if statement condition
+  // CHECK-FIXES:      {{^  i = 4;$}}
+  // CHECK-FIXES-NEXT: {{^  {$}}
+  // CHECK-FIXES-NEXT: {{^    i = 5;$}}
+  // CHECK-FIXES-NEXT: {{^  }$}}
+  // CHECK-FIXES-NEXT: {{^  i = 7;$}}
+
+  i = 8;
+  if (false) {
+    i = 9;
+  }
+  i = 11;
+  // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: {{.*}} in if statement condition
+  // CHECK-FIXES:      {{^  i = 8;$}}
+  // CHECK-FIXES-NEXT: {{^  $}}
+  // CHECK-FIXES-NEXT: {{^  i = 11;$}}
+}
+
+void operator_equals() {
+  int i = 0;
+  bool b1 = (i > 2);
+  if (b1 == true) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(b1\) {$}}
+    i = 5;
+  } else {
+    i = 6;
+  }
+  bool b2 = (i > 4);
+  if (b2 == false) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(!b2\) {$}}
+    i = 7;
+  } else {
+    i = 9;
+  }
+  bool b3 = (i > 6);
+  if (true == b3) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(b3\) {$}}
+    i = 10;
+  } else {
+    i = 11;
+  }
+  bool b4 = (i > 8);
+  if (false == b4) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(!b4\) {$}}
+    i = 12;
+  } else {
+    i = 13;
+  }
+}
+
+void operator_or() {
+  int i = 0;
+  bool b5 = (i > 10);
+  if (b5 || false) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(b5\) {$}}
+    i = 14;
+  } else {
+    i = 15;
+  }
+  bool b6 = (i > 10);
+  if (b6 || true) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(true\) {$}}
+    i = 16;
+  } else {
+    i = 17;
+  }
+  bool b7 = (i > 10);
+  if (false || b7) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(b7\) {$}}
+    i = 18;
+  } else {
+    i = 19;
+  }
+  bool b8 = (i > 10);
+  if (true || b8) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(true\) {$}}
+    i = 20;
+  } else {
+    i = 21;
+  }
+}
+
+void operator_and() {
+  int i = 0;
+  bool b9 = (i > 20);
+  if (b9 && false) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(false\) {$}}
+    i = 22;
+  } else {
+    i = 23;
+  }
+  bool ba = (i > 20);
+  if (ba && true) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(ba\) {$}}
+    i = 24;
+  } else {
+    i = 25;
+  }
+  bool bb = (i > 20);
+  if (false && bb) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(false\) {$}}
+    i = 26;
+  } else {
+    i = 27;
+  }
+  bool bc = (i > 20);
+  if (true && bc) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(bc\) {$}}
+    i = 28;
+  } else {
+    i = 29;
+  }
+}
+
+void ternary_operator() {
+  int i = 0;
+  bool bd = (i > 20) ? true : false;
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: {{.*}} in ternary expression result
+  // CHECK-FIXES: {{^  bool bd = i > 20;$}}
+
+  bool be = (i > 20) ? false : true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: {{.*}} in ternary expression result
+  // CHECK-FIXES: {{^  bool be = i <= 20;$}}
+
+  bool bf = ((i > 20)) ? false : true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: {{.*}} in ternary expression result
+  // CHECK-FIXES: {{^  bool bf = i <= 20;$}}
+}
+
+void operator_not_equal() {
+  int i = 0;
+  bool bf = (i > 20);
+  if (false != bf) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(bf\) {$}}
+    i = 30;
+  } else {
+    i = 31;
+  }
+  bool bg = (i > 20);
+  if (true != bg) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(!bg\) {$}}
+    i = 32;
+  } else {
+    i = 33;
+  }
+  bool bh = (i > 20);
+  if (bh != false) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(bh\) {$}}
+    i = 34;
+  } else {
+    i = 35;
+  }
+  bool bi = (i > 20);
+  if (bi != true) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(!bi\) {$}}
+    i = 36;
+  } else {
+    i = 37;
+  }
+}
+
+void nested_booleans() {
+  if (false || (true || false)) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(false \|\| \(true\)\) {$}}
+  }
+  if (true && (true || false)) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(true && \(true\)\) {$}}
+  }
+  if (false || (true && false)) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(false \|\| \(false\)\) {$}}
+  }
+  if (true && (true && false)) {
+    // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: {{.*}} to boolean operator
+    // CHECK-FIXES: {{^  if \(true && \(false\)\) {$}}
+  }
+}
+
+static constexpr bool truthy() {
+  return true;
+}
+
+#define HAS_XYZ_FEATURE true
+#define M1(what) M2(true, what)
+#define M2(condition, what) if (condition) what
+
+void macros_and_constexprs(int i = 0) {
+  bool b = (i == 1);
+  if (b && truthy()) {
+    // leave this alone; if you want it simplified, then you should
+    // inline the constexpr function first.
+    i = 1;
+  }
+  i = 2;
+  if (b && HAS_XYZ_FEATURE) {
+    // leave this alone; if you want it simplified, then you should
+    // inline the macro first.
+    i = 3;
+  }
+  if (HAS_XYZ_FEATURE) {
+    i = 5;
+  }
+  i = 4;
+  M1(i = 7);
+}
+
+#undef HAS_XYZ_FEATURE
+
+bool conditional_return_statements(int i) {
+  if (i == 0) return true; else return false;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:22: warning: {{.*}} in conditional return statement
+// CHECK-FIXES:      {{^}}  return i == 0;{{$}}
+// CHECK-FIXES-NEXT: {{^}$}}
+
+bool conditional_return_statements_then_expr(int i, int j) {
+  if (i == j) return (i == 0); else return false;
+}
+
+bool conditional_return_statements_else_expr(int i, int j) {
+  if (i == j) return true; else return (i == 0);
+}
+
+bool negated_conditional_return_statements(int i) {
+  if (i == 0) return false; else return true;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:22: warning: {{.*}} in conditional return statement
+// CHECK-FIXES:      {{^}}  return i != 0;{{$}}
+// CHECK-FIXES-NEXT: {{^}$}}
+
+bool negative_condition_conditional_return_statement(int i) {
+  if (!(i == 0)) return false; else return true;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:25: warning: {{.*}} in conditional return statement
+// CHECK-FIXES:      {{^}}  return i == 0;{{$}}
+// CHECK-FIXES-NEXT: {{^}$}}
+
+bool conditional_compound_return_statements(int i) {
+  if (i == 1) {
+    return true;
+  } else {
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return statement
+// CHECK-FIXES:      {{^}}bool conditional_compound_return_statements(int i) {{{$}}
+// CHECK-FIXES-NEXT: {{^}}  return i == 1;{{$}}
+// CHECK-FIXES-NEXT: {{^}$}}
+
+bool negated_conditional_compound_return_statements(int i) {
+  if (i == 1) {
+    return false;
+  } else {
+    return true;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return statement
+// CHECK-FIXES:      {{^}}bool negated_conditional_compound_return_statements(int i) {{{$}}
+// CHECK-FIXES-NEXT: {{^}}  return i != 1;{{$}}
+// CHECK-FIXES-NEXT: {{^}$}}
+
+bool conditional_return_statements_side_effects_then(int i) {
+  if (i == 2) {
+    macros_and_constexprs();
+    return true;
+  } else
+    return false;
+}
+
+bool negated_conditional_return_statements_side_effects_then(int i) {
+  if (i == 2) {
+    macros_and_constexprs();
+    return false;
+  } else
+    return true;
+}
+
+bool conditional_return_statements_side_effects_else(int i) {
+  if (i == 2)
+    return true;
+  else {
+    macros_and_constexprs();
+    return false;
+  }
+}
+
+bool negated_conditional_return_statements_side_effects_else(int i) {
+  if (i == 2)
+    return false;
+  else {
+    macros_and_constexprs();
+    return true;
+  }
+}
+
+void lambda_conditional_return_statements() {
+  auto lambda = [](int n) -> bool { if (n > 0) return true; else return false; };
+  // CHECK-MESSAGES: :[[@LINE-1]]:55: warning: {{.*}} in conditional return statement
+  // CHECK-FIXES: {{^}}  auto lambda = [](int n) -> bool { return n > 0; };{{$}}
+
+  auto lambda2 = [](int n) -> bool {
+    if (n > 0) {
+        return true;
+    } else {
+        return false;
+    }
+  };
+  // CHECK-MESSAGES: :[[@LINE-5]]:16: warning: {{.*}} in conditional return statement
+  // CHECK-FIXES:      {{^}}  auto lambda2 = [](int n) -> bool {{{$}}
+  // CHECK-FIXES-NEXT: {{^}}    return n > 0;{{$}}
+  // CHECK-FIXES-NEXT: {{^}}  };{{$}}
+
+  auto lambda3 = [](int n) -> bool { if (n > 0) {macros_and_constexprs(); return true; } else return false; };
+
+  auto lambda4 = [](int n) -> bool {
+    if (n > 0)
+        return true;
+    else {
+        macros_and_constexprs();
+        return false;
+    }
+  };
+
+  auto lambda5 = [](int n) -> bool { if (n > 0) return false; else return true; };
+  // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: {{.*}} in conditional return statement
+  // CHECK-FIXES: {{^}}  auto lambda5 = [](int n) -> bool { return n <= 0; };{{$}}
+
+  auto lambda6 = [](int n) -> bool {
+    if (n > 0) {
+        return false;
+    } else {
+        return true;
+    }
+  };
+  // CHECK-MESSAGES: :[[@LINE-5]]:16: warning: {{.*}} in conditional return statement
+  // CHECK-FIXES:      {{^}}  auto lambda6 = [](int n) -> bool {{{$}}
+  // CHECK-FIXES-NEXT: {{^}}    return n <= 0;{{$}}
+  // CHECK-FIXES-NEXT: {{^}}  };{{$}}
+}
+
+void simple_conditional_assignment_statements(int i) {
+  bool b;
+  if (i > 10)
+    b = true;
+  else
+    b = false;
+  bool bb = false;
+  // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: {{.*}} in conditional assignment
+  // CHECK-FIXES: bool b;
+  // CHECK-FIXES: {{^  }}b = i > 10;{{$}}
+  // CHECK-FIXES: bool bb = false;
+
+  bool c;
+  if (i > 20)
+    c = false;
+  else
+    c = true;
+  bool c2 = false;
+  // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: {{.*}} in conditional assignment
+  // CHECK-FIXES: bool c;
+  // CHECK-FIXES: {{^  }}c = i <= 20;{{$}}
+  // CHECK-FIXES: bool c2 = false;
+
+  // Unchanged: different variables.
+  bool b2;
+  if (i > 12)
+    b = true;
+  else
+    b2 = false;
+
+  // Unchanged: no else statement.
+  bool b3;
+  if (i > 15)
+    b3 = true;
+
+  // Unchanged: not boolean assignment.
+  int j;
+  if (i > 17)
+    j = 10;
+  else
+    j = 20;
+
+  // Unchanged: different variables assigned.
+  int k = 0;
+  bool b4 = false;
+  if (i > 10)
+    b4 = true;
+  else
+    k = 10;
+}
+
+void complex_conditional_assignment_statements(int i) {
+  bool d;
+  if (i > 30) {
+    d = true;
+  } else {
+    d = false;
+  }
+  d = false;
+  // CHECK-MESSAGES: :[[@LINE-5]]:9: warning: {{.*}} in conditional assignment
+  // CHECK-FIXES: bool d;
+  // CHECK-FIXES: {{^  }}d = i > 30;{{$}}
+  // CHECK-FIXES: d = false;
+
+  bool e;
+  if (i > 40) {
+    e = false;
+  } else {
+    e = true;
+  }
+  e = false;
+  // CHECK-MESSAGES: :[[@LINE-5]]:9: warning: {{.*}} in conditional assignment
+  // CHECK-FIXES: bool e;
+  // CHECK-FIXES: {{^  }}e = i <= 40;{{$}}
+  // CHECK-FIXES: e = false;
+
+  // Unchanged: no else statement.
+  bool b3;
+  if (i > 15) {
+    b3 = true;
+  }
+
+  // Unchanged: not a boolean assignment.
+  int j;
+  if (i > 17) {
+    j = 10;
+  } else {
+    j = 20;
+  }
+
+  // Unchanged: multiple statements.
+  bool f;
+  if (j > 10) {
+    j = 10;
+    f = true;
+  } else {
+    j = 20;
+    f = false;
+  }
+
+  // Unchanged: multiple statements.
+  bool g;
+  if (j > 10)
+    f = true;
+  else {
+    j = 20;
+    f = false;
+  }
+
+  // Unchanged: multiple statements.
+  bool h;
+  if (j > 10) {
+    j = 10;
+    f = true;
+  } else
+    f = false;
+}
+
+// Unchanged: chained return statements, but ChainedConditionalReturn not set.
+bool chained_conditional_compound_return(int i) {
+  if (i < 0) {
+    return true;
+  } else if (i < 10) {
+    return false;
+  } else if (i > 20) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+// Unchanged: chained return statements, but ChainedConditionalReturn not set.
+bool chained_conditional_return(int i) {
+  if (i < 0)
+    return true;
+  else if (i < 10)
+    return false;
+  else if (i > 20)
+    return true;
+  else
+    return false;
+}
+
+// Unchanged: chained assignments, but ChainedConditionalAssignment not set.
+void chained_conditional_compound_assignment(int i) {
+  bool b;
+  if (i < 0) {
+    b = true;
+  } else if (i < 10) {
+    b = false;
+  } else if (i > 20) {
+    b = true;
+  } else {
+    b = false;
+  }
+}
+
+// Unchanged: chained return statements, but ChainedConditionalReturn not set.
+void chained_conditional_assignment(int i) {
+  bool b;
+  if (i < 0)
+    b = true;
+  else if (i < 10)
+    b = false;
+  else if (i > 20)
+    b = true;
+  else
+    b = false;
+}
+
+// Unchanged: chained return statements, but ChainedConditionalReturn not set.
+bool chained_simple_if_return_negated(int i) {
+  if (i < 5)
+    return false;
+  if (i > 10)
+    return false;
+  return true;
+}
+
+// Unchanged: chained return statements, but ChainedConditionalReturn not set.
+bool complex_chained_if_return_return(int i) {
+  if (i < 5) {
+    return true;
+  }
+  if (i > 10) {
+    return true;
+  }
+  return false;
+}
+
+// Unchanged: chained return statements, but ChainedConditionalReturn not set.
+bool complex_chained_if_return_return_negated(int i) {
+  if (i < 5) {
+    return false;
+  }
+  if (i > 10) {
+    return false;
+  }
+  return true;
+}
+
+// Unchanged: chained return statements, but ChainedConditionalReturn not set.
+bool chained_simple_if_return(int i) {
+  if (i < 5)
+    return true;
+  if (i > 10)
+    return true;
+  return false;
+}
+
+bool simple_if_return_return(int i) {
+  if (i > 10)
+    return true;
+  return false;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool simple_if_return_return(int i) {{{$}}
+// CHECK-FIXES: {{^  return i > 10;$}}
+// CHECK-FIXES: {{^}$}}
+
+bool simple_if_return_return_negated(int i) {
+  if (i > 10)
+    return false;
+  return true;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool simple_if_return_return_negated(int i) {{{$}}
+// CHECK-FIXES: {{^  return i <= 10;$}}
+// CHECK-FIXES: {{^}$}}
+
+bool complex_if_return_return(int i) {
+  if (i > 10) {
+    return true;
+  }
+  return false;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool complex_if_return_return(int i) {{{$}}
+// CHECK-FIXES: {{^  return i > 10;$}}
+// CHECK-FIXES: {{^}$}}
+
+bool complex_if_return_return_negated(int i) {
+  if (i > 10) {
+    return false;
+  }
+  return true;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool complex_if_return_return_negated(int i) {{{$}}
+// CHECK-FIXES: {{^  return i <= 10;$}}
+// CHECK-FIXES: {{^}$}}
+
+bool if_implicit_bool_expr(int i) {
+  if (i & 1) {
+    return true;
+  } else {
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}  return (i & 1) != 0;{{$}}
+
+bool negated_if_implicit_bool_expr(int i) {
+  if (i - 1) {
+    return false;
+  } else {
+    return true;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}  return (i - 1) == 0;{{$}}
+
+bool implicit_int(int i) {
+  if (i) {
+    return true;
+  } else {
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}  return i != 0;{{$}}
+
+bool explicit_bool(bool b) {
+  if (b) {
+    return true;
+  } else {
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}  return b;{{$}}
+
+class Implicit {
+public:
+  operator bool() {
+    return true;
+  }
+};
+
+bool object_bool_implicit_conversion(Implicit O) {
+  if (O) {
+    return true;
+  } else {
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}  return O;{{$}}
+
+bool negated_explicit_bool(bool b) {
+  if (!b) {
+    return true;
+  } else {
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}  return !b;{{$}}
+
+bool bitwise_complement_conversion(int i) {
+  if (~i) {
+    return true;
+  } else {
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}  return ~i != 0;{{$}}
+
+bool logical_or(bool a, bool b) {
+  if (a || b) {
+    return true;
+  } else {
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}  return a || b;{{$}}
+
+bool logical_and(bool a, bool b) {
+  if (a && b) {
+    return true;
+  } else {
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}  return a && b;{{$}}
+
+class Comparable
+{
+public:
+  bool operator==(Comparable const &rhs) { return true; }
+  bool operator!=(Comparable const &rhs) { return false; }
+};
+
+bool comparable_objects() {
+  Comparable c;
+  Comparable d;
+  if (c == d) {
+    return true;
+  } else {
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}  return c == d;{{$}}
+
+bool negated_comparable_objects() {
+  Comparable c;
+  Comparable d;
+  if (c == d) {
+    return false;
+  } else {
+    return true;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}  return c != d;{{$}}
+
+struct X {
+  explicit operator bool();
+};
+
+void explicit_conversion_assignment(X x) {
+  bool y;
+  if (x) {
+    y = true;
+  } else {
+    y = false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:9: warning: {{.*}} in conditional assignment
+// CHECK-FIXES: {{^  bool y;$}}
+// CHECK-FIXES: {{^}}  y = static_cast<bool>(x);{{$}}
+
+void ternary_integer_condition(int i) {
+  bool b = i ? true : false;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:16: warning: {{.*}} in ternary expression result
+// CHECK-FIXES: bool b = i != 0;{{$}}
+
+bool non_null_pointer_condition(int *p1) {
+  if (p1) {
+    return true;
+  } else {
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: return p1 != nullptr;{{$}}
+
+bool null_pointer_condition(int *p2) {
+  if (!p2) {
+    return true;
+  } else {
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: return p2 == nullptr;{{$}}
+
+bool negated_non_null_pointer_condition(int *p3) {
+  if (p3) {
+    return false;
+  } else {
+    return true;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: return p3 == nullptr;{{$}}
+
+bool negated_null_pointer_condition(int *p4) {
+  if (!p4) {
+    return false;
+  } else {
+    return true;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: return p4 != nullptr;{{$}}
+
+bool comments_in_the_middle(bool b) {
+  if (b) {
+    return true;
+  } else {
+    // something wicked this way comes
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-6]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}  if (b) {
+// CHECK-FIXES: // something wicked this way comes{{$}}
+
+bool preprocessor_in_the_middle(bool b) {
+  if (b) {
+    return true;
+  } else {
+#define SOMETHING_WICKED false
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-6]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}  if (b) {
+// CHECK-FIXES: {{^}}#define SOMETHING_WICKED false
+
+bool integer_not_zero(int i) {
+  if (i) {
+    return false;
+  } else {
+    return true;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}  return i == 0;{{$}}
+
+class A {
+public:
+    int m;
+};
+
+bool member_pointer_nullptr(int A::*p) {
+  if (p) {
+    return true;
+  } else {
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: return p != nullptr;{{$}}
+
+bool integer_member_implicit_cast(A *p) {
+  if (p->m) {
+    return true;
+  } else {
+    return false;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: return p->m != 0;{{$}}
+
+bool operator!=(const A&, const A&) { return false; }
+bool expr_with_cleanups(A &S) {
+  if (S != (A)S)
+    return false;
+
+  return true;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: S == (A)S;{{$}}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-subscript-expr.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-subscript-expr.cpp
new file mode 100644
index 0000000..16197dc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-simplify-subscript-expr.cpp
@@ -0,0 +1,108 @@
+// RUN: %check_clang_tidy %s readability-simplify-subscript-expr %t \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: readability-simplify-subscript-expr.Types, \
+// RUN:   value: '::std::basic_string;::std::basic_string_view;MyVector'}]}" --
+
+namespace std {
+
+template <class T>
+class basic_string {
+ public:
+   using size_type = unsigned;
+   using value_type = T;
+   using reference = value_type&;
+   using const_reference = const value_type&;
+
+   reference operator[](size_type);
+   const_reference operator[](size_type) const;
+   T* data();
+   const T* data() const;
+};
+
+using string = basic_string<char>;
+
+template <class T>
+class basic_string_view {
+ public:
+  using size_type = unsigned;
+  using const_reference = const T&;
+  using const_pointer = const T*;
+
+  constexpr const_reference operator[](size_type) const;
+  constexpr const_pointer data() const noexcept;
+};
+
+using string_view = basic_string_view<char>;
+
+}
+
+template <class T>
+class MyVector {
+ public:
+  using size_type = unsigned;
+  using const_reference = const T&;
+  using const_pointer = const T*;
+
+  const_reference operator[](size_type) const;
+  const T* data() const noexcept;
+};
+
+#define DO(x) do { x; } while (false)
+#define ACCESS(x) (x)
+#define GET(x, i) (x).data()[i]
+
+template <class T>
+class Foo {
+ public:
+  char bar(int i) {
+    return x.data()[i];
+  }
+ private:
+  T x;
+};
+
+void f(int i) {
+  MyVector<int> v;
+  int x = v.data()[i];
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: accessing an element of the container does not require a call to 'data()'; did you mean to use 'operator[]'? [readability-simplify-subscript-expr]
+  // CHECK-FIXES: int x = v[i];
+
+  std::string s;
+  char c1 = s.data()[i];
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: accessing an element
+  // CHECK-FIXES: char c1 = s[i];
+
+  std::string_view sv;
+  char c2 = sv.data()[i];
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: accessing an element
+  // CHECK-FIXES: char c2 = sv[i];
+
+  std::string* ps = &s;
+  char c3 = ps->data()[i];
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: accessing an element
+  // CHECK-FIXES: char c3 = (*ps)[i];
+
+  char c4 = (*ps).data()[i];
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: accessing an element
+  // CHECK-FIXES: char c4 = (*ps)[i];
+
+  DO(char c5 = s.data()[i]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: accessing an element
+  // CHECK-FIXES: DO(char c5 = s[i]);
+
+  char c6 = ACCESS(s).data()[i];
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: accessing an element
+  // CHECK-FIXES: char c6 = ACCESS(s)[i];
+
+  char c7 = ACCESS(s.data())[i];
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: accessing an element
+  // CHECK-FIXES: char c7 = ACCESS(s)[i];
+
+  char c8 = ACCESS(s.data()[i]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: accessing an element
+  // CHECK-FIXES: char c8 = ACCESS(s[i]);
+
+  char c9 = GET(s, i);
+
+  char c10 = Foo<std::string>{}.bar(i);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance-nesting-threshold.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance-nesting-threshold.cpp
new file mode 100644
index 0000000..0375249
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance-nesting-threshold.cpp
@@ -0,0 +1,33 @@
+// RUN: %check_clang_tidy %s readability-static-accessed-through-instance %t -- -config="{CheckOptions: [{key: readability-static-accessed-through-instance.NameSpecifierNestingThreshold, value: 4}]}" --
+
+// Nested specifiers
+namespace M {
+namespace N {
+struct V {
+  static int v;
+  struct T {
+    static int t;
+    struct U {
+      static int u;
+    };
+  };
+};
+}
+}
+
+void f(M::N::V::T::U u) {
+  M::N::V v;
+  v.v = 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  M::N::V::v = 12;{{$}}
+
+  M::N::V::T w;
+  w.t = 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  M::N::V::T::t = 12;{{$}}
+
+  // u.u is not changed, because the nesting level is over 4
+  u.u = 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  u.u = 12;{{$}}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance.cpp
new file mode 100644
index 0000000..fc42a1d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance.cpp
@@ -0,0 +1,222 @@
+// RUN: %check_clang_tidy %s readability-static-accessed-through-instance %t
+
+struct C {
+  static void foo();
+  static int x;
+  int nsx;
+  void mf() {
+    (void)&x;    // OK, x is accessed inside the struct.
+    (void)&C::x; // OK, x is accessed using a qualified-id.
+    foo();       // OK, foo() is accessed inside the struct.
+  }
+  void ns() const;
+};
+
+int C::x = 0;
+
+struct CC {
+  void foo();
+  int x;
+};
+
+template <typename T> struct CT {
+  static T foo();
+  static T x;
+  int nsx;
+  void mf() {
+    (void)&x;    // OK, x is accessed inside the struct.
+    (void)&C::x; // OK, x is accessed using a qualified-id.
+    foo();       // OK, foo() is accessed inside the struct.
+  }
+};
+
+// Expressions with side effects
+C &f(int, int, int, int);
+void g() {
+  f(1, 2, 3, 4).x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance  [readability-static-accessed-through-instance]
+  // CHECK-FIXES: {{^}}  f(1, 2, 3, 4).x;{{$}}
+}
+
+int i(int &);
+void j(int);
+C h();
+bool a();
+int k(bool);
+
+void f(C c) {
+  j(i(h().x));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: static member
+  // CHECK-FIXES: {{^}}  j(i(h().x));{{$}}
+
+  // The execution of h() depends on the return value of a().
+  j(k(a() && h().x));
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: static member
+  // CHECK-FIXES: {{^}}  j(k(a() && h().x));{{$}}
+
+  if ([c]() {
+        c.ns();
+        return c;
+      }().x == 15)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-5]]:7: warning: static member
+  // CHECK-FIXES: {{^}}  if ([c]() {{{$}}
+}
+
+// Nested specifiers
+namespace N {
+struct V {
+  static int v;
+  struct T {
+    static int t;
+    struct U {
+      static int u;
+    };
+  };
+};
+}
+
+void f(N::V::T::U u) {
+  N::V v;
+  v.v = 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  N::V::v = 12;{{$}}
+
+  N::V::T w;
+  w.t = 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  N::V::T::t = 12;{{$}}
+
+  // u.u is not changed to N::V::T::U::u; because the nesting level is over 3.
+  u.u = 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  u.u = 12;{{$}}
+
+  using B = N::V::T::U;
+  B b;
+  b.u;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  B::u;{{$}}
+}
+
+// Templates
+template <typename T> T CT<T>::x;
+
+template <typename T> struct CCT {
+  T foo();
+  T x;
+};
+
+typedef C D;
+
+using E = D;
+
+#define FOO(c) c.foo()
+#define X(c) c.x
+
+template <typename T> void f(T t, C c) {
+  t.x; // OK, t is a template parameter.
+  c.x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  C::x;{{$}}
+}
+
+template <int N> struct S { static int x; };
+
+template <> struct S<0> { int x; };
+
+template <int N> void h() {
+  S<N> sN;
+  sN.x; // OK, value of N affects whether x is static or not.
+
+  S<2> s2;
+  s2.x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  S<2>::x;{{$}}
+}
+
+void static_through_instance() {
+  C *c1 = new C();
+  c1->foo(); // 1
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  C::foo(); // 1{{$}}
+  c1->x; // 2
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  C::x; // 2{{$}}
+  c1->nsx; // OK, nsx is a non-static member.
+
+  const C *c2 = new C();
+  c2->foo(); // 2
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  C::foo(); // 2{{$}}
+
+  C::foo(); // OK, foo() is accessed using a qualified-id.
+  C::x;     // OK, x is accessed using a qualified-id.
+
+  D d;
+  d.foo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  D::foo();{{$}}
+  d.x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  D::x;{{$}}
+
+  E e;
+  e.foo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  E::foo();{{$}}
+  e.x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  E::x;{{$}}
+
+  CC *cc = new CC;
+
+  f(*c1, *c1);
+  f(*cc, *c1);
+
+  // Macros: OK, macros are not checked.
+  FOO((*c1));
+  X((*c1));
+  FOO((*cc));
+  X((*cc));
+
+  // Templates
+  CT<int> ct;
+  ct.foo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  CT<int>::foo();{{$}}
+  ct.x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  CT<int>::x;{{$}}
+  ct.nsx; // OK, nsx is a non-static member
+
+  CCT<int> cct;
+  cct.foo(); // OK, CCT has no static members.
+  cct.x;     // OK, CCT has no static members.
+
+  h<4>();
+}
+
+// Overloaded member access operator
+struct Q {
+  static int K;
+  int y = 0;
+};
+
+int Q::K = 0;
+
+struct Qptr {
+  Q *q;
+
+  explicit Qptr(Q *qq) : q(qq) {}
+
+  Q *operator->() {
+    ++q->y;
+    return q;
+  }
+};
+
+int func(Qptr qp) {
+  qp->y = 10; // OK, the overloaded operator might have side-effects.
+  qp->K = 10; //
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-definition-in-anonymous-namespace.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-definition-in-anonymous-namespace.cpp
new file mode 100644
index 0000000..5c3c8c1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-static-definition-in-anonymous-namespace.cpp
@@ -0,0 +1,49 @@
+// RUN: %check_clang_tidy %s readability-static-definition-in-anonymous-namespace %t
+
+namespace {
+
+int a = 1;
+const int b = 1;
+static int c = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: 'c' is a static definition in anonymous namespace; static is redundant here [readability-static-definition-in-anonymous-namespace]
+// CHECK-FIXES: {{^}}int c = 1;
+static const int d = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'd' is a static definition in anonymous namespace
+// CHECK-FIXES: {{^}}const int d = 1;
+const static int e = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'e' is a static definition in anonymous namespace
+// CHECK-FIXES: {{^}}const int e = 1;
+
+void f() {
+  int a = 1;
+  static int b = 1;
+}
+
+static int g() {
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: 'g' is a static definition in anonymous namespace
+// CHECK-FIXES: {{^}}int g() {
+  return 1;
+}
+
+#define DEFINE_STATIC static
+// CHECK-FIXES: {{^}}#define DEFINE_STATIC static
+DEFINE_STATIC int h = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: 'h' is a static definition in anonymous namespace
+// CHECK-FIXES: {{^}}DEFINE_STATIC int h = 1;
+
+#define DEFINE_STATIC_VAR(x) static int x = 2
+// CHECK-FIXES: {{^}}#define DEFINE_STATIC_VAR(x) static int x = 2
+DEFINE_STATIC_VAR(i);
+// CHECK-FIXES: {{^}}DEFINE_STATIC_VAR(i);
+
+} // namespace
+
+namespace N {
+
+int a = 1;
+const int b = 1;
+static int c = 1;
+static const int d = 1;
+const static int e = 1;
+
+} // namespace N
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-string-compare.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-string-compare.cpp
new file mode 100644
index 0000000..9bd11da
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-string-compare.cpp
@@ -0,0 +1,119 @@
+// RUN: %check_clang_tidy %s readability-string-compare %t -- -- -std=c++11
+
+namespace std {
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C>>
+class basic_string {
+public:
+  basic_string();
+  basic_string(const C *, unsigned int size);
+  int compare(const basic_string<char> &str) const;
+  int compare(const C *) const;
+  int compare(int, int, const basic_string<char> &str) const;
+  bool empty();
+};
+bool operator==(const basic_string<char> &lhs, const basic_string<char> &rhs);
+bool operator!=(const basic_string<char> &lhs, const basic_string<char> &rhs);
+bool operator==(const basic_string<char> &lhs, const char *&rhs);
+typedef basic_string<char> string;
+}
+
+void func(bool b);
+
+std::string comp() {
+  std::string str("a", 1);
+  return str;
+}
+
+void Test() {
+  std::string str1("a", 1);
+  std::string str2("b", 1);
+
+  if (str1.compare(str2)) {
+  }
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings; use the string equality operator instead [readability-string-compare]
+  if (!str1.compare(str2)) {
+  }
+  // CHECK-MESSAGES: [[@LINE-2]]:8: warning: do not use 'compare' to test equality of strings; use the string equality operator instead [readability-string-compare]
+  if (str1.compare(str2) == 0) {
+  }
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+  // CHECK-FIXES: if (str1 == str2) {
+  if (str1.compare(str2) != 0) {
+  }
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+  // CHECK-FIXES: if (str1 != str2) {
+  if (str1.compare("foo") == 0) {
+  }
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+  // CHECK-FIXES: if (str1 == "foo") {
+  if (0 == str1.compare(str2)) {
+  }
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+  // CHECK-FIXES: if (str2 == str1) {
+  if (0 != str1.compare(str2)) {
+  }
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+  // CHECK-FIXES: if (str2 != str1) {
+  func(str1.compare(str2));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: do not use 'compare' to test equality of strings;
+  if (str2.empty() || str1.compare(str2) != 0) {
+  }
+  // CHECK-MESSAGES: [[@LINE-2]]:23: warning: do not use 'compare' to test equality of strings;
+  // CHECK-FIXES: if (str2.empty() || str1 != str2) {
+  std::string *str3 = &str1;
+  if (str3->compare(str2)) {
+  }
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+  if (str3->compare(str2) == 0) {
+  }
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+  // CHECK-FIXES: if (*str3 == str2) {
+  if (str2.compare(*str3) == 0) {
+  }
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+  // CHECK-FIXES: if (str2 == *str3) {
+  if (comp().compare(str1) == 0) {
+  }
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+  // CHECK-FIXES: if (comp() == str1) {
+  if (str1.compare(comp()) == 0) {
+  }
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+  // CHECK-FIXES: if (str1 == comp()) {
+  if (str1.compare(comp())) {
+  }
+  // CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
+}
+
+void Valid() {
+  std::string str1("a", 1);
+  std::string str2("b", 1);
+  if (str1 == str2) {
+  }
+  if (str1 != str2) {
+  }
+  if (str1.compare(str2) == str1.compare(str2)) {
+  }
+  if (0 == 0) {
+  }
+  if (str1.compare(str2) > 0) {
+  }
+  if (str1.compare(1, 3, str2)) {
+  }
+  if (str1.compare(str2) > 0) {
+  }
+  if (str1.compare(str2) < 0) {
+  }
+  if (str1.compare(str2) == 2) {
+  }
+  if (str1.compare(str2) == -3) {
+  }
+  if (str1.compare(str2) == 1) {
+  }
+  if (str1.compare(str2) == -1) {
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-uniqueptr-delete-release.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-uniqueptr-delete-release.cpp
new file mode 100644
index 0000000..bd51bc6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/readability-uniqueptr-delete-release.cpp
@@ -0,0 +1,76 @@
+// RUN: %check_clang_tidy %s readability-uniqueptr-delete-release %t
+
+namespace std {
+template <typename T>
+struct default_delete {};
+
+template <typename T, typename D = default_delete<T>>
+class unique_ptr {
+ public:
+  unique_ptr();
+  ~unique_ptr();
+  explicit unique_ptr(T*);
+  template <typename U, typename E>
+  unique_ptr(unique_ptr<U, E>&&);
+  T* release();
+};
+}  // namespace std
+
+std::unique_ptr<int>& ReturnsAUnique();
+
+void Positives() {
+  std::unique_ptr<int> P;
+  delete P.release();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer '= nullptr' to 'delete x.release()' to reset unique_ptr<> objects [readability-uniqueptr-delete-release]
+  // CHECK-FIXES: {{^}}  P = nullptr;
+
+  auto P2 = P;
+  delete P2.release();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer '= nullptr' to 'delete x.release()' to reset unique_ptr<> objects [readability-uniqueptr-delete-release]
+  // CHECK-FIXES: {{^}}  P2 = nullptr;
+
+  std::unique_ptr<int> Array[20];
+  delete Array[4].release();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer '= nullptr' to 'delete
+  // CHECK-FIXES: {{^}}  Array[4] = nullptr;
+
+  delete ReturnsAUnique().release();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer '= nullptr' to 'delete
+  // CHECK-FIXES: {{^}}  ReturnsAUnique() = nullptr;
+}
+
+struct NotDefaultDeleter {};
+
+struct NotUniquePtr {
+  int* release();
+};
+
+void Negatives() {
+  std::unique_ptr<int, NotDefaultDeleter> P;
+  delete P.release();
+
+  NotUniquePtr P2;
+  delete P2.release();
+}
+
+template <typename T, typename D>
+void NegativeDeleterT() {
+  // Ideally this would trigger a warning, but we have all dependent types
+  // disabled for now.
+  std::unique_ptr<T> P;
+  delete P.release();
+
+  // We ignore this one because the deleter is a template argument.
+  // Not all instantiations will use the default deleter.
+  std::unique_ptr<int, D> P2;
+  delete P2.release();
+}
+template void NegativeDeleterT<int, std::default_delete<int>>();
+
+// Test some macros
+
+#define DELETE_RELEASE(x) delete (x).release()
+void NegativesWithTemplate() {
+  std::unique_ptr<int> P;
+  DELETE_RELEASE(P);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/run-clang-tidy.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/run-clang-tidy.cpp
new file mode 100644
index 0000000..2207e43
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/run-clang-tidy.cpp
@@ -0,0 +1,17 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -c %/t/test.cpp\",\"file\":\"%/t/test.cpp\"}]" | sed -e 's/\\/\\\\/g' > %t/compile_commands.json
+// RUN: echo "Checks: '-*,modernize-use-auto'" > %t/.clang-tidy
+// RUN: echo "WarningsAsErrors: '*'" >> %t/.clang-tidy
+// RUN: echo "CheckOptions:" >> %t/.clang-tidy
+// RUN: echo "  - key:             modernize-use-auto.MinTypeNameLength" >> %t/.clang-tidy
+// RUN: echo "    value:           '0'" >> %t/.clang-tidy
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: cd "%t"
+// RUN: not %run_clang_tidy "%t/test.cpp"
+
+int main()
+{
+  int* x = new int();
+  delete x;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/select-checks.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/select-checks.cpp
new file mode 100644
index 0000000..791def7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/select-checks.cpp
@@ -0,0 +1,11 @@
+// RUN: clang-tidy %s -checks='-*,llvm-namespace-*' -- 2>&1 | FileCheck -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy %s -checks='-*,an-unknown-check' -- 2>&1 | FileCheck -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK2 %s
+
+// CHECK2: Error: no checks enabled.
+
+namespace i {
+}
+// CHECK: :[[@LINE-1]]:2: warning: namespace 'i' not terminated with a closing comment [llvm-namespace-comment]
+
+// Expect no warnings from the google-explicit-constructor check:
+class A { A(int i); };
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/serialize-diagnostics.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/serialize-diagnostics.cpp
new file mode 100644
index 0000000..8b0895a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/serialize-diagnostics.cpp
@@ -0,0 +1,3 @@
+// RUN: not clang-tidy -checks=-*,llvm-namespace-comment %s -- -serialize-diagnostics %t | FileCheck %s
+// CHECK: :[[@LINE+1]]:12: error: expected ';' after struct [clang-diagnostic-error]
+struct A {}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/static-analyzer-config.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/static-analyzer-config.cpp
new file mode 100644
index 0000000..cee0a4c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/static-analyzer-config.cpp
@@ -0,0 +1,19 @@
+// RUN: clang-tidy %s -checks='-*,clang-analyzer-unix.Malloc' -config='{CheckOptions: [{ key: "clang-analyzer-unix.Malloc:Optimistic", value: true}]}' -- | FileCheck %s
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+void free(void *);
+void __attribute((ownership_returns(malloc))) *my_malloc(size_t);
+void __attribute((ownership_takes(malloc, 1))) my_free(void *);
+
+void f1() {
+  void *p = malloc(12);
+  return;
+  // CHECK: warning: Potential leak of memory pointed to by 'p' [clang-analyzer-unix.Malloc]
+}
+
+void af2() {
+  void *p = my_malloc(12);
+  my_free(p);
+  free(p);
+  // CHECK: warning: Attempt to free released memory [clang-analyzer-unix.Malloc]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/static-analyzer.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/static-analyzer.cpp
new file mode 100644
index 0000000..b0015aa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/static-analyzer.cpp
@@ -0,0 +1,17 @@
+// RUN: clang-tidy %s -checks='-*,clang-analyzer-*' -- | FileCheck %s
+extern void *malloc(unsigned long);
+extern void free(void *);
+
+void f() {
+  int *p = new int(42);
+  delete p;
+  delete p;
+  // CHECK: warning: Attempt to free released memory [clang-analyzer-cplusplus.NewDelete]
+}
+
+void g() {
+  void *q = malloc(132);
+  free(q);
+  free(q);
+  // CHECK: warning: Attempt to free released memory [clang-analyzer-unix.Malloc]
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/temporaries.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/temporaries.cpp
new file mode 100644
index 0000000..3df4c60
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/temporaries.cpp
@@ -0,0 +1,24 @@
+// RUN: clang-tidy -checks='-*,clang-analyzer-core.NullDereference' %s -- | FileCheck %s
+
+struct NoReturnDtor {
+  ~NoReturnDtor() __attribute__((noreturn));
+};
+
+extern bool check(const NoReturnDtor &);
+
+// CHECK-NOT: warning
+void testNullPointerDereferencePositive() {
+  int *value = 0;
+  // CHECK: [[@LINE+1]]:10: warning: Dereference of null pointer (loaded from variable 'value') [clang-analyzer-core.NullDereference]
+  *value = 1;
+}
+
+// CHECK-NOT: warning
+void testNullPointerDereference() {
+  int *value = 0;
+  if (check(NoReturnDtor())) {
+    // This unreachable code causes a warning if analysis of temporary
+    // destructors is not enabled.
+    *value = 1;
+  }
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/validate-check-names.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/validate-check-names.cpp
new file mode 100644
index 0000000..35bfb09
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/validate-check-names.cpp
@@ -0,0 +1,2 @@
+// Check names may only contain alphanumeric characters, '-', '_', and '.'.
+// RUN: clang-tidy -checks=* -list-checks | grep '^    ' | cut -b5- | not grep -v '^[a-zA-Z0-9_.\-]\+$'
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/vfsoverlay.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/vfsoverlay.cpp
new file mode 100644
index 0000000..5704b71
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/vfsoverlay.cpp
@@ -0,0 +1,8 @@
+// RUN: sed -e "s:INPUT_DIR:%S/Inputs/vfsoverlay:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsoverlay/vfsoverlay.yaml > %t.yaml
+// RUN: clang-tidy %s -checks='-*,modernize-use-nullptr' -vfsoverlay %t.yaml -- -I %t | FileCheck %s
+// REQUIRES: shell
+
+#include "not_real.h"
+
+X *ptr = 0;
+// CHECK: warning: use nullptr [modernize-use-nullptr]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors-diagnostics.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors-diagnostics.cpp
new file mode 100644
index 0000000..9f90b62
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors-diagnostics.cpp
@@ -0,0 +1,18 @@
+// RUN: clang-tidy %s -checks='-*,llvm-namespace-comment,clang-diagnostic*' \
+// RUN:   -- -Wunused-variable 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-WARN -implicit-check-not='{{warning|error}}:'
+// RUN: not clang-tidy %s -checks='-*,llvm-namespace-comment,clang-diagnostic*' \
+// RUN:   -warnings-as-errors='clang-diagnostic*' -- -Wunused-variable 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-WERR -implicit-check-not='{{warning|error}}:'
+// RUN: not clang-tidy %s -checks='-*,llvm-namespace-comment,clang-diagnostic*' \
+// RUN:   -warnings-as-errors='clang-diagnostic*' -quiet -- -Wunused-variable 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-WERR-QUIET -implicit-check-not='{{warning|error}}:'
+
+void f() { int i; }
+// CHECK-WARN: warning: unused variable 'i' [clang-diagnostic-unused-variable]
+// CHECK-WERR: error: unused variable 'i' [clang-diagnostic-unused-variable,-warnings-as-errors]
+// CHECK-WERR-QUIET: error: unused variable 'i' [clang-diagnostic-unused-variable,-warnings-as-errors]
+
+// CHECK-WARN-NOT: treated as
+// CHECK-WERR: 1 warning treated as error
+// CHECK-WERR-QUIET-NOT: treated as
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors-plural.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors-plural.cpp
new file mode 100644
index 0000000..a14759d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors-plural.cpp
@@ -0,0 +1,24 @@
+// RUN: clang-tidy %s -checks='-*,llvm-namespace-comment,clang-diagnostic*' -- 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-WARN -implicit-check-not='{{warning|error}}:'
+// RUN: not clang-tidy %s -checks='-*,llvm-namespace-comment,clang-diagnostic*' \
+// RUN:   -warnings-as-errors='llvm-namespace-comment' -- 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-WERR -implicit-check-not='{{warning|error}}:'
+// RUN: not clang-tidy %s -checks='-*,llvm-namespace-comment,clang-diagnostic*' \
+// RUN:   -warnings-as-errors='llvm-namespace-comment' -quiet -- 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-WERR-QUIET -implicit-check-not='{{warning|error}}:'
+
+namespace j {
+}
+// CHECK-WARN: warning: namespace 'j' not terminated with a closing comment [llvm-namespace-comment]
+// CHECK-WERR: error: namespace 'j' not terminated with a closing comment [llvm-namespace-comment,-warnings-as-errors]
+// CHECK-WERR-QUIET: error: namespace 'j' not terminated with a closing comment [llvm-namespace-comment,-warnings-as-errors]
+
+namespace k {
+}
+// CHECK-WARN: warning: namespace 'k' not terminated with a closing comment [llvm-namespace-comment]
+// CHECK-WERR: error: namespace 'k' not terminated with a closing comment [llvm-namespace-comment,-warnings-as-errors]
+// CHECK-WERR-QUIET: error: namespace 'k' not terminated with a closing comment [llvm-namespace-comment,-warnings-as-errors]
+
+// CHECK-WARN-NOT: treated as
+// CHECK-WERR: 2 warnings treated as errors
+// CHECK-WERR-QUIET-NOT: treated as
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors.cpp
new file mode 100644
index 0000000..44afb83
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/warnings-as-errors.cpp
@@ -0,0 +1,13 @@
+// RUN: clang-tidy %s -checks='-*,llvm-namespace-comment' -- 2>&1 | FileCheck %s --check-prefix=CHECK-WARN -implicit-check-not='{{warning|error}}:'
+// RUN: not clang-tidy %s -checks='-*,llvm-namespace-comment' -warnings-as-errors='llvm-namespace-comment' -- 2>&1 | FileCheck %s --check-prefix=CHECK-WERR -implicit-check-not='{{warning|error}}:'
+// RUN: not clang-tidy %s -checks='-*,llvm-namespace-comment' -warnings-as-errors='llvm-namespace-comment' -quiet -- 2>&1 | FileCheck %s --check-prefix=CHECK-WERR-QUIET -implicit-check-not='{{warning|error}}:'
+
+namespace i {
+}
+// CHECK-WARN: warning: namespace 'i' not terminated with a closing comment [llvm-namespace-comment]
+// CHECK-WERR: error: namespace 'i' not terminated with a closing comment [llvm-namespace-comment,-warnings-as-errors]
+// CHECK-WERR-QUIET: error: namespace 'i' not terminated with a closing comment [llvm-namespace-comment,-warnings-as-errors]
+
+// CHECK-WARN-NOT: treated as
+// CHECK-WERR: 1 warning treated as error
+// CHECK-WERR-QUIET-NOT: treated as
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/zircon-temporary-objects.cpp b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/zircon-temporary-objects.cpp
new file mode 100644
index 0000000..b29b482
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clang-tidy/zircon-temporary-objects.cpp
@@ -0,0 +1,109 @@
+// RUN: %check_clang_tidy %s zircon-temporary-objects %t -- \
+// RUN:   -config="{CheckOptions: [{key: zircon-temporary-objects.Names, value: 'Foo;NS::Bar'}]}" \
+// RUN:   -header-filter=.* \
+// RUN: -- -std=c++11
+
+// Should flag instances of Foo, NS::Bar.
+
+class Foo {
+public:
+  Foo() = default;
+  Foo(int Val) : Val(Val){};
+
+private:
+  int Val;
+};
+
+namespace NS {
+
+class Bar {
+public:
+  Bar() = default;
+  Bar(int Val) : Val(Val){};
+
+private:
+  int Val;
+};
+
+} // namespace NS
+
+class Bar {
+public:
+  Bar() = default;
+  Bar(int Val) : Val(Val){};
+
+private:
+  int Val;
+};
+
+int func(Foo F) { return 1; };
+
+int main() {
+  Foo F;
+  Foo *F2 = new Foo();
+  new Foo();
+  Foo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'Foo' is prohibited
+  Foo F3 = Foo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: creating a temporary object of type 'Foo' is prohibited
+
+  Bar();
+  NS::Bar();
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'NS::Bar' is prohibited
+
+  int A = func(Foo());
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: creating a temporary object of type 'Foo' is prohibited
+
+  Foo F4(0);
+  Foo *F5 = new Foo(0);
+  new Foo(0);
+  Foo(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'Foo' is prohibited
+  Foo F6 = Foo(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: creating a temporary object of type 'Foo' is prohibited
+
+  Bar(0);
+  NS::Bar(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'NS::Bar' is prohibited
+
+  int B = func(Foo(0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: creating a temporary object of type 'Foo' is prohibited
+}
+
+namespace NS {
+
+void f() {
+  Bar();
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'NS::Bar' is prohibited
+  Bar(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: creating a temporary object of type 'NS::Bar' is prohibited
+}
+
+} // namespace NS
+
+template <typename Ty>
+Ty make_ty() { return Ty(); }
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: creating a temporary object of type 'Foo' is prohibited
+// CHECK-MESSAGES: :[[@LINE-2]]:23: warning: creating a temporary object of type 'NS::Bar' is prohibited
+
+void ty_func() {
+  make_ty<Bar>();
+  make_ty<NS::Bar>();
+  make_ty<Foo>();
+}
+
+// Inheriting the disallowed class does not trigger the check.
+
+class Bingo : NS::Bar {}; // Not explicitly disallowed
+
+void f2() {
+  Bingo();
+}
+
+template <typename Ty>
+class Quux : Ty {};
+
+void f3() {
+  Quux<NS::Bar>();
+  Quux<Bar>();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/Inputs/sstream.h b/src/third_party/llvm-project/clang-tools-extra/test/clangd/Inputs/sstream.h
new file mode 100644
index 0000000..980963a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/Inputs/sstream.h
@@ -0,0 +1,3 @@
+namespace std {
+class basic_ostringstream {};
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/completion-snippets.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/completion-snippets.test
new file mode 100644
index 0000000..0689631
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/completion-snippets.test
@@ -0,0 +1,41 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+# RUN: clangd -lit-test -pch-storage=memory < %s | FileCheck -strict-whitespace %s
+{
+  "jsonrpc": "2.0",
+  "id": 0,
+  "method": "initialize",
+  "params": {
+    "processId": 123,
+    "rootPath": "clangd",
+    "capabilities": {
+      "textDocument": {
+        "completion": {
+          "completionItem": {
+            "snippetSupport": true
+          }
+        }
+      }
+    },
+    "trace": "off"
+  }
+}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"int func_with_args(int a, int b);\nint main() {\nfunc_with\n}"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":2,"character":7}}}
+#      CHECK:  "id": 1
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": {{.*}}
+# CHECK-NEXT:    "items": [
+# CHECK:           "filterText": "func_with_args",
+# CHECK-NEXT:      "insertText": "func_with_args(${1:int a}, ${2:int b})",
+# CHECK-NEXT:      "insertTextFormat": 2,
+# CHECK-NEXT:      "kind": 3,
+# CHECK-NEXT:      "label": " func_with_args(int a, int b)",
+# CHECK-NEXT:      "sortText": "{{.*}}func_with_args"
+# CHECK-NEXT:    }
+# CHECK-NEXT:    ]
+# CHECK-NEXT:  }
+---
+{"jsonrpc":"2.0","id":4,"method":"shutdown"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/completion.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/completion.test
new file mode 100644
index 0000000..c679e32
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/completion.test
@@ -0,0 +1,44 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+# RUN: clangd -lit-test -pch-storage=memory < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"struct S { int a; };\nint main() {\nS().\n}"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":2,"character":4}}}
+#      CHECK:  "id": 1
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": false,
+# CHECK-NEXT:    "items": [
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "detail": "int",
+# CHECK-NEXT:      "filterText": "a",
+# CHECK-NEXT:      "insertText": "a",
+# CHECK-NEXT:      "insertTextFormat": 1,
+# CHECK-NEXT:      "kind": 5,
+# CHECK-NEXT:      "label": " a",
+# CHECK-NEXT:      "sortText": "{{.*}}a"
+# CHECK-NEXT:    }
+# CHECK-NEXT:  ]
+---
+# Update the source file and check for completions again.
+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///main.cpp","version":2},"contentChanges":[{"text":"struct S { int b; };\nint main() {\nS().\n}"}]}}
+---
+{"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":2,"character":4}}}
+#      CHECK:  "id": 3,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": false,
+# CHECK-NEXT:    "items": [
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "detail": "int",
+# CHECK-NEXT:      "filterText": "b",
+# CHECK-NEXT:      "insertText": "b",
+# CHECK-NEXT:      "insertTextFormat": 1,
+# CHECK-NEXT:      "kind": 5,
+# CHECK-NEXT:      "label": " b",
+# CHECK-NEXT:      "sortText": "{{.*}}b"
+# CHECK-NEXT:    }
+# CHECK-NEXT:  ]
+---
+{"jsonrpc":"2.0","id":4,"method":"shutdown"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/crash-non-added-files.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/crash-non-added-files.test
new file mode 100644
index 0000000..d86f7d2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/crash-non-added-files.test
@@ -0,0 +1,34 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","id":2,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"test:///foo.c"},"range":{"start":{"line":104,"character":13},"end":{"line":0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 37}},"severity":2,"message":"using the result of an assignment as a condition without parentheses"},{"range":{"start": {"line": 0, "character": 34}, "end": {"line": 0, "character": 35}},"severity":3,"message":"place parentheses around the assignment to silence this warning"},{"range":{"start": {"line": 0, "character": 34}, "end": {"line": 0, "character": 35}},"severity":3,"message":"use '==' to turn this assignment into an equality comparison"}]}}}
+#      CHECK:  "error": {
+# CHECK-NEXT:    "code": -32602
+# CHECK-NEXT:    "message": "onCodeAction called for non-added file"
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "id": 2,
+---
+{"jsonrpc":"2.0","id":3,"method":"textDocument/rangeFormatting","params":{"textDocument":{"uri":"test:///foo.c"},"range":{"start":{"line":1,"character":4},"end":{"line":1,"character":12}},"options":{"tabSize":4,"insertSpaces":true}}}
+#      CHECK:  "error": {
+# CHECK-NEXT:    "code": -32602
+# CHECK-NEXT:    "message": "onDocumentRangeFormatting called for non-added file"
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "id": 3,
+---
+{"jsonrpc":"2.0","id":4,"method":"textDocument/formatting","params":{"textDocument":{"uri":"test:///foo.c"},"options":{"tabSize":4,"insertSpaces":true}}}
+#      CHECK:  "error": {
+# CHECK-NEXT:    "code": -32602
+# CHECK-NEXT:    "message": "onDocumentFormatting called for non-added file"
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "id": 4,
+---
+{"jsonrpc":"2.0","id":5,"method":"textDocument/onTypeFormatting","params":{"textDocument":{"uri":"test:///foo.c"},"position":{"line":3,"character":1},"ch":"}","options":{"tabSize":4,"insertSpaces":true}}}
+#      CHECK:  "error": {
+# CHECK-NEXT:    "code": -32602
+# CHECK-NEXT:    "message": "onDocumentOnTypeFormatting called for non-added file"
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "id": 5,
+---
+{"jsonrpc":"2.0","id":6,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/delimited-input-comment-at-the-end.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/delimited-input-comment-at-the-end.test
new file mode 100644
index 0000000..9c10b92
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/delimited-input-comment-at-the-end.test
@@ -0,0 +1,12 @@
+# RUN: clangd -input-style=delimited -run-synchronously -input-mirror-file %t < %s

+# RUN: grep '{"jsonrpc":"2.0","id":3,"method":"exit"}' %t

+#

+# RUN: clangd -lit-test -input-mirror-file %t < %s

+# RUN: grep '{"jsonrpc":"2.0","id":3,"method":"exit"}' %t

+#

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

+---

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

+---

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

+# comment at the end

diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/diagnostics.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/diagnostics.test
new file mode 100644
index 0000000..afd1277
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/diagnostics.test
@@ -0,0 +1,28 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","version":1,"text":"void main() {}"}}}
+#      CHECK:  "method": "textDocument/publishDiagnostics",
+# CHECK-NEXT:  "params": {
+# CHECK-NEXT:    "diagnostics": [
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "message": "return type of 'main' is not 'int'",
+# CHECK-NEXT:        "range": {
+# CHECK-NEXT:          "end": {
+# CHECK-NEXT:            "character": 4,
+# CHECK-NEXT:            "line": 0
+# CHECK-NEXT:          },
+# CHECK-NEXT:          "start": {
+# CHECK-NEXT:            "character": 0,
+# CHECK-NEXT:            "line": 0
+# CHECK-NEXT:          }
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "severity": 2
+# CHECK-NEXT:      }
+# CHECK-NEXT:    ],
+# CHECK-NEXT:    "uri": "file://{{.*}}/foo.c"
+# CHECK-NEXT:  }
+---
+{"jsonrpc":"2.0","id":5,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/execute-command.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/execute-command.test
new file mode 100644
index 0000000..9686d04
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/execute-command.test
@@ -0,0 +1,64 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","version":1,"text":"int main(int i, char **a) { if (i = 2) {}}"}}}
+#      CHECK:  "method": "textDocument/publishDiagnostics",
+# CHECK-NEXT:  "params": {
+# CHECK-NEXT:    "diagnostics": [
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "message": "using the result of an assignment as a condition without parentheses",
+# CHECK-NEXT:        "range": {
+# CHECK-NEXT:          "end": {
+# CHECK-NEXT:            "character": 37,
+# CHECK-NEXT:            "line": 0
+# CHECK-NEXT:          },
+# CHECK-NEXT:          "start": {
+# CHECK-NEXT:            "character": 32,
+# CHECK-NEXT:            "line": 0
+# CHECK-NEXT:          }
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "severity": 2
+# CHECK-NEXT:      }
+# CHECK-NEXT:    ],
+# CHECK-NEXT:    "uri": "file://{{.*}}/foo.c"
+# CHECK-NEXT:  }
+---
+# No command name
+{"jsonrpc":"2.0","id":3,"method":"workspace/executeCommand","params":{}}
+---
+# Invalid, non-scalar command name
+{"jsonrpc":"2.0","id":4,"method":"workspace/executeCommand","params":{"command": {}}}
+---
+{"jsonrpc":"2.0","id":5,"method":"workspace/executeCommand","params":{"command":"clangd.applyFix","custom":"foo", "arguments":[{"changes":{"test:///foo.c":[{"range":{"start":{"line":0,"character":32},"end":{"line":0,"character":32}},"newText":"("},{"range":{"start":{"line":0,"character":37},"end":{"line":0,"character":37}},"newText":")"}]}}]}}
+---
+# Arguments not a sequence.
+{"jsonrpc":"2.0","id":6,"method":"workspace/executeCommand","params":{"command":"clangd.applyFix","arguments":"foo"}}
+---
+# Unknown command.
+{"jsonrpc":"2.0","id":7,"method":"workspace/executeCommand","params":{"command":"mycommand"}}
+---
+# ApplyFix argument not a mapping node.
+{"jsonrpc":"2.0","id":8,"method":"workspace/executeCommand","params":{"command":"clangd.applyFix","custom":"foo", "arguments":[""]}}
+---
+# Custom field in WorkspaceEdit
+{"jsonrpc":"2.0","id":9,"method":"workspace/executeCommand","params":{"command":"clangd.applyFix","arguments":[{"custom":"foo", "changes":{"test:///foo.c":[{"range":{"start":{"line":0,"character":32},"end":{"line":0,"character":32}},"newText":"("},{"range":{"start":{"line":0,"character":37},"end":{"line":0,"character":37}},"newText":")"}]}}]}}
+---
+# changes in WorkspaceEdit with no mapping node
+{"jsonrpc":"2.0","id":10,"method":"workspace/executeCommand","params":{"command":"clangd.applyFix","arguments":[{"changes":"foo"}]}}
+---
+# Custom field in WorkspaceEditChange
+{"jsonrpc":"2.0","id":11,"method":"workspace/executeCommand","params":{"command":"clangd.applyFix","arguments":[{"changes":{"test:///foo.c":[{"range":{"start":{"line":0,"character":32},"end":{"line":0,"character":32}},"newText":"("},{"range":{"start":{"line":0,"character":37},"end":{"line":0,"character":37}},"newText":")"}], "custom":"foo"}}]}}
+---
+# No sequence node for TextEdits
+{"jsonrpc":"2.0","id":12,"method":"workspace/executeCommand","params":{"command":"clangd.applyFix","arguments":[{"changes":{"test:///foo.c":"bar"}}]}}
+---
+# No mapping node for TextEdit
+{"jsonrpc":"2.0","id":13,"method":"workspace/executeCommand","params":{"command":"clangd.applyFix","arguments":[{"changes":{"test:///foo.c":[""]}}]}}
+---
+# TextEdit not decoded
+{"jsonrpc":"2.0","id":14,"method":"workspace/executeCommand","params":{"command":"clangd.applyFix","arguments":[{"changes":{"test:///foo.c":[{"range":{"start":{"line":0,"character":32},"end":{"line":0,"character":32}},"newText":"("},{"range":"","newText":")"}]}}]}}
+---
+# Command name after arguments
+{"jsonrpc":"2.0","id":9,"method":"workspace/executeCommand","params":{"arguments":[{"custom":"foo", "changes":{"test:///foo.c":[{"range":{"start":{"line":0,"character":32},"end":{"line":0,"character":32}},"newText":"("},{"range":{"start":{"line":0,"character":37},"end":{"line":0,"character":37}},"newText":")"}]}}],"command":"clangd.applyFix"}}
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/extra-flags.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/extra-flags.test
new file mode 100644
index 0000000..f360cca
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/extra-flags.test
@@ -0,0 +1,52 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","version":1,"text":"int main() { int i; return i; }"},"metadata":{"extraFlags":["-Wall"]}}}
+#      CHECK:  "method": "textDocument/publishDiagnostics",
+# CHECK-NEXT:  "params": {
+# CHECK-NEXT:    "diagnostics": [
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "message": "variable 'i' is uninitialized when used here",
+# CHECK-NEXT:        "range": {
+# CHECK-NEXT:          "end": {
+# CHECK-NEXT:            "character": 28,
+# CHECK-NEXT:            "line": 0
+# CHECK-NEXT:          },
+# CHECK-NEXT:          "start": {
+# CHECK-NEXT:            "character": 27,
+# CHECK-NEXT:            "line": 0
+# CHECK-NEXT:          }
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "severity": 2
+# CHECK-NEXT:      }
+# CHECK-NEXT:    ],
+# CHECK-NEXT:    "uri": "file://{{.*}}/foo.c"
+# CHECK-NEXT:  }
+---
+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///foo.c","version":2},"contentChanges":[{"text":"int main() { int i; return i+1; }"}]}}
+#      CHECK:  "method": "textDocument/publishDiagnostics",
+# CHECK-NEXT:  "params": {
+# CHECK-NEXT:    "diagnostics": [
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "message": "variable 'i' is uninitialized when used here",
+# CHECK-NEXT:        "range": {
+# CHECK-NEXT:          "end": {
+# CHECK-NEXT:            "character": 28,
+# CHECK-NEXT:            "line": 0
+# CHECK-NEXT:          },
+# CHECK-NEXT:          "start": {
+# CHECK-NEXT:            "character": 27,
+# CHECK-NEXT:            "line": 0
+# CHECK-NEXT:          }
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "severity": 2
+# CHECK-NEXT:      }
+# CHECK-NEXT:    ],
+# CHECK-NEXT:    "uri": "file://{{.*}}/foo.c"
+# CHECK-NEXT:  }
+---
+{"jsonrpc":"2.0","id":5,"method":"shutdown"}
+---
+{"jsonrpc":"2.0":"method":"exit"}
+
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/fixits.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/fixits.test
new file mode 100644
index 0000000..f8eb20c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/fixits.test
@@ -0,0 +1,210 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","version":1,"text":"int main(int i, char **a) { if (i = 2) {}}"}}}
+#      CHECK:    "method": "textDocument/publishDiagnostics",
+# CHECK-NEXT:  "params": {
+# CHECK-NEXT:    "diagnostics": [
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "message": "using the result of an assignment as a condition without parentheses",
+# CHECK-NEXT:        "range": {
+# CHECK-NEXT:          "end": {
+# CHECK-NEXT:            "character": 37,
+# CHECK-NEXT:            "line": 0
+# CHECK-NEXT:          },
+# CHECK-NEXT:          "start": {
+# CHECK-NEXT:            "character": 32,
+# CHECK-NEXT:            "line": 0
+# CHECK-NEXT:          }
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "severity": 2
+# CHECK-NEXT:      }
+# CHECK-NEXT:    ],
+# CHECK-NEXT:    "uri": "file://{{.*}}/foo.c"
+# CHECK-NEXT:  }
+---
+{"jsonrpc":"2.0","id":2,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"test:///foo.c"},"range":{"start":{"line":104,"character":13},"end":{"line":0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 37}},"severity":2,"message":"using the result of an assignment as a condition without parentheses"}]}}}
+#      CHECK:  "id": 2,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "arguments": [
+# CHECK-NEXT:        {
+# CHECK-NEXT:          "changes": {
+# CHECK-NEXT:            "file://{{.*}}/foo.c": [
+# CHECK-NEXT:              {
+# CHECK-NEXT:                "newText": "(",
+# CHECK-NEXT:                "range": {
+# CHECK-NEXT:                  "end": {
+# CHECK-NEXT:                    "character": 32,
+# CHECK-NEXT:                    "line": 0
+# CHECK-NEXT:                  },
+# CHECK-NEXT:                  "start": {
+# CHECK-NEXT:                    "character": 32,
+# CHECK-NEXT:                    "line": 0
+# CHECK-NEXT:                  }
+# CHECK-NEXT:                }
+# CHECK-NEXT:              },
+# CHECK-NEXT:              {
+# CHECK-NEXT:                "newText": ")",
+# CHECK-NEXT:                "range": {
+# CHECK-NEXT:                  "end": {
+# CHECK-NEXT:                    "character": 37,
+# CHECK-NEXT:                    "line": 0
+# CHECK-NEXT:                  },
+# CHECK-NEXT:                  "start": {
+# CHECK-NEXT:                    "character": 37,
+# CHECK-NEXT:                    "line": 0
+# CHECK-NEXT:                  }
+# CHECK-NEXT:                }
+# CHECK-NEXT:              }
+# CHECK-NEXT:            ]
+# CHECK-NEXT:          }
+# CHECK-NEXT:        }
+# CHECK-NEXT:      ],
+# CHECK-NEXT:      "command": "clangd.applyFix",
+# CHECK-NEXT:      "title": "Apply fix: place parentheses around the assignment to silence this warning"
+# CHECK-NEXT:    },
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "arguments": [
+# CHECK-NEXT:        {
+# CHECK-NEXT:          "changes": {
+# CHECK-NEXT:            "file://{{.*}}/foo.c": [
+# CHECK-NEXT:              {
+# CHECK-NEXT:                "newText": "==",
+# CHECK-NEXT:                "range": {
+# CHECK-NEXT:                  "end": {
+# CHECK-NEXT:                    "character": 35,
+# CHECK-NEXT:                    "line": 0
+# CHECK-NEXT:                  },
+# CHECK-NEXT:                  "start": {
+# CHECK-NEXT:                    "character": 34,
+# CHECK-NEXT:                    "line": 0
+# CHECK-NEXT:                  }
+# CHECK-NEXT:                }
+# CHECK-NEXT:              }
+# CHECK-NEXT:            ]
+# CHECK-NEXT:          }
+# CHECK-NEXT:        }
+# CHECK-NEXT:      ],
+# CHECK-NEXT:      "command": "clangd.applyFix",
+# CHECK-NEXT:      "title": "Apply fix: use '==' to turn this assignment into an equality comparison"
+# CHECK-NEXT:    }
+# CHECK-NEXT:  ]
+---
+{"jsonrpc":"2.0","id":3,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"test:///foo.c"},"range":{"start":{"line":104,"character":13},"end":{"line":0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 37}},"severity":2,"message":"using the result of an assignment as a condition without parentheses"}]}}}
+# Make sure unused "code" and "source" fields ignored gracefully
+#      CHECK:  "id": 3,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "arguments": [
+# CHECK-NEXT:        {
+# CHECK-NEXT:          "changes": {
+# CHECK-NEXT:            "file://{{.*}}/foo.c": [
+# CHECK-NEXT:              {
+# CHECK-NEXT:                "newText": "(",
+# CHECK-NEXT:                "range": {
+# CHECK-NEXT:                  "end": {
+# CHECK-NEXT:                    "character": 32,
+# CHECK-NEXT:                    "line": 0
+# CHECK-NEXT:                  },
+# CHECK-NEXT:                  "start": {
+# CHECK-NEXT:                    "character": 32,
+# CHECK-NEXT:                    "line": 0
+# CHECK-NEXT:                  }
+# CHECK-NEXT:                }
+# CHECK-NEXT:              },
+# CHECK-NEXT:              {
+# CHECK-NEXT:                "newText": ")",
+# CHECK-NEXT:                "range": {
+# CHECK-NEXT:                  "end": {
+# CHECK-NEXT:                    "character": 37,
+# CHECK-NEXT:                    "line": 0
+# CHECK-NEXT:                  },
+# CHECK-NEXT:                  "start": {
+# CHECK-NEXT:                    "character": 37,
+# CHECK-NEXT:                    "line": 0
+# CHECK-NEXT:                  }
+# CHECK-NEXT:                }
+# CHECK-NEXT:              }
+# CHECK-NEXT:            ]
+# CHECK-NEXT:          }
+# CHECK-NEXT:        }
+# CHECK-NEXT:      ],
+# CHECK-NEXT:      "command": "clangd.applyFix",
+# CHECK-NEXT:      "title": "Apply fix: place parentheses around the assignment to silence this warning"
+# CHECK-NEXT:    },
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "arguments": [
+# CHECK-NEXT:        {
+# CHECK-NEXT:          "changes": {
+# CHECK-NEXT:            "file://{{.*}}/foo.c": [
+# CHECK-NEXT:              {
+# CHECK-NEXT:                "newText": "==",
+# CHECK-NEXT:                "range": {
+# CHECK-NEXT:                  "end": {
+# CHECK-NEXT:                    "character": 35,
+# CHECK-NEXT:                    "line": 0
+# CHECK-NEXT:                  },
+# CHECK-NEXT:                  "start": {
+# CHECK-NEXT:                    "character": 34,
+# CHECK-NEXT:                    "line": 0
+# CHECK-NEXT:                  }
+# CHECK-NEXT:                }
+# CHECK-NEXT:              }
+# CHECK-NEXT:            ]
+# CHECK-NEXT:          }
+# CHECK-NEXT:        }
+# CHECK-NEXT:      ],
+# CHECK-NEXT:      "command": "clangd.applyFix",
+# CHECK-NEXT:      "title": "Apply fix: use '==' to turn this assignment into an equality comparison"
+# CHECK-NEXT:    }
+# CHECK-NEXT:  ]
+---
+{"jsonrpc":"2.0","id":4,"method":"workspace/executeCommand","params":{"command":"clangd.applyFix","arguments":[{"changes":{"test:///foo.c":[{"range":{"start":{"line":0,"character":32},"end":{"line":0,"character":32}},"newText":"("},{"range":{"start":{"line":0,"character":37},"end":{"line":0,"character":37}},"newText":")"}]}}]}}
+#      CHECK:  "id": 4,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": "Fix applied."
+#
+#      CHECK:  "id": 1,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "method": "workspace/applyEdit",
+# CHECK-NEXT:  "params": {
+# CHECK-NEXT:    "edit": {
+# CHECK-NEXT:      "changes": {
+# CHECK-NEXT:        "{{.*}}/foo.c": [
+# CHECK-NEXT:          {
+# CHECK-NEXT:            "newText": "(",
+# CHECK-NEXT:            "range": {
+# CHECK-NEXT:              "end": {
+# CHECK-NEXT:                "character": 32,
+# CHECK-NEXT:                "line": 0
+# CHECK-NEXT:              },
+# CHECK-NEXT:              "start": {
+# CHECK-NEXT:                "character": 32,
+# CHECK-NEXT:                "line": 0
+# CHECK-NEXT:              }
+# CHECK-NEXT:            }
+# CHECK-NEXT:          },
+# CHECK-NEXT:          {
+# CHECK-NEXT:            "newText": ")",
+# CHECK-NEXT:            "range": {
+# CHECK-NEXT:              "end": {
+# CHECK-NEXT:                "character": 37,
+# CHECK-NEXT:                "line": 0
+# CHECK-NEXT:              },
+# CHECK-NEXT:              "start": {
+# CHECK-NEXT:                "character": 37,
+# CHECK-NEXT:                "line": 0
+# CHECK-NEXT:              }
+# CHECK-NEXT:            }
+# CHECK-NEXT:          }
+# CHECK-NEXT:        ]
+# CHECK-NEXT:      }
+# CHECK-NEXT:    }
+# CHECK-NEXT:  }
+---
+{"jsonrpc":"2.0","id":4,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/formatting.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/formatting.test
new file mode 100644
index 0000000..8e0ae5b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/formatting.test
@@ -0,0 +1,187 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","version":1,"text":"int foo ( int x ) {\n    x = x+1;\n    return x;\n    }"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/rangeFormatting","params":{"textDocument":{"uri":"test:///foo.c"},"range":{"start":{"line":1,"character":4},"end":{"line":1,"character":12}},"options":{"tabSize":4,"insertSpaces":true}}}
+#      CHECK:   "id": 1,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "newText": "\n  ",
+# CHECK-NEXT:      "range": {
+# CHECK-NEXT:        "end": {
+# CHECK-NEXT:          "character": 4,
+# CHECK-NEXT:          "line": 1
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "start": {
+# CHECK-NEXT:          "character": 19,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        }
+# CHECK-NEXT:      }
+# CHECK-NEXT:    },
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "newText": " ",
+# CHECK-NEXT:      "range": {
+# CHECK-NEXT:        "end": {
+# CHECK-NEXT:          "character": 9,
+# CHECK-NEXT:          "line": 1
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "start": {
+# CHECK-NEXT:          "character": 9,
+# CHECK-NEXT:          "line": 1
+# CHECK-NEXT:        }
+# CHECK-NEXT:      }
+# CHECK-NEXT:    },
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "newText": " ",
+# CHECK-NEXT:      "range": {
+# CHECK-NEXT:        "end": {
+# CHECK-NEXT:          "character": 10,
+# CHECK-NEXT:          "line": 1
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "start": {
+# CHECK-NEXT:          "character": 10,
+# CHECK-NEXT:          "line": 1
+# CHECK-NEXT:        }
+# CHECK-NEXT:      }
+# CHECK-NEXT:    },
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "newText": "\n  ",
+# CHECK-NEXT:      "range": {
+# CHECK-NEXT:        "end": {
+# CHECK-NEXT:          "character": 4,
+# CHECK-NEXT:          "line": 2
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "start": {
+# CHECK-NEXT:          "character": 12,
+# CHECK-NEXT:          "line": 1
+# CHECK-NEXT:        }
+# CHECK-NEXT:      }
+# CHECK-NEXT:    }
+# CHECK-NEXT:  ]
+---
+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///foo.c","version":5},"contentChanges":[{"text":"int foo ( int x ) {\n  x = x + 1;\n  return x;\n    }"}]}}
+#
+#
+---
+{"jsonrpc":"2.0","id":2,"method":"textDocument/rangeFormatting","params":{"textDocument":{"uri":"test:///foo.c"},"range":{"start":{"line":1,"character":2},"end":{"line":1,"character":12}},"options":{"tabSize":4,"insertSpaces":true}}}
+#      CHECK:  "id": 2,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": []
+---
+{"jsonrpc":"2.0","id":3,"method":"textDocument/formatting","params":{"textDocument":{"uri":"test:///foo.c"},"options":{"tabSize":4,"insertSpaces":true}}}
+#      CHECK:  "id": 3,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "newText": "",
+# CHECK-NEXT:      "range": {
+# CHECK-NEXT:        "end": {
+# CHECK-NEXT:          "character": 8,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "start": {
+# CHECK-NEXT:          "character": 7,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        }
+# CHECK-NEXT:      }
+# CHECK-NEXT:    },
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "newText": "",
+# CHECK-NEXT:      "range": {
+# CHECK-NEXT:        "end": {
+# CHECK-NEXT:          "character": 10,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "start": {
+# CHECK-NEXT:          "character": 9,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        }
+# CHECK-NEXT:      }
+# CHECK-NEXT:    },
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "newText": "",
+# CHECK-NEXT:      "range": {
+# CHECK-NEXT:        "end": {
+# CHECK-NEXT:          "character": 16,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "start": {
+# CHECK-NEXT:          "character": 15,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        }
+# CHECK-NEXT:      }
+# CHECK-NEXT:    },
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "newText": "\n",
+# CHECK-NEXT:      "range": {
+# CHECK-NEXT:        "end": {
+# CHECK-NEXT:          "character": 4,
+# CHECK-NEXT:          "line": 3
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "start": {
+# CHECK-NEXT:          "character": 11,
+# CHECK-NEXT:          "line": 2
+# CHECK-NEXT:        }
+# CHECK-NEXT:      }
+# CHECK-NEXT:    }
+# CHECK-NEXT:  ]
+---
+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///foo.c","version":9},"contentChanges":[{"text":"int foo(int x) {\n  x = x + 1;\n  return x;\n}"}]}}
+---
+{"jsonrpc":"2.0","id":4,"method":"textDocument/formatting","params":{"textDocument":{"uri":"test:///foo.c"},"options":{"tabSize":4,"insertSpaces":true}}}
+#      CHECK:  "id": 4,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": []
+---
+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///foo.c","version":5},"contentChanges":[{"text":"int foo ( int x ) {\n  x = x + 1;\n  return x;\n}"}]}}
+---
+{"jsonrpc":"2.0","id":5,"method":"textDocument/onTypeFormatting","params":{"textDocument":{"uri":"test:///foo.c"},"position":{"line":3,"character":1},"ch":"}","options":{"tabSize":4,"insertSpaces":true}}}
+#      CHECK:  "id": 5,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "newText": "",
+# CHECK-NEXT:      "range": {
+# CHECK-NEXT:        "end": {
+# CHECK-NEXT:          "character": 8,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "start": {
+# CHECK-NEXT:          "character": 7,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        }
+# CHECK-NEXT:      }
+# CHECK-NEXT:    },
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "newText": "",
+# CHECK-NEXT:      "range": {
+# CHECK-NEXT:        "end": {
+# CHECK-NEXT:          "character": 10,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "start": {
+# CHECK-NEXT:          "character": 9,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        }
+# CHECK-NEXT:      }
+# CHECK-NEXT:    },
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "newText": "",
+# CHECK-NEXT:      "range": {
+# CHECK-NEXT:        "end": {
+# CHECK-NEXT:          "character": 16,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "start": {
+# CHECK-NEXT:          "character": 15,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        }
+# CHECK-NEXT:      }
+# CHECK-NEXT:    }
+# CHECK-NEXT:  ]
+---
+{"jsonrpc":"2.0","id":6,"method":"shutdown"}
+---
+{"jsonrpc":"2.0":"method":"exit"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/hover.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/hover.test
new file mode 100644
index 0000000..8f1ead0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/hover.test
@@ -0,0 +1,24 @@
+# RUN: clangd -lit-test < %s | FileCheck %s

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

+---

+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"void foo(); int main() { foo(); }\n"}}}

+---

+{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":0,"character":27}}}

+#      CHECK:  "id": 1,

+# CHECK-NEXT:  "jsonrpc": "2.0",

+# CHECK-NEXT:  "result": {

+# CHECK-NEXT:    "contents": {

+# CHECK-NEXT:      "kind": "plaintext",

+# CHECK-NEXT:      "value": "Declared in global namespace\n\nvoid foo()"

+# CHECK-NEXT:    }

+# CHECK-NEXT:  }

+# CHECK-NEXT:}

+---

+{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":0,"character":10}}}

+#      CHECK:  "id": 1,

+# CHECK-NEXT:  "jsonrpc": "2.0",

+# CHECK-NEXT:  "result": null

+---

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

+---

+{"jsonrpc":"2.0","method":"exit"}

diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/initialize-params-invalid.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/initialize-params-invalid.test
new file mode 100644
index 0000000..99c04c6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/initialize-params-invalid.test
@@ -0,0 +1,46 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+# Test with invalid initialize request parameters
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":"","rootUri":"test:///workspace","capabilities":{},"trace":"off"}}
+#      CHECK:  "id": 0,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "capabilities": {
+# CHECK-NEXT:      "codeActionProvider": true,
+# CHECK-NEXT:      "completionProvider": {
+# CHECK-NEXT:        "resolveProvider": false,
+# CHECK-NEXT:        "triggerCharacters": [
+# CHECK-NEXT:          ".",
+# CHECK-NEXT:          ">",
+# CHECK-NEXT:          ":"
+# CHECK-NEXT:        ]
+# CHECK-NEXT:      },
+# CHECK-NEXT:      "definitionProvider": true,
+# CHECK-NEXT:      "documentFormattingProvider": true,
+# CHECK-NEXT:      "documentHighlightProvider": true,
+# CHECK-NEXT:      "documentOnTypeFormattingProvider": {
+# CHECK-NEXT:        "firstTriggerCharacter": "}",
+# CHECK-NEXT:        "moreTriggerCharacter": []
+# CHECK-NEXT:      },
+# CHECK-NEXT:      "documentRangeFormattingProvider": true,
+# CHECK-NEXT:      "documentSymbolProvider": true,
+# CHECK-NEXT:      "executeCommandProvider": {
+# CHECK-NEXT:        "commands": [
+# CHECK-NEXT:          "clangd.applyFix"
+# CHECK-NEXT:        ]
+# CHECK-NEXT:      },
+# CHECK-NEXT:      "hoverProvider": true,
+# CHECK-NEXT:      "renameProvider": true,
+# CHECK-NEXT:      "signatureHelpProvider": {
+# CHECK-NEXT:        "triggerCharacters": [
+# CHECK-NEXT:          "(",
+# CHECK-NEXT:          ","
+# CHECK-NEXT:        ]
+# CHECK-NEXT:      },
+# CHECK-NEXT:      "textDocumentSync": 2,
+# CHECK-NEXT:      "workspaceSymbolProvider": true
+# CHECK-NEXT:    }
+# CHECK-NEXT:  }
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/initialize-params.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/initialize-params.test
new file mode 100644
index 0000000..a04d70a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/initialize-params.test
@@ -0,0 +1,49 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+# Test initialize request parameters with rootUri
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootUri":"test:///workspace","capabilities":{},"trace":"off"}}
+#      CHECK:  "id": 0,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "capabilities": {
+# CHECK-NEXT:      "codeActionProvider": true,
+# CHECK-NEXT:      "completionProvider": {
+# CHECK-NEXT:        "resolveProvider": false,
+# CHECK-NEXT:        "triggerCharacters": [
+# CHECK-NEXT:          ".",
+# CHECK-NEXT:          ">",
+# CHECK-NEXT:          ":"
+# CHECK-NEXT:        ]
+# CHECK-NEXT:      },
+# CHECK-NEXT:      "definitionProvider": true,
+# CHECK-NEXT:      "documentFormattingProvider": true,
+# CHECK-NEXT:      "documentHighlightProvider": true,
+# CHECK-NEXT:      "documentOnTypeFormattingProvider": {
+# CHECK-NEXT:        "firstTriggerCharacter": "}",
+# CHECK-NEXT:        "moreTriggerCharacter": []
+# CHECK-NEXT:      },
+# CHECK-NEXT:      "documentRangeFormattingProvider": true,
+# CHECK-NEXT:      "documentSymbolProvider": true,
+# CHECK-NEXT:      "executeCommandProvider": {
+# CHECK-NEXT:        "commands": [
+# CHECK-NEXT:          "clangd.applyFix"
+# CHECK-NEXT:        ]
+# CHECK-NEXT:      },
+# CHECK-NEXT:      "hoverProvider": true,
+# CHECK-NEXT:      "renameProvider": true,
+# CHECK-NEXT:      "signatureHelpProvider": {
+# CHECK-NEXT:        "triggerCharacters": [
+# CHECK-NEXT:          "(",
+# CHECK-NEXT:          ","
+# CHECK-NEXT:        ]
+# CHECK-NEXT:      },
+# CHECK-NEXT:      "textDocumentSync": 2,
+# CHECK-NEXT:      "workspaceSymbolProvider": true
+# CHECK-NEXT:    }
+# CHECK-NEXT:  }
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+#      CHECK:  "id": 3,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": null
+---
+{"jsonrpc":"2.0":"method":"exit"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/input-mirror.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/input-mirror.test
new file mode 100644
index 0000000..88409c4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/input-mirror.test
@@ -0,0 +1,14 @@
+# RUN: clangd -pretty -run-synchronously -input-mirror-file %t < %s

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

+# RUN: diff -b %t %s

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

+#

+Content-Length: 125

+

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

+Content-Length: 172

+

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

+Content-Length: 44

+

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

diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/lit.local.cfg b/src/third_party/llvm-project/clang-tools-extra/test/clangd/lit.local.cfg
new file mode 100644
index 0000000..ef338c7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/lit.local.cfg
@@ -0,0 +1,6 @@
+import re
+# We rely on the default -std being derived from the filetype.
+# PS4 sets a different -std, and many tests break.
+# FIXME: make our tests less brittle instead.
+if re.match(r'.*-scei-ps4', config.target_triple):
+  config.unsupported = True
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/protocol.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/protocol.test
new file mode 100644
index 0000000..7295ca5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/protocol.test
@@ -0,0 +1,110 @@
+# RUN: not clangd -pretty -run-synchronously < %s | FileCheck -strict-whitespace %s

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

+# vim: fileformat=dos

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

+#

+# Note that we invert the test because we intent to let clangd exit prematurely.

+#

+# Test protocol parsing

+Content-Length: 125

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

+

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

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

+#

+#      CHECK:  "jsonrpc": "2.0",

+# CHECK-NEXT:  "result": {

+#      CHECK:  }

+Content-Length: 246

+

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

+

+Content-Length: 104

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///main.cpp"}}}

+

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

+Content-Length: 146

+

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

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

+#

+#      CHECK:  "id": 1,

+# CHECK-NEXT:  "jsonrpc": "2.0",

+# CHECK-NEXT:  "result": {

+# CHECK-NEXT:    "isIncomplete": false,

+# CHECK-NEXT:    "items": [

+#      CHECK:        "filterText": "a",

+# CHECK-NEXT:        "insertText": "a",

+# CHECK-NEXT:        "insertTextFormat": 1,

+# CHECK-NEXT:        "kind": 5,

+# CHECK-NEXT:        "label": " a",

+# CHECK-NEXT:        "sortText": "{{.*}}"

+#      CHECK:    ]

+# CHECK-NEXT:  }

+

+X-Test: Testing

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

+Content-Length: 146

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

+X-Testing: Test

+

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

+

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

+Content-Length: 10

+Content-Length: 146

+

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

+# Test message with duplicate Content-Length headers

+#

+#      CHECK:  "id": 3,

+# CHECK-NEXT:  "jsonrpc": "2.0",

+# CHECK-NEXT:  "result": {

+# CHECK-NEXT:    "isIncomplete": false,

+# CHECK-NEXT:    "items": [

+#      CHECK:        "filterText": "a",

+# CHECK-NEXT:        "insertText": "a",

+# CHECK-NEXT:        "insertTextFormat": 1,

+# CHECK-NEXT:        "kind": 5,

+# CHECK-NEXT:        "label": " a",

+# CHECK-NEXT:        "sortText": "{{.*}}"

+#      CHECK:    ]

+# CHECK-NEXT:  }

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

+

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

+Content-Length: 10

+

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

+# Test message with malformed Content-Length

+#

+# STDERR: JSON parse error

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

+

+Content-Length: 146

+

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

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

+#

+#      CHECK:  "id": 5,

+# CHECK-NEXT:  "jsonrpc": "2.0",

+# CHECK-NEXT:  "result": {

+# CHECK-NEXT:    "isIncomplete": false,

+# CHECK-NEXT:    "items": [

+#      CHECK:        "filterText": "a",

+# CHECK-NEXT:        "insertText": "a",

+# CHECK-NEXT:        "insertTextFormat": 1,

+# CHECK-NEXT:        "kind": 5,

+# CHECK-NEXT:        "label": " a",

+# CHECK-NEXT:        "sortText": "{{.*}}"

+#      CHECK:    ]

+# CHECK-NEXT:  }

+Content-Length: 1024

+

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

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

+#

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

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

+

diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/rename.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/rename.test
new file mode 100644
index 0000000..991cf21
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/rename.test
@@ -0,0 +1,39 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.cpp","languageId":"cpp","version":1,"text":"int foo;"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/rename","params":{"textDocument":{"uri":"test:///foo.cpp"},"position":{"line":0,"character":5},"newName":"bar"}}
+#      CHECK:  "id": 1,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "changes": {
+# CHECK-NEXT:      "file://{{.*}}/foo.cpp": [
+# CHECK-NEXT:        {
+# CHECK-NEXT:          "newText": "bar",
+# CHECK-NEXT:          "range": {
+# CHECK-NEXT:            "end": {
+# CHECK-NEXT:              "character": 7
+# CHECK-NEXT:              "line": 0
+# CHECK-NEXT:            },
+# CHECK-NEXT:            "start": {
+# CHECK-NEXT:              "character": 4
+# CHECK-NEXT:              "line": 0
+# CHECK-NEXT:            }
+# CHECK-NEXT:          }
+# CHECK-NEXT:        }
+# CHECK-NEXT:      ]
+# CHECK-NEXT:    }
+# CHECK-NEXT:  }
+---
+{"jsonrpc":"2.0","id":2,"method":"textDocument/rename","params":{"textDocument":{"uri":"test:///foo.cpp"},"position":{"line":0,"character":2},"newName":"bar"}}
+#      CHECK:  "error": {
+# CHECK-NEXT:    "code": -32603,
+# CHECK-NEXT:    "message": "clang diagnostic"
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "id": 2,
+# CHECK-NEXT:  "jsonrpc": "2.0"
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/shutdown-with-exit.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/shutdown-with-exit.test
new file mode 100644
index 0000000..b247529
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/shutdown-with-exit.test
@@ -0,0 +1,4 @@
+# RUN: clangd -lit-test < %s
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+---
+{"jsonrpc":"2.0":"method":"exit"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/shutdown-without-exit.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/shutdown-without-exit.test
new file mode 100644
index 0000000..a3e86e9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/shutdown-without-exit.test
@@ -0,0 +1,2 @@
+# RUN: not clangd -lit-test < %s
+{"jsonrpc":"2.0":"method":"exit"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/signature-help.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/signature-help.test
new file mode 100644
index 0000000..f13f49c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/signature-help.test
@@ -0,0 +1,25 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+# Start a session.
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"void x(int);\nint main(){\nx("}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/signatureHelp","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":2,"character":2}}}
+#      CHECK: "id": 1,
+# CHECK-NEXT: "jsonrpc": "2.0",
+# CHECK-NEXT: "result": {
+# CHECK-NEXT:   "activeParameter": 0,
+# CHECK-NEXT:   "activeSignature": 0,
+# CHECK-NEXT:   "signatures": [
+# CHECK-NEXT:     {
+# CHECK-NEXT:       "label": "x(int) -> void",
+# CHECK-NEXT:       "parameters": [
+# CHECK-NEXT:         {
+# CHECK-NEXT:           "label": "int"
+# CHECK-NEXT:         }
+# CHECK-NEXT:       ]
+# CHECK-NEXT:     }
+# CHECK-NEXT:   ]
+# CHECK-NEXT: }
+---
+{"jsonrpc":"2.0","id":100000,"method":"shutdown"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/spaces-in-delimited-input.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/spaces-in-delimited-input.test
new file mode 100644
index 0000000..63e3e0b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/spaces-in-delimited-input.test
@@ -0,0 +1,13 @@
+# RUN: clangd -input-style=delimited -run-synchronously < %s 2>&1 | FileCheck %s

+# RUN: clangd -lit-test -run-synchronously < %s 2>&1 | FileCheck %s

+#

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

+

+---

+

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

+

+---

+

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

+# CHECK-NOT: JSON parse error

diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/symbols.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/symbols.test
new file mode 100644
index 0000000..5b07f8f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/symbols.test
@@ -0,0 +1,84 @@
+# RUN: env CPATH=%S/Inputs clangd -lit-test < %s | FileCheck %s

+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"workspace":{"symbol":{"symbolKind":{"valueSet": [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}}}},"trace":"off"}}

+---

+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"#include <sstream.h>\nvoid foo(); int main() { foo(); }\n"}}}

+---

+{"jsonrpc":"2.0","id":1,"method":"workspace/symbol","params":{"query":"std::basic_ostringstream"}}

+#      CHECK:  "id": 1,

+# CHECK-NEXT:  "jsonrpc": "2.0",

+# CHECK-NEXT:    "result": [

+# CHECK-NEXT:      {

+# CHECK-NEXT:        "containerName": "std",

+# CHECK-NEXT:        "kind": 5,

+# CHECK-NEXT:        "location": {

+# CHECK-NEXT:          "range": {

+# CHECK-NEXT:            "end": {

+# CHECK-NEXT:              "character": {{.*}},

+# CHECK-NEXT:              "line": {{.*}}

+# CHECK-NEXT:            },

+# CHECK-NEXT:            "start": {

+# CHECK-NEXT:              "character": {{.*}},

+# CHECK-NEXT:              "line": {{.*}}

+# CHECK-NEXT:            }

+# CHECK-NEXT:          },

+# CHECK-NEXT:          "uri": "file://{{.*}}/sstream.h"

+# CHECK-NEXT:        },

+# CHECK-NEXT:        "name": "basic_ostringstream"

+# CHECK-NEXT:      }

+# CHECK-NEXT:    ]

+# CHECK-NEXT:}

+---

+{"jsonrpc":"2.0","id":2,"method":"textDocument/documentSymbol","params":{"textDocument":{"uri":"test:///main.cpp"}}}

+#      CHECK:  "id": 2,

+# CHECK-NEXT:  "jsonrpc": "2.0",

+# CHECK-NEXT:    "result": [

+# CHECK-NEXT:      {

+# CHECK-NEXT:        "containerName": "",

+# CHECK-NEXT:        "kind": 12,

+# CHECK-NEXT:        "location": {

+# CHECK-NEXT:          "range": {

+# CHECK-NEXT:            "end": {

+# CHECK-NEXT:              "character": {{.*}},

+# CHECK-NEXT:              "line": {{.*}}

+# CHECK-NEXT:            },

+# CHECK-NEXT:            "start": {

+# CHECK-NEXT:              "character": {{.*}},

+# CHECK-NEXT:              "line": {{.*}}

+# CHECK-NEXT:            }

+# CHECK-NEXT:          },

+# CHECK-NEXT:          "uri": "file://{{.*}}/main.cpp"

+# CHECK-NEXT:        },

+# CHECK-NEXT:        "name": "foo"

+# CHECK-NEXT:      }

+# CHECK-NEXT:      {

+# CHECK-NEXT:        "containerName": "",

+# CHECK-NEXT:        "kind": 12,

+# CHECK-NEXT:        "location": {

+# CHECK-NEXT:          "range": {

+# CHECK-NEXT:            "end": {

+# CHECK-NEXT:              "character": {{.*}},

+# CHECK-NEXT:              "line": {{.*}}

+# CHECK-NEXT:            },

+# CHECK-NEXT:            "start": {

+# CHECK-NEXT:              "character": {{.*}},

+# CHECK-NEXT:              "line": {{.*}}

+# CHECK-NEXT:            }

+# CHECK-NEXT:          },

+# CHECK-NEXT:          "uri": "file://{{.*}}/main.cpp"

+# CHECK-NEXT:        },

+# CHECK-NEXT:        "name": "main"

+# CHECK-NEXT:      }

+# CHECK-NEXT:    ]

+# CHECK-NEXT:}

+---

+{"jsonrpc":"2.0","id":3,"method":"textDocument/documentSymbol","params":{"textDocument":{"uri":"test:///foo.cpp"}}}

+#      CHECK:  "error": {

+# CHECK-NEXT:    "code": -32602,

+# CHECK-NEXT:    "message": "trying to get AST for non-added document"

+# CHECK-NEXT:  },

+# CHECK-NEXT:  "id": 3,

+# CHECK-NEXT:  "jsonrpc": "2.0"

+---

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

+---

+{"jsonrpc":"2.0","method":"exit"}

diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/test-uri-posix.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/test-uri-posix.test
new file mode 100644
index 0000000..15cc09f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/test-uri-posix.test
@@ -0,0 +1,11 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+# UNSUPPORTED: mingw32,win32
+# Test authority-less URI
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","version":1,"text":"void main() {}"}}}
+# CHECK:    "uri": "file:///clangd-test/foo.c"
+---
+{"jsonrpc":"2.0","id":5,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/test-uri-windows.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/test-uri-windows.test
new file mode 100644
index 0000000..7ec290e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/test-uri-windows.test
@@ -0,0 +1,11 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+# REQUIRES: mingw32 || win32
+# Test authority-less URI
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","version":1,"text":"void main() {}"}}}
+# CHECK:    "uri": "file:///C:/clangd-test/foo.c"
+---
+{"jsonrpc":"2.0","id":5,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/textdocument-didchange-fail.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/textdocument-didchange-fail.test
new file mode 100644
index 0000000..3bd01e9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/textdocument-didchange-fail.test
@@ -0,0 +1,37 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+# RUN: clangd -lit-test -pch-storage=memory < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"int main() {}\n"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":0,"character":6}}}
+#      CHECK:  "id": 1,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "range": {
+# CHECK-NEXT:        "end": {
+# CHECK-NEXT:          "character": 8,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "start": {
+# CHECK-NEXT:          "character": 4,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        }
+# CHECK-NEXT:      },
+# CHECK-NEXT:      "uri": "file://{{.*}}/clangd-test/main.cpp"
+# CHECK-NEXT:    }
+# CHECK-NEXT:  ]
+---
+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///main.cpp"},"contentChanges":[{"range":{"start":{"line":100,"character":0},"end":{"line":100,"character":0}},"text": "foo"}]}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":0,"character":6}}}
+#      CHECK:  "error": {
+# CHECK-NEXT:    "code": -32602,
+# CHECK-NEXT:    "message": "trying to get AST for non-added document"
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "id": 1,
+# CHECK-NEXT:  "jsonrpc": "2.0"
+# CHECK-NEXT:}
+---
+{"jsonrpc":"2.0","id":4,"method":"shutdown"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/too_large.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/too_large.test
new file mode 100644
index 0000000..7b846c3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/too_large.test
@@ -0,0 +1,7 @@
+# RUN: not clangd -run-synchronously < %s 2>&1 | FileCheck -check-prefix=STDERR %s

+# vim: fileformat=dos

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

+#

+Content-Length: 2147483648

+

+# STDERR: Refusing to read message

diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/trace.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/trace.test
new file mode 100644
index 0000000..9036128
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/trace.test
@@ -0,0 +1,23 @@
+# RUN: env CLANGD_TRACE=%t clangd -lit-test < %s && FileCheck %s < %t
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","version":1,"text":"void main() {}"}}}
+# These assertions are a bit loose, to avoid brittleness.
+# CHECK: {"displayTimeUnit":"ns","traceEvents":[
+# CHECK: {
+# CHECK:   "args": {
+# CHECK:     "File": "{{.*(/|\\)}}foo.c"
+# CHECK:   },
+# CHECK:   "name": "BuildPreamble",
+# CHECK:   "ph": "X",
+# CHECK: }
+# CHECK: {
+# CHECK:   "args": {
+# CHECK:     "File": "{{.*(/|\\)}}foo.c"
+# CHECK:   },
+# CHECK:   "name": "BuildAST",
+# CHECK:   "ph": "X",
+# CHECK: }
+# CHECK: },
+---
+{"jsonrpc":"2.0","id":5,"method":"shutdown"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/unsupported-method.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/unsupported-method.test
new file mode 100644
index 0000000..7737b4f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/unsupported-method.test
@@ -0,0 +1,16 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":""}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/jumpInTheAirLikeYouJustDontCare","params":{}}
+#      CHECK:  "error": {
+# CHECK-NEXT:    "code": -32601,
+# CHECK-NEXT:    "message": "method not found"
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "id": 1,
+# CHECK-NEXT:  "jsonrpc": "2.0"
+---
+{"jsonrpc":"2.0","id":2,"method":"shutdown"}
+---
+{"jsonrpc":"2.0":"method":"exit"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/clangd/xrefs.test b/src/third_party/llvm-project/clang-tools-extra/test/clangd/xrefs.test
new file mode 100644
index 0000000..f2e17c4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/clangd/xrefs.test
@@ -0,0 +1,57 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"int x = 0;\nint y = x;"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":1,"character":8}}}
+#      CHECK:  "id": 1,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:    {
+# CHECK-NEXT:      "range": {
+# CHECK-NEXT:        "end": {
+# CHECK-NEXT:          "character": 5,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "start": {
+# CHECK-NEXT:          "character": 4,
+# CHECK-NEXT:          "line": 0
+# CHECK-NEXT:        }
+# CHECK-NEXT:      },
+# CHECK-NEXT:      "uri": "file://{{.*}}/{{([A-Z]:/)?}}main.cpp"
+# CHECK-NEXT:    }
+# CHECK-NEXT:  ]
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":1,"character":8}}}
+#      CHECK: "id": 1
+# CHECK-NEXT: "jsonrpc": "2.0",
+# CHECK-NEXT: "result": [
+# CHECK-NEXT:   {
+# CHECK-NEXT:     "kind": 1,
+# CHECK-NEXT:     "range": {
+# CHECK-NEXT:       "end": {
+# CHECK-NEXT:         "character": 5,
+# CHECK-NEXT:         "line": 0
+# CHECK-NEXT:       },
+# CHECK-NEXT:       "start": {
+# CHECK-NEXT:         "character": 4,
+# CHECK-NEXT:         "line": 0
+# CHECK-NEXT:       }
+# CHECK-NEXT:     }
+# CHECK-NEXT:   },
+# CHECK-NEXT:   {
+# CHECK-NEXT:     "kind": 2,
+# CHECK-NEXT:     "range": {
+# CHECK-NEXT:       "end": {
+# CHECK-NEXT:         "character": 9,
+# CHECK-NEXT:         "line": 1
+# CHECK-NEXT:       },
+# CHECK-NEXT:       "start": {
+# CHECK-NEXT:         "character": 8,
+# CHECK-NEXT:         "line": 1
+# CHECK-NEXT:       }
+# CHECK-NEXT:     }
+# CHECK-NEXT:   }
+# CHECK-NEXT: ]
+---
+{"jsonrpc":"2.0","id":10000,"method":"shutdown"}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/Inputs/database_template.json b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/Inputs/database_template.json
new file mode 100644
index 0000000..ec71c56
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/Inputs/database_template.json
@@ -0,0 +1,7 @@
+[
+{
+  "directory": "test_dir/build",
+  "command": "clang++ -I../include -o bar.o test_dir/src/bar.cpp",
+  "file": "test_dir/src/bar.cpp"
+}
+]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/Inputs/fake_yaml_db.yaml b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/Inputs/fake_yaml_db.yaml
new file mode 100644
index 0000000..b599005
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/Inputs/fake_yaml_db.yaml
@@ -0,0 +1,71 @@
+---
+Name:           foo
+Contexts:
+  - ContextType:     Namespace
+    ContextName:     a
+  - ContextType:     Namespace
+    ContextName:     b
+FilePath:        foo.h
+Type:            Class
+Seen:            1
+Used:            0
+---
+Name:           foo_bar
+Contexts:
+  - ContextType:     Namespace
+    ContextName:     a
+  - ContextType:     Namespace
+    ContextName:     b
+FilePath:        foobar.h
+Type:            Class
+Seen:            0
+Used:            0
+---
+Name:           bar
+Contexts:
+  - ContextType:     Namespace
+    ContextName:     a
+  - ContextType:     Namespace
+    ContextName:     b
+FilePath:        ../include/bar.h
+Type:            Class
+Seen:            1
+Used:            0
+---
+Name:           bar
+Contexts:
+  - ContextType:     Namespace
+    ContextName:     a
+  - ContextType:     Namespace
+    ContextName:     b
+FilePath:        ../include/bar.h
+Type:            Class
+Seen:            3
+Used:            0
+---
+Name:           bar
+Contexts:
+  - ContextType:     Namespace
+    ContextName:     a
+  - ContextType:     Namespace
+    ContextName:     b
+FilePath:        ../include/zbar.h
+Type:            Class
+Seen:            3
+Used:            0
+---
+Name:           b
+Contexts:
+FilePath:        var.h
+Type:            Variable
+Seen:            1
+Used:            0
+---
+Name:            bar
+Contexts:
+  - ContextType:    Namespace
+    ContextName:    c
+FilePath:        test/include-fixer/baz.h
+Type:            Class
+Seen:            1
+Used:            0
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/Inputs/merge/a.yaml b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/Inputs/merge/a.yaml
new file mode 100644
index 0000000..174db0e5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/Inputs/merge/a.yaml
@@ -0,0 +1,20 @@
+---
+Name:           foo
+Contexts:
+  - ContextType:     Namespace
+    ContextName:     a
+FilePath:        foo.h
+Type:            Class
+Seen:            1
+Used:            1
+...
+---
+Name:           bar
+Contexts:
+  - ContextType:     Namespace
+    ContextName:     a
+FilePath:        ../include/bar.h
+Type:            Class
+Seen:            1
+Used:            2
+...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/Inputs/merge/b.yaml b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/Inputs/merge/b.yaml
new file mode 100644
index 0000000..8689320
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/Inputs/merge/b.yaml
@@ -0,0 +1,20 @@
+---
+Name:           foo
+Contexts:
+  - ContextType:     Namespace
+    ContextName:     a
+FilePath:        foo.h
+Type:            Class
+Seen:            1
+Used:            2
+...
+---
+Name:           bar
+Contexts:
+  - ContextType:     Namespace
+    ContextName:     a
+FilePath:        ../include/barbar.h
+Type:            Class
+Seen:            1
+Used:            0
+...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/commandline_options.cpp b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/commandline_options.cpp
new file mode 100644
index 0000000..3cc77b4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/commandline_options.cpp
@@ -0,0 +1,15 @@
+// RUN: echo "foo f;" > %t.cpp
+// RUN: clang-include-fixer -db=fixed -input='foo= "foo.h","bar.h"' -output-headers %t.cpp -- | FileCheck %s
+// RUN: cat %t.cpp | clang-include-fixer -stdin -insert-header='{FilePath: "%/t.cpp", QuerySymbolInfos: [{RawIdentifier: foo, Range: {Offset: 0, Length: 3}}], HeaderInfos: [{Header: "\"foo.h\"", QualifiedName: "foo"}]}' %t.cpp | FileCheck %s -check-prefix=CHECK-CODE
+// RUN: cat %t.cpp | not clang-include-fixer -stdin -insert-header='{FilePath: "%/t.cpp", QuerySymbolInfos: [{RawIdentifier: foo, Range: {Offset: 0, Length: 3}}], HeaderInfos: [{Header: "\"foo.h\"", QualifiedName: "foo"},{Header: "\"foo2.h\"", QualifiedName: "foo"}]}' %t.cpp
+// RUN: cat %t.cpp | clang-include-fixer -stdin -insert-header='{FilePath: "%/t.cpp", QuerySymbolInfos: [{RawIdentifier: foo, Range: {Offset: 0, Length: 3}}], HeaderInfos: [{Header: "\"foo.h\"", QualifiedName: "a:foo"},{Header: "\"foo.h\"", QualifiedName: "b:foo"}]}' %t.cpp
+//
+// CHECK:     "HeaderInfos": [
+// CHECK-NEXT:  {"Header": "\"foo.h\"",
+// CHECK-NEXT:   "QualifiedName": "foo"},
+// CHECK-NEXT:  {"Header": "\"bar.h\"",
+// CHECK-NEXT:   "QualifiedName": "foo"}
+// CHECK-NEXT:]
+//
+// CHECK-CODE: #include "foo.h"
+// CHECK-CODE: foo f;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/exit_on_fatal.cpp b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/exit_on_fatal.cpp
new file mode 100644
index 0000000..fc8c95a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/exit_on_fatal.cpp
@@ -0,0 +1,10 @@
+// RUN: sed -e 's#//.*$##' %s > %t.cpp
+// RUN: not clang-include-fixer -db=fixed -input='foo= "foo.h"' %t.cpp --
+// RUN: FileCheck %s -input-file=%t.cpp
+
+// CHECK-NOT: #include
+// CHECK: #include "doesnotexist.h"
+// CHECK-NEXT: foo f;
+
+#include "doesnotexist.h"
+foo f;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/fixeddb.cpp b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/fixeddb.cpp
new file mode 100644
index 0000000..90068db
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/fixeddb.cpp
@@ -0,0 +1,8 @@
+// RUN: sed -e 's#//.*$##' %s > %t.cpp
+// RUN: clang-include-fixer -db=fixed -input='foo= "foo.h","bar.h"' %t.cpp --
+// RUN: FileCheck %s -input-file=%t.cpp
+
+// CHECK: #include "foo.h"
+// CHECK: foo f;
+
+foo f;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/include_path.cpp b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/include_path.cpp
new file mode 100644
index 0000000..28b6ace
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/include_path.cpp
@@ -0,0 +1,19 @@
+// RUN: mkdir -p %T/include-fixer/include
+// RUN: mkdir -p %T/include-fixer/symbols
+// RUN: mkdir -p %T/include-fixer/build
+// RUN: mkdir -p %T/include-fixer/src
+// RUN: sed 's|test_dir|%/T/include-fixer|g' %S/Inputs/database_template.json > %T/include-fixer/build/compile_commands.json
+// RUN: echo -e '#include "bar.h"\nb::a::bar f;' > %T/include-fixer/src/bar.cpp
+// RUN: echo 'namespace b { namespace a { class bar {}; } }' > %T/include-fixer/include/bar.h
+// RUN: cd %T/include-fixer/build
+// RUN: find-all-symbols -output-dir=%T/include-fixer/symbols -p=. %T/include-fixer/src/bar.cpp
+// RUN: find-all-symbols -merge-dir=%T/include-fixer/symbols %T/include-fixer/build/find_all_symbols.yaml
+// RUN: FileCheck -input-file=%T/include-fixer/build/find_all_symbols.yaml -check-prefix=CHECK-YAML %s
+//
+// RUN: echo 'b::a::bar f;' > %T/include-fixer/src/bar.cpp
+// RUN: clang-include-fixer -db=yaml -input=%T/include-fixer/build/find_all_symbols.yaml -minimize-paths=true -p=. %T/include-fixer/src/bar.cpp
+// RUN: FileCheck -input-file=%T/include-fixer/src/bar.cpp %s
+
+// CHECK-YAML: ..{{[/\\]}}include{{[/\\]}}bar.h
+// CHECK: #include "bar.h"
+// CHECK: b::a::bar f;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/merge.test b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/merge.test
new file mode 100644
index 0000000..cee751b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/merge.test
@@ -0,0 +1,33 @@
+# RUN: find-all-symbols -merge-dir=%S/Inputs/merge %t.merged
+# RUN: sed '/^#/d' %s > %t.golden
+# RUN: diff -u %t.golden %t.merged
+---
+Name:            bar
+Contexts:        
+  - ContextType:     Namespace
+    ContextName:     a
+FilePath:        ../include/bar.h
+Type:            Class
+Seen:            1
+Used:            1
+...
+---
+Name:            bar
+Contexts:        
+  - ContextType:     Namespace
+    ContextName:     a
+FilePath:        ../include/barbar.h
+Type:            Class
+Seen:            1
+Used:            0
+...
+---
+Name:            foo
+Contexts:        
+  - ContextType:     Namespace
+    ContextName:     a
+FilePath:        foo.h
+Type:            Class
+Seen:            2
+Used:            2
+...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/multiple_fixes.cpp b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/multiple_fixes.cpp
new file mode 100644
index 0000000..35a73b4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/multiple_fixes.cpp
@@ -0,0 +1,13 @@
+// REQUIRES: shell
+// RUN: sed -e 's#//.*$##' %s > %t.cpp
+// RUN: mkdir -p %T/include-fixer/multiple-fixes
+// RUN: echo 'foo f;' > %T/include-fixer/multiple-fixes/foo.cpp
+// RUN: echo 'bar b;' > %T/include-fixer/multiple-fixes/bar.cpp
+// RUN: clang-include-fixer -db=fixed -input='foo= "foo.h";bar= "bar.h"' %T/include-fixer/multiple-fixes/*.cpp --
+// RUN: FileCheck -input-file=%T/include-fixer/multiple-fixes/bar.cpp %s -check-prefix=CHECK-BAR
+// RUN: FileCheck -input-file=%T/include-fixer/multiple-fixes/foo.cpp %s -check-prefix=CHECK-FOO
+//
+// CHECK-FOO: #include "foo.h"
+// CHECK-FOO: foo f;
+// CHECK-BAR: #include "bar.h"
+// CHECK-BAR: bar b;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/prefix_variable.cpp b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/prefix_variable.cpp
new file mode 100644
index 0000000..b39cdb8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/prefix_variable.cpp
@@ -0,0 +1,10 @@
+// RUN: sed -e 's#//.*$##' %s > %t.cpp
+// RUN: clang-include-fixer -db=yaml -input=%p/Inputs/fake_yaml_db.yaml %t.cpp --
+// RUN: FileCheck %s -input-file=%t.cpp
+
+// CHECK-NOT: #include
+// CHECK: doesnotexist f;
+
+namespace b {
+doesnotexist f;
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/query_symbol.cpp b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/query_symbol.cpp
new file mode 100644
index 0000000..84c3a23
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/query_symbol.cpp
@@ -0,0 +1,13 @@
+// RUN: clang-include-fixer -db=fixed -input='foo= "foo.h","bar.h"' -query-symbol="foo" test.cpp -- | FileCheck %s
+
+// CHECK:     "FilePath": "test.cpp",
+// CHECK-NEXT:"QuerySymbolInfos": [
+// CHECK-NEXT:   {"RawIdentifier": "foo",
+// CHECK-NEXT:    "Range":{"Offset":0,"Length":0}}
+// CHECK-NEXT:],
+// CHECK-NEXT:"HeaderInfos": [
+// CHECK-NEXT:  {"Header": "\"foo.h\"",
+// CHECK-NEXT:   "QualifiedName": "foo"},
+// CHECK-NEXT:  {"Header": "\"bar.h\"",
+// CHECK-NEXT:   "QualifiedName": "foo"}
+// CHECK-NEXT:]
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/ranking.cpp b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/ranking.cpp
new file mode 100644
index 0000000..2dabe16
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/ranking.cpp
@@ -0,0 +1,13 @@
+// RUN: clang-include-fixer -db=yaml -input=%S/Inputs/fake_yaml_db.yaml -output-headers %s -- | FileCheck %s
+// RUN: clang-include-fixer -query-symbol bar -db=yaml -input=%S/Inputs/fake_yaml_db.yaml -output-headers %s -- | FileCheck %s
+
+// CHECK:     "HeaderInfos": [
+// CHECK-NEXT:  {"Header": "\"test/include-fixer/baz.h\"",
+// CHECK-NEXT:   "QualifiedName": "c::bar"},
+// CHECK-NEXT:  {"Header": "\"../include/bar.h\"",
+// CHECK-NEXT:   "QualifiedName": "b::a::bar"},
+// CHECK-NEXT:  {"Header": "\"../include/zbar.h\"",
+// CHECK-NEXT:   "QualifiedName": "b::a::bar"}
+// CHECK-NEXT:]
+
+bar b;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/yaml_fuzzy.cpp b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/yaml_fuzzy.cpp
new file mode 100644
index 0000000..705542d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/yaml_fuzzy.cpp
@@ -0,0 +1,9 @@
+// RUN: sed -e 's#//.*$##' %s > %t.cpp
+// RUN: clang-include-fixer -db=fuzzyYaml -input=%p/Inputs/fake_yaml_db.yaml %t.cpp --
+// RUN: FileCheck %s -input-file=%t.cpp
+
+// include-fixer will add the include, but doesn't complete the symbol.
+// CHECK: #include "foobar.h"
+// CHECK: fba f;
+
+b::a::fba f;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/yamldb.cpp b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/yamldb.cpp
new file mode 100644
index 0000000..d17b414
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/yamldb.cpp
@@ -0,0 +1,8 @@
+// RUN: sed -e 's#//.*$##' %s > %t.cpp
+// RUN: clang-include-fixer -db=yaml -input=%p/Inputs/fake_yaml_db.yaml %t.cpp --
+// RUN: FileCheck %s -input-file=%t.cpp
+
+// CHECK: #include "foo.h"
+// CHECK: b::a::foo f;
+
+b::a::foo f;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/yamldb_autodetect.cpp b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/yamldb_autodetect.cpp
new file mode 100644
index 0000000..1997390
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/yamldb_autodetect.cpp
@@ -0,0 +1,11 @@
+// RUN: mkdir -p %T/foo/bar
+// RUN: cp %p/Inputs/fake_yaml_db.yaml %T/find_all_symbols_db.yaml
+// RUN: cd %T/foo
+// RUN: sed -e 's#//.*$##' %s > bar/test.cpp
+// RUN: clang-include-fixer -db=yaml bar/test.cpp --
+// RUN: FileCheck %s -input-file=bar/test.cpp
+
+// CHECK: #include "foo.h"
+// CHECK: b::a::foo f;
+
+b::a::foo f;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/yamldb_plugin.cpp b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/yamldb_plugin.cpp
new file mode 100644
index 0000000..5b6760a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/include-fixer/yamldb_plugin.cpp
@@ -0,0 +1,25 @@
+// REQUIRES: static-analyzer
+// RUN: c-index-test -test-load-source-reparse 2 all %s -Xclang -add-plugin -Xclang clang-include-fixer -fspell-checking -Xclang -plugin-arg-clang-include-fixer -Xclang -input=%p/Inputs/fake_yaml_db.yaml 2>&1 | FileCheck %s
+
+foo f;
+foo g;
+unknown u;
+
+// CHECK: yamldb_plugin.cpp:4:1: error: unknown type name 'foo'; did you mean 'foo'?
+// CHECK: Number FIX-ITs = 1
+// CHECK: FIX-IT: Replace [4:1 - 4:4] with "foo"
+// CHECK: yamldb_plugin.cpp:4:1: note: Add '#include "foo.h"' to provide the missing declaration [clang-include-fixer]
+// CHECK: Number FIX-ITs = 1
+// CHECK: FIX-IT: Insert "#include "foo.h"
+// CHECK: yamldb_plugin.cpp:5:1: error: unknown type name 'foo'; did you mean 'foo'?
+// CHECK: Number FIX-ITs = 1
+// CHECK: FIX-IT: Replace [5:1 - 5:4] with "foo"
+// CHECK: yamldb_plugin.cpp:5:1: note: Add '#include "foo.h"' to provide the missing declaration [clang-include-fixer]
+// CHECK: Number FIX-ITs = 1
+// CHECK: FIX-IT: Insert "#include "foo.h"
+// CHECK: " at 4:1
+// CHECK: yamldb_plugin.cpp:6:1:
+// CHECK: error: unknown type name 'unknown'
+// CHECK: Number FIX-ITs = 0
+// CHECK-NOT: error
+// CHECK-NOT: FIX-IT
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/lit.cfg b/src/third_party/llvm-project/clang-tools-extra/test/lit.cfg
new file mode 100644
index 0000000..4b4718a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/lit.cfg
@@ -0,0 +1,139 @@
+# -*- Python -*-
+
+import os
+import platform
+import re
+import subprocess
+
+import lit.formats
+import lit.util
+
+# Configuration file for the 'lit' test runner.
+
+# name: The name of this test suite.
+config.name = 'Clang Tools'
+
+# Tweak PATH for Win32
+if platform.system() == 'Windows':
+    # Seek sane tools in directories and set to $PATH.
+    path = getattr(config, 'lit_tools_dir', None)
+    path = lit_config.getToolsPath(path,
+                                   config.environment['PATH'],
+                                   ['cmp.exe', 'grep.exe', 'sed.exe'])
+    if path is not None:
+        path = os.path.pathsep.join((path,
+                                     config.environment['PATH']))
+        config.environment['PATH'] = path
+
+# Choose between lit's internal shell pipeline runner and a real shell.  If
+# LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override.
+use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL")
+if use_lit_shell:
+    # 0 is external, "" is default, and everything else is internal.
+    execute_external = (use_lit_shell == "0")
+else:
+    # Otherwise we default to internal on Windows and external elsewhere, as
+    # bash on Windows is usually very slow.
+    execute_external = (not sys.platform in ['win32'])
+
+# testFormat: The test format to use to interpret tests.
+#
+# For now we require '&&' between commands, until they get globally killed and
+# the test runner updated.
+config.test_format = lit.formats.ShTest(execute_external)
+
+# suffixes: A list of file extensions to treat as test files.
+config.suffixes = ['.c', '.cpp', '.hpp', '.m', '.mm', '.cu', '.ll', '.cl', '.s',
+  '.modularize', '.module-map-checker', '.test']
+
+# Test-time dependencies located in directories called 'Inputs' are excluded
+# from test suites; there won't be any lit tests within them.
+config.excludes = ['Inputs']
+
+# test_source_root: The root path where tests are located.
+config.test_source_root = os.path.dirname(__file__)
+
+# test_exec_root: The root path where tests should be run.
+config.test_exec_root = os.path.join(config.clang_tools_binary_dir, 'test')
+
+# Clear some environment variables that might affect Clang.
+#
+# This first set of vars are read by Clang, but shouldn't affect tests
+# that aren't specifically looking for these features, or are required
+# simply to run the tests at all.
+#
+# FIXME: Should we have a tool that enforces this?
+
+# safe_env_vars = ('TMPDIR', 'TEMP', 'TMP', 'USERPROFILE', 'PWD',
+#                  'MACOSX_DEPLOYMENT_TARGET', 'IPHONEOS_DEPLOYMENT_TARGET',
+#                  'IOS_SIMULATOR_DEPLOYMENT_TARGET',
+#                  'VCINSTALLDIR', 'VC100COMNTOOLS', 'VC90COMNTOOLS',
+#                  'VC80COMNTOOLS')
+possibly_dangerous_env_vars = ['COMPILER_PATH', 'RC_DEBUG_OPTIONS',
+                               'CINDEXTEST_PREAMBLE_FILE', 'LIBRARY_PATH',
+                               'CPATH', 'C_INCLUDE_PATH', 'CPLUS_INCLUDE_PATH',
+                               'OBJC_INCLUDE_PATH', 'OBJCPLUS_INCLUDE_PATH',
+                               'LIBCLANG_TIMING', 'LIBCLANG_OBJTRACKING',
+                               'LIBCLANG_LOGGING', 'LIBCLANG_BGPRIO_INDEX',
+                               'LIBCLANG_BGPRIO_EDIT', 'LIBCLANG_NOTHREADS',
+                               'LIBCLANG_RESOURCE_USAGE',
+                               'LIBCLANG_CODE_COMPLETION_LOGGING']
+# Clang/Win32 may refer to %INCLUDE%. vsvarsall.bat sets it.
+if platform.system() != 'Windows':
+    possibly_dangerous_env_vars.append('INCLUDE')
+for name in possibly_dangerous_env_vars:
+  if name in config.environment:
+    del config.environment[name]
+
+# Tweak the PATH to include the tools dir and the scripts dir.
+path = os.path.pathsep.join((
+        config.clang_tools_dir, config.llvm_tools_dir, config.environment['PATH']))
+config.environment['PATH'] = path
+
+path = os.path.pathsep.join((config.clang_libs_dir, config.llvm_libs_dir,
+                              config.environment.get('LD_LIBRARY_PATH','')))
+config.environment['LD_LIBRARY_PATH'] = path
+
+# When running under valgrind, we mangle '-vg' onto the end of the triple so we
+# can check it with XFAIL and XTARGET.
+if lit_config.useValgrind:
+    config.target_triple += '-vg'
+
+# Set available features we allow tests to conditionalize on.
+#
+# As of 2011.08, crash-recovery tests still do not pass on FreeBSD.
+if platform.system() not in ['FreeBSD']:
+    config.available_features.add('crash-recovery')
+
+# Shell execution
+if execute_external:
+    config.available_features.add('shell')
+
+# Exclude MSYS due to transforming '/' to 'X:/mingwroot/'.
+if not platform.system() in ['Windows'] or not execute_external:
+    config.available_features.add('shell-preserves-root')
+
+# ANSI escape sequences in non-dumb terminal
+if platform.system() not in ['Windows']:
+    config.available_features.add('ansi-escape-sequences')
+
+if config.clang_staticanalyzer:
+    config.available_features.add('static-analyzer')
+    check_clang_tidy = os.path.join(
+        config.test_source_root, "clang-tidy", "check_clang_tidy.py")
+    config.substitutions.append(
+        ('%check_clang_tidy',
+         '%s %s' % (config.python_executable, check_clang_tidy)) )
+    clang_tidy_diff = os.path.join(
+        config.test_source_root, "..", "clang-tidy", "tool", "clang-tidy-diff.py")
+    config.substitutions.append(
+        ('%clang_tidy_diff',
+         '%s %s' % (config.python_executable, clang_tidy_diff)) )
+    run_clang_tidy = os.path.join(
+        config.test_source_root, "..", "clang-tidy", "tool", "run-clang-tidy.py")
+    config.substitutions.append(
+        ('%run_clang_tidy',
+         '%s %s' % (config.python_executable, run_clang_tidy)) )
+else:
+    # exclude the clang-tidy test directory
+    config.excludes.append('clang-tidy')
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/lit.site.cfg.in b/src/third_party/llvm-project/clang-tools-extra/test/lit.site.cfg.in
new file mode 100644
index 0000000..948e469
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/lit.site.cfg.in
@@ -0,0 +1,29 @@
+@LIT_SITE_CFG_IN_HEADER@
+
+import sys
+
+config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
+config.llvm_libs_dir = "@LLVM_LIBS_DIR@"
+config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
+config.clang_tools_binary_dir = "@CLANG_TOOLS_BINARY_DIR@"
+config.clang_tools_dir = "@CLANG_TOOLS_DIR@"
+config.clang_libs_dir = "@SHLIBDIR@"
+config.python_executable = "@PYTHON_EXECUTABLE@"
+config.target_triple = "@TARGET_TRIPLE@"
+config.clang_staticanalyzer = @CLANG_ENABLE_STATIC_ANALYZER@
+
+# Support substitution of the tools and libs dirs with user parameters. This is
+# used when we can't determine the tool dir at configuration time.
+try:
+    config.clang_tools_dir = config.clang_tools_dir % lit_config.params
+    config.llvm_tools_dir = config.llvm_tools_dir % lit_config.params
+    config.llvm_libs_dir = config.llvm_libs_dir % lit_config.params
+except KeyError:
+    e = sys.exc_info()[1]
+    key, = e.args
+    lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key))
+
+@LIT_SITE_CFG_IN_FOOTER@
+
+# Let the main config do the real work.
+lit_config.load_config(config, "@CLANG_TOOLS_SOURCE_DIR@/test/lit.cfg")
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/Anonymous.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/Anonymous.h
new file mode 100644
index 0000000..8388eca
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/Anonymous.h
@@ -0,0 +1,11 @@
+// Exercise some anonymous type issues.
+
+// Anonymous enum.
+enum {
+  Tag1
+};
+
+// Anonymous enum typedef.
+typedef enum {
+  Tag2
+} AnonymousEnum;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CompileError/HasError.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CompileError/HasError.h
new file mode 100644
index 0000000..4395cb1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CompileError/HasError.h
@@ -0,0 +1,2 @@
+typedef WithoutDep BadType;
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CompileError/Level1A.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CompileError/Level1A.h
new file mode 100644
index 0000000..10eef67
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CompileError/Level1A.h
@@ -0,0 +1 @@
+#define MACRO_1A 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CompileError/module.modulemap b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CompileError/module.modulemap
new file mode 100644
index 0000000..fbb8e7d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CompileError/module.modulemap
@@ -0,0 +1,10 @@
+// module.map

+

+module Level1A {

+  header "Level1A.h"

+  export *

+}

+module HasError {

+  header "HasError.h"

+  export *

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageNoProblems/Includes1/.hidden/DontFindMe.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageNoProblems/Includes1/.hidden/DontFindMe.h
new file mode 100644
index 0000000..f60b66c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageNoProblems/Includes1/.hidden/DontFindMe.h
@@ -0,0 +1,3 @@
+#error DontFindMe.h shouldn't be found.
+
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageNoProblems/Includes1/Level1A.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageNoProblems/Includes1/Level1A.h
new file mode 100644
index 0000000..10eef67
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageNoProblems/Includes1/Level1A.h
@@ -0,0 +1 @@
+#define MACRO_1A 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageNoProblems/Includes2/Level2A.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageNoProblems/Includes2/Level2A.h
new file mode 100644
index 0000000..9a355df
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageNoProblems/Includes2/Level2A.h
@@ -0,0 +1 @@
+#define MACRO_2A 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageNoProblems/NonIncludes/Level3A.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageNoProblems/NonIncludes/Level3A.h
new file mode 100644
index 0000000..594e284
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageNoProblems/NonIncludes/Level3A.h
@@ -0,0 +1 @@
+#define MACRO_3A 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageNoProblems/module.modulemap b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageNoProblems/module.modulemap
new file mode 100644
index 0000000..d2b0957
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageNoProblems/module.modulemap
@@ -0,0 +1,10 @@
+// module.map
+
+module Level1A {
+  header "Includes1/Level1A.h"
+  export *
+}
+module Level2A {
+  header "Includes2/Level2A.h"
+  export *
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level1A.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level1A.h
new file mode 100644
index 0000000..165efc7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level1A.h
@@ -0,0 +1,2 @@
+#include "Level2A.h"
+#define MACRO_1A 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level1B.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level1B.h
new file mode 100644
index 0000000..1e60798
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level1B.h
@@ -0,0 +1,2 @@
+#include "Level2B.h"
+#define MACRO_1B 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level2A.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level2A.h
new file mode 100644
index 0000000..9a355df
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level2A.h
@@ -0,0 +1 @@
+#define MACRO_2A 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level2B.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level2B.h
new file mode 100644
index 0000000..25b7017
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level2B.h
@@ -0,0 +1 @@
+#define MACRO_2B 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level3A.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level3A.h
new file mode 100644
index 0000000..1699061
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level3A.h
@@ -0,0 +1,2 @@
+#include "Sub/Level3B.h"
+#define MACRO_3A 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level3B b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level3B
new file mode 100644
index 0000000..e1eee7e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Level3B
@@ -0,0 +1 @@
+#define MACRO_3B 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Sub/Level3B.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Sub/Level3B.h
new file mode 100644
index 0000000..e1eee7e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/Sub/Level3B.h
@@ -0,0 +1 @@
+#define MACRO_3B 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/UmbrellaFile.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/UmbrellaFile.h
new file mode 100644
index 0000000..5417a42
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/UmbrellaFile.h
@@ -0,0 +1,3 @@
+#define UMBRELLA_HEADER 1
+#include "UmbrellaInclude1.h"
+#include "UmbrellaInclude2.h"
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/UmbrellaInclude1.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/UmbrellaInclude1.h
new file mode 100644
index 0000000..adf82cb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/UmbrellaInclude1.h
@@ -0,0 +1 @@
+#define UMBRELLA_INCLUDE_1 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/UmbrellaInclude2.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/UmbrellaInclude2.h
new file mode 100644
index 0000000..a3875ab
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/UmbrellaInclude2.h
@@ -0,0 +1 @@
+#define UMBRELLA_INCLUDE_2 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/UmbrellaSub/Umbrell1.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/UmbrellaSub/Umbrell1.h
new file mode 100644
index 0000000..719c223
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/UmbrellaSub/Umbrell1.h
@@ -0,0 +1 @@
+#define UMBRELLA_1 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/UmbrellaSub/Umbrell2.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/UmbrellaSub/Umbrell2.h
new file mode 100644
index 0000000..8efec99
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/UmbrellaSub/Umbrell2.h
@@ -0,0 +1 @@
+#define UMBRELLA_2 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/module.modulemap b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/module.modulemap
new file mode 100644
index 0000000..dbe0bb8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/CoverageProblems/module.modulemap
@@ -0,0 +1,30 @@
+// module.map
+
+module Level1A {
+  header "Level1A.h"
+  export *
+}
+module Level1B {
+  header "Level1B.h"
+  export *
+  module Level2B {
+    header "Level2B.h"
+    export *
+  }
+}
+module Level2A {
+  header "Level2A.h"
+  export *
+}
+module UmbrellaDirectoryModule {
+  umbrella "UmbrellaSub"
+}
+module UmbrellaHeaderModule {
+  umbrella header "UmbrellaFile.h"
+}
+/*
+module NoHeader {
+  header "NoHeader.h"
+  export *
+}
+*/
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/DuplicateHeader1.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/DuplicateHeader1.h
new file mode 100644
index 0000000..2936b08
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/DuplicateHeader1.h
@@ -0,0 +1,2 @@
+// Same decl as in DuplicateHeader2.h.
+typedef int TypeInt;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/DuplicateHeader2.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/DuplicateHeader2.h
new file mode 100644
index 0000000..cef0ffe
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/DuplicateHeader2.h
@@ -0,0 +1,2 @@
+// Same decl as in DuplicateHeader1.h.
+typedef int TypeInt;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/Empty.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/Empty.h
new file mode 100644
index 0000000..d74d27d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/Empty.h
@@ -0,0 +1 @@
+// Empty header for testing #include directives in blocks.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/HeaderGuard.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/HeaderGuard.h
new file mode 100644
index 0000000..64d7476
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/HeaderGuard.h
@@ -0,0 +1,6 @@
+#ifndef _HEADERGUARD_H_
+#define _HEADERGUARD_H_
+#include "HeaderGuardSub1.h"
+#include "HeaderGuardSub2.h"
+#include "HeaderGuardSubSub.h"
+#endif // _HEADERGUARD_H_
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/HeaderGuardSub1.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/HeaderGuardSub1.h
new file mode 100644
index 0000000..36ad80c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/HeaderGuardSub1.h
@@ -0,0 +1,5 @@
+#ifndef _HEADERGUARDSUB1_H_
+#define _HEADERGUARDSUB1_H_
+#include "HeaderGuardSubSub.h"
+#include "HeaderGuardSubSubDefined.h"
+#endif // _HEADERGUARDSUB1_H_
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/HeaderGuardSub2.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/HeaderGuardSub2.h
new file mode 100644
index 0000000..4098c8e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/HeaderGuardSub2.h
@@ -0,0 +1,5 @@
+#ifndef _HEADERGUARDSUB2_H_
+#define _HEADERGUARDSUB2_H_
+#include "HeaderGuardSubSub.h"
+#include "HeaderGuardSubSubDefined.h"
+#endif // _HEADERGUARDSUB2_H_
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/HeaderGuardSubSub.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/HeaderGuardSubSub.h
new file mode 100644
index 0000000..3f230d2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/HeaderGuardSubSub.h
@@ -0,0 +1,9 @@
+#ifndef _HEADERGUARDSUBSUB_H_
+#define _HEADERGUARDSUBSUB_H_
+
+#define SOMETHING 1
+
+// Nest include.  Header guard should not confuse modularize.
+#include "HeaderGuard.h"
+
+#endif // _HEADERGUARDSUBSUB_H_
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/HeaderGuardSubSubDefined.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/HeaderGuardSubSubDefined.h
new file mode 100644
index 0000000..5f0cc62
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/HeaderGuardSubSubDefined.h
@@ -0,0 +1,9 @@
+#if !defined(_HEADERGUARDSUBSUBDEFINED_H_)
+#define _HEADERGUARDSUBSUBDEFINED_H_
+
+#define SOMETHING_OTHER 1
+
+// Nest include.  Header guard should not confuse modularize.
+#include "HeaderGuard.h"
+
+#endif // _HEADERGUARDSUBSUBDEFINED_H_
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/IncludeInExtern.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/IncludeInExtern.h
new file mode 100644
index 0000000..da7de8f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/IncludeInExtern.h
@@ -0,0 +1,3 @@
+extern "C" {
+  #include "Empty.h"
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/IncludeInNamespace.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/IncludeInNamespace.h
new file mode 100644
index 0000000..2122528
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/IncludeInNamespace.h
@@ -0,0 +1,3 @@
+namespace MyNamespace {
+  #include "Empty.h"
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/InconsistentHeader1.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/InconsistentHeader1.h
new file mode 100644
index 0000000..7dfcca9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/InconsistentHeader1.h
@@ -0,0 +1,4 @@
+// Define symbol such that a declaration exists when this header
+// is included, but not when InconsistentHeader2.h is included.
+#define SYMBOL1 1
+#include "InconsistentSubHeader.h"
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/InconsistentHeader2.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/InconsistentHeader2.h
new file mode 100644
index 0000000..a2bcae1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/InconsistentHeader2.h
@@ -0,0 +1,3 @@
+// Set up so the declaration in InconsistentSubHeader.h is not defined.
+#define SYMBOL2 1
+#include "InconsistentSubHeader.h"
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/InconsistentSubHeader.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/InconsistentSubHeader.h
new file mode 100644
index 0000000..f87ea65
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/InconsistentSubHeader.h
@@ -0,0 +1,18 @@
+// Set up so TypeInt only defined during InconsistentHeader1.h include.
+#ifdef SYMBOL1
+#define SYMBOL 1
+#define FUNC_STYLE(a, b) a||b
+#endif
+#ifdef SYMBOL2
+#define SYMBOL 2
+#define FUNC_STYLE(a, b) a&&b
+#endif
+
+#if SYMBOL == 1
+typedef int TypeInt;
+#endif
+
+int var = FUNC_STYLE(1, 0);
+
+#if defined(SYMBOL1)
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/IsDependent.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/IsDependent.h
new file mode 100644
index 0000000..4928110
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/IsDependent.h
@@ -0,0 +1,4 @@
+// This header depends on SomeTypes.h for the TypeInt typedef.
+
+typedef TypeInt NewTypeInt;
+typedef OtherTypeInt OtherNewTypeInt;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/MissingHeader/Level1A.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/MissingHeader/Level1A.h
new file mode 100644
index 0000000..10eef67
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/MissingHeader/Level1A.h
@@ -0,0 +1 @@
+#define MACRO_1A 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/MissingHeader/module.modulemap b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/MissingHeader/module.modulemap
new file mode 100644
index 0000000..daa06fc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/MissingHeader/module.modulemap
@@ -0,0 +1,10 @@
+// module.map

+

+module Level1A {

+  header "Level1A.h"

+  export *

+}

+module Missing {

+  header "Missing.h"

+  export *

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/NamespaceClasses.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/NamespaceClasses.h
new file mode 100644
index 0000000..57e6091
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/NamespaceClasses.h
@@ -0,0 +1,20 @@
+// Define same class name in different namespaces.
+
+namespace Namespace1 {
+  class NamespaceClass {
+  public:
+    NamespaceClass() : Member(0) {}
+  private:
+    int Member;
+  };
+}
+
+namespace Namespace2 {
+  class NamespaceClass {
+  public:
+    NamespaceClass() : Member(0) {}
+  private:
+    int Member;
+  };
+}
+
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/NestedMacro.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/NestedMacro.h
new file mode 100644
index 0000000..2cfc92c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/NestedMacro.h
@@ -0,0 +1,5 @@
+// Verification of fix for nested macro.
+
+#define FUNCMACROINNER(a) a
+#define FUNCMACROOUTER(b, c) FUNCMACROINNER(b) + FUNCMACROINNER(c)
+int FuncMacroValue = FUNCMACROOUTER(1, 2);
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/NoProblems.modulemap b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/NoProblems.modulemap
new file mode 100644
index 0000000..82029c1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/NoProblems.modulemap
@@ -0,0 +1,9 @@
+// NoProblems.modulemap
+module SomeTypes {
+  header "SomeTypes.h"
+  export *
+}
+module SomeDecls {
+  header "SomeDecls.h"
+  export *
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/ProblemsDuplicate.modulemap b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/ProblemsDuplicate.modulemap
new file mode 100644
index 0000000..ff1d2f5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/ProblemsDuplicate.modulemap
@@ -0,0 +1,9 @@
+// ProblemsDuplicate.modulemap
+module DuplicateHeader1 {
+  header "DuplicateHeader1.h"
+  export *
+}
+module DuplicateHeader2 {
+  header "DuplicateHeader2.h"
+  export *
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SomeDecls.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SomeDecls.h
new file mode 100644
index 0000000..8892b65
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SomeDecls.h
@@ -0,0 +1,16 @@
+// Declare a couple of functions - no modules problems.
+
+void FuncOne();
+
+int FuncTwo(int arg);
+
+void FuncOverload(int arg) {}
+void FuncOverload(char *arg) {}
+
+namespace Namespace1 {
+  void FuncNameSpace() {}
+}
+
+namespace Namespace2 {
+  void FuncNameSpace() {}
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SomeOtherTypes.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SomeOtherTypes.h
new file mode 100644
index 0000000..288faff
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SomeOtherTypes.h
@@ -0,0 +1,4 @@
+// Declare another type for the dependency check.
+// This file dependent on SomeTypes.h being included first.
+
+typedef TypeInt OtherTypeInt;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SomeTypes.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SomeTypes.h
new file mode 100644
index 0000000..46c4316
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SomeTypes.h
@@ -0,0 +1,16 @@
+// Define a few different kinds of types - no modules problems.
+
+typedef int TypeInt;
+
+typedef TypeInt NestedTypeInt;
+
+struct TypeStruct {
+  int Member;
+};
+
+class TypeClass {
+public:
+  TypeClass() : Member(0) {}
+private:
+  int Member;
+};
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SubModule1/Header1.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SubModule1/Header1.h
new file mode 100644
index 0000000..ea89f0f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SubModule1/Header1.h
@@ -0,0 +1 @@
+// Header1.h - Empty.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SubModule1/Header2.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SubModule1/Header2.h
new file mode 100644
index 0000000..7c71e98
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SubModule1/Header2.h
@@ -0,0 +1 @@
+// Header2.h - Empty.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SubModule2/Header3.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SubModule2/Header3.h
new file mode 100644
index 0000000..bb56afa
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SubModule2/Header3.h
@@ -0,0 +1 @@
+// Header3.h - Empty.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SubModule2/Header4.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SubModule2/Header4.h
new file mode 100644
index 0000000..07ec951
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/SubModule2/Header4.h
@@ -0,0 +1 @@
+// Header4.h - Empty.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/TemplateClasses.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/TemplateClasses.h
new file mode 100644
index 0000000..3eab6d9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/Inputs/TemplateClasses.h
@@ -0,0 +1,15 @@
+// Exercise some template issues.  Should not produce errors.
+
+// Forward declaration.
+template<class T> class TemplateClass;
+
+// Full declaration.
+template<class T>class TemplateClass {
+public:
+  TemplateClass() {}
+private:
+  T Member;
+};
+
+// Template alias.
+template<class T> using TemplateClassAlias = TemplateClass<T>;
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblems.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblems.modularize
new file mode 100644
index 0000000..b3cc36b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblems.modularize
@@ -0,0 +1,6 @@
+# RUN: modularize %s -x c++
+# RUN: modularize -prefix=%p %s -x c++
+# RUN: modularize -no-coverage-check %S/Inputs/NoProblems.modulemap -x c++
+
+Inputs/SomeTypes.h
+Inputs/SomeDecls.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsAnonymous.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsAnonymous.modularize
new file mode 100644
index 0000000..20b1898
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsAnonymous.modularize
@@ -0,0 +1,3 @@
+# RUN: modularize %s -x c++
+
+Inputs/Anonymous.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsAssistant.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsAssistant.modularize
new file mode 100644
index 0000000..7ddc726
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsAssistant.modularize
@@ -0,0 +1,50 @@
+# RUN: modularize -module-map-path=Output/NoProblemsAssistant.txt -root-module=Root -prefix=%S/Input %s
+# RUN: FileCheck --input-file=%T/NoProblemsAssistant.txt %s
+
+SomeTypes.h
+SomeDecls.h
+SubModule1/Header1.h
+SubModule1/Header2.h
+SubModule2/Header3.h
+SubModule2/Header4.h
+SubModule2/Header5-dash.dot.h
+SubModule2.h
+
+# CHECK: // Output/NoProblemsAssistant.txt
+# CHECK-NEXT: // Generated by: modularize -module-map-path=Output/NoProblemsAssistant.txt -root-module=Root -prefix={{.*}}{{[/\\]}}{{.*}} {{.*}}{{[/\\]}}NoProblemsAssistant.modularize
+# CHECK: module Root {
+# CHECK-NEXT:   module SomeTypes {
+# CHECK-NEXT:     header "SomeTypes.h"
+# CHECK-NEXT:     export *
+# CHECK-NEXT:   }
+# CHECK-NEXT:   module SomeDecls {
+# CHECK-NEXT:     header "SomeDecls.h"
+# CHECK-NEXT:     export *
+# CHECK-NEXT:   }
+# CHECK-NEXT:   module SubModule1 {
+# CHECK-NEXT:     module Header1 {
+# CHECK-NEXT:       header "SubModule1/Header1.h"
+# CHECK-NEXT:       export *
+# CHECK-NEXT:     }
+# CHECK-NEXT:     module Header2 {
+# CHECK-NEXT:       header "SubModule1/Header2.h"
+# CHECK-NEXT:       export *
+# CHECK-NEXT:     }
+# CHECK-NEXT:   }
+# CHECK-NEXT:   module SubModule2 {
+# CHECK-NEXT:     module Header3 {
+# CHECK-NEXT:       header "SubModule2/Header3.h"
+# CHECK-NEXT:       export *
+# CHECK-NEXT:     }
+# CHECK-NEXT:     module Header4 {
+# CHECK-NEXT:       header "SubModule2/Header4.h"
+# CHECK-NEXT:       export *
+# CHECK-NEXT:     }
+# CHECK-NEXT:     module Header5_dash_dot {
+# CHECK-NEXT:       header "SubModule2/Header5-dash.dot.h"
+# CHECK-NEXT:       export *
+# CHECK-NEXT:     }
+# CHECK-NEXT:     header "SubModule2.h"
+# CHECK-NEXT:     export *
+# CHECK-NEXT:   }
+# CHECK-NEXT: }
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsCoverage.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsCoverage.modularize
new file mode 100644
index 0000000..bcb06f8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsCoverage.modularize
@@ -0,0 +1 @@
+# RUN: modularize -I Includes1 -I Includes2 %S/Inputs/CoverageNoProblems/module.modulemap
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsDependencies.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsDependencies.modularize
new file mode 100644
index 0000000..bd5292b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsDependencies.modularize
@@ -0,0 +1,3 @@
+# RUN: modularize %s -x c++
+
+Inputs/IsDependent.h: Inputs/SomeTypes.h Inputs/SomeOtherTypes.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsGuard.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsGuard.modularize
new file mode 100644
index 0000000..a5a80f0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsGuard.modularize
@@ -0,0 +1,5 @@
+# RUN: modularize %s -x c++
+
+Inputs/HeaderGuardSub1.h
+Inputs/HeaderGuardSub2.h
+Inputs/HeaderGuard.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsList.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsList.modularize
new file mode 100644
index 0000000..39261ce
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsList.modularize
@@ -0,0 +1,2 @@
+# RUN: modularize %S/NoProblems.modularize,%S/NoProblemsAnonymous.modularize -x c++
+# RUN: modularize -prefix=%p %S/NoProblems.modularize,%S/NoProblemsAnonymous.modularize -x c++
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsNamespace.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsNamespace.modularize
new file mode 100644
index 0000000..93a4fea
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsNamespace.modularize
@@ -0,0 +1,3 @@
+# RUN: modularize -block-check-header-list-only %s
+
+Inputs/IncludeInNamespace.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsNamespaceClasses.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsNamespaceClasses.modularize
new file mode 100644
index 0000000..1d02c78
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsNamespaceClasses.modularize
@@ -0,0 +1,3 @@
+# RUN: modularize %s -x c++
+
+Inputs/NamespaceClasses.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsNestedMacro.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsNestedMacro.modularize
new file mode 100644
index 0000000..a1c627d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsNestedMacro.modularize
@@ -0,0 +1,3 @@
+# RUN: modularize %s -x c++
+
+Inputs/NestedMacro.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsTemplateClasses.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsTemplateClasses.modularize
new file mode 100644
index 0000000..d41c43c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/NoProblemsTemplateClasses.modularize
@@ -0,0 +1,3 @@
+# RUN: modularize %s -x c++
+
+Inputs/TemplateClasses.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsCompileError.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsCompileError.modularize
new file mode 100644
index 0000000..a7ad298
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsCompileError.modularize
@@ -0,0 +1,3 @@
+# RUN: not modularize %S/Inputs/CompileError/module.modulemap 2>&1 | FileCheck %s
+
+# CHECK: {{.*}}{{[/\\]}}Inputs{{[/\\]}}CompileError{{[/\\]}}HasError.h:1:9: error: unknown type name 'WithoutDep'
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsCoverage.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsCoverage.modularize
new file mode 100644
index 0000000..5a1c348
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsCoverage.modularize
@@ -0,0 +1,5 @@
+# RUN: not modularize %S/Inputs/CoverageProblems/module.modulemap 2>&1 | FileCheck %s
+
+# CHECK: warning: {{.*}}{{[/\\]}}Inputs/CoverageProblems/module.modulemap does not account for file: {{.*}}{{[/\\]}}Inputs/CoverageProblems/Level3A.h
+# CHECK-NEXT: warning: {{.*}}{{[/\\]}}Inputs/CoverageProblems/module.modulemap does not account for file: {{.*}}{{[/\\]}}Inputs/CoverageProblems/Level3B
+# CHECK-NEXT: warning: {{.*}}{{[/\\]}}Inputs/CoverageProblems/module.modulemap does not account for file: {{.*}}{{[/\\]}}Inputs/CoverageProblems/Sub/Level3B.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsDisplayLists.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsDisplayLists.modularize
new file mode 100644
index 0000000..31be95c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsDisplayLists.modularize
@@ -0,0 +1,16 @@
+# RUN: not modularize -display-file-lists %S/Inputs/CompileError/module.modulemap 2>&1 | FileCheck %s
+
+# CHECK: {{.*}}{{[/\\]}}Inputs{{[/\\]}}CompileError{{[/\\]}}HasError.h:1:9: error: unknown type name 'WithoutDep'
+
+# CHECK: These are the files with possible errors:
+
+# CHECK: Inputs/CompileError/HasError.h
+
+# CHECK: These are the files with no detected errors:
+
+# CHECK: Inputs/CompileError/Level1A.h
+
+# CHECK: These are the combined files, with problem files preceded by #:
+
+# CHECK: {{.*}}Inputs/CompileError/HasError.h
+# CHECK: Inputs/CompileError/Level1A.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsDuplicate.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsDuplicate.modularize
new file mode 100644
index 0000000..301c9cc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsDuplicate.modularize
@@ -0,0 +1,9 @@
+# RUN: not modularize %s -x c++ 2>&1 | FileCheck %s
+# RUN: not modularize %S/Inputs/ProblemsDuplicate.modulemap -x c++ 2>&1 | FileCheck %s
+
+Inputs/DuplicateHeader1.h
+Inputs/DuplicateHeader2.h
+
+# CHECK: error: value 'TypeInt' defined at multiple locations:
+# CHECK-NEXT:    {{.*}}{{[/\\]}}Inputs{{[/\\]}}DuplicateHeader1.h:2:13
+# CHECK-NEXT:    {{.*}}{{[/\\]}}Inputs{{[/\\]}}DuplicateHeader2.h:2:13
\ No newline at end of file
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsExternC.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsExternC.modularize
new file mode 100644
index 0000000..b91d7e5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsExternC.modularize
@@ -0,0 +1,12 @@
+# RUN: not modularize %s -x c++ 2>&1 | FileCheck %s
+
+Inputs/IncludeInExtern.h
+
+# CHECK: {{.*}}{{[/\\]}}Inputs{{[/\\]}}IncludeInExtern.h:2:3:
+# CHECK-NEXT:   #include "Empty.h"
+# CHECK-NEXT:   ^
+# CHECK-NEXT: error: Include directive within extern "C" {}.
+# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}IncludeInExtern.h:1:1:
+# CHECK-NEXT: extern "C" {
+# CHECK-NEXT: ^
+# CHECK-NEXT: The "extern "C" {}" block is here.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsInconsistent.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsInconsistent.modularize
new file mode 100644
index 0000000..04d0b01
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsInconsistent.modularize
@@ -0,0 +1,108 @@
+# RUN: not modularize %s -x c++ 2>&1 | FileCheck %s
+
+Inputs/InconsistentHeader1.h
+Inputs/InconsistentHeader2.h
+
+# CHECK: error: macro 'SYMBOL' defined at multiple locations:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:3:9
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:7:9
+# CHECK-NEXT: error: macro 'FUNC_STYLE' defined at multiple locations:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:4:9
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:8:9
+# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:15:11:
+# CHECK-NEXT: int var = FUNC_STYLE(1, 0);
+# CHECK-NEXT:           ^
+# CHECK-NEXT: error: Macro instance 'FUNC_STYLE(1, 0);' has different values in this header, depending on how it was included.
+# CHECK-NEXT:   'FUNC_STYLE(1, 0);' expanded to: '1||0' with respect to these inclusion paths:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h
+# CHECK-NEXT:       {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
+# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:4:9:
+# CHECK-NEXT: #define FUNC_STYLE(a, b) a||b
+# CHECK-NEXT:         ^
+# CHECK-NEXT: Macro defined here.
+# CHECK-NEXT:   'FUNC_STYLE(1, 0);' expanded to: '1&&0' with respect to these inclusion paths:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h
+# CHECK-NEXT:       {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
+# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:8:9:
+# CHECK-NEXT: #define FUNC_STYLE(a, b) a&&b
+# CHECK-NEXT:         ^
+# CHECK-NEXT: Macro defined here.
+# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:11:5:
+# CHECK-NEXT: #if SYMBOL == 1
+# CHECK-NEXT:     ^
+# CHECK-NEXT: error: Macro instance 'SYMBOL' has different values in this header, depending on how it was included.
+# CHECK-NEXT:   'SYMBOL' expanded to: '1' with respect to these inclusion paths:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h
+# CHECK-NEXT:       {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
+# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:3:9:
+# CHECK-NEXT: #define SYMBOL 1
+# CHECK-NEXT:         ^
+# CHECK-NEXT: Macro defined here.
+# CHECK-NEXT:   'SYMBOL' expanded to: '2' with respect to these inclusion paths:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h
+# CHECK-NEXT:       {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
+# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:7:9:
+# CHECK-NEXT: #define SYMBOL 2
+# CHECK-NEXT:         ^
+# CHECK-NEXT: Macro defined here.
+# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:17:5:
+# CHECK-NEXT: #if defined(SYMBOL1)
+# CHECK-NEXT:     ^
+# CHECK-NEXT: error: Macro instance 'defined(SYMBOL1)' has different values in this header, depending on how it was included.
+# CHECK-NEXT:   'defined(SYMBOL1)' expanded to: 'true' with respect to these inclusion paths:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h
+# CHECK-NEXT:       {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
+# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h:3:9:
+# CHECK-NEXT: #define SYMBOL1 1
+# CHECK-NEXT:         ^
+# CHECK-NEXT: Macro defined here.
+# CHECK-NEXT:   'defined(SYMBOL1)' expanded to: 'false' with respect to these inclusion paths:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h
+# CHECK-NEXT:       {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
+# CHECK-NEXT: (no macro definition)
+# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:11:2
+# CHECK-NEXT: #if SYMBOL == 1
+# CHECK-NEXT: ^
+# CHECK-NEXT: error: Conditional expression instance 'SYMBOL == 1' has different values in this header, depending on how it was included.
+# CHECK-NEXT:   'SYMBOL == 1' expanded to: 'true' with respect to these inclusion paths:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h
+# CHECK-NEXT:       {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
+# CHECK-NEXT:   'SYMBOL == 1' expanded to: 'false' with respect to these inclusion paths:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h
+# CHECK-NEXT:       {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
+# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:2:2
+# CHECK-NEXT: #ifdef SYMBOL1
+# CHECK-NEXT: ^
+# CHECK-NEXT: error: Conditional expression instance 'SYMBOL1' has different values in this header, depending on how it was included.
+# CHECK-NEXT:   'SYMBOL1' expanded to: 'true' with respect to these inclusion paths:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h
+# CHECK-NEXT:       {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
+# CHECK-NEXT:   'SYMBOL1' expanded to: 'false' with respect to these inclusion paths:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h
+# CHECK-NEXT:       {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
+# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:6:2
+# CHECK-NEXT: #ifdef SYMBOL2
+# CHECK-NEXT: ^
+# CHECK-NEXT: error: Conditional expression instance 'SYMBOL2' has different values in this header, depending on how it was included.
+# CHECK-NEXT:   'SYMBOL2' expanded to: 'false' with respect to these inclusion paths:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h
+# CHECK-NEXT:       {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
+# CHECK-NEXT:   'SYMBOL2' expanded to: 'true' with respect to these inclusion paths:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h
+# CHECK-NEXT:       {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
+# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:17:2
+# CHECK-NEXT: #if defined(SYMBOL1)
+# CHECK-NEXT: ^
+# CHECK-NEXT: error: Conditional expression instance 'defined(SYMBOL1)' has different values in this header, depending on how it was included.
+# CHECK-NEXT:   'defined(SYMBOL1)' expanded to: 'true' with respect to these inclusion paths:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h
+# CHECK-NEXT:       {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
+# CHECK-NEXT:   'defined(SYMBOL1)' expanded to: 'false' with respect to these inclusion paths:
+# CHECK-NEXT:     {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h
+# CHECK-NEXT:       {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
+# CHECK-NEXT: error: header '{{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h' has different contents depending on how it was included.
+# CHECK-NEXT: note: 'SYMBOL' in {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h at 3:9 not always provided
+# CHECK-NEXT: note: 'FUNC_STYLE' in {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h at 4:9 not always provided
+# CHECK-NEXT: note: 'SYMBOL' in {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h at 7:9 not always provided
+# CHECK-NEXT: note: 'FUNC_STYLE' in {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h at 8:9 not always provided
+# CHECK-NEXT: note: 'TypeInt' in {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h at 12:13 not always provided
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsMissingHeader.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsMissingHeader.modularize
new file mode 100644
index 0000000..bc731fb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsMissingHeader.modularize
@@ -0,0 +1,3 @@
+# RUN: not modularize %S/Inputs/MissingHeader/module.modulemap 2>&1 | FileCheck %s
+
+# CHECK: {{.*}}{{[/\\]}}Inputs/MissingHeader/module.modulemap:8:10: error : Header not found: Missing.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsNamespace.modularize b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsNamespace.modularize
new file mode 100644
index 0000000..d4bc353
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/ProblemsNamespace.modularize
@@ -0,0 +1,12 @@
+# RUN: not modularize %s -x c++ 2>&1 | FileCheck %s
+
+Inputs/IncludeInNamespace.h
+
+# CHECK: {{.*}}{{[/\\]}}Inputs{{[/\\]}}IncludeInNamespace.h:2:3:
+# CHECK-NEXT:   #include "Empty.h"
+# CHECK-NEXT:   ^
+# CHECK-NEXT: error: Include directive within namespace MyNamespace {}.
+# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}IncludeInNamespace.h:1:1:
+# CHECK-NEXT: namespace MyNamespace {
+# CHECK-NEXT: ^
+# CHECK-NEXT: The "namespace MyNamespace {}" block is here.
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/modularize/SubModule2.h b/src/third_party/llvm-project/clang-tools-extra/test/modularize/SubModule2.h
new file mode 100644
index 0000000..70d711b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/modularize/SubModule2.h
@@ -0,0 +1,3 @@
+// SubModule2.h - Master header with same name as directory.
+#include "SubModule2/Header3.h"
+#include "SubModule2/Header4.h"
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/Level1A.h b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/Level1A.h
new file mode 100644
index 0000000..165efc7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/Level1A.h
@@ -0,0 +1,2 @@
+#include "Level2A.h"
+#define MACRO_1A 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/Level1B.h b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/Level1B.h
new file mode 100644
index 0000000..1e60798
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/Level1B.h
@@ -0,0 +1,2 @@
+#include "Level2B.h"
+#define MACRO_1B 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/Level2A.h b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/Level2A.h
new file mode 100644
index 0000000..9a355df
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/Level2A.h
@@ -0,0 +1 @@
+#define MACRO_2A 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/Level2B.h b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/Level2B.h
new file mode 100644
index 0000000..25b7017
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/Level2B.h
@@ -0,0 +1 @@
+#define MACRO_2B 1
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/ModularizeList.txt b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/ModularizeList.txt
new file mode 100644
index 0000000..8193db6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/ModularizeList.txt
@@ -0,0 +1,4 @@
+Level1A.h
+Level1B.h
+Level2A.h
+Level2B.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/module.map b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/module.map
new file mode 100644
index 0000000..31f33c5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/Inputs/module.map
@@ -0,0 +1,18 @@
+// module.map

+

+module Level1A {

+  header "Level1A.h"

+  export *

+}

+module Level1B {

+  header "Level1B.h"

+  export *

+  module Level2B {

+    header "Level2B.h"

+    export *

+  }

+}

+module Level2A {

+  header "Level2A.h"

+  export *

+}

diff --git a/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-conditional.cpp b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-conditional.cpp
new file mode 100644
index 0000000..ac5d3b3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-conditional.cpp
@@ -0,0 +1,304 @@
+// RUN: pp-trace -ignore FileChanged %s -undef -target x86_64 -std=c++11 | FileCheck --strict-whitespace %s
+
+#if 1
+#endif
+
+#if 0
+#endif
+
+#if 1
+#else
+#endif
+
+#if 0
+#else
+#endif
+
+#if 1
+#elif 1
+#endif
+#if 1
+#elif 0
+#endif
+
+#if 0
+#elif 1
+#endif
+#if 0
+#elif 0
+#endif
+#if 1
+#elif 1
+#endif
+#if 1
+#elif 0
+#endif
+
+#if 0
+#elif 1
+#else
+#endif
+#if 0
+#elif 0
+#else
+#endif
+#if 1
+#elif 1
+#else
+#endif
+#if 1
+#elif 0
+#else
+#endif
+
+#define MACRO 1
+#ifdef MACRO
+#endif
+#ifdef NO_MACRO
+#endif
+#ifndef MACRO
+#endif
+#ifndef NO_MACRO
+#endif
+
+// CHECK: ---
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK:        MacroNameTok: __STDC__
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK:        MacroNameTok: __STDC_HOSTED__
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK:        MacroNameTok: __cplusplus
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK:        MacroNameTok: __STDC_UTF_16__
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK:        MacroNameTok: __STDC_UTF_32__
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK:      - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:3:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:3:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:4:1"]
+// CHECK-NEXT:   ConditionValue: CVK_True
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:4:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:3:2"
+// CHECK-NEXT: - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:6:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:6:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:7:1"]
+// CHECK-NEXT:   ConditionValue: CVK_False
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:7:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:6:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:6:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:7:2"]
+// CHECK-NEXT: - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:9:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:9:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:10:1"]
+// CHECK-NEXT:   ConditionValue: CVK_True
+// CHECK-NEXT: - Callback: Else
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:10:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:9:2"
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:11:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:9:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:10:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:11:2"]
+// CHECK-NEXT: - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:14:1"]
+// CHECK-NEXT:   ConditionValue: CVK_False
+// CHECK-NEXT: - Callback: Else
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:14:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:14:2"]
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:15:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:2"
+// CHECK-NEXT: - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:17:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:17:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:18:1"]
+// CHECK-NEXT:   ConditionValue: CVK_True
+// CHECK-NEXT: - Callback: Elif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:18:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:18:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:19:1"]
+// CHECK-NEXT:   ConditionValue: CVK_NotEvaluated
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:17:2"
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:19:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:17:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:18:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:19:2"]
+// CHECK-NEXT: - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:20:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:20:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:21:1"]
+// CHECK-NEXT:   ConditionValue: CVK_True
+// CHECK-NEXT: - Callback: Elif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:21:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:21:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:22:1"]
+// CHECK-NEXT:   ConditionValue: CVK_NotEvaluated
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:20:2"
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:22:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:20:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:21:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:22:2"]
+// CHECK-NEXT: - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:25:1"]
+// CHECK-NEXT:   ConditionValue: CVK_False
+// CHECK-NEXT: - Callback: Elif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:25:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:25:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:26:1"]
+// CHECK-NEXT:   ConditionValue: CVK_True
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:25:2"]
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:26:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:2"
+// CHECK-NEXT: - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:27:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:27:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:28:1"]
+// CHECK-NEXT:   ConditionValue: CVK_False
+// CHECK-NEXT: - Callback: Elif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:28:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:28:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:29:1"]
+// CHECK-NEXT:   ConditionValue: CVK_False
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:27:2"
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:29:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:27:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:27:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:29:2"]
+// CHECK-NEXT: - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:30:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:30:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:31:1"]
+// CHECK-NEXT:   ConditionValue: CVK_True
+// CHECK-NEXT: - Callback: Elif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:31:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:31:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:32:1"]
+// CHECK-NEXT:   ConditionValue: CVK_NotEvaluated
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:30:2"
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:32:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:30:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:31:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:32:2"]
+// CHECK-NEXT: - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:33:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:33:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:34:1"]
+// CHECK-NEXT:   ConditionValue: CVK_True
+// CHECK-NEXT: - Callback: Elif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:34:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:34:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:35:1"]
+// CHECK-NEXT:   ConditionValue: CVK_NotEvaluated
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:33:2"
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:35:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:33:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:34:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:35:2"]
+// CHECK-NEXT: - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:38:1"]
+// CHECK-NEXT:   ConditionValue: CVK_False
+// CHECK-NEXT: - Callback: Elif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:38:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:38:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:39:1"]
+// CHECK-NEXT:   ConditionValue: CVK_True
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:38:2"]
+// CHECK-NEXT: - Callback: Else
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:39:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:2"
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:40:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:39:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:40:2"]
+// CHECK-NEXT: - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:42:1"]
+// CHECK-NEXT:   ConditionValue: CVK_False
+// CHECK-NEXT: - Callback: Elif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:42:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:42:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:43:1"]
+// CHECK-NEXT:   ConditionValue: CVK_False
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:2"
+// CHECK-NEXT: - Callback: Else
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:43:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:43:2"]
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:44:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:2"
+// CHECK-NEXT: - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:45:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:45:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:46:1"]
+// CHECK-NEXT:   ConditionValue: CVK_True
+// CHECK-NEXT: - Callback: Elif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:46:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:46:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:47:1"]
+// CHECK-NEXT:   ConditionValue: CVK_NotEvaluated
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:45:2"
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:48:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:45:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:46:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:48:2"]
+// CHECK-NEXT: - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:49:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:49:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:50:1"]
+// CHECK-NEXT:   ConditionValue: CVK_True
+// CHECK-NEXT: - Callback: Elif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:50:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:50:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:51:1"]
+// CHECK-NEXT:   ConditionValue: CVK_NotEvaluated
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:49:2"
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:52:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:49:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:50:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:52:2"]
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK-NEXT:   MacroNameTok: MACRO
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: Ifdef
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:55:2"
+// CHECK-NEXT:   MacroNameTok: MACRO
+// CHECK-NEXT:   MacroDefinition: [(local)]
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:56:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:55:2"
+// CHECK-NEXT: - Callback: Ifdef
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:57:2"
+// CHECK-NEXT:   MacroNameTok: NO_MACRO
+// CHECK-NEXT:   MacroDefinition: []
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:58:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:57:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:57:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:58:2"]
+// CHECK-NEXT: - Callback: Ifndef
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:59:2"
+// CHECK-NEXT:   MacroNameTok: MACRO
+// CHECK-NEXT:   MacroDefinition: [(local)]
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:60:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:59:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:59:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:60:2"]
+// CHECK-NEXT: - Callback: Ifndef
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:61:2"
+// CHECK-NEXT:   MacroNameTok: NO_MACRO
+// CHECK-NEXT:   MacroDefinition: []
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:62:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:61:2"
+// CHECK-NEXT: - Callback: EndOfMainFile
+// CHECK-NEXT: ...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-ident.cpp b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-ident.cpp
new file mode 100644
index 0000000..9981c39
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-ident.cpp
@@ -0,0 +1,10 @@
+// RUN: pp-trace -ignore FileChanged,MacroDefined %s -undef -target x86_64 -std=c++11 | FileCheck --strict-whitespace %s
+
+#ident "$Id$"
+
+// CHECK: ---
+// CHECK-NEXT: - Callback: Ident
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-ident.cpp:3:2"
+// CHECK-NEXT:   Str: "$Id$"
+// CHECK-NEXT: - Callback: EndOfMainFile
+// CHECK-NEXT: ...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-include.cpp b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-include.cpp
new file mode 100644
index 0000000..7d925d8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-include.cpp
@@ -0,0 +1,141 @@
+// RUN: pp-trace %s -undef -target x86_64 -std=c++11 | FileCheck --strict-whitespace %s
+
+#include "Inputs/Level1A.h"
+#include "Inputs/Level1B.h"
+
+// CHECK: ---
+// CHECK-NEXT: - Callback: FileChanged
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-include.cpp:1:1"
+// CHECK-NEXT:   Reason: EnterFile
+// CHECK-NEXT:   FileType: C_User
+// CHECK-NEXT:   PrevFID: (invalid)
+// CHECK-NEXT: - Callback: FileChanged
+// CHECK-NEXT:   Loc: "<built-in>:1:1"
+// CHECK-NEXT:   Reason: EnterFile
+// CHECK-NEXT:   FileType: C_User
+// CHECK-NEXT:   PrevFID: (invalid)
+// CHECK-NEXT: - Callback: FileChanged
+// CHECK-NEXT:   Loc: "<built-in>:1:1"
+// CHECK-NEXT:   Reason: RenameFile
+// CHECK-NEXT:   FileType: C_System
+// CHECK-NEXT:   PrevFID: (invalid)
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK:        MacroNameTok: __STDC__
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK:        MacroNameTok: __STDC_HOSTED__
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK:        MacroNameTok: __cplusplus
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK:        MacroNameTok: __STDC_UTF_16__
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK:        MacroNameTok: __STDC_UTF_32__
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK:      - Callback: FileChanged
+// CHECK-NEXT:   Loc: "<command line>:1:1"
+// CHECK-NEXT:   Reason: EnterFile
+// CHECK-NEXT:   FileType: C_User
+// CHECK-NEXT:   PrevFID: (invalid)
+// CHECK-NEXT: - Callback: FileChanged
+// CHECK-NEXT:   Loc: "<built-in>:1:1"
+// CHECK-NEXT:   Reason: ExitFile
+// CHECK-NEXT:   FileType: C_User
+// CHECK-NEXT:   PrevFID: (invalid)
+// CHECK-NEXT: - Callback: FileChanged
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-include.cpp:1:1"
+// CHECK-NEXT:   Reason: ExitFile
+// CHECK-NEXT:   FileType: C_User
+// CHECK-NEXT:   PrevFID: (getFileEntryForID failed)
+// CHECK-NEXT: - Callback: InclusionDirective
+// CHECK-NEXT:   IncludeTok: include
+// CHECK-NEXT:   FileName: "Inputs/Level1A.h"
+// CHECK-NEXT:   IsAngled: false
+// CHECK-NEXT:   FilenameRange: "Inputs/Level1A.h"
+// CHECK-NEXT:   File: "{{.*}}{{[/\\]}}Inputs/Level1A.h"
+// CHECK-NEXT:   SearchPath: "{{.*}}{{[/\\]}}pp-trace"
+// CHECK-NEXT:   RelativePath: "Inputs/Level1A.h"
+// CHECK-NEXT:   Imported: (null)
+// CHECK-NEXT: - Callback: FileChanged
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}Inputs/Level1A.h:1:1"
+// CHECK-NEXT:   Reason: EnterFile
+// CHECK-NEXT:   FileType: C_User
+// CHECK-NEXT:   PrevFID: (invalid)
+// CHECK-NEXT: - Callback: InclusionDirective
+// CHECK-NEXT:   IncludeTok: include
+// CHECK-NEXT:   FileName: "Level2A.h"
+// CHECK-NEXT:   IsAngled: false
+// CHECK-NEXT:   FilenameRange: "Level2A.h"
+// CHECK-NEXT:   File: "{{.*}}{{[/\\]}}Inputs/Level2A.h"
+// CHECK-NEXT:   SearchPath: "{{.*}}{{[/\\]}}Inputs"
+// CHECK-NEXT:   RelativePath: "Level2A.h"
+// CHECK-NEXT:   Imported: (null)
+// CHECK-NEXT: - Callback: FileChanged
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}Inputs/Level2A.h:1:1"
+// CHECK-NEXT:   Reason: EnterFile
+// CHECK-NEXT:   FileType: C_User
+// CHECK-NEXT:   PrevFID: (invalid)
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK-NEXT:   MacroNameTok: MACRO_2A
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: FileChanged
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}Inputs/Level1A.h:2:1"
+// CHECK-NEXT:   Reason: ExitFile
+// CHECK-NEXT:   FileType: C_User
+// CHECK-NEXT:   PrevFID: "{{.*}}{{[/\\]}}Inputs/Level2A.h"
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK-NEXT:   MacroNameTok: MACRO_1A
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: FileChanged
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-include.cpp:4:1"
+// CHECK-NEXT:   Reason: ExitFile
+// CHECK-NEXT:   FileType: C_User
+// CHECK-NEXT:   PrevFID: "{{.*}}{{[/\\]}}Inputs/Level1A.h"
+// CHECK-NEXT: - Callback: InclusionDirective
+// CHECK-NEXT:   IncludeTok: include
+// CHECK-NEXT:   FileName: "Inputs/Level1B.h"
+// CHECK-NEXT:   IsAngled: false
+// CHECK-NEXT:   FilenameRange: "Inputs/Level1B.h"
+// CHECK-NEXT:   File: "{{.*}}{{[/\\]}}Inputs/Level1B.h"
+// CHECK-NEXT:   SearchPath: "{{.*}}{{[/\\]}}pp-trace"
+// CHECK-NEXT:   RelativePath: "Inputs/Level1B.h"
+// CHECK-NEXT:   Imported: (null)
+// CHECK-NEXT: - Callback: FileChanged
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}Inputs/Level1B.h:1:1"
+// CHECK-NEXT:   Reason: EnterFile
+// CHECK-NEXT:   FileType: C_User
+// CHECK-NEXT:   PrevFID: (invalid)
+// CHECK-NEXT: - Callback: InclusionDirective
+// CHECK-NEXT:   IncludeTok: include
+// CHECK-NEXT:   FileName: "Level2B.h"
+// CHECK-NEXT:   IsAngled: false
+// CHECK-NEXT:   FilenameRange: "Level2B.h"
+// CHECK-NEXT:   File: "{{.*}}{{[/\\]}}Inputs/Level2B.h"
+// CHECK-NEXT:   SearchPath: "{{.*}}{{[/\\]}}Inputs"
+// CHECK-NEXT:   RelativePath: "Level2B.h"
+// CHECK-NEXT:   Imported: (null)
+// CHECK-NEXT: - Callback: FileChanged
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}Inputs/Level2B.h:1:1"
+// CHECK-NEXT:   Reason: EnterFile
+// CHECK-NEXT:   FileType: C_User
+// CHECK-NEXT:   PrevFID: (invalid)
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK-NEXT:   MacroNameTok: MACRO_2B
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: FileChanged
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}Inputs/Level1B.h:2:1"
+// CHECK-NEXT:   Reason: ExitFile
+// CHECK-NEXT:   FileType: C_User
+// CHECK-NEXT:   PrevFID: "{{.*}}{{[/\\]}}Inputs/Level2B.h"
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK-NEXT:   MacroNameTok: MACRO_1B
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: FileChanged
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-include.cpp:5:1"
+// CHECK-NEXT:   Reason: ExitFile
+// CHECK-NEXT:   FileType: C_User
+// CHECK-NEXT:   PrevFID: "{{.*}}{{[/\\]}}Inputs/Level1B.h"
+// CHECK-NEXT: - Callback: EndOfMainFile
+// CHECK-NEXT: ...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp
new file mode 100644
index 0000000..e6ba761
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp
@@ -0,0 +1,101 @@
+// RUN: pp-trace -ignore FileChanged %s -undef -target x86_64 -std=c++11 | FileCheck --strict-whitespace %s
+
+#define MACRO 1
+int i = MACRO;
+#if defined(MACRO)
+#endif
+#undef MACRO
+#if defined(MACRO)
+#endif
+#define FUNCMACRO(ARG1) ARG1
+int j = FUNCMACRO(1);
+#define X X_IMPL(a+y,b) X_IMPL2(c)
+#define X_IMPL(p1,p2)
+#define X_IMPL2(p1)
+X
+
+// CHECK: ---
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK:        MacroNameTok: __STDC__
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK:        MacroNameTok: __STDC_HOSTED__
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK:        MacroNameTok: __cplusplus
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK:        MacroNameTok: __STDC_UTF_16__
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK:        MacroNameTok: __STDC_UTF_32__
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK:      - Callback: MacroDefined
+// CHECK-NEXT:   MacroNameTok: MACRO
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroExpands
+// CHECK-NEXT:   MacroNameTok: MACRO
+// CHECK-NEXT:   MacroDefinition: [(local)]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:4:9", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:4:9"]
+// CHECK-NEXT:   Args: (null)
+// CHECK-NEXT: - Callback: Defined
+// CHECK-NEXT:   MacroNameTok: MACRO
+// CHECK-NEXT:   MacroDefinition: [(local)]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:5:5", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:5:19"]
+// CHECK-NEXT: - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-macro.cpp:5:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:5:4", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:6:1"]
+// CHECK-NEXT:   ConditionValue: CVK_True
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-macro.cpp:6:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-macro.cpp:5:2"
+// CHECK-NEXT: - Callback: MacroUndefined
+// CHECK-NEXT:   MacroNameTok: MACRO
+// CHECK-NEXT:   MacroDefinition: [(local)]
+// CHECK-NEXT: - Callback: Defined
+// CHECK-NEXT:   MacroNameTok: MACRO
+// CHECK-NEXT:   MacroDefinition: []
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:8:5", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:8:19"]
+// CHECK-NEXT: - Callback: If
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-macro.cpp:8:2"
+// CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:8:4", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:9:1"]
+// CHECK-NEXT:   ConditionValue: CVK_False
+// CHECK-NEXT: - Callback: Endif
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-macro.cpp:9:2"
+// CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-macro.cpp:8:2"
+// CHECK-NEXT: - Callback: SourceRangeSkipped
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:8:1", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:9:2"]
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK-NEXT:   MacroNameTok: FUNCMACRO
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroExpands
+// CHECK-NEXT:   MacroNameTok: FUNCMACRO
+// CHECK-NEXT:   MacroDefinition: [(local)]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:11:9", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:11:20"]
+// CHECK-NEXT:   Args: [1]
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK-NEXT:   MacroNameTok: X
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK-NEXT:   MacroNameTok: X_IMPL
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroDefined
+// CHECK-NEXT:   MacroNameTok: X_IMPL2
+// CHECK-NEXT:   MacroDirective: MD_Define
+// CHECK-NEXT: - Callback: MacroExpands
+// CHECK-NEXT:   MacroNameTok: X
+// CHECK-NEXT:   MacroDefinition: [(local)]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:15:1", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:15:1"]
+// CHECK-NEXT:   Args: (null)
+// CHECK-NEXT: - Callback: MacroExpands
+// CHECK-NEXT:   MacroNameTok: X_IMPL
+// CHECK-NEXT:   MacroDefinition: [(local)]
+// CHECK-NEXT:   Range: [(nonfile), (nonfile)]
+// CHECK-NEXT:   Args: [a <plus> y, b]
+// CHECK-NEXT: - Callback: MacroExpands
+// CHECK-NEXT:   MacroNameTok: X_IMPL2
+// CHECK-NEXT:   MacroDefinition: [(local)]
+// CHECK-NEXT:   Range: [(nonfile), (nonfile)]
+// CHECK-NEXT:   Args: [c]
+// CHECK-NEXT: - Callback: EndOfMainFile
+// CHECK-NEXT: ...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-modules.cpp b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-modules.cpp
new file mode 100644
index 0000000..5e9e1de
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-modules.cpp
@@ -0,0 +1,20 @@
+// RUN: rm -rf %t
+// RUN: pp-trace -ignore FileChanged,MacroDefined %s -x objective-c++ -undef -target x86_64 -std=c++11 -fmodules -fcxx-modules -fmodules-cache-path=%t -I%S -I%S/Input | FileCheck --strict-whitespace %s
+
+// CHECK: ---
+
+@import Level1A;
+
+// CHECK-NEXT: - Callback: moduleImport
+// CHECK-NEXT:   ImportLoc: "{{.*}}{{[/\\]}}pp-trace-modules.cpp:[[@LINE-3]]:2"
+// CHECK-NEXT:   Path: [{Name: Level1A, Loc: "{{.*}}{{[/\\]}}pp-trace-modules.cpp:[[@LINE-4]]:9"}]
+// CHECK-NEXT:   Imported: Level1A
+
+@import Level1B.Level2B;
+
+// CHECK-NEXT: - Callback: moduleImport
+// CHECK-NEXT:   ImportLoc: "{{.*}}{{[/\\]}}pp-trace-modules.cpp:[[@LINE-3]]:2"
+// CHECK-NEXT:   Path: [{Name: Level1B, Loc: "{{.*}}{{[/\\]}}pp-trace-modules.cpp:[[@LINE-4]]:9"}, {Name: Level2B, Loc: "{{.*}}{{[/\\]}}pp-trace-modules.cpp:[[@LINE-4]]:17"}]
+// CHECK-NEXT:   Imported: Level2B
+// CHECK-NEXT: - Callback: EndOfMainFile
+// CHECK-NEXT: ...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-pragma-general.cpp b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-pragma-general.cpp
new file mode 100644
index 0000000..6caef0b
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-pragma-general.cpp
@@ -0,0 +1,118 @@
+// RUN: pp-trace -ignore FileChanged,MacroDefined %s | FileCheck --strict-whitespace %s
+
+#pragma clang diagnostic push
+#pragma clang diagnostic pop
+#pragma clang diagnostic ignored "-Wformat"
+#pragma clang diagnostic warning "-Wformat"
+#pragma clang diagnostic error "-Wformat"
+#pragma clang diagnostic fatal "-Wformat"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic pop
+#pragma GCC diagnostic ignored "-Wformat"
+#pragma GCC diagnostic warning "-Wformat"
+#pragma GCC diagnostic error "-Wformat"
+#pragma GCC diagnostic fatal "-Wformat"
+
+void foo() {
+#pragma clang __debug captured
+{ }
+}
+
+// CHECK: ---
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:3:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDiagnosticPush
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:3:15"
+// CHECK-NEXT:   Namespace: clang
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:4:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDiagnosticPop
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:4:15"
+// CHECK-NEXT:   Namespace: clang
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:5:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDiagnostic
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:5:15"
+// CHECK-NEXT:   Namespace: clang
+// CHECK-NEXT:   Mapping: MAP_IGNORE
+// CHECK-NEXT:   Str: -Wformat
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:6:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDiagnostic
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:6:15"
+// CHECK-NEXT:   Namespace: clang
+// CHECK-NEXT:   Mapping: MAP_WARNING
+// CHECK-NEXT:   Str: -Wformat
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:7:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDiagnostic
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:7:15"
+// CHECK-NEXT:   Namespace: clang
+// CHECK-NEXT:   Mapping: MAP_ERROR
+// CHECK-NEXT:   Str: -Wformat
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:8:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDiagnostic
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:8:15"
+// CHECK-NEXT:   Namespace: clang
+// CHECK-NEXT:   Mapping: MAP_FATAL
+// CHECK-NEXT:   Str: -Wformat
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:10:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDiagnosticPush
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:10:13"
+// CHECK-NEXT:   Namespace: GCC
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:11:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDiagnosticPop
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:11:13"
+// CHECK-NEXT:   Namespace: GCC
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:12:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDiagnostic
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:12:13"
+// CHECK-NEXT:   Namespace: GCC
+// CHECK-NEXT:   Mapping: MAP_IGNORE
+// CHECK-NEXT:   Str: -Wformat
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:13:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDiagnostic
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:13:13"
+// CHECK-NEXT:   Namespace: GCC
+// CHECK-NEXT:   Mapping: MAP_WARNING
+// CHECK-NEXT:   Str: -Wformat
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:14:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDiagnostic
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:14:13"
+// CHECK-NEXT:   Namespace: GCC
+// CHECK-NEXT:   Mapping: MAP_ERROR
+// CHECK-NEXT:   Str: -Wformat
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:15:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDiagnostic
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:15:13"
+// CHECK-NEXT:   Namespace: GCC
+// CHECK-NEXT:   Mapping: MAP_FATAL
+// CHECK-NEXT:   Str: -Wformat
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:18:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDebug
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:18:23"
+// CHECK-NEXT:   DebugType: captured
+// CHECK-NEXT: - Callback: EndOfMainFile
+// CHECK-NEXT: ...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-pragma-ms.cpp b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-pragma-ms.cpp
new file mode 100644
index 0000000..33c9f7f
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-pragma-ms.cpp
@@ -0,0 +1,100 @@
+// RUN: pp-trace -ignore FileChanged,MacroDefined %s -target x86_64-unknown-windows-msvc -fms-extensions -w | FileCheck --strict-whitespace %s
+
+#pragma comment(compiler, "compiler comment")
+#pragma comment(exestr, "exestr comment")
+#pragma comment(lib, "lib comment")
+#pragma comment(linker, "linker comment")
+#pragma comment(user, "user comment")
+
+#pragma detect_mismatch("name argument", "value argument")
+
+#pragma __debug(assert)
+
+#pragma message("message argument")
+
+#pragma warning(push, 1)
+#pragma warning(pop)
+#pragma warning(disable : 1 2 3 ; error : 4 5 6 ; suppress : 7 8 9)
+
+// CHECK: ---
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:3:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaComment
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:3:9"
+// CHECK-NEXT:   Kind: compiler
+// CHECK-NEXT:   Str: compiler comment
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:4:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaComment
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:4:9"
+// CHECK-NEXT:   Kind: exestr
+// CHECK-NEXT:   Str: exestr comment
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:5:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaComment
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:5:9"
+// CHECK-NEXT:   Kind: lib
+// CHECK-NEXT:   Str: lib comment
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:6:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaComment
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:6:9"
+// CHECK-NEXT:   Kind: linker
+// CHECK-NEXT:   Str: linker comment
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:7:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaComment
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:7:9"
+// CHECK-NEXT:   Kind: user
+// CHECK-NEXT:   Str: user comment
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:9:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDetectMismatch
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:9:9"
+// CHECK-NEXT:   Name: name argument
+// CHECK-NEXT:   Value: value argument
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:11:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:13:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaMessage
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:13:9"
+// CHECK-NEXT:   Namespace: 
+// CHECK-NEXT:   Kind: PMK_Message
+// CHECK-NEXT:   Str: message argument
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:15:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaWarningPush
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:15:9"
+// CHECK-NEXT:   Level: 1
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:16:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaWarningPop
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:16:9"
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:17:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaWarning
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:17:9"
+// CHECK-NEXT:   WarningSpec: disable
+// CHECK-NEXT:   Ids: [1, 2, 3]
+// CHECK-NEXT: - Callback: PragmaWarning
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:17:9"
+// CHECK-NEXT:   WarningSpec: error
+// CHECK-NEXT:   Ids: [4, 5, 6]
+// CHECK-NEXT: - Callback: PragmaWarning
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:17:9"
+// CHECK-NEXT:   WarningSpec: suppress
+// CHECK-NEXT:   Ids: [7, 8, 9]
+// CHECK-NEXT: - Callback: EndOfMainFile
+// CHECK-NEXT: ...
diff --git a/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-pragma-opencl.cpp b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-pragma-opencl.cpp
new file mode 100644
index 0000000..cfd72c0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/test/pp-trace/pp-trace-pragma-opencl.cpp
@@ -0,0 +1,33 @@
+// RUN: pp-trace -ignore FileChanged,MacroDefined %s -x cl | FileCheck --strict-whitespace %s
+
+#pragma OPENCL EXTENSION all : disable
+#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : disable
+#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable
+
+// CHECK: ---
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-opencl.cpp:3:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaOpenCLExtension
+// CHECK-NEXT:   NameLoc: "{{.*}}{{[/\\]}}pp-trace-pragma-opencl.cpp:3:26"
+// CHECK-NEXT:   Name: all
+// CHECK-NEXT:   StateLoc: "{{.*}}{{[/\\]}}pp-trace-pragma-opencl.cpp:3:32"
+// CHECK-NEXT:   State: 0
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-opencl.cpp:4:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaOpenCLExtension
+// CHECK-NEXT:   NameLoc: "{{.*}}{{[/\\]}}pp-trace-pragma-opencl.cpp:4:26"
+// CHECK-NEXT:   Name: cl_khr_int64_base_atomics
+// CHECK-NEXT:   StateLoc: "{{.*}}{{[/\\]}}pp-trace-pragma-opencl.cpp:4:54"
+// CHECK-NEXT:   State: 0
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-opencl.cpp:5:1"
+// CHECK-NEXT:   Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaOpenCLExtension
+// CHECK-NEXT:   NameLoc: "{{.*}}{{[/\\]}}pp-trace-pragma-opencl.cpp:5:26"
+// CHECK-NEXT:   Name: cl_khr_int64_base_atomics
+// CHECK-NEXT:   StateLoc: "{{.*}}{{[/\\]}}pp-trace-pragma-opencl.cpp:5:54"
+// CHECK-NEXT:   State: 1
+// CHECK-NEXT: - Callback: EndOfMainFile
+// CHECK-NEXT: ...
diff --git a/src/third_party/llvm-project/clang-tools-extra/tool-template/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/tool-template/CMakeLists.txt
new file mode 100644
index 0000000..6478157
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/tool-template/CMakeLists.txt
@@ -0,0 +1,17 @@
+set(LLVM_LINK_COMPONENTS
+  Support
+  )
+
+add_clang_executable(tool-template
+  ToolTemplate.cpp
+  )
+
+target_link_libraries(tool-template
+  PRIVATE
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFrontend
+  clangTooling
+  clangToolingRefactor
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/tool-template/ToolTemplate.cpp b/src/third_party/llvm-project/clang-tools-extra/tool-template/ToolTemplate.cpp
new file mode 100644
index 0000000..5345d77
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/tool-template/ToolTemplate.cpp
@@ -0,0 +1,122 @@
+//===---- tools/extra/ToolTemplate.cpp - Template for refactoring tool ----===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements an empty refactoring tool using the clang tooling.
+//  The goal is to lower the "barrier to entry" for writing refactoring tools.
+//
+//  Usage:
+//  tool-template <cmake-output-dir> <file1> <file2> ...
+//
+//  Where <cmake-output-dir> is a CMake build directory in which a file named
+//  compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in
+//  CMake to get this output).
+//
+//  <file1> ... specify the paths of files in the CMake source tree. This path
+//  is looked up in the compile command database. If the path of a file is
+//  absolute, it needs to point into CMake's source tree. If the path is
+//  relative, the current working directory needs to be in the CMake source
+//  tree and the file must be in a subdirectory of the current working
+//  directory. "./" prefixes in the relative files will be automatically
+//  removed, but the rest of a relative path must be a suffix of a path in
+//  the compile command line database.
+//
+//  For example, to use tool-template on all files in a subtree of the
+//  source tree, use:
+//
+//    /path/in/subtree $ find . -name '*.cpp'|
+//        xargs tool-template /path/to/build
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Execution.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Refactoring/AtomicChange.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Signals.h"
+
+using namespace clang;
+using namespace clang::ast_matchers;
+using namespace clang::tooling;
+using namespace llvm;
+
+namespace {
+class ToolTemplateCallback : public MatchFinder::MatchCallback {
+public:
+  ToolTemplateCallback(ExecutionContext &Context) : Context(Context) {}
+
+  void run(const MatchFinder::MatchResult &Result) override {
+    // TODO: This routine will get called for each thing that the matchers
+    // find.
+    // At this point, you can examine the match, and do whatever you want,
+    // including replacing the matched text with other text
+    auto *D = Result.Nodes.getNodeAs<NamedDecl>("decl");
+    assert(D);
+    // Use AtomicChange to get a key.
+    if (D->getLocStart().isValid()) {
+      AtomicChange Change(*Result.SourceManager, D->getLocStart());
+      Context.reportResult(Change.getKey(), D->getQualifiedNameAsString());
+    }
+  }
+
+  void onStartOfTranslationUnit() override {
+    Context.reportResult("START", "Start of TU.");
+  }
+  void onEndOfTranslationUnit() override {
+    Context.reportResult("END", "End of TU.");
+  }
+
+private:
+  ExecutionContext &Context;
+};
+} // end anonymous namespace
+
+// Set up the command line options
+static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
+static cl::OptionCategory ToolTemplateCategory("tool-template options");
+
+int main(int argc, const char **argv) {
+  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+
+  auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
+      argc, argv, ToolTemplateCategory);
+
+  if (!Executor) {
+    llvm::errs() << llvm::toString(Executor.takeError()) << "\n";
+    return 1;
+  }
+
+  ast_matchers::MatchFinder Finder;
+  ToolTemplateCallback Callback(*Executor->get()->getExecutionContext());
+
+  // TODO: Put your matchers here.
+  // Use Finder.addMatcher(...) to define the patterns in the AST that you
+  // want to match against. You are not limited to just one matcher!
+  //
+  // This is a sample matcher:
+  Finder.addMatcher(
+      namedDecl(cxxRecordDecl(), isExpansionInMainFile()).bind("decl"),
+      &Callback);
+
+  auto Err = Executor->get()->execute(newFrontendActionFactory(&Finder));
+  if (Err) {
+    llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+  }
+  Executor->get()->getToolResults()->forEachResult(
+      [](llvm::StringRef key, llvm::StringRef value) {
+        llvm::errs() << "----" << key.str() << "\n" << value.str() << "\n";
+      });
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/unittests/CMakeLists.txt
new file mode 100644
index 0000000..82f54d5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/CMakeLists.txt
@@ -0,0 +1,25 @@
+add_custom_target(ExtraToolsUnitTests)
+set_target_properties(ExtraToolsUnitTests PROPERTIES FOLDER "Extra Tools Unit Tests")
+
+function(add_extra_unittest test_dirname)
+  add_unittest(ExtraToolsUnitTests ${test_dirname} ${ARGN})
+endfunction()
+
+if(CLANG_BUILT_STANDALONE)
+  # LLVMTestingSupport library is needed for clangd tests.
+  if (EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Testing/Support
+      AND NOT TARGET LLVMTestingSupport)
+    add_subdirectory(${LLVM_MAIN_SRC_DIR}/lib/Testing/Support
+      lib/Testing/Support)
+  endif()
+endif()
+
+add_subdirectory(change-namespace)
+add_subdirectory(clang-apply-replacements)
+add_subdirectory(clang-move)
+add_subdirectory(clang-query)
+if(CLANG_ENABLE_STATIC_ANALYZER)
+  add_subdirectory(clang-tidy)
+endif()
+add_subdirectory(clangd)
+add_subdirectory(include-fixer)
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/change-namespace/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/unittests/change-namespace/CMakeLists.txt
new file mode 100644
index 0000000..3745bbd
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/change-namespace/CMakeLists.txt
@@ -0,0 +1,29 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  )
+
+get_filename_component(CHANGE_NAMESPACE_SOURCE_DIR
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../change-namespace REALPATH)
+include_directories(
+  ${CHANGE_NAMESPACE_SOURCE_DIR}
+  )
+
+# We'd like clang/unittests/Tooling/RewriterTestContext.h in the test.
+include_directories(${CLANG_SOURCE_DIR})
+
+add_extra_unittest(ChangeNamespaceTests
+  ChangeNamespaceTests.cpp
+  )
+
+target_link_libraries(ChangeNamespaceTests
+  PRIVATE
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangChangeNamespace
+  clangFormat
+  clangFrontend
+  clangRewrite
+  clangTooling
+  clangToolingCore
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/change-namespace/ChangeNamespaceTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/change-namespace/ChangeNamespaceTests.cpp
new file mode 100644
index 0000000..917f7b0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/change-namespace/ChangeNamespaceTests.cpp
@@ -0,0 +1,2249 @@
+//===-- ChangeNamespaceTests.cpp - Change namespace unit tests ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ChangeNamespace.h"
+#include "unittests/Tooling/RewriterTestContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Format/Format.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "gtest/gtest.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace change_namespace {
+namespace {
+
+class ChangeNamespaceTest : public ::testing::Test {
+public:
+  std::string runChangeNamespaceOnCode(llvm::StringRef Code) {
+    clang::RewriterTestContext Context;
+    clang::FileID ID = Context.createInMemoryFile(FileName, Code);
+
+    std::map<std::string, tooling::Replacements> FileToReplacements;
+    change_namespace::ChangeNamespaceTool NamespaceTool(
+        OldNamespace, NewNamespace, FilePattern,
+        /*WhiteListedSymbolPatterns*/ {}, &FileToReplacements);
+    ast_matchers::MatchFinder Finder;
+    NamespaceTool.registerMatchers(&Finder);
+    std::unique_ptr<tooling::FrontendActionFactory> Factory =
+        tooling::newFrontendActionFactory(&Finder);
+    if (!tooling::runToolOnCodeWithArgs(Factory->create(), Code, {"-std=c++11"},
+                                        FileName))
+      return "";
+    formatAndApplyAllReplacements(FileToReplacements, Context.Rewrite);
+    return format(Context.getRewrittenText(ID));
+  }
+
+  std::string format(llvm::StringRef Code) {
+    tooling::Replacements Replaces = format::reformat(
+        format::getLLVMStyle(), Code, {tooling::Range(0, Code.size())});
+    auto ChangedCode = tooling::applyAllReplacements(Code, Replaces);
+    EXPECT_TRUE(static_cast<bool>(ChangedCode));
+    if (!ChangedCode) {
+      llvm::errs() << llvm::toString(ChangedCode.takeError());
+      return "";
+    }
+    return *ChangedCode;
+  }
+
+protected:
+  std::string FileName = "input.cc";
+  std::string OldNamespace = "na::nb";
+  std::string NewNamespace = "x::y";
+  std::string FilePattern = "input.cc";
+};
+
+TEST_F(ChangeNamespaceTest, NoMatchingNamespace) {
+  std::string Code = "namespace na {\n"
+                     "namespace nx {\n"
+                     "class A {};\n"
+                     "} // namespace nx\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "namespace nx {\n"
+                         "class A {};\n"
+                         "} // namespace nx\n"
+                         "} // namespace na\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, SimpleMoveWithoutTypeRefs) {
+  std::string Code = "namespace na {\n"
+                     "namespace nb {\n"
+                     "class A {};\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "\n\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "class A {};\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, NewNsNestedInOldNs) {
+  NewNamespace = "na::nb::nc";
+  std::string Code = "namespace na {\n"
+                     "namespace nb {\n"
+                     "class A {};\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "namespace nb {\n"
+                         "namespace nc {\n"
+                         "class A {};\n"
+                         "} // namespace nc\n"
+                         "} // namespace nb\n"
+                         "} // namespace na\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, NewNsNestedInOldNsWithSurroundingNewLines) {
+  NewNamespace = "na::nb::nc";
+  std::string Code = "namespace na {\n"
+                     "namespace nb {\n"
+                     "\n"
+                     "class A {};\n"
+                     "\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "namespace nb {\n"
+                         "namespace nc {\n"
+                         "\n"
+                         "class A {};\n"
+                         "\n"
+                         "} // namespace nc\n"
+                         "} // namespace nb\n"
+                         "} // namespace na\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, MoveOldNsWithSurroundingNewLines) {
+  NewNamespace = "nx::ny";
+  std::string Code = "namespace na {\n"
+                     "namespace nb {\n"
+                     "\n"
+                     "class A {};\n"
+                     "\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "\n\n"
+                         "namespace nx {\n"
+                         "namespace ny {\n"
+                         "\n"
+                         "class A {};\n"
+                         "\n"
+                         "} // namespace ny\n"
+                         "} // namespace nx\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, NewNsNestedInOldNsWithRefs) {
+  NewNamespace = "na::nb::nc";
+  std::string Code = "namespace na {\n"
+                     "class A {};\n"
+                     "namespace nb {\n"
+                     "class B {};\n"
+                     "class C {};\n"
+                     "void f() { A a; B b; }\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "class A {};\n"
+                         "namespace nb {\n"
+                         "namespace nc {\n"
+                         "class B {};\n"
+                         "class C {};\n"
+                         "void f() { A a; B b; }\n"
+                         "} // namespace nc\n"
+                         "} // namespace nb\n"
+                         "} // namespace na\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, SimpleMoveIntoAnotherNestedNamespace) {
+  NewNamespace = "na::nc";
+  std::string Code = "namespace na {\n"
+                     "namespace nb {\n"
+                     "class A {};\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "\n"
+                         "namespace nc {\n"
+                         "class A {};\n"
+                         "} // namespace nc\n"
+                         "} // namespace na\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, MoveIntoAnotherNestedNamespaceWithRef) {
+  NewNamespace = "na::nc";
+  std::string Code = "namespace na {\n"
+                     "class A {};\n"
+                     "namespace nb {\n"
+                     "class X { A a; };\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "class A {};\n"
+                         "\n"
+                         "namespace nc {\n"
+                         "class X { A a; };\n"
+                         "} // namespace nc\n"
+                         "} // namespace na\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, MoveIntoExistingNamespaceAndShortenRefs) {
+  std::string Code = "namespace x {\n"
+                     "namespace z {\n"
+                     "class Z {};\n"
+                     "} // namespace z\n"
+                     "namespace y {\n"
+                     "class T {};\n"
+                     "} // namespace y\n"
+                     "} // namespace x\n"
+                     "namespace na {\n"
+                     "class A{};\n"
+                     "namespace nb {\n"
+                     "class X { A a; x::z::Z zz; x::y::T t; };\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace x {\n"
+                         "namespace z {\n"
+                         "class Z {};\n"
+                         "} // namespace z\n"
+                         "namespace y {\n"
+                         "class T {};\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n"
+                         "namespace na {\n"
+                         "class A {};\n\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "class X { na::A a; z::Z zz; T t; };\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, SimpleMoveNestedNamespace) {
+  NewNamespace = "na::x::y";
+  std::string Code = "namespace na {\n"
+                     "class A {};\n"
+                     "namespace nb {\n"
+                     "class B {};\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "class A {};\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "class B {};\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n"
+                         "} // namespace na\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, SimpleMoveWithTypeRefs) {
+  std::string Code = "namespace na {\n"
+                     "class C_A {};\n"
+                     "namespace nc {\n"
+                     "class C_C {};"
+                     "} // namespace nc\n"
+                     "namespace nb {\n"
+                     "class C_X {\n"
+                     "public:\n"
+                     "  C_A a;\n"
+                     "  nc::C_C c;\n"
+                     "};\n"
+                     "class C_Y {\n"
+                     "  C_X x;\n"
+                     "};\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "class C_A {};\n"
+                         "namespace nc {\n"
+                         "class C_C {};"
+                         "} // namespace nc\n"
+                         "\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "class C_X {\n"
+                         "public:\n"
+                         "  na::C_A a;\n"
+                         "  na::nc::C_C c;\n"
+                         "};\n"
+                         "class C_Y {\n"
+                         "  C_X x;\n"
+                         "};\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, TypeLocInTemplateSpecialization) {
+  std::string Code = "namespace na {\n"
+                     "class A {};\n"
+                     "template <typename T>\n"
+                     "class B {};\n"
+                     "template <typename T1, typename T2>\n"
+                     "class Two {};\n"
+                     "namespace nc { class C {}; }\n"
+                     "} // na\n"
+                     "\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "void f() {\n"
+                     "  B<A> b;\n"
+                     "  B<nc::C> b_c;\n"
+                     "  Two<A, nc::C> two;\n"
+                     "}\n"
+                     "} // nb\n"
+                     "} // na\n";
+  std::string Expected = "namespace na {\n"
+                         "class A {};\n"
+                         "template <typename T>\n"
+                         "class B {};\n"
+                         "template <typename T1, typename T2>\n"
+                         "class Two {};\n"
+                         "namespace nc { class C {}; }\n"
+                         "} // na\n"
+                         "\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() {\n"
+                         "  na::B<na::A> b;\n"
+                         "  na::B<na::nc::C> b_c;\n"
+                         "  na::Two<na::A, na::nc::C> two;\n"
+                         "}\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, LeaveForwardDeclarationBehind) {
+  std::string Code = "namespace na {\n"
+                     "namespace nb {\n"
+                     "class FWD;\n"
+                     "class FWD2;\n"
+                     "class A {\n"
+                     "  FWD *fwd;\n"
+                     "};\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "namespace nb {\n"
+                         "class FWD;\n"
+                         "class FWD2;\n"
+                         "} // namespace nb\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "\n"
+                         "class A {\n"
+                         "  na::nb::FWD *fwd;\n"
+                         "};\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, InsertForwardDeclsProperly) {
+  std::string Code = "namespace na {\n"
+                     "namespace nb {\n"
+                     "\n"
+                     "class FWD;\n"
+                     "class FWD2;\n"
+                     "class A {\n"
+                     "  FWD *fwd;\n"
+                     "};\n"
+                     "\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "namespace nb {\n"
+                         "class FWD;\n"
+                         "class FWD2;\n"
+                         "} // namespace nb\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "\n"
+                         "class A {\n"
+                         "  na::nb::FWD *fwd;\n"
+                         "};\n"
+                         "\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, TemplateClassForwardDeclaration) {
+  std::string Code = "namespace na {\n"
+                     "namespace nb {\n"
+                     "class FWD;\n"
+                     "template<typename T> class FWD_TEMP;\n"
+                     "class A {\n"
+                     "  FWD *fwd;\n"
+                     "};\n"
+                     "template<typename T> class TEMP {};\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "namespace nb {\n"
+                         "class FWD;\n"
+                         "template<typename T> class FWD_TEMP;\n"
+                         "} // namespace nb\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "\n"
+                         "class A {\n"
+                         "  na::nb::FWD *fwd;\n"
+                         "};\n"
+                         "template<typename T> class TEMP {};\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, DontMoveForwardDeclarationInClass) {
+  std::string Code = "namespace na {\n"
+                     "namespace nb {\n"
+                     "class A {\n"
+                     "  class FWD;\n"
+                     "  FWD *fwd;\n"
+                     "  template<typename T> class FWD_TEMP;\n"
+                     "};\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "\n\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "class A {\n"
+                         "  class FWD;\n"
+                         "  FWD *fwd;\n"
+                         "  template<typename T> class FWD_TEMP;\n"
+                         "};\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, MoveFunctions) {
+  std::string Code = "namespace na {\n"
+                     "class C_A {};\n"
+                     "namespace nc {\n"
+                     "class C_C {};"
+                     "} // namespace nc\n"
+                     "namespace nb {\n"
+                     "void fwd();\n"
+                     "void f(C_A ca, nc::C_C cc) {\n"
+                     "  C_A ca_1 = ca;\n"
+                     "}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace na {\n"
+                         "class C_A {};\n"
+                         "namespace nc {\n"
+                         "class C_C {};"
+                         "} // namespace nc\n"
+                         "\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void fwd();\n"
+                         "void f(na::C_A ca, na::nc::C_C cc) {\n"
+                         "  na::C_A ca_1 = ca;\n"
+                         "}\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, FixUsingShadowDecl) {
+  std::string Code = "class GLOB {};\n"
+                     "using BLOG = GLOB;\n"
+                     "namespace na {\n"
+                     "namespace nc {\n"
+                     "class SAME {};\n"
+                     "}\n"
+                     "namespace nd {\n"
+                     "class SAME {};\n"
+                     "}\n"
+                     "namespace nb {\n"
+                     "using nc::SAME;\n"
+                     "using YO = nd::SAME;\n"
+                     "typedef nd::SAME IDENTICAL;\n"
+                     "void f(nd::SAME Same) {}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "class GLOB {};\n"
+                         "using BLOG = GLOB;\n"
+                         "namespace na {\n"
+                         "namespace nc {\n"
+                         "class SAME {};\n"
+                         "}\n"
+                         "namespace nd {\n"
+                         "class SAME {};\n"
+                         "}\n"
+                         "\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "using ::na::nc::SAME;\n"
+                         "using YO = na::nd::SAME;\n"
+                         "typedef na::nd::SAME IDENTICAL;\n"
+                         "void f(na::nd::SAME Same) {}\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, DontFixUsingShadowDeclInClasses) {
+  std::string Code = "namespace na {\n"
+                     "class A {};\n"
+                     "class Base { public: Base() {} void m() {} };\n"
+                     "namespace nb {\n"
+                     "class D : public Base {\n"
+                     "public:\n"
+                     "  using AA = A; using B = Base;\n"
+                     "  using Base::m; using Base::Base;\n"
+                     "};"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace na {\n"
+                         "class A {};\n"
+                         "class Base { public: Base() {} void m() {} };\n"
+                         "\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "class D : public na::Base {\n"
+                         "public:\n"
+                         "  using AA = na::A; using B = na::Base;\n"
+                         "  using Base::m; using Base::Base;\n"
+                         "};"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, TypeInNestedNameSpecifier) {
+  std::string Code =
+      "namespace na {\n"
+      "class C_A {\n"
+      "public:\n"
+      "  class Nested {\n"
+      "    public:\n"
+      "      static int NestedX;\n"
+      "      static void nestedFunc() {}\n"
+      "  };\n"
+      "};\n"
+      "namespace nb {\n"
+      "class C_X {\n"
+      "  C_A na;\n"
+      "  C_A::Nested nested;\n"
+      "  void f() {\n"
+      "    C_A::Nested::nestedFunc();\n"
+      "    int X = C_A::Nested::NestedX;\n"
+      "  }\n"
+      "};\n"
+      "}  // namespace nb\n"
+      "}  // namespace na\n";
+  std::string Expected =
+      "namespace na {\n"
+      "class C_A {\n"
+      "public:\n"
+      "  class Nested {\n"
+      "    public:\n"
+      "      static int NestedX;\n"
+      "      static void nestedFunc() {}\n"
+      "  };\n"
+      "};\n"
+      "\n"
+      "}  // namespace na\n"
+      "namespace x {\n"
+      "namespace y {\n"
+      "class C_X {\n"
+      "  na::C_A na;\n"
+      "  na::C_A::Nested nested;\n"
+      "  void f() {\n"
+      "    na::C_A::Nested::nestedFunc();\n"
+      "    int X = na::C_A::Nested::NestedX;\n"
+      "  }\n"
+      "};\n"
+      "}  // namespace y\n"
+      "}  // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, FixFunctionNameSpecifiers) {
+  std::string Code =
+      "namespace na {\n"
+      "class A {\n"
+      "public:\n"
+      "  static void f() {}\n"
+      "  static void g();\n"
+      "};\n"
+      "void A::g() {}"
+      "void a_f() {}\n"
+      "static void static_f() {}\n"
+      "namespace nb {\n"
+      "void f() { a_f(); static_f(); A::f(); }\n"
+      "void g() { f(); A::g(); }\n"
+      "}  // namespace nb\n"
+      "}  // namespace na\n";
+  std::string Expected =
+      "namespace na {\n"
+      "class A {\n"
+      "public:\n"
+      "  static void f() {}\n"
+      "  static void g();\n"
+      "};\n"
+      "void A::g() {}"
+      "void a_f() {}\n"
+      "static void static_f() {}\n"
+      "\n"
+      "}  // namespace na\n"
+      "namespace x {\n"
+      "namespace y {\n"
+      "void f() { na::a_f(); na::static_f(); na::A::f(); }\n"
+      "void g() { f(); na::A::g(); }\n"
+      "}  // namespace y\n"
+      "}  // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, FixOverloadedOperatorFunctionNameSpecifiers) {
+  std::string Code =
+      "namespace na {\n"
+      "class A {\n"
+      "public:\n"
+      "  int x;\n"
+      "  bool operator==(const A &RHS) const { return x == RHS.x; }\n"
+      "};\n"
+      "bool operator<(const A &LHS, const A &RHS) { return LHS.x == RHS.x; }\n"
+      "namespace nb {\n"
+      "bool f() {\n"
+      "  A x, y;\n"
+      "  auto f = operator<;\n"
+      "  return (x == y) && (x < y) && (operator<(x, y));\n"
+      "}\n"
+      "}  // namespace nb\n"
+      "}  // namespace na\n";
+  std::string Expected =
+      "namespace na {\n"
+      "class A {\n"
+      "public:\n"
+      "  int x;\n"
+      "  bool operator==(const A &RHS) const { return x == RHS.x; }\n"
+      "};\n"
+      "bool operator<(const A &LHS, const A &RHS) { return LHS.x == RHS.x; }\n"
+      "\n"
+      "}  // namespace na\n"
+      "namespace x {\n"
+      "namespace y {\n"
+      "bool f() {\n"
+      "  na::A x, y;\n"
+      "  auto f = na::operator<;\n"
+      // FIXME: function calls to overloaded operators are not fixed now even if
+      // they are referenced by qualified names.
+      "  return (x == y) && (x < y) && (operator<(x,y));\n"
+      "}\n"
+      "}  // namespace y\n"
+      "}  // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, FixNonCallingFunctionReferences) {
+  std::string Code = "namespace na {\n"
+                     "class A {\n"
+                     "public:\n"
+                     "  static void f() {}\n"
+                     "};\n"
+                     "void a_f() {}\n"
+                     "static void s_f() {}\n"
+                     "namespace nb {\n"
+                     "void f() {\n"
+                     "  auto *ref1 = A::f;\n"
+                     "  auto *ref2 = a_f;\n"
+                     "  auto *ref3 = s_f;\n"
+                     "}\n"
+                     "}  // namespace nb\n"
+                     "}  // namespace na\n";
+  std::string Expected =
+      "namespace na {\n"
+      "class A {\n"
+      "public:\n"
+      "  static void f() {}\n"
+      "};\n"
+      "void a_f() {}\n"
+      "static void s_f() {}\n"
+      "\n"
+      "}  // namespace na\n"
+      "namespace x {\n"
+      "namespace y {\n"
+      "void f() {\n"
+      "  auto *ref1 = na::A::f;\n"
+      "  auto *ref2 = na::a_f;\n"
+      "  auto *ref3 = na::s_f;\n"
+      "}\n"
+      "}  // namespace y\n"
+      "}  // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, MoveAndFixGlobalVariables) {
+  std::string Code = "namespace na {\n"
+                     "int GlobA;\n"
+                     "static int GlobAStatic = 0;\n"
+                     "namespace nc { int GlobC; }\n"
+                     "namespace nb {\n"
+                     "int GlobB;\n"
+                     "void f() {\n"
+                     "  int a = GlobA;\n"
+                     "  int b = GlobAStatic;\n"
+                     "  int c = nc::GlobC;\n"
+                     "}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace na {\n"
+                         "int GlobA;\n"
+                         "static int GlobAStatic = 0;\n"
+                         "namespace nc { int GlobC; }\n"
+                         "\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "int GlobB;\n"
+                         "void f() {\n"
+                         "  int a = na::GlobA;\n"
+                         "  int b = na::GlobAStatic;\n"
+                         "  int c = na::nc::GlobC;\n"
+                         "}\n"
+                         "}  // namespace y\n"
+                         "}  // namespace x\n";
+
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, DoNotFixStaticVariableOfClass) {
+  std::string Code = "namespace na {\n"
+                     "class A {\n"
+                     "public:\n"
+                     "static int A1;\n"
+                     "static int A2;\n"
+                     "};\n"
+                     "int A::A1 = 0;\n"
+                     "namespace nb {\n"
+                     "void f() {\n"
+                     "  int a = A::A1; int b = A::A2;\n"
+                     "}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace na {\n"
+                         "class A {\n"
+                         "public:\n"
+                         "static int A1;\n"
+                         "static int A2;\n"
+                         "};\n"
+                         "int A::A1 = 0;\n"
+                         "\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() {\n"
+                         "  int a = na::A::A1; int b = na::A::A2;\n"
+                         "}\n"
+                         "}  // namespace y\n"
+                         "}  // namespace x\n";
+
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, NoMisplaceAtEOF) {
+  std::string Code = "namespace na {\n"
+                     "namespace nb {\n"
+                     "class A;\n"
+                     "class B {};\n"
+                     "}"
+                     "}";
+  std::string Expected = "namespace na {\n"
+                         "namespace nb {\n"
+                         "class A;\n"
+                         "}\n"
+                         "}\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "\n"
+                         "class B {};\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, CommentsBeforeMovedClass) {
+  std::string Code = "namespace na {\n"
+                     "namespace nb {\n"
+                     "\n\n"
+                     "// Wild comments.\n"
+                     "\n"
+                     "// Comments.\n"
+                     "// More comments.\n"
+                     "class B {\n"
+                     "  // Private comments.\n"
+                     "  int a;\n"
+                     "};\n"
+                     "}\n"
+                     "}";
+  std::string Expected = "\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "\n\n"
+                         "// Wild comments.\n"
+                         "\n"
+                         "// Comments.\n"
+                         "// More comments.\n"
+                         "class B {\n"
+                         "  // Private comments.\n"
+                         "  int a;\n"
+                         "};\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingShadowDeclInGlobal) {
+  std::string Code = "namespace glob {\n"
+                     "class Glob {};\n"
+                     "void GFunc() {}\n"
+                     "}\n"
+                     "using glob::Glob;\n"
+                     "using glob::GFunc;\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "void f() { Glob g; GFunc(); }\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace glob {\n"
+                         "class Glob {};\n"
+                         "void GFunc() {}\n"
+                         "}\n"
+                         "using glob::Glob;\n"
+                         "using glob::GFunc;\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() { Glob g; GFunc(); }\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingShadowDeclsInAnonymousNamespaces) {
+  std::string Code = "namespace util {\n"
+                     "class Util {};\n"
+                     "void func() {}\n"
+                     "}\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "namespace {\n"
+                     "using ::util::Util;\n"
+                     "using ::util::func;\n"
+                     "void f() { Util u; func(); }\n"
+                     "}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace util {\n"
+                         "class Util {};\n"
+                         "void func() {}\n"
+                         "} // namespace util\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "namespace {\n"
+                         "using ::util::Util;\n"
+                         "using ::util::func;\n"
+                         "void f() { Util u; func(); }\n"
+                         "}\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingNamespaceInGlobal) {
+  std::string Code = "namespace glob {\n"
+                     "class Glob {};\n"
+                     "}\n"
+                     "using namespace glob;\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "void f() { Glob g; }\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace glob {\n"
+                         "class Glob {};\n"
+                         "}\n"
+                         "using namespace glob;\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() { Glob g; }\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, NamespaceAliasInGlobal) {
+  std::string Code = "namespace glob {\n"
+                     "class Glob {};\n"
+                     "}\n"
+                     "namespace glob2 { class Glob2 {}; }\n"
+                     "namespace gl = glob;\n"
+                     "namespace gl2 = glob2;\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "void f() { gl::Glob g; gl2::Glob2 g2; }\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected =
+      "namespace glob {\n"
+      "class Glob {};\n"
+      "}\n"
+      "namespace glob2 { class Glob2 {}; }\n"
+      "namespace gl = glob;\n"
+      "namespace gl2 = glob2;\n"
+      "\n"
+      "namespace x {\n"
+      "namespace y {\n"
+      "void f() { gl::Glob g; gl2::Glob2 g2; }\n"
+      "} // namespace y\n"
+      "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, NamespaceAliasInNamespace) {
+  std::string Code = "namespace glob {\n"
+                     "class Glob {};\n"
+                     "}\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "namespace gl = glob;\n"
+                     "void f() { gl::Glob g; }\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace glob {\n"
+                         "class Glob {};\n"
+                         "}\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "namespace gl = glob;\n"
+                         "void f() { gl::Glob g; }\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, NamespaceAliasInAncestorNamespace) {
+  NewNamespace = "na::nx";
+  std::string Code = "namespace glob {\n"
+                     "class Glob {};\n"
+                     "}\n"
+                     "namespace other { namespace gl = glob; }\n"
+                     "namespace na {\n"
+                     "namespace ga = glob;\n"
+                     "namespace nb {\n"
+                     "void f() { ga::Glob g; }\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace glob {\n"
+                         "class Glob {};\n"
+                         "}\n"
+                         "namespace other { namespace gl = glob; }\n"
+                         "namespace na {\n"
+                         "namespace ga = glob;\n"
+                         "\n"
+                         "namespace nx {\n"
+                         "void f() { ga::Glob g; }\n"
+                         "} // namespace nx\n"
+                         "} // namespace na\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, NamespaceAliasInOtherNamespace) {
+  std::string Code = "namespace glob {\n"
+                     "class Glob {};\n"
+                     "}\n"
+                     "namespace other { namespace gl = glob; }\n"
+                     "namespace na {\n"
+                     "namespace ga = glob;\n"
+                     "namespace nb {\n"
+                     "void f() { glob::Glob g; }\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace glob {\n"
+                         "class Glob {};\n"
+                         "}\n"
+                         "namespace other { namespace gl = glob; }\n"
+                         "namespace na {\n"
+                         "namespace ga = glob;\n"
+                         "\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() { glob::Glob g; }\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingDeclAfterReference) {
+  std::string Code = "namespace glob {\n"
+                     "class Glob {};\n"
+                     "}\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "void f() { glob::Glob g; }\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n"
+                     "using glob::Glob;\n"
+                     "using namespace glob;\n";
+
+  std::string Expected = "namespace glob {\n"
+                         "class Glob {};\n"
+                         "}\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() { glob::Glob g; }\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n"
+                         "using glob::Glob;\n"
+                         "using namespace glob;\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingNamespaceAfterReference) {
+  NewNamespace = "na::nc";
+  std::string Code = "namespace glob {\n"
+                     "class Glob {};\n"
+                     "}\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "void f() { glob::Glob g; }\n"
+                     "} // namespace nb\n"
+                     "using namespace glob;\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace glob {\n"
+                         "class Glob {};\n"
+                         "}\n"
+                         "namespace na {\n"
+                         "\n"
+                         "namespace nc {\n"
+                         "void f() { glob::Glob g; }\n"
+                         "} // namespace nc\n"
+                         "using namespace glob;\n"
+                         "} // namespace na\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingNamespaceAndUsingShadowInGlobal) {
+  std::string Code = "namespace glob1 {\n"
+                     "namespace glob2 {\n"
+                     "class Glob {};\n"
+                     "}\n"
+                     "}\n"
+                     "using glob1::glob2::Glob;\n"
+                     "using namespace glob1;\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "void f() { Glob g; }\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace glob1 {\n"
+                         "namespace glob2 {\n"
+                         "class Glob {};\n"
+                         "}\n"
+                         "}\n"
+                         "using glob1::glob2::Glob;\n"
+                         "using namespace glob1;\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() { Glob g; }\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingAliasInGlobal) {
+  std::string Code = "namespace glob {\n"
+                     "class Glob {};\n"
+                     "}\n"
+                     "using GLB = glob::Glob;\n"
+                     "using BLG = glob::Glob;\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "void f() { GLB g; BLG blg; }\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace glob {\n"
+                         "class Glob {};\n"
+                         "}\n"
+                         "using GLB = glob::Glob;\n"
+                         "using BLG = glob::Glob;\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() { GLB g; BLG blg; }\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingShadowDeclAndMovedNamespace) {
+  std::string Code = "namespace na { class C_A {};\n }\n"
+                     "using na::C_A;\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "class C_X {\n"
+                     "public:\n"
+                     "  C_A a;\n"
+                     "};\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na { class C_A {};\n }\n"
+                         "using na::C_A;\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "class C_X {\n"
+                         "public:\n"
+                         "  C_A a;\n"
+                         "};\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingNamespaceDeclAndMovedNamespace) {
+  std::string Code = "namespace na { class C_A {};\n }\n"
+                     "using namespace na;\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "class C_X {\n"
+                     "public:\n"
+                     "  C_A ca;\n"
+                     "};\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na { class C_A {};\n }\n"
+                         "using namespace na;\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "class C_X {\n"
+                         "public:\n"
+                         "  C_A ca;\n"
+                         "};\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingShadowDeclInFunction) {
+  std::string Code = "namespace glob {\n"
+                     "class Glob {};\n"
+                     "}\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "void f() {\n"
+                     "  using glob::Glob;\n"
+                     "  Glob g;\n"
+                     "}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace glob {\n"
+                         "class Glob {};\n"
+                         "}\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() {\n"
+                         "  using ::glob::Glob;\n"
+                         "  Glob g;\n"
+                         "}\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingShadowDeclInClass) {
+  std::string Code = "namespace na { class C_A {}; }\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "void f() {\n"
+                     "  using ::na::C_A;\n"
+                     "  C_A ca;\n"
+                     "}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na { class C_A {}; }\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() {\n"
+                         "  using ::na::C_A;\n"
+                         "  C_A ca;\n"
+                         "}\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingDeclInMovedNamespace) {
+  std::string Code = "namespace nx { void f(); }\n"
+                     "namespace na {\n"
+                     "using nx::f;\n"
+                     "namespace nb {\n"
+                     "void d() { f(); }\n"
+                     "} // nb\n"
+                     "} // na\n";
+
+  std::string Expected = "namespace nx { void f(); }\n"
+                         "namespace na {\n"
+                         "using nx::f;\n"
+                         "\n"
+                         "} // na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void d() { nx::f(); }\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingDeclInMovedNamespaceNotNested) {
+  OldNamespace = "na";
+  std::string Code = "namespace nx { void f(); }\n"
+                     "namespace na {\n"
+                     "using ::nx::f;\n"
+                     "void d() { f(); }\n"
+                     "} // na\n";
+
+  std::string Expected = "namespace nx { void f(); }\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "using ::nx::f;\n"
+                         "void d() { f(); }\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingDeclInMovedNamespaceMultiNested) {
+  OldNamespace = "a::b::c::d";
+  NewNamespace = "a::b::x::y";
+  std::string Code = "namespace nx { void f(); void g(); }\n"
+                     "namespace a {\n"
+                     "namespace b {\n"
+                     "using ::nx::f;\n"
+                     "namespace c {\n"
+                     "using ::nx::g;\n"
+                     "namespace d {\n"
+                     "void d() { f(); g(); }\n"
+                     "} // d\n"
+                     "} // c\n"
+                     "} // b\n"
+                     "} // a\n";
+
+  std::string Expected = "namespace nx { void f(); void g(); }\n"
+                         "namespace a {\n"
+                         "namespace b {\n"
+                         "using ::nx::f;\n"
+                         "namespace c {\n"
+                         "using ::nx::g;\n"
+                         "\n"
+                         "} // c\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void d() { f(); nx::g(); }\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n"
+                         "} // b\n"
+                         "} // a\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingShadowDeclInTheParentOfOldNamespace) {
+  OldNamespace = "nb::nc";
+  NewNamespace = "nb::nd";
+  std::string Code = "namespace na { class A {}; }\n"
+                     "namespace nb {\n"
+                     "using na::A;\n"
+                     "namespace nc {\n"
+                     "void d() { A a; }\n"
+                     "} // nc\n"
+                     "} // nb\n";
+
+  std::string Expected = "namespace na { class A {}; }\n"
+                         "namespace nb {\n"
+                         "using na::A;\n"
+                         "\n"
+                         "namespace nd {\n"
+                         "void d() { A a; }\n"
+                         "} // namespace nd\n"
+                         "} // nb\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingShadowDeclInOldNamespace) {
+  OldNamespace = "nb";
+  NewNamespace = "nc";
+  std::string Code = "namespace na { class A {}; }\n"
+                     "namespace nb {\n"
+                     "using na::A;\n"
+                     "void d() { A a; }\n"
+                     "struct X { A a; };\n"
+                     "} // nb\n";
+
+  std::string Expected = "namespace na { class A {}; }\n"
+                         "\n"
+                         "namespace nc {\n"
+                         "using ::na::A;\n"
+                         "void d() { A a; }\n"
+                         "struct X { A a; };\n"
+                         "} // namespace nc\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingShadowDeclOfTemplateClass) {
+  OldNamespace = "nb";
+  NewNamespace = "nc";
+  std::string Code = "namespace na {\n"
+                     "template <typename T>\n"
+                     "class A { T t; };\n"
+                     "} // namespace na\n"
+                     "namespace nb {\n"
+                     "using na::A;\n"
+                     "void d() { A<int> a; }\n"
+                     "} // nb\n";
+
+  std::string Expected = "namespace na {\n"
+                         "template <typename T>\n"
+                         "class A { T t; };\n"
+                         "} // namespace na\n"
+                         "\n"
+                         "namespace nc {\n"
+                         "using ::na::A;\n"
+                         "void d() { A<int> a; }\n"
+                         "} // namespace nc\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingShadowDeclOfTemplateFunction) {
+  OldNamespace = "nb";
+  NewNamespace = "nc";
+  std::string Code = "namespace na {\n"
+                     "template <typename T>\n"
+                     "void f() { T t; };\n"
+                     "} // namespace na\n"
+                     "namespace nb {\n"
+                     "using na::f;\n"
+                     "void d() { f<int>(); }\n"
+                     "} // nb\n";
+
+  std::string Expected = "namespace na {\n"
+                         "template <typename T>\n"
+                         "void f() { T t; };\n"
+                         "} // namespace na\n"
+                         "\n"
+                         "namespace nc {\n"
+                         "using ::na::f;\n"
+                         "void d() { f<int>(); }\n"
+                         "} // namespace nc\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingAliasDecl) {
+  std::string Code =
+      "namespace nx { namespace ny { class X {}; } }\n"
+      "namespace na {\n"
+      "namespace nb {\n"
+      "using Y = nx::ny::X;\n"
+      "void f() { Y y; }\n"
+      "} // namespace nb\n"
+      "} // namespace na\n";
+
+  std::string Expected = "namespace nx { namespace ny { class X {}; } }\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "using Y = nx::ny::X;\n"
+                         "void f() { Y y; }\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingAliasDeclInGlobal) {
+  std::string Code =
+      "namespace nx { namespace ny { class X {}; } }\n"
+      "using Y = nx::ny::X;\n"
+      "namespace na {\n"
+      "namespace nb {\n"
+      "void f() { Y y; }\n"
+      "} // namespace nb\n"
+      "} // namespace na\n";
+
+  std::string Expected = "namespace nx { namespace ny { class X {}; } }\n"
+                         "using Y = nx::ny::X;\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() { Y y; }\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+
+TEST_F(ChangeNamespaceTest, TypedefAliasDecl) {
+  std::string Code =
+      "namespace nx { namespace ny { class X {}; } }\n"
+      "namespace na {\n"
+      "namespace nb {\n"
+      "typedef nx::ny::X Y;\n"
+      "void f() { Y y; }\n"
+      "} // namespace nb\n"
+      "} // namespace na\n";
+
+  std::string Expected = "namespace nx { namespace ny { class X {}; } }\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "typedef nx::ny::X Y;\n"
+                         "void f() { Y y; }\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, DerivedClassWithConstructors) {
+  std::string Code =
+      "namespace nx { namespace ny { class X { public: X(int i) {} }; } }\n"
+      "namespace na {\n"
+      "namespace nb {\n"
+      "class A : public nx::ny::X {\n"
+      "public:\n"
+      "  A() : X(0) {}\n"
+      "  A(int i);\n"
+      "};\n"
+      "A::A(int i) : X(i) {}\n"
+      "} // namespace nb\n"
+      "} // namespace na\n";
+  std::string Expected =
+      "namespace nx { namespace ny { class X { public: X(int i) {} }; } }\n"
+      "\n\n"
+      "namespace x {\n"
+      "namespace y {\n"
+      "class A : public nx::ny::X {\n"
+      "public:\n"
+      "  A() : X(0) {}\n"
+      "  A(int i);\n"
+      "};\n"
+      "A::A(int i) : X(i) {}\n"
+      "} // namespace y\n"
+      "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, DerivedClassWithQualifiedConstructors) {
+  std::string Code =
+      "namespace nx { namespace ny { class X { public: X(int i) {} }; } }\n"
+      "namespace na {\n"
+      "namespace nb {\n"
+      "class A : public nx::ny::X {\n"
+      "public:\n"
+      "  A() : X::X(0) {}\n"
+      "  A(int i);\n"
+      "};\n"
+      "A::A(int i) : X::X(i) {}\n"
+      "} // namespace nb\n"
+      "} // namespace na\n";
+  std::string Expected =
+      "namespace nx { namespace ny { class X { public: X(int i) {} }; } }\n"
+      "\n\n"
+      "namespace x {\n"
+      "namespace y {\n"
+      "class A : public nx::ny::X {\n"
+      "public:\n"
+      "  A() : X::X(0) {}\n"
+      "  A(int i);\n"
+      "};\n"
+      "A::A(int i) : X::X(i) {}\n"
+      "} // namespace y\n"
+      "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, DerivedClassWithConstructorsAndTypeRefs) {
+  std::string Code =
+      "namespace nx { namespace ny { class X { public: X(int i) {} }; } }\n"
+      "namespace na {\n"
+      "namespace nb {\n"
+      "class A : public nx::ny::X {\n"
+      "public:\n"
+      "  A() : X(0) {}\n"
+      "  A(int i);\n"
+      "};\n"
+      "A::A(int i) : X(i) { X x(1);}\n"
+      "} // namespace nb\n"
+      "} // namespace na\n";
+  std::string Expected =
+      "namespace nx { namespace ny { class X { public: X(int i) {} }; } }\n"
+      "\n\n"
+      "namespace x {\n"
+      "namespace y {\n"
+      "class A : public nx::ny::X {\n"
+      "public:\n"
+      "  A() : X(0) {}\n"
+      "  A(int i);\n"
+      "};\n"
+      "A::A(int i) : X(i) { nx::ny::X x(1);}\n"
+      "} // namespace y\n"
+      "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, MoveToGlobalNamespace) {
+  NewNamespace = "";
+  std::string Code = "namespace na {\n"
+                     "class C_A {};\n"
+                     "namespace nc {\n"
+                     "class C_C {};"
+                     "} // namespace nc\n"
+                     "namespace nb {\n"
+                     "class C_X {\n"
+                     "public:\n"
+                     "  C_A a;\n"
+                     "  nc::C_C c;\n"
+                     "};\n"
+                     "class C_Y {\n"
+                     "  C_X x;\n"
+                     "};\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "class C_A {};\n"
+                         "namespace nc {\n"
+                         "class C_C {};"
+                         "} // namespace nc\n"
+                         "\n"
+                         "} // namespace na\n"
+                         "class C_X {\n"
+                         "public:\n"
+                         "  na::C_A a;\n"
+                         "  na::nc::C_C c;\n"
+                         "};\n"
+                         "class C_Y {\n"
+                         "  C_X x;\n"
+                         "};\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, KeepGlobalSpecifier) {
+  std::string Code = "class Glob {};\n"
+                      "namespace na {\n"
+                     "class C_A {};\n"
+                     "namespace nc {\n"
+                     "class C_C {};"
+                     "} // namespace nc\n"
+                     "namespace nb {\n"
+                     "class C_X {\n"
+                     "public:\n"
+                     "  ::Glob glob_1;\n"
+                     "  Glob glob_2;\n"
+                     "  C_A a_1;\n"
+                     "  ::na::C_A a_2;\n"
+                     "  nc::C_C c;\n"
+                     "};\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "class Glob {};\n"
+                         "namespace na {\n"
+                         "class C_A {};\n"
+                         "namespace nc {\n"
+                         "class C_C {};"
+                         "} // namespace nc\n"
+                         "\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "class C_X {\n"
+                         "public:\n"
+                         "  ::Glob glob_1;\n"
+                         "  Glob glob_2;\n"
+                         "  na::C_A a_1;\n"
+                         "  ::na::C_A a_2;\n"
+                         "  na::nc::C_C c;\n"
+                         "};\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, UsingAliasInTemplate) {
+  NewNamespace = "na::nb::nc";
+  std::string Code = "namespace some_ns {\n"
+                     "template <typename T, typename S>\n"
+                     "class G {};\n"
+                     "} // namespace some_ns\n"
+                     "namespace na {\n"
+                     "template<typename P>\n"
+                     "using GG = some_ns::G<int, P>;\n"
+                     "} // namespace na\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "void f() {\n"
+                     "  GG<float> g;\n"
+                     "}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace some_ns {\n"
+                         "template <typename T, typename S>\n"
+                         "class G {};\n"
+                         "} // namespace some_ns\n"
+                         "namespace na {\n"
+                         "template<typename P>\n"
+                         "using GG = some_ns::G<int, P>;\n"
+                         "} // namespace na\n"
+                         "namespace na {\n"
+                         "namespace nb {\n"
+                         "namespace nc {\n"
+                         "void f() {\n"
+                         "  GG<float> g;\n"
+                         "}\n"
+                         "} // namespace nc\n"
+                         "} // namespace nb\n"
+                         "} // namespace na\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, TemplateUsingAliasInBaseClass) {
+  NewNamespace = "na::nb::nc";
+  std::string Code = "namespace some_ns {\n"
+                     "template <typename T, typename S>\n"
+                     "class G {};\n"
+                     "} // namespace some_ns\n"
+                     "namespace na {\n"
+                     "class Base {\n"
+                     "public:\n"
+                     "  template<typename P>\n"
+                     "  using GG = some_ns::G<int, P>;\n"
+                     "\n"
+                     "  struct Nested {};\n"
+                     "};\n"
+                     "class Derived : public Base {};\n"
+                     "} // namespace na\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "void f() {\n"
+                     "  Derived::GG<float> g;\n"
+                     "  const Derived::GG<int> gg;\n"
+                     "  const Derived::GG<int>* gg_ptr;\n"
+                     "  struct Derived::Nested nested;\n"
+                     "  const struct Derived::Nested *nested_ptr;\n"
+                     "}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace some_ns {\n"
+                         "template <typename T, typename S>\n"
+                         "class G {};\n"
+                         "} // namespace some_ns\n"
+                         "namespace na {\n"
+                         "class Base {\n"
+                         "public:\n"
+                         "  template<typename P>\n"
+                         "  using GG = some_ns::G<int, P>;\n"
+                         "\n"
+                         "  struct Nested {};\n"
+                         "};\n"
+                         "class Derived : public Base {};\n"
+                         "} // namespace na\n"
+                         "namespace na {\n"
+                         "namespace nb {\n"
+                         "namespace nc {\n"
+                         "void f() {\n"
+                         "  Derived::GG<float> g;\n"
+                         "  const Derived::GG<int> gg;\n"
+                         "  const Derived::GG<int>* gg_ptr;\n"
+                         "  struct Derived::Nested nested;\n"
+                         "  const struct Derived::Nested *nested_ptr;\n"
+                         "}\n"
+                         "} // namespace nc\n"
+                         "} // namespace nb\n"
+                         "} // namespace na\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, ExistingNamespaceConflictWithNewNamespace) {
+  OldNamespace = "nx";
+  NewNamespace = "ny::na::nc";
+  std::string Code = "namespace na {\n"
+                     "class A {};\n"
+                     "} // namespace na\n"
+                     "namespace nb {\n"
+                     "class B {};\n"
+                     "} // namespace nb\n"
+                     "namespace nx {\n"
+                     "class X {\n"
+                     " na::A a; nb::B b;\n"
+                     "};\n"
+                     "} // namespace nx\n";
+  std::string Expected = "namespace na {\n"
+                         "class A {};\n"
+                         "} // namespace na\n"
+                         "namespace nb {\n"
+                         "class B {};\n"
+                         "} // namespace nb\n"
+                         "\n"
+                         "namespace ny {\n"
+                         "namespace na {\n"
+                         "namespace nc {\n"
+                         "class X {\n"
+                         " ::na::A a; nb::B b;\n"
+                         "};\n"
+                         "} // namespace nc\n"
+                         "} // namespace na\n"
+                         "} // namespace ny\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, SymbolConflictWithNewNamespace) {
+  OldNamespace = "nx";
+  NewNamespace = "ny::na::nc";
+  std::string Code = "namespace na {\n"
+                     "class A {};\n"
+                     "namespace nb {\n"
+                     "class B {};\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n"
+                     "namespace ny {\n"
+                     "class Y {};\n"
+                     "}\n"
+                     "namespace nx {\n"
+                     "class X {\n"
+                     "  na::A a; na::nb::B b;\n"
+                     "  ny::Y y;"
+                     "};\n"
+                     "} // namespace nx\n";
+  std::string Expected = "namespace na {\n"
+                         "class A {};\n"
+                         "namespace nb {\n"
+                         "class B {};\n"
+                         "} // namespace nb\n"
+                         "} // namespace na\n"
+                         "namespace ny {\n"
+                         "class Y {};\n"
+                         "}\n"
+                         "\n"
+                         "namespace ny {\n"
+                         "namespace na {\n"
+                         "namespace nc {\n"
+                         "class X {\n"
+                         "  ::na::A a; ::na::nb::B b;\n"
+                         "  Y y;\n"
+                         "};\n"
+                         "} // namespace nc\n"
+                         "} // namespace na\n"
+                         "} // namespace ny\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, ShortenNamespaceSpecifier) {
+  OldNamespace = "nx";
+  NewNamespace = "ny::na";
+  std::string Code = "class G {};\n"
+                     "namespace ny {\n"
+                     "class Y {};\n"
+                     "namespace na {\n"
+                     "class A {};\n"
+                     "namespace nc { class C {}; } // namespace nc\n"
+                     "}\n // namespace na\n"
+                     "}\n // namespace ny\n"
+                     "namespace nx {\n"
+                     "class X {\n"
+                     " G g; ny::Y y; ny::na::A a; ny::na::nc::C c;\n"
+                     "};\n"
+                     "} // namespace nx\n";
+  std::string Expected = "class G {};\n"
+                         "namespace ny {\n"
+                         "class Y {};\n"
+                         "namespace na {\n"
+                         "class A {};\n"
+                         "namespace nc { class C {}; } // namespace nc\n"
+                         "}\n // namespace na\n"
+                         "}\n // namespace ny\n"
+                         "\n"
+                         "namespace ny {\n"
+                         "namespace na {\n"
+                         "class X {\n"
+                         " G g; Y y; A a; nc::C c;\n"
+                         "};\n"
+                         "} // namespace na\n"
+                         "} // namespace ny\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, ShortenNamespaceSpecifierInAnonymousNamespace) {
+  OldNamespace = "nx";
+  NewNamespace = "ny::na";
+  std::string Code = "class G {};\n"
+                     "namespace ny {\n"
+                     "class Y {};\n"
+                     "namespace na {\n"
+                     "class A {};\n"
+                     "namespace nc { class C {}; } // namespace nc\n"
+                     "}\n // namespace na\n"
+                     "}\n // namespace ny\n"
+                     "namespace nx {\n"
+                     "namespace {\n"
+                     "class X {\n"
+                     " G g; ::ny::Y y; ::ny::na::A a; ::ny::na::nc::C c;\n"
+                     "};\n"
+                     "} // namespace\n"
+                     "} // namespace nx\n";
+  std::string Expected = "class G {};\n"
+                         "namespace ny {\n"
+                         "class Y {};\n"
+                         "namespace na {\n"
+                         "class A {};\n"
+                         "namespace nc { class C {}; } // namespace nc\n"
+                         "}\n // namespace na\n"
+                         "}\n // namespace ny\n"
+                         "\n"
+                         "namespace ny {\n"
+                         "namespace na {\n"
+                         "namespace {\n"
+                         "class X {\n"
+                         " G g; Y y; A a; nc::C c;\n"
+                         "};\n"
+                         "} // namespace\n"
+                         "} // namespace na\n"
+                         "} // namespace ny\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, SimpleMoveEnum) {
+  std::string Code = "namespace na {\n"
+                     "namespace nb {\n"
+                     "enum class X { X1, X2 };\n"
+                     "enum Y { Y1, Y2 };\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "\n\nnamespace x {\n"
+                         "namespace y {\n"
+                         "enum class X { X1, X2 };\n"
+                         "enum Y { Y1, Y2 };\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, ReferencesToEnums) {
+  std::string Code = "enum Glob { G1, G2 };\n"
+                     "namespace na {\n"
+                     "enum class X { X1 };\n"
+                     "enum Y { Y1, Y2 };\n"
+                     "namespace nb {\n"
+                     "void f() {\n"
+                     "  Glob g1 = Glob::G1;\n"
+                     "  Glob g2 = G2;\n"
+                     "  X x1 = X::X1;\n"
+                     "  Y y1 = Y::Y1;\n"
+                     "  Y y2 = Y2;\n"
+                     "}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "enum Glob { G1, G2 };\n"
+                         "namespace na {\n"
+                         "enum class X { X1 };\n"
+                         "enum Y { Y1, Y2 };\n"
+                         "\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() {\n"
+                         "  Glob g1 = Glob::G1;\n"
+                         "  Glob g2 = G2;\n"
+                         "  na::X x1 = na::X::X1;\n"
+                         "  na::Y y1 = na::Y::Y1;\n"
+                         "  na::Y y2 = na::Y2;\n"
+                         "}\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, NoRedundantEnumUpdate) {
+  std::string Code = "namespace ns {\n"
+                     "enum class X { X1 };\n"
+                     "enum Y { Y1, Y2 };\n"
+                     "} // namespace ns\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "void f() {\n"
+                     "  ns::X x1 = ns::X::X1;\n"
+                     "  ns::Y y1 = ns::Y::Y1;\n"
+                     "  ns::Y y2 = ns::Y2;\n"
+                     "}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace ns {\n"
+                         "enum class X { X1 };\n"
+                         "enum Y { Y1, Y2 };\n"
+                         "} // namespace ns\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() {\n"
+                         "  ns::X x1 = ns::X::X1;\n"
+                         "  ns::Y y1 = ns::Y::Y1;\n"
+                         "  ns::Y y2 = ns::Y2;\n"
+                         "}\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  ;
+
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, EnumsAndUsingShadows) {
+  std::string Code = "namespace ns {\n"
+                     "enum class X { X1 };\n"
+                     "enum Y { Y1, Y2, Y3 };\n"
+                     "} // namespace ns\n"
+                     "using ns::X;\n"
+                     "using ns::Y;\n"
+                     "using ns::Y::Y2;\n"
+                     "using ns::Y::Y3;\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "void f() {\n"
+                     "  X x1 = X::X1;\n"
+                     "  Y y1 = Y::Y1;\n"
+                     "  Y y2 = Y2;\n"
+                     "  Y y3 = Y3;\n"
+                     "}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace ns {\n"
+                         "enum class X { X1 };\n"
+                         "enum Y { Y1, Y2, Y3 };\n"
+                         "} // namespace ns\n"
+                         "using ns::X;\n"
+                         "using ns::Y;\n"
+                         "using ns::Y::Y2;\n"
+                         "using ns::Y::Y3;\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() {\n"
+                         "  X x1 = X::X1;\n"
+                         "  Y y1 = Y::Y1;\n"
+                         "  Y y2 = Y2;\n"
+                         "  Y y3 = Y3;\n"
+                         "}\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, EnumsAndAliases) {
+  std::string Code = "namespace ns {\n"
+                     "enum class X { X1 };\n"
+                     "enum Y { Y1, Y2, Y3 };\n"
+                     "} // namespace ns\n"
+                     "typedef ns::X TX;\n"
+                     "typedef ns::Y TY;\n"
+                     "using UX = ns::X;\n"
+                     "using UY = ns::Y;\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "void f() {\n"
+                     "  ns::X x1 = ns::X::X1;\n"
+                     "  TX tx1 = TX::X1;\n"
+                     "  UX ux1 = UX::X1;\n"
+                     "  ns::Y y1 = ns::Y::Y1;\n"
+                     "  TY ty1 = TY::Y1;\n"
+                     "  UY uy1 = UY::Y1;\n"
+                     "}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace ns {\n"
+                         "enum class X { X1 };\n"
+                         "enum Y { Y1, Y2, Y3 };\n"
+                         "} // namespace ns\n"
+                         "typedef ns::X TX;\n"
+                         "typedef ns::Y TY;\n"
+                         "using UX = ns::X;\n"
+                         "using UY = ns::Y;\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() {\n"
+                         "  ns::X x1 = ns::X::X1;\n"
+                         "  TX tx1 = TX::X1;\n"
+                         "  UX ux1 = UX::X1;\n"
+                         "  ns::Y y1 = ns::Y::Y1;\n"
+                         "  TY ty1 = TY::Y1;\n"
+                         "  UY uy1 = UY::Y1;\n"
+                         "}\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, EnumInClass) {
+  std::string Code = "namespace na {\n"
+                     "struct X { enum E { E1 }; };\n"
+                     "namespace nb {\n"
+                     "void f() {\n"
+                     "  X::E e = X::E1;\n"
+                     "  X::E ee = X::E::E1;\n"
+                     "}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "struct X { enum E { E1 }; };\n"
+                         "\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() {\n"
+                         "  na::X::E e = na::X::E1;\n"
+                         "  na::X::E ee = na::X::E::E1;\n"
+                         "}\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, TypeAsTemplateParameter) {
+  std::string Code = "namespace na {\n"
+                     "struct X {};\n"
+                     "namespace nb {\n"
+                     "template <typename TT>\n"
+                     "void TempTemp(const TT& t) {\n"
+                     "  TT tmp;\n"
+                     "}\n"
+                     "template <typename T>\n"
+                     "void Temp(const T& t) {\n"
+                     "  T tmp = t;\n"
+                     "  TempTemp(tmp);\n"
+                     "  TempTemp(t);\n"
+                     "}\n"
+                     "void f() {\n"
+                     "  X x;\n"
+                     "  Temp(x);\n"
+                     "}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "struct X {};\n"
+                         "\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "template <typename TT>\n"
+                         "void TempTemp(const TT& t) {\n"
+                         "  TT tmp;\n"
+                         "}\n"
+                         "template <typename T>\n"
+                         "void Temp(const T& t) {\n"
+                         "  T tmp = t;\n"
+                         "  TempTemp(tmp);\n"
+                         "  TempTemp(t);\n"
+                         "}\n"
+                         "void f() {\n"
+                         "  na::X x;\n"
+                         "  Temp(x);\n"
+                         "}\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, DefaultMoveConstructors) {
+  std::string Code = "namespace na {\n"
+                     "class B {\n"
+                     " public:\n"
+                     "  B() = default;\n"
+                     "  // Allow move only.\n"
+                     "  B(B&&) = default;\n"
+                     "  B& operator=(B&&) = default;\n"
+                     "  B(const B&) = delete;\n"
+                     "  B& operator=(const B&) = delete;\n"
+                     " private:\n"
+                     "  int ref_;\n"
+                     "};\n"
+                     "} // namespace na\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "class A {\n"
+                     "public:\n"
+                     "  A() = default;\n"
+                     "  A(A&&) = default;\n"
+                     "  A& operator=(A&&) = default;\n"
+                     "private:\n"
+                     "  B b;\n"
+                     "  A(const A&) = delete;\n"
+                     "  A& operator=(const A&) = delete;\n"
+                     "};\n"
+                     "void f() { A a; a = A(); A aa = A(); }\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "class B {\n"
+                         " public:\n"
+                         "  B() = default;\n"
+                         "  // Allow move only.\n"
+                         "  B(B&&) = default;\n"
+                         "  B& operator=(B&&) = default;\n"
+                         "  B(const B&) = delete;\n"
+                         "  B& operator=(const B&) = delete;\n"
+                         " private:\n"
+                         "  int ref_;\n"
+                         "};\n"
+                         "} // namespace na\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "class A {\n"
+                         "public:\n"
+                         "  A() = default;\n"
+                         "  A(A&&) = default;\n"
+                         "  A& operator=(A&&) = default;\n"
+                         "private:\n"
+                         "  na::B b;\n"
+                         "  A(const A&) = delete;\n"
+                         "  A& operator=(const A&) = delete;\n"
+                         "};\n"
+                         "void f() { A a; a = A(); A aa = A(); }\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, InjectedClassNameInFriendDecl) {
+  OldNamespace = "d";
+  NewNamespace = "e";
+  std::string Code = "namespace a{\n"
+                     "template <typename T>\n"
+                     "class Base {\n"
+                     " public:\n"
+                     "  void f() {\n"
+                     "    T t;\n"
+                     "    t.priv();\n"
+                     "  }\n"
+                     "};\n"
+                     "}  // namespace a\n"
+                     "namespace d {\n"
+                     "class D : public a::Base<D> {\n"
+                     " private:\n"
+                     "  friend class Base<D>;\n"
+                     "  void priv() {}\n"
+                     "  Base b;\n"
+                     "};\n"
+                     "\n"
+                     "void f() {\n"
+                     "  D d;\n"
+                     "  a:: Base<D> b;\n"
+                     "  b.f();\n"
+                     "}\n"
+                     "}  // namespace d\n";
+  std::string Expected = "namespace a{\n"
+                         "template <typename T>\n"
+                         "class Base {\n"
+                         " public:\n"
+                         "  void f() {\n"
+                         "    T t;\n"
+                         "    t.priv();\n"
+                         "  }\n"
+                         "};\n"
+                         "}  // namespace a\n"
+                         "\n"
+                         "namespace e {\n"
+                         "class D : public a::Base<D> {\n"
+                         " private:\n"
+                         "  friend class Base<D>;\n"
+                         "  void priv() {}\n"
+                         "  a::Base b;\n"
+                         "};\n"
+                         "\n"
+                         "void f() {\n"
+                         "  D d;\n"
+                         "  a::Base<D> b;\n"
+                         "  b.f();\n"
+                         "}\n"
+                         "}  // namespace e\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+} // anonymous namespace
+} // namespace change_namespace
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp
new file mode 100644
index 0000000..85aaebf
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp
@@ -0,0 +1,55 @@
+//===- clang-apply-replacements/ApplyReplacementsTest.cpp
+//----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang-apply-replacements/Tooling/ApplyReplacements.h"
+#include "clang/Format/Format.h"
+#include "gtest/gtest.h"
+
+using namespace clang::replace;
+using namespace llvm;
+
+namespace clang {
+namespace tooling {
+
+static TUDiagnostics
+makeTUDiagnostics(const std::string &MainSourceFile, StringRef DiagnosticName,
+                  const DiagnosticMessage &Message,
+                  const StringMap<Replacements> &Replacements,
+                  StringRef BuildDirectory) {
+  TUDiagnostics TUs;
+  TUs.push_back({MainSourceFile,
+                 {{DiagnosticName,
+                   Message,
+                   Replacements,
+                   {},
+                   Diagnostic::Warning,
+                   BuildDirectory}}});
+  return TUs;
+}
+
+// Test to ensure diagnostics with no fixes, will be merged correctly
+// before applying.
+TEST(ApplyReplacementsTest, mergeDiagnosticsWithNoFixes) {
+  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions());
+  DiagnosticsEngine Diagnostics(
+      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), DiagOpts.get());
+  FileManager Files((FileSystemOptions()));
+  SourceManager SM(Diagnostics, Files);
+  TUReplacements TURs;
+  TUDiagnostics TUs =
+      makeTUDiagnostics("path/to/source.cpp", "diagnostic", {}, {}, "path/to");
+  FileToChangesMap ReplacementsMap;
+
+  EXPECT_TRUE(mergeAndDeduplicate(TURs, TUs, ReplacementsMap, SM));
+  EXPECT_TRUE(ReplacementsMap.empty());
+}
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-apply-replacements/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-apply-replacements/CMakeLists.txt
new file mode 100644
index 0000000..9e5fac2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-apply-replacements/CMakeLists.txt
@@ -0,0 +1,20 @@
+get_filename_component(ClangApplyReplacementsLocation
+  "${CMAKE_CURRENT_SOURCE_DIR}/../../clang-apply-replacements/include" REALPATH)
+get_filename_component(CommonIncLocation
+  "${CMAKE_CURRENT_SOURCE_DIR}/../include" REALPATH)
+include_directories(
+  ${ClangApplyReplacementsLocation}
+  ${CommonIncLocation}
+  )
+
+add_extra_unittest(ClangApplyReplacementsTests
+  ApplyReplacementsTest.cpp
+  )
+
+target_link_libraries(ClangApplyReplacementsTests
+  PRIVATE
+  clangApplyReplacements
+  clangBasic
+  clangToolingCore
+  clangToolingRefactor
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-move/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-move/CMakeLists.txt
new file mode 100644
index 0000000..fea15e1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-move/CMakeLists.txt
@@ -0,0 +1,29 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  )
+
+get_filename_component(INCLUDE_FIXER_SOURCE_DIR
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../clang-move REALPATH)
+include_directories(
+  ${INCLUDE_FIXER_SOURCE_DIR}
+  )
+
+# We'd like to clang/unittests/Tooling/RewriterTestContext.h in the test.
+include_directories(${CLANG_SOURCE_DIR})
+
+add_extra_unittest(ClangMoveTests
+  ClangMoveTests.cpp
+  )
+
+target_link_libraries(ClangMoveTests
+  PRIVATE
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFormat
+  clangFrontend
+  clangMove
+  clangRewrite
+  clangTooling
+  clangToolingCore
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp
new file mode 100644
index 0000000..45e3f68
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp
@@ -0,0 +1,635 @@
+//===-- ClangMoveTest.cpp - clang-move unit tests -------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangMove.h"
+#include "unittests/Tooling/RewriterTestContext.h"
+#include "clang/Format/Format.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/StringRef.h"
+#include "gtest/gtest.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace move {
+namespace {
+
+const char TestHeader[] = "namespace a {\n"
+                          "class C1; // test\n"
+                          "template <typename T> class C2;\n"
+                          "namespace b {\n"
+                          "// This is a Foo class\n"
+                          "// which is used in\n"
+                          "// test.\n"
+                          "class Foo {\n"
+                          "public:\n"
+                          "  void f();\n"
+                          "\n"
+                          "private:\n"
+                          "  C1 *c1;\n"
+                          "  static int b;\n"
+                          "}; // abc\n"
+                          "\n"
+                          "class Foo2 {\n"
+                          "public:\n"
+                          "  int f();\n"
+                          "};\n"
+                          "} // namespace b\n"
+                          "} // namespace a\n";
+
+const char TestCC[] = "#include \"foo.h\"\n"
+                      "namespace a {\n"
+                      "namespace b {\n"
+                      "namespace {\n"
+                      "// comment1.\n"
+                      "void f1() {}\n"
+                      "/// comment2.\n"
+                      "int kConstInt1 = 0;\n"
+                      "} // namespace\n"
+                      "\n"
+                      "/* comment 3*/\n"
+                      "static int kConstInt2 = 1;\n"
+                      "\n"
+                      "/** comment4\n"
+                      " */\n"
+                      "static int help() {\n"
+                      "  int a = 0;\n"
+                      "  return a;\n"
+                      "}\n"
+                      "\n"
+                      "// comment5\n"
+                      "// comment5\n"
+                      "void Foo::f() {\n"
+                      "  f1();\n"
+                      "  kConstInt1;\n"
+                      "  kConstInt2;\n"
+                      "  help();\n"
+                      "}\n"
+                      "\n"
+                      "/////////////\n"
+                      "// comment //\n"
+                      "/////////////\n"
+                      "int Foo::b = 2;\n"
+                      "int Foo2::f() {\n"
+                      "  kConstInt1;\n"
+                      "  kConstInt2;\n"
+                      "  help();\n"
+                      "  f1();\n"
+                      "  return 1;\n"
+                      "}\n"
+                      "} // namespace b\n"
+                      "} // namespace a\n";
+
+const char ExpectedTestHeader[] = "namespace a {\n"
+                                  "class C1; // test\n"
+                                  "template <typename T> class C2;\n"
+                                  "namespace b {\n"
+                                  "\n"
+                                  "class Foo2 {\n"
+                                  "public:\n"
+                                  "  int f();\n"
+                                  "};\n"
+                                  "} // namespace b\n"
+                                  "} // namespace a\n";
+
+const char ExpectedTestCC[] = "#include \"foo.h\"\n"
+                              "namespace a {\n"
+                              "namespace b {\n"
+                              "namespace {\n"
+                              "// comment1.\n"
+                              "void f1() {}\n"
+                              "/// comment2.\n"
+                              "int kConstInt1 = 0;\n"
+                              "} // namespace\n"
+                              "\n"
+                              "/* comment 3*/\n"
+                              "static int kConstInt2 = 1;\n"
+                              "\n"
+                              "/** comment4\n"
+                              " */\n"
+                              "static int help() {\n"
+                              "  int a = 0;\n"
+                              "  return a;\n"
+                              "}\n"
+                              "\n"
+                              "int Foo2::f() {\n"
+                              "  kConstInt1;\n"
+                              "  kConstInt2;\n"
+                              "  help();\n"
+                              "  f1();\n"
+                              "  return 1;\n"
+                              "}\n"
+                              "} // namespace b\n"
+                              "} // namespace a\n";
+
+const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"
+                                 "#define NEW_FOO_H\n"
+                                 "\n"
+                                 "namespace a {\n"
+                                 "class C1; // test\n"
+                                 "\n"
+                                 "template <typename T> class C2;\n"
+                                 "namespace b {\n"
+                                 "// This is a Foo class\n"
+                                 "// which is used in\n"
+                                 "// test.\n"
+                                 "class Foo {\n"
+                                 "public:\n"
+                                 "  void f();\n"
+                                 "\n"
+                                 "private:\n"
+                                 "  C1 *c1;\n"
+                                 "  static int b;\n"
+                                 "}; // abc\n"
+                                 "} // namespace b\n"
+                                 "} // namespace a\n"
+                                 "\n"
+                                 "#endif // NEW_FOO_H\n";
+
+const char ExpectedNewCC[] = "namespace a {\n"
+                             "namespace b {\n"
+                             "namespace {\n"
+                             "// comment1.\n"
+                             "void f1() {}\n"
+                             "\n"
+                             "/// comment2.\n"
+                             "int kConstInt1 = 0;\n"
+                             "} // namespace\n"
+                             "\n"
+                             "/* comment 3*/\n"
+                             "static int kConstInt2 = 1;\n"
+                             "\n"
+                             "/** comment4\n"
+                             " */\n"
+                             "static int help() {\n"
+                             "  int a = 0;\n"
+                             "  return a;\n"
+                             "}\n"
+                             "\n"
+                             "// comment5\n"
+                             "// comment5\n"
+                             "void Foo::f() {\n"
+                             "  f1();\n"
+                             "  kConstInt1;\n"
+                             "  kConstInt2;\n"
+                             "  help();\n"
+                             "}\n"
+                             "\n"
+                             "/////////////\n"
+                             "// comment //\n"
+                             "/////////////\n"
+                             "int Foo::b = 2;\n"
+                             "} // namespace b\n"
+                             "} // namespace a\n";
+
+#ifdef _WIN32
+const char WorkingDir[] = "C:\\test";
+#else
+const char WorkingDir[] = "/test";
+#endif
+
+const char TestHeaderName[] = "foo.h";
+const char TestCCName[] = "foo.cc";
+
+std::map<std::string, std::string>
+runClangMoveOnCode(const move::MoveDefinitionSpec &Spec,
+                   const char *const Header = TestHeader,
+                   const char *const CC = TestCC,
+                   DeclarationReporter *const Reporter = nullptr) {
+  clang::RewriterTestContext Context;
+
+  Context.InMemoryFileSystem->setCurrentWorkingDirectory(WorkingDir);
+
+  std::map<llvm::StringRef, clang::FileID> FileToFileID;
+
+  auto CreateFiles = [&Context, &FileToFileID](llvm::StringRef Name,
+                                               llvm::StringRef Code) {
+    if (!Name.empty()) {
+      FileToFileID[Name] = Context.createInMemoryFile(Name, Code);
+    }
+  };
+  CreateFiles(Spec.NewCC, "");
+  CreateFiles(Spec.NewHeader, "");
+  CreateFiles(TestHeaderName, Header);
+  CreateFiles(TestCCName, CC);
+
+  std::map<std::string, tooling::Replacements> FileToReplacements;
+  ClangMoveContext MoveContext = {Spec, FileToReplacements, WorkingDir, "LLVM",
+                                  Reporter != nullptr};
+
+  auto Factory = llvm::make_unique<clang::move::ClangMoveActionFactory>(
+      &MoveContext, Reporter);
+
+ // std::string IncludeArg = Twine("-I" + WorkingDir;
+  tooling::runToolOnCodeWithArgs(
+      Factory->create(), CC, Context.InMemoryFileSystem,
+      {"-std=c++11", "-fparse-all-comments", "-I."}, TestCCName, "clang-move",
+      std::make_shared<PCHContainerOperations>());
+  formatAndApplyAllReplacements(FileToReplacements, Context.Rewrite, "llvm");
+  // The Key is file name, value is the new code after moving the class.
+  std::map<std::string, std::string> Results;
+  for (const auto &It : FileToReplacements) {
+    // The path may come out as "./foo.h", normalize to "foo.h".
+    SmallString<32> FilePath (It.first);
+    llvm::sys::path::remove_dots(FilePath);
+    Results[FilePath.str().str()] = Context.getRewrittenText(FileToFileID[FilePath]);
+  }
+  return Results;
+}
+
+TEST(ClangMove, MoveHeaderAndCC) {
+  move::MoveDefinitionSpec Spec;
+  Spec.Names = {std::string("a::b::Foo")};
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+  std::string ExpectedHeader = "#include \"" + Spec.NewHeader + "\"\n\n";
+  auto Results = runClangMoveOnCode(Spec);
+  EXPECT_EQ(ExpectedTestHeader, Results[Spec.OldHeader]);
+  EXPECT_EQ(ExpectedTestCC, Results[Spec.OldCC]);
+  EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
+  EXPECT_EQ(ExpectedHeader + ExpectedNewCC, Results[Spec.NewCC]);
+}
+
+TEST(ClangMove, MoveHeaderOnly) {
+  move::MoveDefinitionSpec Spec;
+  Spec.Names = {std::string("a::b::Foo")};
+  Spec.OldHeader = "foo.h";
+  Spec.NewHeader = "new_foo.h";
+  auto Results = runClangMoveOnCode(Spec);
+  EXPECT_EQ(2u, Results.size());
+  EXPECT_EQ(ExpectedTestHeader, Results[Spec.OldHeader]);
+  EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
+}
+
+TEST(ClangMove, MoveCCOnly) {
+  move::MoveDefinitionSpec Spec;
+  Spec.Names = {std::string("a::b::Foo")};
+  Spec.OldCC = "foo.cc";
+  Spec.NewCC = "new_foo.cc";
+  std::string ExpectedHeader = "#include \"foo.h\"\n\n";
+  auto Results = runClangMoveOnCode(Spec);
+  EXPECT_EQ(2u, Results.size());
+  EXPECT_EQ(ExpectedTestCC, Results[Spec.OldCC]);
+  EXPECT_EQ(ExpectedHeader + ExpectedNewCC, Results[Spec.NewCC]);
+}
+
+TEST(ClangMove, MoveNonExistClass) {
+  move::MoveDefinitionSpec Spec;
+  Spec.Names = {std::string("NonExistFoo")};
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+  auto Results = runClangMoveOnCode(Spec);
+  EXPECT_EQ(0u, Results.size());
+}
+
+TEST(ClangMove, HeaderIncludeSelf) {
+  move::MoveDefinitionSpec Spec;
+  Spec.Names = {std::string("Foo")};
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+
+  const char TestHeader[] = "#ifndef FOO_H\n"
+                            "#define FOO_H\n"
+                            "#include \"foo.h\"\n"
+                            "class Foo {};\n"
+                            "#endif\n";
+  const char TestCode[] = "#include \"foo.h\"";
+  const char ExpectedNewHeader[] = "#ifndef FOO_H\n"
+                                   "#define FOO_H\n"
+                                   "#include \"new_foo.h\"\n"
+                                   "class Foo {};\n"
+                                   "#endif\n";
+  const char ExpectedNewCC[] = "#include \"new_foo.h\"";
+  auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
+  EXPECT_EQ("", Results[Spec.OldHeader]);
+  EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
+  EXPECT_EQ(ExpectedNewCC, Results[Spec.NewCC]);
+}
+
+TEST(ClangMove, MoveAll) {
+  std::vector<std::string> TestHeaders = {
+    "class A {\npublic:\n  int f();\n};",
+    // forward declaration.
+    "class B;\nclass A {\npublic:\n  int f();\n};",
+    // template forward declaration.
+    "template <typename T> class B;\nclass A {\npublic:\n  int f();\n};",
+    "namespace a {}\nclass A {\npublic:\n  int f();\n};",
+    "namespace a {}\nusing namespace a;\nclass A {\npublic:\n  int f();\n};",
+  };
+  const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
+  move::MoveDefinitionSpec Spec;
+  Spec.Names.push_back("A");
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+  for (const auto& Header : TestHeaders) {
+    auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
+    EXPECT_EQ(Header, Results[Spec.NewHeader]);
+    EXPECT_EQ("", Results[Spec.OldHeader]);
+    EXPECT_EQ("", Results[Spec.OldCC]);
+  }
+}
+
+TEST(ClangMove, MoveAllMultipleClasses) {
+  move::MoveDefinitionSpec Spec;
+  std::vector<std::string> TestHeaders = {
+    "class C;\nclass A {\npublic:\n  int f();\n};\nclass B {};",
+    "class C;\nclass B;\nclass A {\npublic:\n  int f();\n};\nclass B {};",
+  };
+  const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
+  Spec.Names = {std::string("A"), std::string("B")};
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+  for (const auto& Header : TestHeaders) {
+    auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
+    EXPECT_EQ(Header, Results[Spec.NewHeader]);
+    EXPECT_EQ("", Results[Spec.OldHeader]);
+    EXPECT_EQ("", Results[Spec.OldCC]);
+  }
+}
+
+TEST(ClangMove, DontMoveAll) {
+  const char ExpectedHeader[] = "#ifndef NEW_FOO_H\n"
+                                "#define NEW_FOO_H\n"
+                                "\n"
+                                "class A {\npublic:\n  int f();\n};\n"
+                                "\n"
+                                "#endif // NEW_FOO_H\n";
+  const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
+  std::vector<std::string> TestHeaders = {
+    "class B {};\nclass A {\npublic:\n  int f();\n};\n",
+    "void f() {};\nclass A {\npublic:\n  int f();\n};\n",
+  };
+  move::MoveDefinitionSpec Spec;
+  Spec.Names.push_back("A");
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+  for (const auto& Header : TestHeaders) {
+    auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
+    EXPECT_EQ(ExpectedHeader, Results[Spec.NewHeader]);
+    // The expected old header should not contain class A definition.
+    std::string ExpectedOldHeader = Header.substr(0, Header.size() - 32);
+    EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
+  }
+}
+
+TEST(ClangMove, IgnoreMacroSymbolsAndMoveAll) {
+  const char TestCode[] = "#include \"foo.h\"";
+  std::vector<std::string> TestHeaders = {
+    "#define DEFINE_Foo int Foo = 1;\nDEFINE_Foo;\nclass Bar {};\n",
+    "#define DEFINE(x) int var_##x = 1;\nDEFINE(foo);\nclass Bar {};\n",
+  };
+  move::MoveDefinitionSpec Spec;
+  Spec.Names.push_back("Bar");
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+
+  for (const auto& Header : TestHeaders) {
+    auto Results = runClangMoveOnCode(Spec, Header.c_str(), TestCode);
+    EXPECT_EQ("", Results[Spec.OldHeader]);
+    EXPECT_EQ(Header, Results[Spec.NewHeader]);
+  }
+}
+
+TEST(ClangMove, MacroInFunction) {
+  const char TestHeader[] = "#define INT int\n"
+                            "class A {\npublic:\n  int f();\n};\n"
+                            "class B {};\n";
+  const char TestCode[] = "#include \"foo.h\"\n"
+                          "INT A::f() { return 0; }\n";
+  const char ExpectedNewCode[] = "#include \"new_foo.h\"\n\n"
+                                 "INT A::f() { return 0; }\n";
+  move::MoveDefinitionSpec Spec;
+  Spec.Names.push_back("A");
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+  auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
+  EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);
+}
+
+TEST(ClangMove, DefinitionInMacro) {
+  const char TestHeader[] = "#define DEF(CLASS) void CLASS##_::f() {}\n"
+                            "#define DEF2(CLASS, ...) void CLASS##_::f2() {}\n"
+                            "class A_ {\nvoid f();\nvoid f2();\n};\n"
+                            "class B {};\n";
+  const char TestCode[] = "#include \"foo.h\"\n"
+                          "DEF(A)\n\n"
+                          "DEF2(A,\n"
+                          "     123)\n";
+  const char ExpectedNewCode[] = "#include \"new_foo.h\"\n\n"
+                                 "DEF(A)\n\n"
+                                 "DEF2(A, 123)\n";
+  move::MoveDefinitionSpec Spec;
+  Spec.Names.push_back("A_");
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+  auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
+  EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);
+}
+
+TEST(ClangMove, WellFormattedCode) {
+  const std::string CommonHeader =
+      "namespace a {\n"
+      "namespace b {\n"
+      "namespace c {\n"
+      "class C;\n"
+      "\n"
+      "class A {\npublic:\n  void f();\n  void f2();\n};\n"
+      "} // namespace c\n"
+      "} // namespace b\n"
+      "\n"
+      "namespace d {\n"
+      "namespace e {\n"
+      "class B {\npublic:\n  void f();\n};\n"
+      "} // namespace e\n"
+      "} // namespace d\n"
+      "} // namespace a\n";
+  const std::string CommonCode = "\n"
+                                 "namespace a {\n"
+                                 "namespace b {\n"
+                                 "namespace c {\n"
+                                 "void A::f() {}\n"
+                                 "\n"
+                                 "void A::f2() {}\n"
+                                 "} // namespace c\n"
+                                 "} // namespace b\n"
+                                 "\n"
+                                 "namespace d {\n"
+                                 "namespace e {\n"
+                                 "void B::f() {}\n"
+                                 "} // namespace e\n"
+                                 "} // namespace d\n"
+                                 "} // namespace a\n";
+  // Add dummy class to prevent behavior of moving all declarations from header.
+  const std::string TestHeader = CommonHeader + "class D {};\n";
+  const std::string TestCode = "#include \"foo.h\"\n" + CommonCode;
+  const std::string ExpectedNewHeader = "#ifndef NEW_FOO_H\n"
+                                        "#define NEW_FOO_H\n"
+                                        "\n" +
+                                        CommonHeader +
+                                        "\n"
+                                        "#endif // NEW_FOO_H\n";
+  const std::string ExpectedNewCC = "#include \"new_foo.h\"\n" + CommonCode;
+  move::MoveDefinitionSpec Spec;
+  Spec.Names.push_back("a::b::c::A");
+  Spec.Names.push_back("a::d::e::B");
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+  auto Results = runClangMoveOnCode(Spec, TestHeader.c_str(), TestCode.c_str());
+  EXPECT_EQ(ExpectedNewCC, Results[Spec.NewCC]);
+  EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
+}
+
+TEST(ClangMove, AddDependentNewHeader) {
+  const char TestHeader[] = "class A {};\n"
+                            "class B {};\n";
+  const char TestCode[] = "#include \"foo.h\"\n";
+  const char ExpectedOldHeader[] = "#include \"new_foo.h\"\nclass B {};\n";
+  const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"
+                                   "#define NEW_FOO_H\n"
+                                   "\n"
+                                   "class A {};\n"
+                                   "\n"
+                                   "#endif // NEW_FOO_H\n";
+  move::MoveDefinitionSpec Spec;
+  Spec.Names.push_back("A");
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+  Spec.OldDependOnNew = true;
+  auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
+  EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
+  EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
+}
+
+TEST(ClangMove, AddDependentOldHeader) {
+  const char TestHeader[] = "class A {};\n"
+                            "class B {};\n";
+  const char TestCode[] = "#include \"foo.h\"\n";
+  const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"
+                                   "#define NEW_FOO_H\n"
+                                   "\n"
+                                   "#include \"foo.h\"\n"
+                                   "\n"
+                                   "class B {};\n"
+                                   "\n"
+                                   "#endif // NEW_FOO_H\n";
+  const char ExpectedOldHeader[] = "class A {};\n";
+  move::MoveDefinitionSpec Spec;
+  Spec.Names.push_back("B");
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+  Spec.NewDependOnOld = true;
+  auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
+  EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
+  EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
+}
+
+TEST(ClangMove, DumpDecls) {
+  const char TestHeader[] = "template <typename T>\n"
+                            "class A {\n"
+                            " public:\n"
+                            "  void f();\n"
+                            "  template <typename U> void h();\n"
+                            "  static int b;\n"
+                            "};\n"
+                            "\n"
+                            "template <typename T> void A<T>::f() {}\n"
+                            "\n"
+                            "template <typename T>\n"
+                            "template <typename U>\n"
+                            "void A<T>::h() {}\n"
+                            "\n"
+                            "template <typename T> int A<T>::b = 2;\n"
+                            "\n"
+                            "template <> class A<int> {};\n"
+                            "\n"
+                            "class B {};\n"
+                            "\n"
+                            "namespace a {\n"
+                            "class Move1 {};\n"
+                            "void f1() {}\n"
+                            "void f2();\n"
+                            "} // namespace a\n"
+                            "\n"
+                            "class ForwardClass;\n"
+                            "namespace a {\n"
+                            "namespace b {\n"
+                            "class Move1 { public : void f(); };\n"
+                            "void f() {}\n"
+                            "enum E1 { Green };\n"
+                            "enum class E2 { Red };\n"
+                            "typedef int Int2;\n"
+                            "typedef A<double> A_d;"
+                            "using Int = int;\n"
+                            "extern int kGlobalInt;\n"
+                            "extern const char* const kGlobalStr;\n"
+                            "} // namespace b\n"
+                            "} // namespace a\n"
+                            "#define DEFINE_FOO class Foo {};\n"
+                            "DEFINE_FOO\n";
+  const char TestCode[] = "#include \"foo.h\"\n";
+  move::MoveDefinitionSpec Spec;
+  Spec.Names.push_back("B");
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+  DeclarationReporter Reporter;
+  std::set<DeclarationReporter::DeclarationPair> ExpectedDeclarations = {
+      {"A", "Class"},
+      {"B", "Class"},
+      {"a::Move1", "Class"},
+      {"a::f1", "Function"},
+      {"a::f2", "Function"},
+      {"a::b::Move1", "Class"},
+      {"a::b::f", "Function"},
+      {"a::b::E1", "Enum"},
+      {"a::b::E2", "Enum"},
+      {"a::b::Int2", "TypeAlias"},
+      {"a::b::A_d", "TypeAlias"},
+      {"a::b::Int", "TypeAlias"},
+      {"a::b::kGlobalInt", "Variable"},
+      {"a::b::kGlobalStr", "Variable"}};
+  runClangMoveOnCode(Spec, TestHeader, TestCode, &Reporter);
+  std::set<DeclarationReporter::DeclarationPair> Results;
+  for (const auto& DelPair : Reporter.getDeclarationList())
+    Results.insert(DelPair);
+  EXPECT_EQ(ExpectedDeclarations, Results);
+}
+
+} // namespace
+} // namespce move
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-query/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-query/CMakeLists.txt
new file mode 100644
index 0000000..21d82b7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-query/CMakeLists.txt
@@ -0,0 +1,23 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  )
+
+include_directories(
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../clang-query
+  )
+
+add_extra_unittest(ClangQueryTests
+  QueryEngineTest.cpp
+  QueryParserTest.cpp
+  )
+
+target_link_libraries(ClangQueryTests
+  PRIVATE
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangDynamicASTMatchers
+  clangFrontend
+  clangQuery
+  clangTooling
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-query/QueryEngineTest.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-query/QueryEngineTest.cpp
new file mode 100644
index 0000000..631a53e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-query/QueryEngineTest.cpp
@@ -0,0 +1,146 @@
+//===---- QueryTest.cpp - clang-query test --------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Query.h"
+#include "QueryParser.h"
+#include "QuerySession.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+#include <string>
+
+using namespace clang;
+using namespace clang::ast_matchers;
+using namespace clang::ast_matchers::dynamic;
+using namespace clang::query;
+using namespace clang::tooling;
+
+class QueryEngineTest : public ::testing::Test {
+  ArrayRef<std::unique_ptr<ASTUnit>> mkASTUnit2(std::unique_ptr<ASTUnit> a,
+                                                std::unique_ptr<ASTUnit> b) {
+    ASTs[0] = std::move(a);
+    ASTs[1] = std::move(b);
+    return ArrayRef<std::unique_ptr<ASTUnit>>(ASTs);
+  }
+
+protected:
+  QueryEngineTest()
+      : S(mkASTUnit2(buildASTFromCode("void foo1(void) {}\nvoid foo2(void) {}",
+                                      "foo.cc"),
+                     buildASTFromCode("void bar1(void) {}\nvoid bar2(void) {}",
+                                      "bar.cc"))),
+        OS(Str) {}
+
+  std::unique_ptr<ASTUnit> ASTs[2];
+  QuerySession S;
+
+  std::string Str;
+  llvm::raw_string_ostream OS;
+};
+
+TEST_F(QueryEngineTest, Basic) {
+  DynTypedMatcher FnMatcher = functionDecl();
+  DynTypedMatcher FooMatcher = functionDecl(hasName("foo1"));
+
+  EXPECT_TRUE(NoOpQuery().run(OS, S));
+
+  EXPECT_EQ("", OS.str());
+
+  Str.clear();
+
+  EXPECT_FALSE(InvalidQuery("Parse error").run(OS, S));
+
+  EXPECT_EQ("Parse error\n", OS.str());
+
+  Str.clear();
+
+  EXPECT_TRUE(HelpQuery().run(OS, S));
+
+  EXPECT_TRUE(OS.str().find("Available commands:") != std::string::npos);
+
+  Str.clear();
+
+  EXPECT_TRUE(MatchQuery(FnMatcher).run(OS, S));
+
+  EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") !=
+              std::string::npos);
+  EXPECT_TRUE(OS.str().find("foo.cc:2:1: note: \"root\" binds here") !=
+              std::string::npos);
+  EXPECT_TRUE(OS.str().find("bar.cc:1:1: note: \"root\" binds here") !=
+              std::string::npos);
+  EXPECT_TRUE(OS.str().find("bar.cc:2:1: note: \"root\" binds here") !=
+              std::string::npos);
+  EXPECT_TRUE(OS.str().find("4 matches.") != std::string::npos);
+
+  Str.clear();
+
+  EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S));
+
+  EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") !=
+              std::string::npos);
+  EXPECT_TRUE(OS.str().find("1 match.") != std::string::npos);
+
+  Str.clear();
+
+  EXPECT_TRUE(
+      SetQuery<OutputKind>(&QuerySession::OutKind, OK_Print).run(OS, S));
+  EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S));
+
+  EXPECT_TRUE(OS.str().find("Binding for \"root\":\nvoid foo1()") !=
+              std::string::npos);
+
+  Str.clear();
+
+  EXPECT_TRUE(SetQuery<OutputKind>(&QuerySession::OutKind, OK_Dump).run(OS, S));
+  EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S));
+
+  EXPECT_TRUE(OS.str().find("FunctionDecl") != std::string::npos);
+
+  Str.clear();
+
+  EXPECT_TRUE(SetQuery<bool>(&QuerySession::BindRoot, false).run(OS, S));
+  EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S));
+
+  EXPECT_TRUE(OS.str().find("No bindings.") != std::string::npos);
+
+  Str.clear();
+
+  EXPECT_FALSE(MatchQuery(isArrow()).run(OS, S));
+
+  EXPECT_EQ("Not a valid top-level matcher.\n", OS.str());
+}
+
+TEST_F(QueryEngineTest, LetAndMatch) {
+  EXPECT_TRUE(QueryParser::parse("let x \"foo1\"", S)->run(OS, S));
+  EXPECT_EQ("", OS.str());
+  Str.clear();
+
+  EXPECT_TRUE(QueryParser::parse("let y hasName(x)", S)->run(OS, S));
+  EXPECT_EQ("", OS.str());
+  Str.clear();
+
+  EXPECT_TRUE(QueryParser::parse("match functionDecl(y)", S)->run(OS, S));
+  EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") !=
+              std::string::npos);
+  EXPECT_TRUE(OS.str().find("1 match.") != std::string::npos);
+  Str.clear();
+
+  EXPECT_TRUE(QueryParser::parse("unlet x", S)->run(OS, S));
+  EXPECT_EQ("", OS.str());
+  Str.clear();
+
+  EXPECT_FALSE(QueryParser::parse("let y hasName(x)", S)->run(OS, S));
+  EXPECT_EQ("1:2: Error parsing argument 1 for matcher hasName.\n"
+            "1:10: Value not found: x\n", OS.str());
+  Str.clear();
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp
new file mode 100644
index 0000000..5588ea3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp
@@ -0,0 +1,158 @@
+//===---- QueryParserTest.cpp - clang-query test --------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "QueryParser.h"
+#include "Query.h"
+#include "QuerySession.h"
+#include "llvm/LineEditor/LineEditor.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace clang::query;
+
+class QueryParserTest : public ::testing::Test {
+protected:
+  QueryParserTest() : QS(llvm::ArrayRef<std::unique_ptr<ASTUnit>>()) {}
+  QueryRef parse(StringRef Code) { return QueryParser::parse(Code, QS); }
+
+  QuerySession QS;
+};
+
+TEST_F(QueryParserTest, NoOp) {
+  QueryRef Q = parse("");
+  EXPECT_TRUE(isa<NoOpQuery>(Q));
+
+  Q = parse("\n");
+  EXPECT_TRUE(isa<NoOpQuery>(Q));
+}
+
+TEST_F(QueryParserTest, Invalid) {
+  QueryRef Q = parse("foo");
+  ASSERT_TRUE(isa<InvalidQuery>(Q));
+  EXPECT_EQ("unknown command: foo", cast<InvalidQuery>(Q)->ErrStr);
+}
+
+TEST_F(QueryParserTest, Help) {
+  QueryRef Q = parse("help");
+  ASSERT_TRUE(isa<HelpQuery>(Q));
+
+  Q = parse("help me");
+  ASSERT_TRUE(isa<InvalidQuery>(Q));
+  EXPECT_EQ("unexpected extra input: ' me'", cast<InvalidQuery>(Q)->ErrStr);
+}
+
+TEST_F(QueryParserTest, Set) {
+  QueryRef Q = parse("set");
+  ASSERT_TRUE(isa<InvalidQuery>(Q));
+  EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr);
+
+  Q = parse("set foo bar");
+  ASSERT_TRUE(isa<InvalidQuery>(Q));
+  EXPECT_EQ("unknown variable: 'foo'", cast<InvalidQuery>(Q)->ErrStr);
+
+  Q = parse("set output");
+  ASSERT_TRUE(isa<InvalidQuery>(Q));
+  EXPECT_EQ("expected 'diag', 'print' or 'dump', got ''",
+            cast<InvalidQuery>(Q)->ErrStr);
+
+  Q = parse("set bind-root true foo");
+  ASSERT_TRUE(isa<InvalidQuery>(Q));
+  EXPECT_EQ("unexpected extra input: ' foo'", cast<InvalidQuery>(Q)->ErrStr);
+
+  Q = parse("set output foo");
+  ASSERT_TRUE(isa<InvalidQuery>(Q));
+  EXPECT_EQ("expected 'diag', 'print' or 'dump', got 'foo'",
+            cast<InvalidQuery>(Q)->ErrStr);
+
+  Q = parse("set output dump");
+  ASSERT_TRUE(isa<SetQuery<OutputKind> >(Q));
+  EXPECT_EQ(&QuerySession::OutKind, cast<SetQuery<OutputKind> >(Q)->Var);
+  EXPECT_EQ(OK_Dump, cast<SetQuery<OutputKind> >(Q)->Value);
+
+  Q = parse("set bind-root foo");
+  ASSERT_TRUE(isa<InvalidQuery>(Q));
+  EXPECT_EQ("expected 'true' or 'false', got 'foo'",
+            cast<InvalidQuery>(Q)->ErrStr);
+
+  Q = parse("set bind-root true");
+  ASSERT_TRUE(isa<SetQuery<bool> >(Q));
+  EXPECT_EQ(&QuerySession::BindRoot, cast<SetQuery<bool> >(Q)->Var);
+  EXPECT_EQ(true, cast<SetQuery<bool> >(Q)->Value);
+}
+
+TEST_F(QueryParserTest, Match) {
+  QueryRef Q = parse("match decl()");
+  ASSERT_TRUE(isa<MatchQuery>(Q));
+  EXPECT_TRUE(cast<MatchQuery>(Q)->Matcher.canConvertTo<Decl>());
+
+  Q = parse("m stmt()");
+  ASSERT_TRUE(isa<MatchQuery>(Q));
+  EXPECT_TRUE(cast<MatchQuery>(Q)->Matcher.canConvertTo<Stmt>());
+}
+
+TEST_F(QueryParserTest, LetUnlet) {
+  QueryRef Q = parse("let foo decl()");
+  ASSERT_TRUE(isa<LetQuery>(Q));
+  EXPECT_EQ("foo", cast<LetQuery>(Q)->Name);
+  EXPECT_TRUE(cast<LetQuery>(Q)->Value.isMatcher());
+  EXPECT_TRUE(cast<LetQuery>(Q)->Value.getMatcher().hasTypedMatcher<Decl>());
+
+  Q = parse("let bar \"str\"");
+  ASSERT_TRUE(isa<LetQuery>(Q));
+  EXPECT_EQ("bar", cast<LetQuery>(Q)->Name);
+  EXPECT_TRUE(cast<LetQuery>(Q)->Value.isString());
+  EXPECT_EQ("str", cast<LetQuery>(Q)->Value.getString());
+
+  Q = parse("let");
+  ASSERT_TRUE(isa<InvalidQuery>(Q));
+  EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr);
+
+  Q = parse("unlet x");
+  ASSERT_TRUE(isa<LetQuery>(Q));
+  EXPECT_EQ("x", cast<LetQuery>(Q)->Name);
+  EXPECT_FALSE(cast<LetQuery>(Q)->Value.hasValue());
+
+  Q = parse("unlet");
+  ASSERT_TRUE(isa<InvalidQuery>(Q));
+  EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr);
+
+  Q = parse("unlet x bad_data");
+  ASSERT_TRUE(isa<InvalidQuery>(Q));
+  EXPECT_EQ("unexpected extra input: ' bad_data'",
+            cast<InvalidQuery>(Q)->ErrStr);
+}
+
+TEST_F(QueryParserTest, Complete) {
+  std::vector<llvm::LineEditor::Completion> Comps =
+      QueryParser::complete("", 0, QS);
+  ASSERT_EQ(6u, Comps.size());
+  EXPECT_EQ("help ", Comps[0].TypedText);
+  EXPECT_EQ("help", Comps[0].DisplayText);
+  EXPECT_EQ("let ", Comps[1].TypedText);
+  EXPECT_EQ("let", Comps[1].DisplayText);
+  EXPECT_EQ("match ", Comps[2].TypedText);
+  EXPECT_EQ("match", Comps[2].DisplayText);
+  EXPECT_EQ("set ", Comps[3].TypedText);
+  EXPECT_EQ("set", Comps[3].DisplayText);
+  EXPECT_EQ("unlet ", Comps[4].TypedText);
+  EXPECT_EQ("unlet", Comps[4].DisplayText);
+  EXPECT_EQ("quit", Comps[5].DisplayText);
+  EXPECT_EQ("quit ", Comps[5].TypedText);
+
+  Comps = QueryParser::complete("set o", 5, QS);
+  ASSERT_EQ(1u, Comps.size());
+  EXPECT_EQ("utput ", Comps[0].TypedText);
+  EXPECT_EQ("output", Comps[0].DisplayText);
+
+  Comps = QueryParser::complete("match while", 11, QS);
+  ASSERT_EQ(1u, Comps.size());
+  EXPECT_EQ("Stmt(", Comps[0].TypedText);
+  EXPECT_EQ("Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)",
+            Comps[0].DisplayText);
+}
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/CMakeLists.txt
new file mode 100644
index 0000000..a678e59
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/CMakeLists.txt
@@ -0,0 +1,38 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  )
+
+get_filename_component(CLANG_LINT_SOURCE_DIR
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../clang-tidy REALPATH)
+include_directories(${CLANG_LINT_SOURCE_DIR})
+
+add_extra_unittest(ClangTidyTests
+  ClangTidyDiagnosticConsumerTest.cpp
+  ClangTidyOptionsTest.cpp
+  ExprMutationAnalyzerTest.cpp
+  IncludeInserterTest.cpp
+  GoogleModuleTest.cpp
+  LLVMModuleTest.cpp
+  NamespaceAliaserTest.cpp
+  ObjCModuleTest.cpp
+  OverlappingReplacementsTest.cpp
+  UsingInserterTest.cpp
+  ReadabilityModuleTest.cpp)
+
+target_link_libraries(ClangTidyTests
+  PRIVATE
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFrontend
+  clangLex
+  clangTidy
+  clangTidyAndroidModule
+  clangTidyGoogleModule
+  clangTidyLLVMModule
+  clangTidyObjCModule
+  clangTidyReadabilityModule
+  clangTidyUtils
+  clangTooling
+  clangToolingCore
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp
new file mode 100644
index 0000000..5547f98
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp
@@ -0,0 +1,94 @@
+#include "ClangTidy.h"

+#include "ClangTidyTest.h"

+#include "gtest/gtest.h"

+

+namespace clang {

+namespace tidy {

+namespace test {

+

+class TestCheck : public ClangTidyCheck {

+public:

+  TestCheck(StringRef Name, ClangTidyContext *Context)

+      : ClangTidyCheck(Name, Context) {}

+  void registerMatchers(ast_matchers::MatchFinder *Finder) override {

+    Finder->addMatcher(ast_matchers::varDecl().bind("var"), this);

+  }

+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override {

+    const auto *Var = Result.Nodes.getNodeAs<VarDecl>("var");

+    // Add diagnostics in the wrong order.

+    diag(Var->getLocation(), "variable");

+    diag(Var->getTypeSpecStartLoc(), "type specifier");

+  }

+};

+

+TEST(ClangTidyDiagnosticConsumer, SortsErrors) {

+  std::vector<ClangTidyError> Errors;

+  runCheckOnCode<TestCheck>("int a;", &Errors);

+  EXPECT_EQ(2ul, Errors.size());

+  EXPECT_EQ("type specifier", Errors[0].Message.Message);

+  EXPECT_EQ("variable", Errors[1].Message.Message);

+}

+

+TEST(GlobList, Empty) {

+  GlobList Filter("");

+

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

+  EXPECT_FALSE(Filter.contains("aaa"));

+}

+

+TEST(GlobList, Nothing) {

+  GlobList Filter("-*");

+

+  EXPECT_FALSE(Filter.contains(""));

+  EXPECT_FALSE(Filter.contains("a"));

+  EXPECT_FALSE(Filter.contains("-*"));

+  EXPECT_FALSE(Filter.contains("-"));

+  EXPECT_FALSE(Filter.contains("*"));

+}

+

+TEST(GlobList, Everything) {

+  GlobList Filter("*");

+

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

+  EXPECT_TRUE(Filter.contains("aaaa"));

+  EXPECT_TRUE(Filter.contains("-*"));

+  EXPECT_TRUE(Filter.contains("-"));

+  EXPECT_TRUE(Filter.contains("*"));

+}

+

+TEST(GlobList, Simple) {

+  GlobList Filter("aaa");

+

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

+  EXPECT_FALSE(Filter.contains(""));

+  EXPECT_FALSE(Filter.contains("aa"));

+  EXPECT_FALSE(Filter.contains("aaaa"));

+  EXPECT_FALSE(Filter.contains("bbb"));

+}

+

+TEST(GlobList, WhitespacesAtBegin) {

+  GlobList Filter("-*,   a.b.*");

+

+  EXPECT_TRUE(Filter.contains("a.b.c"));

+  EXPECT_FALSE(Filter.contains("b.c"));

+}

+

+TEST(GlobList, Complex) {

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

+

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

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

+  EXPECT_FALSE(Filter.contains("a."));

+  EXPECT_FALSE(Filter.contains("a.b"));

+  EXPECT_FALSE(Filter.contains("b."));

+  EXPECT_FALSE(Filter.contains("b.b"));

+  EXPECT_TRUE(Filter.contains("a.1.b"));

+  EXPECT_FALSE(Filter.contains("a.1.A.a"));

+  EXPECT_FALSE(Filter.contains("qwe"));

+  EXPECT_FALSE(Filter.contains("asdfqweasdf"));

+  EXPECT_TRUE(Filter.contains("asdfqwEasdf"));

+}

+

+} // namespace test

+} // namespace tidy

+} // namespace clang

diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp
new file mode 100644
index 0000000..f50672c
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp
@@ -0,0 +1,102 @@
+#include "ClangTidyOptions.h"
+#include "gtest/gtest.h"
+#include "llvm/ADT/StringExtras.h"
+
+namespace clang {
+namespace tidy {
+namespace test {
+
+TEST(ParseLineFilter, EmptyFilter) {
+  ClangTidyGlobalOptions Options;
+  EXPECT_FALSE(parseLineFilter("", Options));
+  EXPECT_TRUE(Options.LineFilter.empty());
+  EXPECT_FALSE(parseLineFilter("[]", Options));
+  EXPECT_TRUE(Options.LineFilter.empty());
+}
+
+TEST(ParseLineFilter, InvalidFilter) {
+  ClangTidyGlobalOptions Options;
+  EXPECT_TRUE(!!parseLineFilter("asdf", Options));
+  EXPECT_TRUE(Options.LineFilter.empty());
+
+  EXPECT_TRUE(!!parseLineFilter("[{}]", Options));
+  EXPECT_TRUE(!!parseLineFilter("[{\"name\":\"\"}]", Options));
+  EXPECT_TRUE(
+      !!parseLineFilter("[{\"name\":\"test\",\"lines\":[[1]]}]", Options));
+  EXPECT_TRUE(
+      !!parseLineFilter("[{\"name\":\"test\",\"lines\":[[1,2,3]]}]", Options));
+  EXPECT_TRUE(
+      !!parseLineFilter("[{\"name\":\"test\",\"lines\":[[1,-1]]}]", Options));
+}
+
+TEST(ParseLineFilter, ValidFilter) {
+  ClangTidyGlobalOptions Options;
+  std::error_code Error = parseLineFilter(
+      "[{\"name\":\"file1.cpp\",\"lines\":[[3,15],[20,30],[42,42]]},"
+      "{\"name\":\"file2.h\"},"
+      "{\"name\":\"file3.cc\",\"lines\":[[100,1000]]}]",
+      Options);
+  EXPECT_FALSE(Error);
+  EXPECT_EQ(3u, Options.LineFilter.size());
+  EXPECT_EQ("file1.cpp", Options.LineFilter[0].Name);
+  EXPECT_EQ(3u, Options.LineFilter[0].LineRanges.size());
+  EXPECT_EQ(3u, Options.LineFilter[0].LineRanges[0].first);
+  EXPECT_EQ(15u, Options.LineFilter[0].LineRanges[0].second);
+  EXPECT_EQ(20u, Options.LineFilter[0].LineRanges[1].first);
+  EXPECT_EQ(30u, Options.LineFilter[0].LineRanges[1].second);
+  EXPECT_EQ(42u, Options.LineFilter[0].LineRanges[2].first);
+  EXPECT_EQ(42u, Options.LineFilter[0].LineRanges[2].second);
+  EXPECT_EQ("file2.h", Options.LineFilter[1].Name);
+  EXPECT_EQ(0u, Options.LineFilter[1].LineRanges.size());
+  EXPECT_EQ("file3.cc", Options.LineFilter[2].Name);
+  EXPECT_EQ(1u, Options.LineFilter[2].LineRanges.size());
+  EXPECT_EQ(100u, Options.LineFilter[2].LineRanges[0].first);
+  EXPECT_EQ(1000u, Options.LineFilter[2].LineRanges[0].second);
+}
+
+TEST(ParseConfiguration, ValidConfiguration) {
+  llvm::ErrorOr<ClangTidyOptions> Options =
+      parseConfiguration("Checks: \"-*,misc-*\"\n"
+                         "HeaderFilterRegex: \".*\"\n"
+                         "AnalyzeTemporaryDtors: true\n"
+                         "User: some.user");
+  EXPECT_TRUE(!!Options);
+  EXPECT_EQ("-*,misc-*", *Options->Checks);
+  EXPECT_EQ(".*", *Options->HeaderFilterRegex);
+  EXPECT_EQ("some.user", *Options->User);
+}
+
+TEST(ParseConfiguration, MergeConfigurations) {
+  llvm::ErrorOr<ClangTidyOptions> Options1 = parseConfiguration(R"(
+      Checks: "check1,check2"
+      HeaderFilterRegex: "filter1"
+      AnalyzeTemporaryDtors: true
+      User: user1
+      ExtraArgs: ['arg1', 'arg2']
+      ExtraArgsBefore: ['arg-before1', 'arg-before2']
+  )");
+  ASSERT_TRUE(!!Options1);
+  llvm::ErrorOr<ClangTidyOptions> Options2 = parseConfiguration(R"(
+      Checks: "check3,check4"
+      HeaderFilterRegex: "filter2"
+      AnalyzeTemporaryDtors: false
+      User: user2
+      ExtraArgs: ['arg3', 'arg4']
+      ExtraArgsBefore: ['arg-before3', 'arg-before4']
+  )");
+  ASSERT_TRUE(!!Options2);
+  ClangTidyOptions Options = Options1->mergeWith(*Options2);
+  EXPECT_EQ("check1,check2,check3,check4", *Options.Checks);
+  EXPECT_EQ("filter2", *Options.HeaderFilterRegex);
+  EXPECT_EQ("user2", *Options.User);
+  ASSERT_TRUE(Options.ExtraArgs.hasValue());
+  EXPECT_EQ("arg1,arg2,arg3,arg4", llvm::join(Options.ExtraArgs->begin(),
+                                              Options.ExtraArgs->end(), ","));
+  ASSERT_TRUE(Options.ExtraArgsBefore.hasValue());
+  EXPECT_EQ("arg-before1,arg-before2,arg-before3,arg-before4",
+            llvm::join(Options.ExtraArgsBefore->begin(),
+                       Options.ExtraArgsBefore->end(), ","));
+}
+} // namespace test
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ClangTidyTest.h b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ClangTidyTest.h
new file mode 100644
index 0000000..197c137
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ClangTidyTest.h
@@ -0,0 +1,159 @@
+//===--- ClangTidyTest.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_UNITTESTS_CLANG_TIDY_CLANGTIDYTEST_H
+#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANG_TIDY_CLANGTIDYTEST_H
+
+#include "ClangTidy.h"
+#include "ClangTidyDiagnosticConsumer.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Path.h"
+#include <map>
+#include <memory>
+
+namespace clang {
+namespace tidy {
+namespace test {
+
+class TestClangTidyAction : public ASTFrontendAction {
+public:
+  TestClangTidyAction(SmallVectorImpl<std::unique_ptr<ClangTidyCheck>> &Checks,
+                      ast_matchers::MatchFinder &Finder,
+                      ClangTidyContext &Context)
+      : Checks(Checks), Finder(Finder), Context(Context) {}
+
+private:
+  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
+                                                 StringRef File) override {
+    Context.setSourceManager(&Compiler.getSourceManager());
+    Context.setCurrentFile(File);
+    Context.setASTContext(&Compiler.getASTContext());
+
+    for (auto &Check : Checks) {
+      Check->registerMatchers(&Finder);
+      Check->registerPPCallbacks(Compiler);
+    }
+    return Finder.newASTConsumer();
+  }
+
+  SmallVectorImpl<std::unique_ptr<ClangTidyCheck>> &Checks;
+  ast_matchers::MatchFinder &Finder;
+  ClangTidyContext &Context;
+};
+
+template <typename Check, typename... Checks> struct CheckFactory {
+  static void
+  createChecks(ClangTidyContext *Context,
+               SmallVectorImpl<std::unique_ptr<ClangTidyCheck>> &Result) {
+    CheckFactory<Check>::createChecks(Context, Result);
+    CheckFactory<Checks...>::createChecks(Context, Result);
+  }
+};
+
+template <typename Check> struct CheckFactory<Check> {
+  static void
+  createChecks(ClangTidyContext *Context,
+               SmallVectorImpl<std::unique_ptr<ClangTidyCheck>> &Result) {
+    Result.emplace_back(llvm::make_unique<Check>(
+        "test-check-" + std::to_string(Result.size()), Context));
+  }
+};
+
+template <typename... CheckList>
+std::string
+runCheckOnCode(StringRef Code, std::vector<ClangTidyError> *Errors = nullptr,
+               const Twine &Filename = "input.cc",
+               ArrayRef<std::string> ExtraArgs = None,
+               const ClangTidyOptions &ExtraOptions = ClangTidyOptions(),
+               std::map<StringRef, StringRef> PathsToContent =
+                   std::map<StringRef, StringRef>()) {
+  ClangTidyOptions Options = ExtraOptions;
+  Options.Checks = "*";
+  ClangTidyContext Context(llvm::make_unique<DefaultOptionsProvider>(
+      ClangTidyGlobalOptions(), Options));
+  ClangTidyDiagnosticConsumer DiagConsumer(Context);
+
+  std::vector<std::string> Args(1, "clang-tidy");
+  Args.push_back("-fsyntax-only");
+  std::string extension(llvm::sys::path::extension(Filename.str()));
+  if (extension == ".m" || extension == ".mm") {
+    Args.push_back("-fobjc-abi-version=2");
+    Args.push_back("-fobjc-arc");
+  }
+  if (extension == ".cc" || extension == ".cpp" || extension == ".mm") {
+    Args.push_back("-std=c++11");
+  }
+  Args.push_back("-Iinclude");
+  Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
+  Args.push_back(Filename.str());
+
+  ast_matchers::MatchFinder Finder;
+  llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+      new vfs::InMemoryFileSystem);
+  llvm::IntrusiveRefCntPtr<FileManager> Files(
+      new FileManager(FileSystemOptions(), InMemoryFileSystem));
+
+  SmallVector<std::unique_ptr<ClangTidyCheck>, 1> Checks;
+  CheckFactory<CheckList...>::createChecks(&Context, Checks);
+  tooling::ToolInvocation Invocation(
+      Args, new TestClangTidyAction(Checks, Finder, Context), Files.get());
+  InMemoryFileSystem->addFile(Filename, 0,
+                              llvm::MemoryBuffer::getMemBuffer(Code));
+  for (const auto &FileContent : PathsToContent) {
+    InMemoryFileSystem->addFile(
+        Twine("include/") + FileContent.first, 0,
+        llvm::MemoryBuffer::getMemBuffer(FileContent.second));
+  }
+  Invocation.setDiagnosticConsumer(&DiagConsumer);
+  if (!Invocation.run()) {
+    std::string ErrorText;
+    for (const auto &Error : Context.getErrors()) {
+      ErrorText += Error.Message.Message + "\n";
+    }
+    llvm::report_fatal_error(ErrorText);
+  }
+
+  DiagConsumer.finish();
+  tooling::Replacements Fixes;
+  for (const ClangTidyError &Error : Context.getErrors()) {
+    for (const auto &FileAndFixes : Error.Fix) {
+      for (const auto &Fix : FileAndFixes.second) {
+        auto Err = Fixes.add(Fix);
+        // FIXME: better error handling. Keep the behavior for now.
+        if (Err) {
+          llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+          return "";
+        }
+      }
+    }
+  }
+  if (Errors)
+    *Errors = Context.getErrors();
+  auto Result = tooling::applyAllReplacements(Code, Fixes);
+  if (!Result) {
+    // FIXME: propogate the error.
+    llvm::consumeError(Result.takeError());
+    return "";
+  }
+  return *Result;
+}
+
+#define EXPECT_NO_CHANGES(Check, Code)                                         \
+  EXPECT_EQ(Code, runCheckOnCode<Check>(Code))
+
+} // namespace test
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANG_TIDY_CLANGTIDYTEST_H
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp
new file mode 100644
index 0000000..042d4cb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp
@@ -0,0 +1,611 @@
+//===---------- ExprMutationAnalyzerTest.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 "../clang-tidy/utils/ExprMutationAnalyzer.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/Tooling.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <cctype>
+
+namespace clang {
+namespace tidy {
+namespace test {
+
+using namespace clang::ast_matchers;
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
+using ::testing::ResultOf;
+using ::testing::StartsWith;
+using ::testing::Values;
+
+namespace {
+
+using ExprMatcher = internal::Matcher<Expr>;
+using StmtMatcher = internal::Matcher<Stmt>;
+
+ExprMatcher declRefTo(StringRef Name) {
+  return declRefExpr(to(namedDecl(hasName(Name))));
+}
+
+StmtMatcher withEnclosingCompound(ExprMatcher Matcher) {
+  return expr(Matcher, hasAncestor(compoundStmt().bind("stmt"))).bind("expr");
+}
+
+bool isMutated(const SmallVectorImpl<BoundNodes> &Results, ASTUnit *AST) {
+  const auto *const S = selectFirst<Stmt>("stmt", Results);
+  const auto *const E = selectFirst<Expr>("expr", Results);
+  return utils::ExprMutationAnalyzer(S, &AST->getASTContext()).isMutated(E);
+}
+
+SmallVector<std::string, 1>
+mutatedBy(const SmallVectorImpl<BoundNodes> &Results, ASTUnit *AST) {
+  const auto *const S = selectFirst<Stmt>("stmt", Results);
+  SmallVector<std::string, 1> Chain;
+  utils::ExprMutationAnalyzer Analyzer(S, &AST->getASTContext());
+  for (const auto *E = selectFirst<Expr>("expr", Results); E != nullptr;) {
+    const Stmt *By = Analyzer.findMutation(E);
+    std::string buffer;
+    llvm::raw_string_ostream stream(buffer);
+    By->printPretty(stream, nullptr, AST->getASTContext().getPrintingPolicy());
+    Chain.push_back(StringRef(stream.str()).trim().str());
+    E = dyn_cast<DeclRefExpr>(By);
+  }
+  return Chain;
+}
+
+std::string removeSpace(std::string s) {
+  s.erase(std::remove_if(s.begin(), s.end(),
+                         [](char c) { return std::isspace(c); }),
+          s.end());
+  return s;
+}
+
+} // namespace
+
+TEST(ExprMutationAnalyzerTest, Trivial) {
+  const auto AST = tooling::buildASTFromCode("void f() { int x; x; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+class AssignmentTest : public ::testing::TestWithParam<std::string> {};
+
+TEST_P(AssignmentTest, AssignmentModifies) {
+  const std::string ModExpr = "x " + GetParam() + " 10";
+  const auto AST =
+      tooling::buildASTFromCode("void f() { int x; " + ModExpr + "; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre(ModExpr));
+}
+
+INSTANTIATE_TEST_CASE_P(AllAssignmentOperators, AssignmentTest,
+                        Values("=", "+=", "-=", "*=", "/=", "%=", "&=", "|=",
+                               "^=", "<<=", ">>="), );
+
+class IncDecTest : public ::testing::TestWithParam<std::string> {};
+
+TEST_P(IncDecTest, IncDecModifies) {
+  const std::string ModExpr = GetParam();
+  const auto AST =
+      tooling::buildASTFromCode("void f() { int x; " + ModExpr + "; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre(ModExpr));
+}
+
+INSTANTIATE_TEST_CASE_P(AllIncDecOperators, IncDecTest,
+                        Values("++x", "--x", "x++", "x--"), );
+
+TEST(ExprMutationAnalyzerTest, NonConstMemberFunc) {
+  const auto AST = tooling::buildASTFromCode(
+      "void f() { struct Foo { void mf(); }; Foo x; x.mf(); }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()"));
+}
+
+TEST(ExprMutationAnalyzerTest, ConstMemberFunc) {
+  const auto AST = tooling::buildASTFromCode(
+      "void f() { struct Foo { void mf() const; }; Foo x; x.mf(); }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, NonConstOperator) {
+  const auto AST = tooling::buildASTFromCode(
+      "void f() { struct Foo { Foo& operator=(int); }; Foo x; x = 10; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, ConstOperator) {
+  const auto AST = tooling::buildASTFromCode(
+      "void f() { struct Foo { int operator()() const; }; Foo x; x(); }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, ByValueArgument) {
+  auto AST =
+      tooling::buildASTFromCode("void g(int); void f() { int x; g(x); }");
+  auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCode(
+      "void f() { struct A {}; A operator+(A, int); A x; x + 1; }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCode(
+      "void f() { struct A { A(int); }; int x; A y(x); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCode(
+      "void f() { struct A { A(); A(A); }; A x; A y(x); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, ByNonConstRefArgument) {
+  auto AST =
+      tooling::buildASTFromCode("void g(int&); void f() { int x; g(x); }");
+  auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)"));
+
+  AST = tooling::buildASTFromCode(
+      "void f() { struct A {}; A operator+(A&, int); A x; x + 1; }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x + 1"));
+
+  AST = tooling::buildASTFromCode(
+      "void f() { struct A { A(int&); }; int x; A y(x); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x"));
+
+  AST = tooling::buildASTFromCode(
+      "void f() { struct A { A(); A(A&); }; A x; A y(x); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x"));
+}
+
+TEST(ExprMutationAnalyzerTest, ByConstRefArgument) {
+  auto AST = tooling::buildASTFromCode(
+      "void g(const int&); void f() { int x; g(x); }");
+  auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCode(
+      "void f() { struct A {}; A operator+(const A&, int); A x; x + 1; }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCode(
+      "void f() { struct A { A(const int&); }; int x; A y(x); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCode(
+      "void f() { struct A { A(); A(const A&); }; A x; A y(x); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, ByNonConstRRefArgument) {
+  auto AST = tooling::buildASTFromCode(
+      "void g(int&&); void f() { int x; g(static_cast<int &&>(x)); }");
+  auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()),
+              ElementsAre("g(static_cast<int &&>(x))"));
+
+  AST = tooling::buildASTFromCode(
+      "void f() { struct A {}; A operator+(A&&, int); "
+      "A x; static_cast<A &&>(x) + 1; }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()),
+              ElementsAre("static_cast<A &&>(x) + 1"));
+
+  AST = tooling::buildASTFromCode("void f() { struct A { A(int&&); }; "
+                                  "int x; A y(static_cast<int &&>(x)); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()),
+              ElementsAre("static_cast<int &&>(x)"));
+
+  AST = tooling::buildASTFromCode("void f() { struct A { A(); A(A&&); }; "
+                                  "A x; A y(static_cast<A &&>(x)); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()),
+              ElementsAre("static_cast<A &&>(x)"));
+}
+
+TEST(ExprMutationAnalyzerTest, ByConstRRefArgument) {
+  auto AST = tooling::buildASTFromCode(
+      "void g(const int&&); void f() { int x; g(static_cast<int&&>(x)); }");
+  auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCode(
+      "void f() { struct A {}; A operator+(const A&&, int); "
+      "A x; static_cast<A&&>(x) + 1; }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCode("void f() { struct A { A(const int&&); }; "
+                                  "int x; A y(static_cast<int&&>(x)); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCode("void f() { struct A { A(); A(const A&&); }; "
+                                  "A x; A y(static_cast<A&&>(x)); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, Move) {
+  // Technically almost the same as ByNonConstRRefArgument, just double checking
+  const auto AST = tooling::buildASTFromCode(
+      "namespace std {"
+      "template<class T> struct remove_reference { typedef T type; };"
+      "template<class T> struct remove_reference<T&> { typedef T type; };"
+      "template<class T> struct remove_reference<T&&> { typedef T type; };"
+      "template<class T> typename std::remove_reference<T>::type&& "
+      "move(T&& t) noexcept; }"
+      "void f() { struct A {}; A x; std::move(x); }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("std::move(x)"));
+}
+
+TEST(ExprMutationAnalyzerTest, Forward) {
+  // Technically almost the same as ByNonConstRefArgument, just double checking
+  const auto AST = tooling::buildASTFromCode(
+      "namespace std {"
+      "template<class T> struct remove_reference { typedef T type; };"
+      "template<class T> struct remove_reference<T&> { typedef T type; };"
+      "template<class T> struct remove_reference<T&&> { typedef T type; };"
+      "template<class T> T&& "
+      "forward(typename std::remove_reference<T>::type&) noexcept;"
+      "template<class T> T&& "
+      "forward(typename std::remove_reference<T>::type&&) noexcept;"
+      "void f() { struct A {}; A x; std::forward<A &>(x); }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()),
+              ElementsAre("std::forward<A &>(x)"));
+}
+
+TEST(ExprMutationAnalyzerTest, ReturnAsValue) {
+  const auto AST = tooling::buildASTFromCode("int f() { int x; return x; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, ReturnAsNonConstRef) {
+  const auto AST = tooling::buildASTFromCode("int& f() { int x; return x; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("return x;"));
+}
+
+TEST(ExprMutationAnalyzerTest, ReturnAsConstRef) {
+  const auto AST =
+      tooling::buildASTFromCode("const int& f() { int x; return x; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, ReturnAsNonConstRRef) {
+  const auto AST = tooling::buildASTFromCode(
+      "int&& f() { int x; return static_cast<int &&>(x); }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()),
+              ElementsAre("return static_cast<int &&>(x);"));
+}
+
+TEST(ExprMutationAnalyzerTest, ReturnAsConstRRef) {
+  const auto AST = tooling::buildASTFromCode(
+      "const int&& f() { int x; return static_cast<int&&>(x); }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, TakeAddress) {
+  const auto AST =
+      tooling::buildASTFromCode("void g(int*); void f() { int x; g(&x); }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("&x"));
+}
+
+TEST(ExprMutationAnalyzerTest, ArrayToPointerDecay) {
+  const auto AST =
+      tooling::buildASTFromCode("void g(int*); void f() { int x[2]; g(x); }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x"));
+}
+
+TEST(ExprMutationAnalyzerTest, FollowRefModified) {
+  const auto AST = tooling::buildASTFromCode(
+      "void f() { int x; int& r0 = x; int& r1 = r0; int& r2 = r1; "
+      "int& r3 = r2; r3 = 10; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()),
+              ElementsAre("r0", "r1", "r2", "r3", "r3 = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, FollowRefNotModified) {
+  const auto AST = tooling::buildASTFromCode(
+      "void f() { int x; int& r0 = x; int& r1 = r0; int& r2 = r1; "
+      "int& r3 = r2; int& r4 = r3; int& r5 = r4;}");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, FollowConditionalRefModified) {
+  const auto AST = tooling::buildASTFromCode(
+      "void f() { int x, y; bool b; int &r = b ? x : y; r = 10; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("r", "r = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, FollowConditionalRefNotModified) {
+  const auto AST = tooling::buildASTFromCode(
+      "void f() { int x, y; bool b; int& r = b ? x : y; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, ArrayElementModified) {
+  const auto AST =
+      tooling::buildASTFromCode("void f() { int x[2]; x[0] = 10; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x[0] = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, ArrayElementNotModified) {
+  const auto AST = tooling::buildASTFromCode("void f() { int x[2]; x[0]; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, NestedMemberModified) {
+  const auto AST = tooling::buildASTFromCode(
+      "void f() { struct A { int vi; }; struct B { A va; }; "
+      "struct C { B vb; }; C x; x.vb.va.vi = 10; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.vb.va.vi = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, NestedMemberNotModified) {
+  const auto AST = tooling::buildASTFromCode(
+      "void f() { struct A { int vi; }; struct B { A va; }; "
+      "struct C { B vb; }; C x; x.vb.va.vi; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, CastToValue) {
+  const auto AST =
+      tooling::buildASTFromCode("void f() { int x; static_cast<double>(x); }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, CastToRefModified) {
+  const auto AST = tooling::buildASTFromCode(
+      "void f() { int x; static_cast<int &>(x) = 10; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()),
+              ElementsAre("static_cast<int &>(x) = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, CastToRefNotModified) {
+  const auto AST =
+      tooling::buildASTFromCode("void f() { int x; static_cast<int&>(x); }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, CastToConstRef) {
+  const auto AST = tooling::buildASTFromCode(
+      "void f() { int x; static_cast<const int&>(x); }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, LambdaDefaultCaptureByValue) {
+  const auto AST =
+      tooling::buildASTFromCode("void f() { int x; [=]() { x = 10; }; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, LambdaExplicitCaptureByValue) {
+  const auto AST =
+      tooling::buildASTFromCode("void f() { int x; [x]() { x = 10; }; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, LambdaDefaultCaptureByRef) {
+  const auto AST =
+      tooling::buildASTFromCode("void f() { int x; [&]() { x = 10; }; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()),
+              ElementsAre(ResultOf(removeSpace, "[&](){x=10;}")));
+}
+
+TEST(ExprMutationAnalyzerTest, LambdaExplicitCaptureByRef) {
+  const auto AST =
+      tooling::buildASTFromCode("void f() { int x; [&x]() { x = 10; }; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()),
+              ElementsAre(ResultOf(removeSpace, "[&x](){x=10;}")));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForArrayByRefModified) {
+  const auto AST = tooling::buildASTFromCode(
+      "void f() { int x[2]; for (int& e : x) e = 10; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("e", "e = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForArrayByRefNotModified) {
+  const auto AST =
+      tooling::buildASTFromCode("void f() { int x[2]; for (int& e : x) e; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForArrayByValue) {
+  const auto AST = tooling::buildASTFromCode(
+      "void f() { int x[2]; for (int e : x) e = 10; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForArrayByConstRef) {
+  const auto AST = tooling::buildASTFromCode(
+      "void f() { int x[2]; for (const int& e : x) e; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForNonArrayByRefModified) {
+  const auto AST =
+      tooling::buildASTFromCode("struct V { int* begin(); int* end(); };"
+                                "void f() { V x; for (int& e : x) e = 10; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("e", "e = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForNonArrayByRefNotModified) {
+  const auto AST =
+      tooling::buildASTFromCode("struct V { int* begin(); int* end(); };"
+                                "void f() { V x; for (int& e : x) e; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForNonArrayByValue) {
+  const auto AST = tooling::buildASTFromCode(
+      "struct V { const int* begin() const; const int* end() const; };"
+      "void f() { V x; for (int e : x) e; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForNonArrayByConstRef) {
+  const auto AST = tooling::buildASTFromCode(
+      "struct V { const int* begin() const; const int* end() const; };"
+      "void f() { V x; for (const int& e : x) e; }");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, UnevaluatedExpressions) {
+  auto AST = tooling::buildASTFromCode(
+      "void f() { int x, y; decltype(x = 10) z = y; }");
+  auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCode(
+      "void f() { int x, y; __typeof(x = 10) z = y; }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCode(
+      "void f() { int x, y; __typeof__(x = 10) z = y; }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCode("void f() { int x; sizeof(x = 10); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCode("void f() { int x; alignof(x = 10); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCode("void f() { int x; noexcept(x = 10); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCodeWithArgs("namespace std { class type_info; }"
+                                          "void f() { int x; typeid(x = 10); }",
+                                          {"-frtti"});
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = tooling::buildASTFromCode(
+      "void f() { int x; _Generic(x = 10, int: 0, default: 1); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, NotUnevaluatedExpressions) {
+  auto AST = tooling::buildASTFromCode("void f() { int x; sizeof(int[x++]); }");
+  auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x++"));
+
+  AST = tooling::buildASTFromCodeWithArgs(
+      "namespace std { class type_info; }"
+      "struct A { virtual ~A(); }; struct B : A {};"
+      "struct X { A& f(); }; void f() { X x; typeid(x.f()); }",
+      {"-frtti"});
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.f()"));
+}
+
+} // namespace test
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/GoogleModuleTest.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/GoogleModuleTest.cpp
new file mode 100644
index 0000000..feb7ae9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/GoogleModuleTest.cpp
@@ -0,0 +1,110 @@
+#include "ClangTidyTest.h"
+#include "google/ExplicitConstructorCheck.h"
+#include "google/GlobalNamesInHeadersCheck.h"
+#include "gtest/gtest.h"
+
+using namespace clang::tidy::google;
+
+namespace clang {
+namespace tidy {
+namespace test {
+
+TEST(ExplicitConstructorCheckTest, SingleArgumentConstructorsOnly) {
+  EXPECT_NO_CHANGES(ExplicitConstructorCheck, "class C { C(); };");
+  EXPECT_NO_CHANGES(ExplicitConstructorCheck, "class C { C(int i, int j); };");
+  EXPECT_NO_CHANGES(ExplicitConstructorCheck, "class C { C(const C&); };");
+  EXPECT_NO_CHANGES(ExplicitConstructorCheck, "class C { C(C&&); };");
+  EXPECT_NO_CHANGES(ExplicitConstructorCheck,
+                    "class C { C(const C&) = delete; };");
+  EXPECT_NO_CHANGES(ExplicitConstructorCheck,
+                    "class C { C(int) = delete; };");
+}
+
+TEST(ExplicitConstructorCheckTest, Basic) {
+  EXPECT_EQ("class C { explicit C(int i); };",
+            runCheckOnCode<ExplicitConstructorCheck>("class C { C(int i); };"));
+}
+
+TEST(ExplicitConstructorCheckTest, DefaultParameters) {
+  EXPECT_EQ("class C { explicit C(int i, int j = 0); };",
+            runCheckOnCode<ExplicitConstructorCheck>(
+                "class C { C(int i, int j = 0); };"));
+}
+
+TEST(ExplicitConstructorCheckTest, OutOfLineDefinitions) {
+  EXPECT_EQ("class C { explicit C(int i); }; C::C(int i) {}",
+            runCheckOnCode<ExplicitConstructorCheck>(
+                "class C { C(int i); }; C::C(int i) {}"));
+}
+
+TEST(ExplicitConstructorCheckTest, RemoveExplicit) {
+  EXPECT_EQ("class A { A(const A&); };\n"
+            "class B { /*asdf*/  B(B&&); };\n"
+            "class C { /*asdf*/  C(const C&, int i = 0); };",
+            runCheckOnCode<ExplicitConstructorCheck>(
+                "class A { explicit    A(const A&); };\n"
+                "class B { explicit   /*asdf*/  B(B&&); };\n"
+                "class C { explicit/*asdf*/  C(const C&, int i = 0); };"));
+}
+
+TEST(ExplicitConstructorCheckTest, RemoveExplicitWithMacros) {
+  EXPECT_EQ(
+      "#define A(T) class T##Bar { explicit T##Bar(const T##Bar &b) {} };\n"
+      "A(Foo);",
+      runCheckOnCode<ExplicitConstructorCheck>(
+          "#define A(T) class T##Bar { explicit T##Bar(const T##Bar &b) {} };\n"
+          "A(Foo);"));
+}
+
+class GlobalNamesInHeadersCheckTest : public ::testing::Test {
+protected:
+  bool runCheckOnCode(const std::string &Code, const std::string &Filename) {
+    static const char *const Header = "namespace std {\n"
+                                      "class string {};\n"
+                                      "}  // namespace std\n"
+                                      "\n"
+                                      "#define SOME_MACRO(x) using x\n";
+    std::vector<ClangTidyError> Errors;
+    std::vector<std::string> Args;
+    if (!StringRef(Filename).endswith(".cpp")) {
+      Args.emplace_back("-xc++-header");
+    }
+    test::runCheckOnCode<readability::GlobalNamesInHeadersCheck>(
+        Header + Code, &Errors, Filename, Args);
+    if (Errors.empty())
+      return false;
+    assert(Errors.size() == 1);
+    assert(
+        Errors[0].Message.Message ==
+        "using declarations in the global namespace in headers are prohibited");
+    return true;
+  }
+};
+
+TEST_F(GlobalNamesInHeadersCheckTest, UsingDeclarations) {
+  EXPECT_TRUE(runCheckOnCode("using std::string;", "foo.h"));
+  EXPECT_FALSE(runCheckOnCode("using std::string;", "foo.cpp"));
+  EXPECT_FALSE(runCheckOnCode("namespace my_namespace {\n"
+                              "using std::string;\n"
+                              "}  // my_namespace\n",
+                              "foo.h"));
+  EXPECT_FALSE(runCheckOnCode("SOME_MACRO(std::string);", "foo.h"));
+}
+
+TEST_F(GlobalNamesInHeadersCheckTest, UsingDirectives) {
+  EXPECT_TRUE(runCheckOnCode("using namespace std;", "foo.h"));
+  EXPECT_FALSE(runCheckOnCode("using namespace std;", "foo.cpp"));
+  EXPECT_FALSE(runCheckOnCode("namespace my_namespace {\n"
+                              "using namespace std;\n"
+                              "}  // my_namespace\n",
+                              "foo.h"));
+  EXPECT_FALSE(runCheckOnCode("SOME_MACRO(namespace std);", "foo.h"));
+}
+
+TEST_F(GlobalNamesInHeadersCheckTest, RegressionAnonymousNamespace) {
+  EXPECT_FALSE(runCheckOnCode("namespace {}", "foo.h"));
+}
+
+} // namespace test
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/IncludeInserterTest.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/IncludeInserterTest.cpp
new file mode 100644
index 0000000..a5f5898
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/IncludeInserterTest.cpp
@@ -0,0 +1,612 @@
+//===---- IncludeInserterTest.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 "../clang-tidy/utils/IncludeInserter.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "ClangTidyTest.h"
+#include "gtest/gtest.h"
+
+// FIXME: Canonicalize paths correctly on windows.
+// Currently, adding virtual files will canonicalize the paths before
+// storing the virtual entries.
+// When resolving virtual entries in the FileManager, the paths (for
+// example coming from a #include directive) are not canonicalized
+// to native paths; thus, the virtual file is not found.
+// This needs to be fixed in the FileManager before we can make
+// clang-tidy tests work.
+#if !defined(_WIN32)
+
+namespace clang {
+namespace tidy {
+namespace {
+
+class IncludeInserterCheckBase : public ClangTidyCheck {
+public:
+  IncludeInserterCheckBase(StringRef CheckName, ClangTidyContext *Context)
+      : ClangTidyCheck(CheckName, Context) {}
+
+  void registerPPCallbacks(CompilerInstance &Compiler) override {
+    Inserter.reset(new utils::IncludeInserter(
+        Compiler.getSourceManager(),
+        Compiler.getLangOpts(),
+        utils::IncludeSorter::IS_Google));
+    Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+  }
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override {
+    Finder->addMatcher(ast_matchers::declStmt().bind("stmt"), this);
+  }
+
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
+    auto Diag = diag(Result.Nodes.getNodeAs<DeclStmt>("stmt")->getLocStart(),
+                     "foo, bar");
+    for (StringRef header : HeadersToInclude()) {
+      auto Fixit = Inserter->CreateIncludeInsertion(
+          Result.SourceManager->getMainFileID(), header, IsAngledInclude());
+      if (Fixit) {
+        Diag << *Fixit;
+      }
+    }
+  }
+
+  virtual std::vector<StringRef> HeadersToInclude() const = 0;
+  virtual bool IsAngledInclude() const = 0;
+
+  std::unique_ptr<utils::IncludeInserter> Inserter;
+};
+
+class NonSystemHeaderInserterCheck : public IncludeInserterCheckBase {
+public:
+  NonSystemHeaderInserterCheck(StringRef CheckName, ClangTidyContext *Context)
+      : IncludeInserterCheckBase(CheckName, Context) {}
+
+  std::vector<StringRef> HeadersToInclude() const override {
+    return {"path/to/header.h"};
+  }
+  bool IsAngledInclude() const override { return false; }
+};
+
+class EarlyInAlphabetHeaderInserterCheck : public IncludeInserterCheckBase {
+public:
+  EarlyInAlphabetHeaderInserterCheck(StringRef CheckName, ClangTidyContext *Context)
+      : IncludeInserterCheckBase(CheckName, Context) {}
+
+  std::vector<StringRef> HeadersToInclude() const override {
+    return {"a/header.h"};
+  }
+  bool IsAngledInclude() const override { return false; }
+};
+
+class MultipleHeaderInserterCheck : public IncludeInserterCheckBase {
+public:
+  MultipleHeaderInserterCheck(StringRef CheckName, ClangTidyContext *Context)
+      : IncludeInserterCheckBase(CheckName, Context) {}
+
+  std::vector<StringRef> HeadersToInclude() const override {
+    return {"path/to/header.h", "path/to/header2.h", "path/to/header.h"};
+  }
+  bool IsAngledInclude() const override { return false; }
+};
+
+class CSystemIncludeInserterCheck : public IncludeInserterCheckBase {
+public:
+  CSystemIncludeInserterCheck(StringRef CheckName, ClangTidyContext *Context)
+      : IncludeInserterCheckBase(CheckName, Context) {}
+
+  std::vector<StringRef> HeadersToInclude() const override {
+    return {"stdlib.h"};
+  }
+  bool IsAngledInclude() const override { return true; }
+};
+
+class CXXSystemIncludeInserterCheck : public IncludeInserterCheckBase {
+public:
+  CXXSystemIncludeInserterCheck(StringRef CheckName, ClangTidyContext *Context)
+      : IncludeInserterCheckBase(CheckName, Context) {}
+
+  std::vector<StringRef> HeadersToInclude() const override { return {"set"}; }
+  bool IsAngledInclude() const override { return true; }
+};
+
+template <typename Check>
+std::string runCheckOnCode(StringRef Code, StringRef Filename) {
+  std::vector<ClangTidyError> Errors;
+  return test::runCheckOnCode<Check>(Code, &Errors, Filename, None,
+                                     ClangTidyOptions(),
+                                     {// Main file include
+                                      {"clang_tidy/tests/"
+                                       "insert_includes_test_header.h",
+                                       "\n"},
+                                      // Non system headers
+                                      {"a/header.h", "\n"},
+                                      {"path/to/a/header.h", "\n"},
+                                      {"path/to/z/header.h", "\n"},
+                                      {"path/to/header.h", "\n"},
+                                      {"path/to/header2.h", "\n"},
+                                      // Fake system headers.
+                                      {"stdlib.h", "\n"},
+                                      {"unistd.h", "\n"},
+                                      {"list", "\n"},
+                                      {"map", "\n"},
+                                      {"set", "\n"},
+                                      {"vector", "\n"}});
+}
+
+TEST(IncludeInserterTest, InsertAfterLastNonSystemInclude) {
+  const char *PreCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <list>
+#include <map>
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <list>
+#include <map>
+
+#include "path/to/a/header.h"
+#include "path/to/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<NonSystemHeaderInserterCheck>(
+                          PreCode, "clang_tidy/tests/"
+                                   "insert_includes_test_input2.cc"));
+}
+
+TEST(IncludeInserterTest, InsertMultipleIncludesAndDeduplicate) {
+  const char *PreCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <list>
+#include <map>
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <list>
+#include <map>
+
+#include "path/to/a/header.h"
+#include "path/to/header.h"
+#include "path/to/header2.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<MultipleHeaderInserterCheck>(
+                          PreCode, "clang_tidy/tests/"
+                                   "insert_includes_test_input2.cc"));
+}
+
+TEST(IncludeInserterTest, InsertBeforeFirstNonSystemInclude) {
+  const char *PreCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <list>
+#include <map>
+
+#include "path/to/z/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <list>
+#include <map>
+
+#include "path/to/header.h"
+#include "path/to/z/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<NonSystemHeaderInserterCheck>(
+                          PreCode, "clang_tidy/tests/"
+                                   "insert_includes_test_input2.cc"));
+}
+
+TEST(IncludeInserterTest, InsertBetweenNonSystemIncludes) {
+  const char *PreCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <list>
+#include <map>
+
+#include "path/to/a/header.h"
+#include "path/to/z/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <list>
+#include <map>
+
+#include "path/to/a/header.h"
+#include "path/to/header.h"
+#include "path/to/z/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<NonSystemHeaderInserterCheck>(
+                          PreCode, "clang_tidy/tests/"
+                                   "insert_includes_test_input2.cc"));
+}
+
+TEST(IncludeInserterTest, NonSystemIncludeAlreadyIncluded) {
+  const char *PreCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <list>
+#include <map>
+
+#include "path/to/a/header.h"
+#include "path/to/header.h"
+#include "path/to/z/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  EXPECT_EQ(PreCode, runCheckOnCode<NonSystemHeaderInserterCheck>(
+                         PreCode, "clang_tidy/tests/"
+                                  "insert_includes_test_input2.cc"));
+}
+
+TEST(IncludeInserterTest, InsertNonSystemIncludeAfterLastCXXSystemInclude) {
+  const char *PreCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <list>
+#include <map>
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <list>
+#include <map>
+
+#include "path/to/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<NonSystemHeaderInserterCheck>(
+                          PreCode, "clang_tidy/tests/"
+                                   "insert_includes_test_header.cc"));
+}
+
+TEST(IncludeInserterTest, InsertNonSystemIncludeAfterMainFileInclude) {
+  const char *PreCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include "path/to/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<NonSystemHeaderInserterCheck>(
+                          PreCode, "clang_tidy/tests/"
+                                   "insert_includes_test_header.cc"));
+}
+
+TEST(IncludeInserterTest, InsertCXXSystemIncludeAfterLastCXXSystemInclude) {
+  const char *PreCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <list>
+#include <map>
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <list>
+#include <map>
+#include <set>
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<CXXSystemIncludeInserterCheck>(
+                          PreCode, "clang_tidy/tests/"
+                                   "insert_includes_test_header.cc"));
+}
+
+TEST(IncludeInserterTest, InsertCXXSystemIncludeBeforeFirstCXXSystemInclude) {
+  const char *PreCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <vector>
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <set>
+#include <vector>
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<CXXSystemIncludeInserterCheck>(
+                          PreCode, "clang_tidy/tests/"
+                                   "insert_includes_test_header.cc"));
+}
+
+TEST(IncludeInserterTest, InsertCXXSystemIncludeBetweenCXXSystemIncludes) {
+  const char *PreCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <map>
+#include <vector>
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<CXXSystemIncludeInserterCheck>(
+                          PreCode, "clang_tidy/tests/"
+                                   "insert_includes_test_header.cc"));
+}
+
+TEST(IncludeInserterTest, InsertCXXSystemIncludeAfterMainFileInclude) {
+  const char *PreCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <set>
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<CXXSystemIncludeInserterCheck>(
+                          PreCode, "clang_tidy/tests/"
+                                   "insert_includes_test_header.cc"));
+}
+
+TEST(IncludeInserterTest, InsertCXXSystemIncludeAfterCSystemInclude) {
+  const char *PreCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <stdlib.h>
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <stdlib.h>
+
+#include <set>
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<CXXSystemIncludeInserterCheck>(
+                          PreCode, "clang_tidy/tests/"
+                                   "insert_includes_test_header.cc"));
+}
+
+TEST(IncludeInserterTest, InsertCXXSystemIncludeBeforeNonSystemInclude) {
+  const char *PreCode = R"(
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include <set>
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<CXXSystemIncludeInserterCheck>(
+                          PreCode, "devtools/cymbal/clang_tidy/tests/"
+                                   "insert_includes_test_header.cc"));
+}
+
+TEST(IncludeInserterTest, InsertCSystemIncludeBeforeCXXSystemInclude) {
+  const char *PreCode = R"(
+#include <set>
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include <stdlib.h>
+
+#include <set>
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<CSystemIncludeInserterCheck>(
+                          PreCode, "devtools/cymbal/clang_tidy/tests/"
+                                   "insert_includes_test_header.cc"));
+}
+
+TEST(IncludeInserterTest, InsertIncludeIfThereWasNoneBefore) {
+  const char *PreCode = R"(
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(#include <set>
+
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<CXXSystemIncludeInserterCheck>(
+                          PreCode, "devtools/cymbal/clang_tidy/tests/"
+                                   "insert_includes_test_header.cc"));
+}
+
+TEST(IncludeInserterTest, DontInsertDuplicateIncludeEvenIfMiscategorized) {
+  const char *PreCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "a/header.h"
+#include "path/to/a/header.h"
+#include "path/to/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  const char *PostCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "a/header.h"
+#include "path/to/a/header.h"
+#include "path/to/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<EarlyInAlphabetHeaderInserterCheck>(
+                          PreCode, "workspace_folder/clang_tidy/tests/"
+                                   "insert_includes_test_header.cc"));
+}
+
+TEST(IncludeInserterTest, HandleOrderInSubdirectory) {
+  const char *PreCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "path/to/a/header.h"
+#include "path/to/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  const char *PostCode = R"(
+#include "clang_tidy/tests/insert_includes_test_header.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "a/header.h"
+#include "path/to/a/header.h"
+#include "path/to/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode<EarlyInAlphabetHeaderInserterCheck>(
+                          PreCode, "workspace_folder/clang_tidy/tests/"
+                                   "insert_includes_test_header.cc"));
+}
+
+} // anonymous namespace
+} // namespace tidy
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/LLVMModuleTest.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/LLVMModuleTest.cpp
new file mode 100644
index 0000000..8ab207d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/LLVMModuleTest.cpp
@@ -0,0 +1,219 @@
+#include "ClangTidyTest.h"
+#include "llvm/HeaderGuardCheck.h"
+#include "llvm/IncludeOrderCheck.h"
+#include "gtest/gtest.h"
+
+using namespace clang::tidy::llvm;
+
+namespace clang {
+namespace tidy {
+namespace test {
+
+// FIXME: It seems this might be incompatible to dos path. Investigating.
+#if !defined(_WIN32)
+static std::string runHeaderGuardCheck(StringRef Code, const Twine &Filename,
+                                       Optional<StringRef> ExpectedWarning) {
+  std::vector<ClangTidyError> Errors;
+  std::string Result = test::runCheckOnCode<LLVMHeaderGuardCheck>(
+      Code, &Errors, Filename, std::string("-xc++-header"));
+  if (Errors.size() != (size_t)ExpectedWarning.hasValue())
+    return "invalid error count";
+  if (ExpectedWarning && *ExpectedWarning != Errors.back().Message.Message)
+    return "expected: '" + ExpectedWarning->str() + "', saw: '" +
+           Errors.back().Message.Message + "'";
+  return Result;
+}
+
+namespace {
+struct WithEndifComment : public LLVMHeaderGuardCheck {
+  WithEndifComment(StringRef Name, ClangTidyContext *Context)
+      : LLVMHeaderGuardCheck(Name, Context) {}
+  bool shouldSuggestEndifComment(StringRef Filename) override { return true; }
+};
+} // namespace
+
+static std::string
+runHeaderGuardCheckWithEndif(StringRef Code, const Twine &Filename,
+                             Optional<StringRef> ExpectedWarning) {
+  std::vector<ClangTidyError> Errors;
+  std::string Result = test::runCheckOnCode<WithEndifComment>(
+      Code, &Errors, Filename, std::string("-xc++-header"));
+  if (Errors.size() != (size_t)ExpectedWarning.hasValue())
+    return "invalid error count";
+  if (ExpectedWarning && *ExpectedWarning != Errors.back().Message.Message)
+    return "expected: '" + ExpectedWarning->str() + "', saw: '" +
+           Errors.back().Message.Message + "'";
+  return Result;
+}
+
+TEST(LLVMHeaderGuardCheckTest, FixHeaderGuards) {
+  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
+            "#define LLVM_ADT_FOO_H\n"
+            "#endif\n",
+            runHeaderGuardCheck(
+                "#ifndef FOO\n"
+                "#define FOO\n"
+                "#endif\n",
+                "include/llvm/ADT/foo.h",
+                StringRef("header guard does not follow preferred style")));
+
+  // Allow trailing underscores.
+  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H_\n"
+            "#define LLVM_ADT_FOO_H_\n"
+            "#endif\n",
+            runHeaderGuardCheck("#ifndef LLVM_ADT_FOO_H_\n"
+                                "#define LLVM_ADT_FOO_H_\n"
+                                "#endif\n",
+                                "include/llvm/ADT/foo.h", None));
+
+  EXPECT_EQ("#ifndef LLVM_CLANG_C_BAR_H\n"
+            "#define LLVM_CLANG_C_BAR_H\n"
+            "\n"
+            "\n"
+            "#endif\n",
+            runHeaderGuardCheck("", "./include/clang-c/bar.h",
+                                StringRef("header is missing header guard")));
+
+  EXPECT_EQ("#ifndef LLVM_CLANG_LIB_CODEGEN_C_H\n"
+            "#define LLVM_CLANG_LIB_CODEGEN_C_H\n"
+            "\n"
+            "\n"
+            "#endif\n",
+            runHeaderGuardCheck("", "tools/clang/lib/CodeGen/c.h",
+                                StringRef("header is missing header guard")));
+
+  EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_X_H\n"
+            "#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_X_H\n"
+            "\n"
+            "\n"
+            "#endif\n",
+            runHeaderGuardCheck("", "tools/clang/tools/extra/clang-tidy/x.h",
+                                StringRef("header is missing header guard")));
+
+  EXPECT_EQ(
+      "int foo;\n"
+      "#ifndef LLVM_CLANG_BAR_H\n"
+      "#define LLVM_CLANG_BAR_H\n"
+      "#endif\n",
+      runHeaderGuardCheck("int foo;\n"
+                          "#ifndef LLVM_CLANG_BAR_H\n"
+                          "#define LLVM_CLANG_BAR_H\n"
+                          "#endif\n",
+                          "include/clang/bar.h",
+                          StringRef("code/includes outside of area guarded by "
+                                    "header guard; consider moving it")));
+
+  EXPECT_EQ(
+      "#ifndef LLVM_CLANG_BAR_H\n"
+      "#define LLVM_CLANG_BAR_H\n"
+      "#endif\n"
+      "int foo;\n",
+      runHeaderGuardCheck("#ifndef LLVM_CLANG_BAR_H\n"
+                          "#define LLVM_CLANG_BAR_H\n"
+                          "#endif\n"
+                          "int foo;\n",
+                          "include/clang/bar.h",
+                          StringRef("code/includes outside of area guarded by "
+                                    "header guard; consider moving it")));
+
+  EXPECT_EQ("#ifndef LLVM_CLANG_BAR_H\n"
+            "#define LLVM_CLANG_BAR_H\n"
+            "\n"
+            "int foo;\n"
+            "#ifndef FOOLOLO\n"
+            "#define FOOLOLO\n"
+            "#endif\n"
+            "\n"
+            "#endif\n",
+            runHeaderGuardCheck("int foo;\n"
+                                "#ifndef FOOLOLO\n"
+                                "#define FOOLOLO\n"
+                                "#endif\n",
+                                "include/clang/bar.h",
+                                StringRef("header is missing header guard")));
+
+  // Fix incorrect #endif comments even if we shouldn't add new ones.
+  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
+            "#define LLVM_ADT_FOO_H\n"
+            "#endif // LLVM_ADT_FOO_H\n",
+            runHeaderGuardCheck(
+                "#ifndef FOO\n"
+                "#define FOO\n"
+                "#endif // FOO\n",
+                "include/llvm/ADT/foo.h",
+                StringRef("header guard does not follow preferred style")));
+
+  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
+            "#define LLVM_ADT_FOO_H\n"
+            "#endif // LLVM_ADT_FOO_H\n",
+            runHeaderGuardCheckWithEndif(
+                "#ifndef FOO\n"
+                "#define FOO\n"
+                "#endif\n",
+                "include/llvm/ADT/foo.h",
+                StringRef("header guard does not follow preferred style")));
+
+  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
+            "#define LLVM_ADT_FOO_H\n"
+            "#endif // LLVM_ADT_FOO_H\n",
+            runHeaderGuardCheckWithEndif(
+                "#ifndef LLVM_ADT_FOO_H\n"
+                "#define LLVM_ADT_FOO_H\n"
+                "#endif // LLVM_H\n",
+                "include/llvm/ADT/foo.h",
+                StringRef("#endif for a header guard should reference the "
+                          "guard macro in a comment")));
+
+  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
+            "#define LLVM_ADT_FOO_H\n"
+            "#endif /* LLVM_ADT_FOO_H */\n",
+            runHeaderGuardCheckWithEndif("#ifndef LLVM_ADT_FOO_H\n"
+                                         "#define LLVM_ADT_FOO_H\n"
+                                         "#endif /* LLVM_ADT_FOO_H */\n",
+                                         "include/llvm/ADT/foo.h", None));
+
+  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H_\n"
+            "#define LLVM_ADT_FOO_H_\n"
+            "#endif // LLVM_ADT_FOO_H_\n",
+            runHeaderGuardCheckWithEndif("#ifndef LLVM_ADT_FOO_H_\n"
+                                         "#define LLVM_ADT_FOO_H_\n"
+                                         "#endif // LLVM_ADT_FOO_H_\n",
+                                         "include/llvm/ADT/foo.h", None));
+
+  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
+            "#define LLVM_ADT_FOO_H\n"
+            "#endif // LLVM_ADT_FOO_H\n",
+            runHeaderGuardCheckWithEndif(
+                "#ifndef LLVM_ADT_FOO_H_\n"
+                "#define LLVM_ADT_FOO_H_\n"
+                "#endif // LLVM\n",
+                "include/llvm/ADT/foo.h",
+                StringRef("header guard does not follow preferred style")));
+
+  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
+            "#define LLVM_ADT_FOO_H\n"
+            "#endif \\ \n"
+            "// LLVM_ADT_FOO_H\n",
+            runHeaderGuardCheckWithEndif(
+                "#ifndef LLVM_ADT_FOO_H\n"
+                "#define LLVM_ADT_FOO_H\n"
+                "#endif \\ \n"
+                "// LLVM_ADT_FOO_H\n",
+                "include/llvm/ADT/foo.h",
+                StringRef("backslash and newline separated by space")));
+
+  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
+            "#define LLVM_ADT_FOO_H\n"
+            "#endif  /* LLVM_ADT_FOO_H\\ \n"
+            " FOO */",
+            runHeaderGuardCheckWithEndif("#ifndef LLVM_ADT_FOO_H\n"
+                                         "#define LLVM_ADT_FOO_H\n"
+                                         "#endif  /* LLVM_ADT_FOO_H\\ \n"
+                                         " FOO */",
+                                         "include/llvm/ADT/foo.h", None));
+}
+#endif
+
+} // namespace test
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/NamespaceAliaserTest.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/NamespaceAliaserTest.cpp
new file mode 100644
index 0000000..71286e2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/NamespaceAliaserTest.cpp
@@ -0,0 +1,123 @@
+//===---- NamespaceAliaserTest.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 "../clang-tidy/utils/NamespaceAliaser.h"
+
+#include "ClangTidyTest.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+// This checker is for testing only. It can only run on one test case
+// (e.g. with one SourceManager).
+class InsertAliasCheck : public ClangTidyCheck {
+public:
+  InsertAliasCheck(StringRef Name, ClangTidyContext *Context)
+      :ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override {
+    Finder->addMatcher(ast_matchers::callExpr().bind("foo"), this);
+  }
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
+    if (!Aliaser)
+      Aliaser.reset(new NamespaceAliaser(*Result.SourceManager));
+
+    const auto *Call = Result.Nodes.getNodeAs<CallExpr>("foo");
+    assert(Call != nullptr && "Did not find node \"foo\"");
+    auto Hint = Aliaser->createAlias(*Result.Context, *Call, "::foo::bar",
+                                     {"b", "some_alias"});
+    if (Hint.hasValue())
+      diag(Call->getLocStart(), "Fix for testing") << Hint.getValue();
+
+    diag(Call->getLocStart(), "insert call")
+        << FixItHint::CreateInsertion(
+               Call->getLocStart(),
+               Aliaser->getNamespaceName(*Result.Context, *Call, "::foo::bar") +
+                   "::");
+  }
+
+private:
+  std::unique_ptr<NamespaceAliaser> Aliaser;
+};
+
+template <typename Check>
+std::string runChecker(StringRef Code, unsigned ExpectedWarningCount) {
+  std::map<StringRef, StringRef> AdditionalFileContents = {{"foo.h",
+                                                            "namespace foo {\n"
+                                                            "namespace bar {\n"
+                                                            "}\n"
+                                                            "void func() { }\n"
+                                                            "}"}};
+  std::vector<ClangTidyError> errors;
+
+  std::string result =
+      test::runCheckOnCode<Check>(Code, &errors, "foo.cc", None,
+                                  ClangTidyOptions(), AdditionalFileContents);
+
+  EXPECT_EQ(ExpectedWarningCount, errors.size());
+  return result;
+}
+
+TEST(NamespaceAliaserTest, AddNewAlias) {
+  EXPECT_EQ("#include \"foo.h\"\n"
+            "void f() {\n"
+            "namespace b = ::foo::bar;"
+            " b::f(); }",
+            runChecker<InsertAliasCheck>("#include \"foo.h\"\n"
+                                         "void f() { f(); }",
+                                         2));
+}
+
+TEST(NamespaceAliaserTest, ReuseAlias) {
+  EXPECT_EQ(
+      "#include \"foo.h\"\n"
+      "void f() { namespace x = foo::bar; x::f(); }",
+      runChecker<InsertAliasCheck>("#include \"foo.h\"\n"
+                                   "void f() { namespace x = foo::bar; f(); }",
+                                   1));
+}
+
+TEST(NamespaceAliaserTest, AddsOnlyOneAlias) {
+  EXPECT_EQ("#include \"foo.h\"\n"
+            "void f() {\n"
+            "namespace b = ::foo::bar;"
+            " b::f(); b::f(); }",
+            runChecker<InsertAliasCheck>("#include \"foo.h\"\n"
+                                         "void f() { f(); f(); }",
+                                         3));
+}
+
+TEST(NamespaceAliaserTest, LocalConflict) {
+  EXPECT_EQ("#include \"foo.h\"\n"
+            "void f() {\n"
+            "namespace some_alias = ::foo::bar;"
+            " namespace b = foo; some_alias::f(); }",
+            runChecker<InsertAliasCheck>("#include \"foo.h\"\n"
+                                         "void f() { namespace b = foo; f(); }",
+                                         2));
+}
+
+TEST(NamespaceAliaserTest, GlobalConflict) {
+  EXPECT_EQ("#include \"foo.h\"\n"
+            "namespace b = foo;\n"
+            "void f() {\n"
+            "namespace some_alias = ::foo::bar;"
+            " some_alias::f(); }",
+            runChecker<InsertAliasCheck>("#include \"foo.h\"\n"
+                                         "namespace b = foo;\n"
+                                         "void f() { f(); }",
+                                         2));
+}
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ObjCModuleTest.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ObjCModuleTest.cpp
new file mode 100644
index 0000000..92ae8e1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ObjCModuleTest.cpp
@@ -0,0 +1,49 @@
+//===---- ObjCModuleTest.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 "ClangTidyTest.h"
+#include "gtest/gtest.h"
+#include "objc/ForbiddenSubclassingCheck.h"
+
+using namespace clang::tidy::objc;
+
+namespace clang {
+namespace tidy {
+namespace test {
+
+TEST(ObjCForbiddenSubclassing, AllowedSubclass) {
+  std::vector<ClangTidyError> Errors;
+  runCheckOnCode<ForbiddenSubclassingCheck>(
+      "@interface Foo\n"
+      "@end\n"
+      "@interface Bar : Foo\n"
+      "@end\n",
+      &Errors,
+      "input.m");
+  EXPECT_EQ(0ul, Errors.size());
+}
+
+TEST(ObjCForbiddenSubclassing, ForbiddenSubclass) {
+  std::vector<ClangTidyError> Errors;
+  runCheckOnCode<ForbiddenSubclassingCheck>(
+      "@interface UIImagePickerController\n"
+      "@end\n"
+      "@interface Foo : UIImagePickerController\n"
+      "@end\n",
+      &Errors,
+      "input.m");
+  EXPECT_EQ(1ul, Errors.size());
+  EXPECT_EQ(
+      "Objective-C interface 'Foo' subclasses 'UIImagePickerController', which is not intended to be subclassed",
+      Errors[0].Message.Message);
+}
+
+} // namespace test
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/OverlappingReplacementsTest.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/OverlappingReplacementsTest.cpp
new file mode 100644
index 0000000..b7c4805
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/OverlappingReplacementsTest.cpp
@@ -0,0 +1,409 @@
+//===---- OverlappingReplacementsTest.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 "ClangTidyTest.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace tidy {
+namespace test {
+namespace {
+
+const char BoundDecl[] = "decl";
+const char BoundIf[] = "if";
+
+// We define a reduced set of very small checks that allow to test different
+// overlapping situations (no overlapping, replacements partially overlap, etc),
+// as well as different kinds of diagnostics (one check produces several errors,
+// several replacement ranges in an error, etc).
+class UseCharCheck : public ClangTidyCheck {
+public:
+  UseCharCheck(StringRef CheckName, ClangTidyContext *Context)
+      : ClangTidyCheck(CheckName, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override {
+    using namespace ast_matchers;
+    Finder->addMatcher(varDecl(hasType(isInteger())).bind(BoundDecl), this);
+  }
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
+    auto *VD = Result.Nodes.getNodeAs<VarDecl>(BoundDecl);
+    diag(VD->getLocStart(), "use char") << FixItHint::CreateReplacement(
+        CharSourceRange::getTokenRange(VD->getLocStart(), VD->getLocStart()),
+        "char");
+  }
+};
+
+class IfFalseCheck : public ClangTidyCheck {
+public:
+  IfFalseCheck(StringRef CheckName, ClangTidyContext *Context)
+      : ClangTidyCheck(CheckName, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override {
+    using namespace ast_matchers;
+    Finder->addMatcher(ifStmt().bind(BoundIf), this);
+  }
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
+    auto *If = Result.Nodes.getNodeAs<IfStmt>(BoundIf);
+    auto *Cond = If->getCond();
+    SourceRange Range = Cond->getSourceRange();
+    if (auto *D = If->getConditionVariable()) {
+      Range = SourceRange(D->getLocStart(), D->getLocEnd());
+    }
+    diag(Range.getBegin(), "the cake is a lie") << FixItHint::CreateReplacement(
+        CharSourceRange::getTokenRange(Range), "false");
+  }
+};
+
+class RefactorCheck : public ClangTidyCheck {
+public:
+  RefactorCheck(StringRef CheckName, ClangTidyContext *Context)
+      : ClangTidyCheck(CheckName, Context), NamePattern("::$") {}
+  RefactorCheck(StringRef CheckName, ClangTidyContext *Context,
+                StringRef NamePattern)
+      : ClangTidyCheck(CheckName, Context), NamePattern(NamePattern) {}
+  virtual std::string newName(StringRef OldName) = 0;
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder) final {
+    using namespace ast_matchers;
+    Finder->addMatcher(varDecl(matchesName(NamePattern)).bind(BoundDecl), this);
+  }
+
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) final {
+    auto *VD = Result.Nodes.getNodeAs<VarDecl>(BoundDecl);
+    std::string NewName = newName(VD->getName());
+
+    auto Diag = diag(VD->getLocation(), "refactor %0 into %1")
+                << VD->getName() << NewName
+                << FixItHint::CreateReplacement(
+                       CharSourceRange::getTokenRange(VD->getLocation(),
+                                                      VD->getLocation()),
+                       NewName);
+
+    class UsageVisitor : public RecursiveASTVisitor<UsageVisitor> {
+    public:
+      UsageVisitor(const ValueDecl *VD, StringRef NewName,
+                   DiagnosticBuilder &Diag)
+          : VD(VD), NewName(NewName), Diag(Diag) {}
+      bool VisitDeclRefExpr(DeclRefExpr *E) {
+        if (const ValueDecl *D = E->getDecl()) {
+          if (VD->getCanonicalDecl() == D->getCanonicalDecl()) {
+            Diag << FixItHint::CreateReplacement(
+                CharSourceRange::getTokenRange(E->getSourceRange()), NewName);
+          }
+        }
+        return RecursiveASTVisitor<UsageVisitor>::VisitDeclRefExpr(E);
+      }
+
+    private:
+      const ValueDecl *VD;
+      StringRef NewName;
+      DiagnosticBuilder &Diag;
+    };
+
+    UsageVisitor(VD, NewName, Diag)
+        .TraverseDecl(Result.Context->getTranslationUnitDecl());
+  }
+
+protected:
+  const std::string NamePattern;
+};
+
+class StartsWithPotaCheck : public RefactorCheck {
+public:
+  StartsWithPotaCheck(StringRef CheckName, ClangTidyContext *Context)
+      : RefactorCheck(CheckName, Context, "::pota") {}
+
+  std::string newName(StringRef OldName) override {
+    return "toma" + OldName.substr(4).str();
+  }
+};
+
+class EndsWithTatoCheck : public RefactorCheck {
+public:
+  EndsWithTatoCheck(StringRef CheckName, ClangTidyContext *Context)
+      : RefactorCheck(CheckName, Context, "tato$") {}
+
+  std::string newName(StringRef OldName) override {
+    return OldName.substr(0, OldName.size() - 4).str() + "melo";
+  }
+};
+
+} // namespace
+
+TEST(OverlappingReplacementsTest, UseCharCheckTest) {
+  const char Code[] =
+      R"(void f() {
+  int a = 0;
+  if (int b = 0) {
+    int c = a;
+  }
+})";
+
+  const char CharFix[] =
+      R"(void f() {
+  char a = 0;
+  if (char b = 0) {
+    char c = a;
+  }
+})";
+  EXPECT_EQ(CharFix, runCheckOnCode<UseCharCheck>(Code));
+}
+
+TEST(OverlappingReplacementsTest, IfFalseCheckTest) {
+  const char Code[] =
+      R"(void f() {
+  int potato = 0;
+  if (int b = 0) {
+    int c = potato;
+  } else if (true) {
+    int d = 0;
+  }
+})";
+
+  const char IfFix[] =
+      R"(void f() {
+  int potato = 0;
+  if (false) {
+    int c = potato;
+  } else if (false) {
+    int d = 0;
+  }
+})";
+  EXPECT_EQ(IfFix, runCheckOnCode<IfFalseCheck>(Code));
+}
+
+TEST(OverlappingReplacementsTest, StartsWithCheckTest) {
+  const char Code[] =
+      R"(void f() {
+  int a = 0;
+  int potato = 0;
+  if (int b = 0) {
+    int c = potato;
+  } else if (true) {
+    int d = 0;
+  }
+})";
+
+  const char StartsFix[] =
+      R"(void f() {
+  int a = 0;
+  int tomato = 0;
+  if (int b = 0) {
+    int c = tomato;
+  } else if (true) {
+    int d = 0;
+  }
+})";
+  EXPECT_EQ(StartsFix, runCheckOnCode<StartsWithPotaCheck>(Code));
+}
+
+TEST(OverlappingReplacementsTest, EndsWithCheckTest) {
+  const char Code[] =
+      R"(void f() {
+  int a = 0;
+  int potato = 0;
+  if (int b = 0) {
+    int c = potato;
+  } else if (true) {
+    int d = 0;
+  }
+})";
+
+  const char EndsFix[] =
+      R"(void f() {
+  int a = 0;
+  int pomelo = 0;
+  if (int b = 0) {
+    int c = pomelo;
+  } else if (true) {
+    int d = 0;
+  }
+})";
+  EXPECT_EQ(EndsFix, runCheckOnCode<EndsWithTatoCheck>(Code));
+}
+
+TEST(OverlappingReplacementTest, ReplacementsDoNotOverlap) {
+  std::string Res;
+  const char Code[] =
+      R"(void f() {
+  int potassium = 0;
+  if (true) {
+    int Potato = potassium;
+  }
+})";
+
+  const char CharIfFix[] =
+      R"(void f() {
+  char potassium = 0;
+  if (false) {
+    char Potato = potassium;
+  }
+})";
+  Res = runCheckOnCode<UseCharCheck, IfFalseCheck>(Code);
+  EXPECT_EQ(CharIfFix, Res);
+
+  const char StartsEndsFix[] =
+      R"(void f() {
+  int tomassium = 0;
+  if (true) {
+    int Pomelo = tomassium;
+  }
+})";
+  Res = runCheckOnCode<StartsWithPotaCheck, EndsWithTatoCheck>(Code);
+  EXPECT_EQ(StartsEndsFix, Res);
+
+  const char CharIfStartsEndsFix[] =
+      R"(void f() {
+  char tomassium = 0;
+  if (false) {
+    char Pomelo = tomassium;
+  }
+})";
+  Res = runCheckOnCode<UseCharCheck, IfFalseCheck, StartsWithPotaCheck,
+                       EndsWithTatoCheck>(Code);
+  EXPECT_EQ(CharIfStartsEndsFix, Res);
+}
+
+TEST(OverlappingReplacementsTest, ReplacementInsideOtherReplacement) {
+  std::string Res;
+  const char Code[] =
+      R"(void f() {
+  if (char potato = 0) {
+  } else if (int a = 0) {
+    char potato = 0;
+    if (potato) potato;
+  }
+})";
+
+  // Apply the UseCharCheck together with the IfFalseCheck.
+  //
+  // The 'If' fix contains the other, so that is the one that has to be applied.
+  // } else if (int a = 0) {
+  //            ^^^ -> char
+  //            ~~~~~~~~~ -> false
+  const char CharIfFix[] =
+      R"(void f() {
+  if (false) {
+  } else if (false) {
+    char potato = 0;
+    if (false) potato;
+  }
+})";
+  Res = runCheckOnCode<UseCharCheck, IfFalseCheck>(Code);
+  EXPECT_EQ(CharIfFix, Res);
+  Res = runCheckOnCode<IfFalseCheck, UseCharCheck>(Code);
+  EXPECT_EQ(CharIfFix, Res);
+
+  // Apply the IfFalseCheck with the StartsWithPotaCheck.
+  //
+  // The 'If' replacement is bigger here.
+  // if (char potato = 0) {
+  //          ^^^^^^ -> tomato
+  //     ~~~~~~~~~~~~~~~ -> false
+  //
+  // But the refactoring is the one that contains the other here:
+  // char potato = 0;
+  //      ^^^^^^ -> tomato
+  // if (potato) potato;
+  //     ^^^^^^  ^^^^^^ -> tomato, tomato
+  //     ~~~~~~ -> false
+  const char IfStartsFix[] =
+      R"(void f() {
+  if (false) {
+  } else if (false) {
+    char tomato = 0;
+    if (tomato) tomato;
+  }
+})";
+  Res = runCheckOnCode<IfFalseCheck, StartsWithPotaCheck>(Code);
+  EXPECT_EQ(IfStartsFix, Res);
+  Res = runCheckOnCode<StartsWithPotaCheck, IfFalseCheck>(Code);
+  EXPECT_EQ(IfStartsFix, Res);
+}
+
+TEST(OverlappingReplacements, TwoReplacementsInsideOne) {
+  std::string Res;
+  const char Code[] =
+      R"(void f() {
+  if (int potato = 0) {
+    int a = 0;
+  }
+})";
+
+  // The two smallest replacements should not be applied.
+  // if (int potato = 0) {
+  //         ^^^^^^ -> tomato
+  //     *** -> char
+  //     ~~~~~~~~~~~~~~ -> false
+  // But other errors from the same checks should not be affected.
+  //   int a = 0;
+  //   *** -> char
+  const char Fix[] =
+      R"(void f() {
+  if (false) {
+    char a = 0;
+  }
+})";
+  Res = runCheckOnCode<UseCharCheck, IfFalseCheck, StartsWithPotaCheck>(Code);
+  EXPECT_EQ(Fix, Res);
+  Res = runCheckOnCode<StartsWithPotaCheck, IfFalseCheck, UseCharCheck>(Code);
+  EXPECT_EQ(Fix, Res);
+}
+
+TEST(OverlappingReplacementsTest,
+     ApplyAtMostOneOfTheChangesWhenPartialOverlapping) {
+  std::string Res;
+  const char Code[] =
+      R"(void f() {
+  if (int potato = 0) {
+    int a = potato;
+  }
+})";
+
+  // These two replacements overlap, but none of them is completely contained
+  // inside the other.
+  // if (int potato = 0) {
+  //         ^^^^^^ -> tomato
+  //     ~~~~~~~~~~~~~~ -> false
+  //   int a = potato;
+  //           ^^^^^^ -> tomato
+  //
+  // The 'StartsWithPotaCheck' fix has endpoints inside the 'IfFalseCheck' fix,
+  // so it is going to be set as inapplicable. The 'if' fix will be applied.
+  const char IfFix[] =
+      R"(void f() {
+  if (false) {
+    int a = potato;
+  }
+})";
+  Res = runCheckOnCode<IfFalseCheck, StartsWithPotaCheck>(Code);
+  EXPECT_EQ(IfFix, Res);
+}
+
+TEST(OverlappingReplacementsTest, TwoErrorsHavePerfectOverlapping) {
+  std::string Res;
+  const char Code[] =
+      R"(void f() {
+  int potato = 0;
+  potato += potato * potato;
+  if (char a = potato) potato;
+})";
+
+  // StartsWithPotaCheck will try to refactor 'potato' into 'tomato', and
+  // EndsWithTatoCheck will try to use 'pomelo'. Both fixes have the same set of
+  // ranges. This is a corner case of one error completely containing another:
+  // the other completely contains the first one as well. Both errors are
+  // discarded.
+
+  Res = runCheckOnCode<StartsWithPotaCheck, EndsWithTatoCheck>(Code);
+  EXPECT_EQ(Code, Res);
+}
+
+} // namespace test
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ReadabilityModuleTest.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ReadabilityModuleTest.cpp
new file mode 100644
index 0000000..a0eca16
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/ReadabilityModuleTest.cpp
@@ -0,0 +1,505 @@
+#include "ClangTidyTest.h"
+#include "readability/BracesAroundStatementsCheck.h"
+#include "readability/NamespaceCommentCheck.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace tidy {
+namespace test {
+
+using readability::BracesAroundStatementsCheck;
+using readability::NamespaceCommentCheck;
+
+TEST(NamespaceCommentCheckTest, Basic) {
+  EXPECT_EQ("namespace i {\n} // namespace i",
+            runCheckOnCode<NamespaceCommentCheck>("namespace i {\n}"));
+  EXPECT_EQ("namespace {\n} // namespace",
+            runCheckOnCode<NamespaceCommentCheck>("namespace {\n}"));
+  EXPECT_EQ("namespace i { namespace j {\n} // namespace j\n } // namespace i",
+            runCheckOnCode<NamespaceCommentCheck>(
+                "namespace i { namespace j {\n} }"));
+}
+
+TEST(NamespaceCommentCheckTest, SingleLineNamespaces) {
+  EXPECT_EQ(
+      "namespace i { namespace j { } }",
+      runCheckOnCode<NamespaceCommentCheck>("namespace i { namespace j { } }"));
+}
+
+TEST(NamespaceCommentCheckTest, CheckExistingComments) {
+  EXPECT_EQ("namespace i { namespace j {\n"
+            "} /* namespace j */ } // namespace i\n"
+            " /* random comment */",
+            runCheckOnCode<NamespaceCommentCheck>(
+                "namespace i { namespace j {\n"
+                "} /* namespace j */ } /* random comment */"));
+  EXPECT_EQ("namespace {\n"
+            "} // namespace",
+            runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
+                                                  "} // namespace"));
+  EXPECT_EQ("namespace {\n"
+            "} //namespace",
+            runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
+                                                  "} //namespace"));
+  EXPECT_EQ("namespace {\n"
+            "} // anonymous namespace",
+            runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
+                                                  "} // anonymous namespace"));
+  EXPECT_EQ("namespace {\n"
+            "} // Anonymous namespace.",
+            runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
+                                                  "} // Anonymous namespace."));
+  EXPECT_EQ(
+      "namespace q {\n"
+      "} // namespace q",
+      runCheckOnCode<NamespaceCommentCheck>("namespace q {\n"
+                                            "} // anonymous namespace q"));
+  EXPECT_EQ(
+      "namespace My_NameSpace123 {\n"
+      "} // namespace My_NameSpace123",
+      runCheckOnCode<NamespaceCommentCheck>("namespace My_NameSpace123 {\n"
+                                            "} // namespace My_NameSpace123"));
+  EXPECT_EQ(
+      "namespace My_NameSpace123 {\n"
+      "} //namespace My_NameSpace123",
+      runCheckOnCode<NamespaceCommentCheck>("namespace My_NameSpace123 {\n"
+                                            "} //namespace My_NameSpace123"));
+  EXPECT_EQ("namespace My_NameSpace123 {\n"
+            "} //  end namespace   My_NameSpace123",
+            runCheckOnCode<NamespaceCommentCheck>(
+                "namespace My_NameSpace123 {\n"
+                "} //  end namespace   My_NameSpace123"));
+  // Understand comments only on the same line.
+  EXPECT_EQ("namespace {\n"
+            "} // namespace\n"
+            "// namespace",
+            runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
+                                                  "}\n"
+                                                  "// namespace"));
+}
+
+TEST(NamespaceCommentCheckTest, FixWrongComments) {
+  EXPECT_EQ("namespace i { namespace jJ0_ {\n"
+            "} // namespace jJ0_\n"
+            " } // namespace i\n"
+            " /* random comment */",
+            runCheckOnCode<NamespaceCommentCheck>(
+                "namespace i { namespace jJ0_ {\n"
+                "} /* namespace qqq */ } /* random comment */"));
+  EXPECT_EQ("namespace {\n"
+            "} // namespace",
+            runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
+                                                  "} // namespace asdf"));
+  // Remove unknown line comments. These are likely to be an unrecognized form
+  // of a namespace ending comment.
+  EXPECT_EQ("namespace {\n"
+            "} // namespace",
+            runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
+                                                  "} // random text"));
+}
+
+TEST(BracesAroundStatementsCheckTest, IfWithComments) {
+  EXPECT_EQ("int main() {\n"
+            "  if (false /*dummy token*/) {\n"
+            "    // comment\n"
+            "    return -1; /**/\n"
+            "}\n"
+            "  if (false) {\n"
+            "    return -1; // comment\n"
+            "}\n"
+            "  if (false) {\n"
+            "    return -1; \n"
+            "}/* multi-line \n comment */\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>(
+                "int main() {\n"
+                "  if (false /*dummy token*/)\n"
+                "    // comment\n"
+                "    return -1; /**/\n"
+                "  if (false)\n"
+                "    return -1; // comment\n"
+                "  if (false)\n"
+                "    return -1; /* multi-line \n comment */\n"
+                "}"));
+  EXPECT_EQ("int main() {\n"
+            "  if (false /*dummy token*/) {\n"
+            "    // comment\n"
+            "    return -1 /**/ ;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>(
+                "int main() {\n"
+                "  if (false /*dummy token*/)\n"
+                "    // comment\n"
+                "    return -1 /**/ ;\n"
+                "}"));
+}
+
+TEST(BracesAroundStatementsCheckTest, If) {
+  EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+                                                 "  if (false) {\n"
+                                                 "    return -1;\n"
+                                                 "  }\n"
+                                                 "}");
+  EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+                                                 "  if (auto Cond = false) {\n"
+                                                 "    return -1;\n"
+                                                 "  }\n"
+                                                 "}");
+  EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+                                                 "  if (false) {\n"
+                                                 "    return -1;\n"
+                                                 "  } else {\n"
+                                                 "    return -2;\n"
+                                                 "  }\n"
+                                                 "}");
+  EXPECT_EQ("int main() {\n"
+            "  if (false) {\n"
+            "    return -1;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+                                                        "  if (false)\n"
+                                                        "    return -1;\n"
+                                                        "}"));
+  EXPECT_EQ("int main() {\n"
+            "  if (auto Cond = false /**/ ) {\n"
+            "    return -1;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>(
+                "int main() {\n"
+                "  if (auto Cond = false /**/ )\n"
+                "    return -1;\n"
+                "}"));
+  // FIXME: Consider adding braces before EMPTY_MACRO and after the statement.
+  EXPECT_NO_CHANGES(BracesAroundStatementsCheck,
+                    "#define EMPTY_MACRO\n"
+                    "int main() {\n"
+                    "  if (auto Cond = false EMPTY_MACRO /**/ ) EMPTY_MACRO\n"
+                    "    return -1;\n"
+                    "}");
+  EXPECT_EQ("int main() {\n"
+            "  if (true) { return -1/**/ ;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>(
+                "int main() {\n"
+                "  if (true) return -1/**/ ;\n"
+                "}"));
+  EXPECT_EQ("int main() {\n"
+            "  if (false) {\n"
+            "    return -1;\n"
+            "  } else {\n"
+            "    return -2;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+                                                        "  if (false)\n"
+                                                        "    return -1;\n"
+                                                        "  else\n"
+                                                        "    return -2;\n"
+                                                        "}"));
+  EXPECT_EQ("int main() {\n"
+            "  if (false) {\n"
+            "    return -1;\n"
+            "  } else if (1 == 2) {\n"
+            "    return -2;\n"
+            "  } else {\n"
+            "    return -3;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+                                                        "  if (false)\n"
+                                                        "    return -1;\n"
+                                                        "  else if (1 == 2)\n"
+                                                        "    return -2;\n"
+                                                        "  else\n"
+                                                        "    return -3;\n"
+                                                        "}"));
+  EXPECT_EQ("int main() {\n"
+            "  if (false) {\n"
+            "    return -1;\n"
+            "  } else if (1 == 2) {\n"
+            "    return -2;\n"
+            "  } else {\n"
+            "    return -3;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+                                                        "  if (false)\n"
+                                                        "    return -1;\n"
+                                                        "  else if (1 == 2) {\n"
+                                                        "    return -2;\n"
+                                                        "  } else\n"
+                                                        "    return -3;\n"
+                                                        "}"));
+}
+
+TEST(BracesAroundStatementsCheckTest, IfElseWithShortStatements) {
+  ClangTidyOptions Options;
+  Options.CheckOptions["test-check-0.ShortStatementLines"] = "1";
+
+  EXPECT_EQ("int main() {\n"
+            "  if (true) return 1;\n"
+            "  if (false) { return -1;\n"
+            "  } else if (1 == 2) { return -2;\n"
+            "  } else { return -3;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>(
+                "int main() {\n"
+                "  if (true) return 1;\n"
+                "  if (false) return -1;\n"
+                "  else if (1 == 2) return -2;\n"
+                "  else return -3;\n"
+                "}",
+                nullptr, "input.cc", None, Options));
+
+  // If the last else is an else-if, we also force it.
+  EXPECT_EQ("int main() {\n"
+            "  if (false) { return -1;\n"
+            "  } else if (1 == 2) { return -2;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>(
+                "int main() {\n"
+                "  if (false) return -1;\n"
+                "  else if (1 == 2) return -2;\n"
+                "}",
+                nullptr, "input.cc", None, Options));
+}
+
+TEST(BracesAroundStatementsCheckTest, For) {
+  EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+                                                 "  for (;;) {\n"
+                                                 "    ;\n"
+                                                 "  }\n"
+                                                 "}");
+  EXPECT_EQ("int main() {\n"
+            "  for (;;) {\n"
+            "    ;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+                                                        "  for (;;)\n"
+                                                        "    ;\n"
+                                                        "}"));
+  EXPECT_EQ("int main() {\n"
+            "  for (;;) {\n"
+            "    /**/ ;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+                                                        "  for (;;)\n"
+                                                        "    /**/ ;\n"
+                                                        "}"));
+  EXPECT_EQ("int main() {\n"
+            "  for (;;) {\n"
+            "    return -1 /**/ ;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+                                                        "  for (;;)\n"
+                                                        "    return -1 /**/ ;\n"
+                                                        "}"));
+}
+
+TEST(BracesAroundStatementsCheckTest, ForRange) {
+  EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+                                                 "  int arr[4];\n"
+                                                 "  for (int i : arr) {\n"
+                                                 "    ;\n"
+                                                 "  }\n"
+                                                 "}");
+  EXPECT_EQ("int main() {\n"
+            "  int arr[4];\n"
+            "  for (int i : arr) {\n"
+            "    ;\n"
+            "}\n"
+            "  for (int i : arr) {\n"
+            "    return -1 ;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+                                                        "  int arr[4];\n"
+                                                        "  for (int i : arr)\n"
+                                                        "    ;\n"
+                                                        "  for (int i : arr)\n"
+                                                        "    return -1 ;\n"
+                                                        "}"));
+}
+
+TEST(BracesAroundStatementsCheckTest, DoWhile) {
+  EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+                                                 "  do {\n"
+                                                 "    ;\n"
+                                                 "  } while (false);\n"
+                                                 "}");
+  EXPECT_EQ("int main() {\n"
+            "  do {\n"
+            "    ;\n"
+            "  } while (false);\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+                                                        "  do\n"
+                                                        "    ;\n"
+                                                        "  while (false);\n"
+                                                        "}"));
+}
+
+TEST(BracesAroundStatementsCheckTest, While) {
+  EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n"
+                                                 "  while (false) {\n"
+                                                 "    ;\n"
+                                                 "  }\n"
+                                                 "}");
+  EXPECT_EQ("int main() {\n"
+            "  while (false) {\n"
+            "    ;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+                                                        "  while (false)\n"
+                                                        "    ;\n"
+                                                        "}"));
+  EXPECT_EQ("int main() {\n"
+            "  while (auto Cond = false) {\n"
+            "    ;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>(
+                "int main() {\n"
+                "  while (auto Cond = false)\n"
+                "    ;\n"
+                "}"));
+  EXPECT_EQ("int main() {\n"
+            "  while (false /*dummy token*/) {\n"
+            "    ;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>(
+                "int main() {\n"
+                "  while (false /*dummy token*/)\n"
+                "    ;\n"
+                "}"));
+  EXPECT_EQ("int main() {\n"
+            "  while (false) {\n"
+            "    break;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+                                                        "  while (false)\n"
+                                                        "    break;\n"
+                                                        "}"));
+  EXPECT_EQ("int main() {\n"
+            "  while (false) {\n"
+            "    break /**/;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+                                                        "  while (false)\n"
+                                                        "    break /**/;\n"
+                                                        "}"));
+  EXPECT_EQ("int main() {\n"
+            "  while (false) {\n"
+            "    /**/;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+                                                        "  while (false)\n"
+                                                        "    /**/;\n"
+                                                        "}"));
+}
+
+TEST(BracesAroundStatementsCheckTest, Nested) {
+  EXPECT_EQ("int main() {\n"
+            "  do { if (true) {}} while (false);\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>(
+                "int main() {\n"
+                "  do if (true) {}while (false);\n"
+                "}"));
+  EXPECT_EQ("int main() {\n"
+            "  do { if (true) {}} while (false);\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>(
+                "int main() {\n"
+                "  do if (true) {}while (false);\n"
+                "}"));
+  EXPECT_EQ(
+      "int main() {\n"
+      "  if (true) {\n"
+      "    // comment\n"
+      "    if (false) {\n"
+      "      // comment\n"
+      "      /**/ ; // comment\n"
+      "    }\n"
+      "}\n"
+      "}",
+      runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n"
+                                                  "  if (true)\n"
+                                                  "    // comment\n"
+                                                  "    if (false) {\n"
+                                                  "      // comment\n"
+                                                  "      /**/ ; // comment\n"
+                                                  "    }\n"
+                                                  "}"));
+}
+
+TEST(BracesAroundStatementsCheckTest, Macros) {
+  EXPECT_NO_CHANGES(BracesAroundStatementsCheck,
+                    "#define IF(COND) if (COND) return -1;\n"
+                    "int main() {\n"
+                    "  IF(false)\n"
+                    "}");
+  EXPECT_NO_CHANGES(BracesAroundStatementsCheck,
+                    "#define FOR(COND) for (COND) return -1;\n"
+                    "int main() {\n"
+                    "  FOR(;;)\n"
+                    "}");
+  EXPECT_EQ("#define DO_IT ++i\n"
+            "int i = 0;\n"
+            "int main() {\n"
+            "  if (false) {\n"
+            "    DO_IT;\n"
+            "  } else if (1 == 2) {\n"
+            "    DO_IT;\n"
+            "  } else {\n"
+            "    DO_IT;\n"
+            "}\n"
+            "}",
+            runCheckOnCode<BracesAroundStatementsCheck>("#define DO_IT ++i\n"
+                                                        "int i = 0;\n"
+                                                        "int main() {\n"
+                                                        "  if (false)\n"
+                                                        "    DO_IT;\n"
+                                                        "  else if (1 == 2)\n"
+                                                        "    DO_IT;\n"
+                                                        "  else\n"
+                                                        "    DO_IT;\n"
+                                                        "}"));
+}
+
+#define EXPECT_NO_CHANGES_WITH_OPTS(Check, Opts, Code)                         \
+  EXPECT_EQ(Code, runCheckOnCode<Check>(Code, nullptr, "input.cc", None, Opts))
+TEST(BracesAroundStatementsCheckTest, ImplicitCastInReturn) {
+  ClangTidyOptions Opts;
+  Opts.CheckOptions["test-check-0.ShortStatementLines"] = "1";
+
+  StringRef Input = "const char *f() {\n"
+                              "  if (true) return \"\";\n"
+                              "  return \"abc\";\n"
+                              "}\n";
+  EXPECT_NO_CHANGES_WITH_OPTS(BracesAroundStatementsCheck, Opts, Input);
+  EXPECT_EQ("const char *f() {\n"
+            "  if (true) { return \"\";\n"
+            "}\n"
+            "  return \"abc\";\n"
+            "}\n",
+            runCheckOnCode<BracesAroundStatementsCheck>(Input));
+}
+
+} // namespace test
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/UsingInserterTest.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/UsingInserterTest.cpp
new file mode 100644
index 0000000..9e465a0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clang-tidy/UsingInserterTest.cpp
@@ -0,0 +1,114 @@
+//===---- UsingInserterTest.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 "../clang-tidy/utils/UsingInserter.h"
+
+#include "ClangTidyTest.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+// Replace all function calls with calls to foo::func. Inserts using
+// declarations as necessary. This checker is for testing only. It
+// can only run on one test case (e.g. wih one SourceManager).
+class InsertUsingCheck : public clang::tidy::ClangTidyCheck {
+public:
+  InsertUsingCheck(StringRef Name, ClangTidyContext *Context)
+      :ClangTidyCheck(Name, Context) {}
+  void registerMatchers(clang::ast_matchers::MatchFinder *Finder) override {
+    Finder->addMatcher(clang::ast_matchers::callExpr().bind("foo"), this);
+  }
+  void
+  check(const clang::ast_matchers::MatchFinder::MatchResult &Result) override {
+    if (!Inserter)
+      Inserter.reset(new UsingInserter(*Result.SourceManager));
+
+    const auto *Call = Result.Nodes.getNodeAs<clang::CallExpr>("foo");
+    assert(Call != nullptr && "Did not find node \"foo\"");
+    auto Hint =
+        Inserter->createUsingDeclaration(*Result.Context, *Call, "::foo::func");
+
+    if (Hint.hasValue())
+      diag(Call->getLocStart(), "Fix for testing") << Hint.getValue();
+
+    diag(Call->getLocStart(), "insert call")
+        << clang::FixItHint::CreateReplacement(
+               Call->getCallee()->getSourceRange(),
+               Inserter->getShortName(*Result.Context, *Call, "::foo::func"));
+  }
+
+private:
+  std::unique_ptr<UsingInserter> Inserter;
+};
+
+template <typename Check>
+std::string runChecker(StringRef Code, unsigned ExpectedWarningCount) {
+  std::map<StringRef, StringRef> AdditionalFileContents = {{"foo.h",
+                                                            "namespace foo {\n"
+                                                            "namespace bar {\n"
+                                                            "}\n"
+                                                            "void func() { }\n"
+                                                            "}"}};
+  std::vector<ClangTidyError> errors;
+
+  std::string result =
+      test::runCheckOnCode<Check>(Code, &errors, "foo.cc", None,
+                                  ClangTidyOptions(), AdditionalFileContents);
+
+  EXPECT_EQ(ExpectedWarningCount, errors.size());
+  return result;
+}
+
+TEST(UsingInserterTest, ReusesExisting) {
+  EXPECT_EQ("#include \"foo.h\"\n"
+            "namespace {"
+            "using ::foo::func;\n"
+            "void f() { func(); }"
+            "}",
+            runChecker<InsertUsingCheck>("#include \"foo.h\"\n"
+                                         "namespace {"
+                                         "using ::foo::func;\n"
+                                         "void f() { f(); }"
+                                         "}",
+                                         1));
+}
+
+TEST(UsingInserterTest, ReusesExistingGlobal) {
+  EXPECT_EQ("#include \"foo.h\"\n"
+            "using ::foo::func;\n"
+            "namespace {"
+            "void f() { func(); }"
+            "}",
+            runChecker<InsertUsingCheck>("#include \"foo.h\"\n"
+                                         "using ::foo::func;\n"
+                                         "namespace {"
+                                         "void f() { f(); }"
+                                         "}",
+                                         1));
+}
+
+TEST(UsingInserterTest, AvoidsConflict) {
+  EXPECT_EQ("#include \"foo.h\"\n"
+            "namespace {"
+            "void f() { int func; ::foo::func(); }"
+            "}",
+            runChecker<InsertUsingCheck>("#include \"foo.h\"\n"
+                                         "namespace {"
+                                         "void f() { int func; f(); }"
+                                         "}",
+                                         1));
+}
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/Annotations.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/Annotations.cpp
new file mode 100644
index 0000000..6bd81c8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/Annotations.cpp
@@ -0,0 +1,87 @@
+//===--- Annotations.cpp - Annotated source code for unit tests -*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+#include "Annotations.h"
+#include "SourceCode.h"
+
+namespace clang {
+namespace clangd {
+using namespace llvm;
+
+// Crash if the assertion fails, printing the message and testcase.
+// More elegant error handling isn't needed for unit tests.
+static void require(bool Assertion, const char *Msg, llvm::StringRef Code) {
+  if (!Assertion) {
+    llvm::errs() << "Annotated testcase: " << Msg << "\n" << Code << "\n";
+    llvm_unreachable("Annotated testcase assertion failed!");
+  }
+}
+
+Annotations::Annotations(StringRef Text) {
+  auto Here = [this] { return offsetToPosition(Code, Code.size()); };
+  auto Require = [Text](bool Assertion, const char *Msg) {
+    require(Assertion, Msg, Text);
+  };
+  Optional<StringRef> Name;
+  SmallVector<std::pair<StringRef, Position>, 8> OpenRanges;
+
+  Code.reserve(Text.size());
+  while (!Text.empty()) {
+    if (Text.consume_front("^")) {
+      Points[Name.getValueOr("")].push_back(Here());
+      Name = None;
+      continue;
+    }
+    if (Text.consume_front("[[")) {
+      OpenRanges.emplace_back(Name.getValueOr(""), Here());
+      Name = None;
+      continue;
+    }
+    Require(!Name, "$name should be followed by ^ or [[");
+    if (Text.consume_front("]]")) {
+      Require(!OpenRanges.empty(), "unmatched ]]");
+      Ranges[OpenRanges.back().first].push_back(
+          {OpenRanges.back().second, Here()});
+      OpenRanges.pop_back();
+      continue;
+    }
+    if (Text.consume_front("$")) {
+      Name = Text.take_while(llvm::isAlnum);
+      Text = Text.drop_front(Name->size());
+      continue;
+    }
+    Code.push_back(Text.front());
+    Text = Text.drop_front();
+  }
+  Require(!Name, "unterminated $name");
+  Require(OpenRanges.empty(), "unmatched [[");
+}
+
+Position Annotations::point(llvm::StringRef Name) const {
+  auto I = Points.find(Name);
+  require(I != Points.end() && I->getValue().size() == 1,
+          "expected exactly one point", Code);
+  return I->getValue()[0];
+}
+std::vector<Position> Annotations::points(llvm::StringRef Name) const {
+  auto P = Points.lookup(Name);
+  return {P.begin(), P.end()};
+}
+Range Annotations::range(llvm::StringRef Name) const {
+  auto I = Ranges.find(Name);
+  require(I != Ranges.end() && I->getValue().size() == 1,
+          "expected exactly one range", Code);
+  return I->getValue()[0];
+}
+std::vector<Range> Annotations::ranges(llvm::StringRef Name) const {
+  auto R = Ranges.lookup(Name);
+  return {R.begin(), R.end()};
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/Annotations.h b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/Annotations.h
new file mode 100644
index 0000000..549a21e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/Annotations.h
@@ -0,0 +1,69 @@
+//===--- Annotations.h - Annotated source code for tests --------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// Annotations lets you mark points and ranges inside source code, for tests:
+//
+//    Annotations Example(R"cpp(
+//       int complete() { x.pri^ }          // ^ indicates a point
+//       void err() { [["hello" == 42]]; }  // [[this is a range]]
+//       $definition^class Foo{};           // points can be named: "definition"
+//       $fail[[static_assert(false, "")]]  // ranges can be named too: "fail"
+//    )cpp");
+//
+//    StringRef Code = Example.code();              // annotations stripped.
+//    std::vector<Position> PP = Example.points();  // all unnamed points
+//    Position P = Example.point();                 // there must be exactly one
+//    Range R = Example.range("fail");              // find named ranges
+//
+// Points/ranges are coordinates into `code()` which is stripped of annotations.
+//
+// Ranges may be nested (and points can be inside ranges), but there's no way
+// to define general overlapping ranges.
+//
+//===---------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_ANNOTATIONS_H
+#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_ANNOTATIONS_H
+#include "Protocol.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace clangd {
+
+class Annotations {
+public:
+  // Parses the annotations from Text. Crashes if it's malformed.
+  Annotations(llvm::StringRef Text);
+
+  // The input text with all annotations stripped.
+  // All points and ranges are relative to this stripped text.
+  llvm::StringRef code() const { return Code; }
+
+  // Returns the position of the point marked by ^ (or $name^) in the text.
+  // Crashes if there isn't exactly one.
+  Position point(llvm::StringRef Name = "") const;
+  // Returns the position of all points marked by ^ (or $name^) in the text.
+  std::vector<Position> points(llvm::StringRef Name = "") const;
+
+  // Returns the location of the range marked by [[ ]] (or $name[[ ]]).
+  // Crashes if there isn't exactly one.
+  Range range(llvm::StringRef Name = "") const;
+  // Returns the location of all ranges marked by [[ ]] (or $name[[ ]]).
+  std::vector<Range> ranges(llvm::StringRef Name = "") const;
+
+private:
+  std::string Code;
+  llvm::StringMap<llvm::SmallVector<Position, 1>> Points;
+  llvm::StringMap<llvm::SmallVector<Range, 1>> Ranges;
+};
+
+} // namespace clangd
+} // namespace clang
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/CMakeLists.txt
new file mode 100644
index 0000000..516060e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/CMakeLists.txt
@@ -0,0 +1,55 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  )
+
+get_filename_component(CLANGD_SOURCE_DIR
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../clangd REALPATH)
+include_directories(
+  ${CLANGD_SOURCE_DIR}
+  )
+
+add_extra_unittest(ClangdTests
+  Annotations.cpp
+  ClangdTests.cpp
+  ClangdUnitTests.cpp
+  CodeCompleteTests.cpp
+  CodeCompletionStringsTests.cpp
+  ContextTests.cpp
+  DexIndexTests.cpp
+  DraftStoreTests.cpp
+  FileDistanceTests.cpp
+  FileIndexTests.cpp
+  FindSymbolsTests.cpp
+  FuzzyMatchTests.cpp
+  GlobalCompilationDatabaseTests.cpp
+  HeadersTests.cpp
+  IndexTests.cpp
+  QualityTests.cpp
+  SourceCodeTests.cpp
+  SymbolCollectorTests.cpp
+  SyncAPI.cpp
+  TUSchedulerTests.cpp
+  TestFS.cpp
+  TestTU.cpp
+  ThreadingTests.cpp
+  TraceTests.cpp
+  URITests.cpp
+  XRefsTests.cpp
+  )
+
+target_link_libraries(ClangdTests
+  PRIVATE
+  clangAST
+  clangBasic
+  clangDaemon
+  clangFormat
+  clangFrontend
+  clangIndex
+  clangLex
+  clangSema
+  clangTooling
+  clangToolingCore
+  clangToolingInclusions
+  LLVMSupport
+  LLVMTestingSupport
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/ClangdTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/ClangdTests.cpp
new file mode 100644
index 0000000..ace2cef
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/ClangdTests.cpp
@@ -0,0 +1,968 @@
+//===-- ClangdTests.cpp - Clangd unit tests ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Annotations.h"
+#include "ClangdLSPServer.h"
+#include "ClangdServer.h"
+#include "Matchers.h"
+#include "SyncAPI.h"
+#include "TestFS.h"
+#include "URI.h"
+#include "clang/Config/config.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Regex.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <algorithm>
+#include <chrono>
+#include <iostream>
+#include <random>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace clang {
+namespace clangd {
+
+using ::testing::ElementsAre;
+using ::testing::Eq;
+using ::testing::Field;
+using ::testing::Gt;
+using ::testing::IsEmpty;
+using ::testing::Pair;
+using ::testing::UnorderedElementsAre;
+
+namespace {
+
+bool diagsContainErrors(const std::vector<Diag> &Diagnostics) {
+  for (auto D : Diagnostics) {
+    if (D.Severity == DiagnosticsEngine::Error ||
+        D.Severity == DiagnosticsEngine::Fatal)
+      return true;
+  }
+  return false;
+}
+
+class ErrorCheckingDiagConsumer : public DiagnosticsConsumer {
+public:
+  void onDiagnosticsReady(PathRef File,
+                          std::vector<Diag> Diagnostics) override {
+    bool HadError = diagsContainErrors(Diagnostics);
+    std::lock_guard<std::mutex> Lock(Mutex);
+    HadErrorInLastDiags = HadError;
+  }
+
+  bool hadErrorInLastDiags() {
+    std::lock_guard<std::mutex> Lock(Mutex);
+    return HadErrorInLastDiags;
+  }
+
+private:
+  std::mutex Mutex;
+  bool HadErrorInLastDiags = false;
+};
+
+/// For each file, record whether the last published diagnostics contained at
+/// least one error.
+class MultipleErrorCheckingDiagConsumer : public DiagnosticsConsumer {
+public:
+  void onDiagnosticsReady(PathRef File,
+                          std::vector<Diag> Diagnostics) override {
+    bool HadError = diagsContainErrors(Diagnostics);
+
+    std::lock_guard<std::mutex> Lock(Mutex);
+    LastDiagsHadError[File] = HadError;
+  }
+
+  /// Exposes all files consumed by onDiagnosticsReady in an unspecified order.
+  /// For each file, a bool value indicates whether the last diagnostics
+  /// contained an error.
+  std::vector<std::pair<Path, bool>> filesWithDiags() const {
+    std::vector<std::pair<Path, bool>> Result;
+    std::lock_guard<std::mutex> Lock(Mutex);
+
+    for (const auto &it : LastDiagsHadError) {
+      Result.emplace_back(it.first(), it.second);
+    }
+
+    return Result;
+  }
+
+  void clear() {
+    std::lock_guard<std::mutex> Lock(Mutex);
+    LastDiagsHadError.clear();
+  }
+
+private:
+  mutable std::mutex Mutex;
+  llvm::StringMap<bool> LastDiagsHadError;
+};
+
+/// Replaces all patterns of the form 0x123abc with spaces
+std::string replacePtrsInDump(std::string const &Dump) {
+  llvm::Regex RE("0x[0-9a-fA-F]+");
+  llvm::SmallVector<StringRef, 1> Matches;
+  llvm::StringRef Pending = Dump;
+
+  std::string Result;
+  while (RE.match(Pending, &Matches)) {
+    assert(Matches.size() == 1 && "Exactly one match expected");
+    auto MatchPos = Matches[0].data() - Pending.data();
+
+    Result += Pending.take_front(MatchPos);
+    Pending = Pending.drop_front(MatchPos + Matches[0].size());
+  }
+  Result += Pending;
+
+  return Result;
+}
+
+std::string dumpASTWithoutMemoryLocs(ClangdServer &Server, PathRef File) {
+  auto DumpWithMemLocs = runDumpAST(Server, File);
+  return replacePtrsInDump(DumpWithMemLocs);
+}
+
+class ClangdVFSTest : public ::testing::Test {
+protected:
+  std::string parseSourceAndDumpAST(
+      PathRef SourceFileRelPath, StringRef SourceContents,
+      std::vector<std::pair<PathRef, StringRef>> ExtraFiles = {},
+      bool ExpectErrors = false) {
+    MockFSProvider FS;
+    ErrorCheckingDiagConsumer DiagConsumer;
+    MockCompilationDatabase CDB;
+    ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+    for (const auto &FileWithContents : ExtraFiles)
+      FS.Files[testPath(FileWithContents.first)] = FileWithContents.second;
+
+    auto SourceFilename = testPath(SourceFileRelPath);
+    Server.addDocument(SourceFilename, SourceContents);
+    auto Result = dumpASTWithoutMemoryLocs(Server, SourceFilename);
+    EXPECT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for diagnostics";
+    EXPECT_EQ(ExpectErrors, DiagConsumer.hadErrorInLastDiags());
+    return Result;
+  }
+};
+
+TEST_F(ClangdVFSTest, Parse) {
+  // FIXME: figure out a stable format for AST dumps, so that we can check the
+  // output of the dump itself is equal to the expected one, not just that it's
+  // different.
+  auto Empty = parseSourceAndDumpAST("foo.cpp", "", {});
+  auto OneDecl = parseSourceAndDumpAST("foo.cpp", "int a;", {});
+  auto SomeDecls = parseSourceAndDumpAST("foo.cpp", "int a; int b; int c;", {});
+  EXPECT_NE(Empty, OneDecl);
+  EXPECT_NE(Empty, SomeDecls);
+  EXPECT_NE(SomeDecls, OneDecl);
+
+  auto Empty2 = parseSourceAndDumpAST("foo.cpp", "");
+  auto OneDecl2 = parseSourceAndDumpAST("foo.cpp", "int a;");
+  auto SomeDecls2 = parseSourceAndDumpAST("foo.cpp", "int a; int b; int c;");
+  EXPECT_EQ(Empty, Empty2);
+  EXPECT_EQ(OneDecl, OneDecl2);
+  EXPECT_EQ(SomeDecls, SomeDecls2);
+}
+
+TEST_F(ClangdVFSTest, ParseWithHeader) {
+  parseSourceAndDumpAST("foo.cpp", "#include \"foo.h\"", {},
+                        /*ExpectErrors=*/true);
+  parseSourceAndDumpAST("foo.cpp", "#include \"foo.h\"", {{"foo.h", ""}},
+                        /*ExpectErrors=*/false);
+
+  const auto SourceContents = R"cpp(
+#include "foo.h"
+int b = a;
+)cpp";
+  parseSourceAndDumpAST("foo.cpp", SourceContents, {{"foo.h", ""}},
+                        /*ExpectErrors=*/true);
+  parseSourceAndDumpAST("foo.cpp", SourceContents, {{"foo.h", "int a;"}},
+                        /*ExpectErrors=*/false);
+}
+
+TEST_F(ClangdVFSTest, Reparse) {
+  MockFSProvider FS;
+  ErrorCheckingDiagConsumer DiagConsumer;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  const auto SourceContents = R"cpp(
+#include "foo.h"
+int b = a;
+)cpp";
+
+  auto FooCpp = testPath("foo.cpp");
+
+  FS.Files[testPath("foo.h")] = "int a;";
+  FS.Files[FooCpp] = SourceContents;
+
+  Server.addDocument(FooCpp, SourceContents);
+  auto DumpParse1 = dumpASTWithoutMemoryLocs(Server, FooCpp);
+  ASSERT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for diagnostics";
+  EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+
+  Server.addDocument(FooCpp, "");
+  auto DumpParseEmpty = dumpASTWithoutMemoryLocs(Server, FooCpp);
+  ASSERT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for diagnostics";
+  EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+
+  Server.addDocument(FooCpp, SourceContents);
+  auto DumpParse2 = dumpASTWithoutMemoryLocs(Server, FooCpp);
+  ASSERT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for diagnostics";
+  EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+
+  EXPECT_EQ(DumpParse1, DumpParse2);
+  EXPECT_NE(DumpParse1, DumpParseEmpty);
+}
+
+TEST_F(ClangdVFSTest, ReparseOnHeaderChange) {
+  MockFSProvider FS;
+  ErrorCheckingDiagConsumer DiagConsumer;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  const auto SourceContents = R"cpp(
+#include "foo.h"
+int b = a;
+)cpp";
+
+  auto FooCpp = testPath("foo.cpp");
+  auto FooH = testPath("foo.h");
+
+  FS.Files[FooH] = "int a;";
+  FS.Files[FooCpp] = SourceContents;
+
+  Server.addDocument(FooCpp, SourceContents);
+  auto DumpParse1 = dumpASTWithoutMemoryLocs(Server, FooCpp);
+  ASSERT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for diagnostics";
+  EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+
+  FS.Files[FooH] = "";
+  Server.addDocument(FooCpp, SourceContents);
+  auto DumpParseDifferent = dumpASTWithoutMemoryLocs(Server, FooCpp);
+  ASSERT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for diagnostics";
+  EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
+
+  FS.Files[FooH] = "int a;";
+  Server.addDocument(FooCpp, SourceContents);
+  auto DumpParse2 = dumpASTWithoutMemoryLocs(Server, FooCpp);
+  ASSERT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for diagnostics";
+  EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+
+  EXPECT_EQ(DumpParse1, DumpParse2);
+  EXPECT_NE(DumpParse1, DumpParseDifferent);
+}
+
+TEST_F(ClangdVFSTest, PropagatesContexts) {
+  static Key<int> Secret;
+  struct FSProvider : public FileSystemProvider {
+    IntrusiveRefCntPtr<vfs::FileSystem> getFileSystem() override {
+      Got = Context::current().getExisting(Secret);
+      return buildTestFS({});
+    }
+    int Got;
+  } FS;
+  struct DiagConsumer : public DiagnosticsConsumer {
+    void onDiagnosticsReady(PathRef File,
+                            std::vector<Diag> Diagnostics) override {
+      Got = Context::current().getExisting(Secret);
+    }
+    int Got;
+  } DiagConsumer;
+  MockCompilationDatabase CDB;
+
+  // Verify that the context is plumbed to the FS provider and diagnostics.
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+  {
+    WithContextValue Entrypoint(Secret, 42);
+    Server.addDocument(testPath("foo.cpp"), "void main(){}");
+  }
+  ASSERT_TRUE(Server.blockUntilIdleForTest());
+  EXPECT_EQ(FS.Got, 42);
+  EXPECT_EQ(DiagConsumer.Got, 42);
+}
+
+// Only enable this test on Unix
+#ifdef LLVM_ON_UNIX
+TEST_F(ClangdVFSTest, SearchLibDir) {
+  // Checks that searches for GCC installation is done through vfs.
+  MockFSProvider FS;
+  ErrorCheckingDiagConsumer DiagConsumer;
+  MockCompilationDatabase CDB;
+  CDB.ExtraClangFlags.insert(CDB.ExtraClangFlags.end(),
+                             {"-xc++", "-target", "x86_64-linux-unknown",
+                              "-m64", "--gcc-toolchain=/randomusr",
+                              "-stdlib=libstdc++"});
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  // Just a random gcc version string
+  SmallString<8> Version("4.9.3");
+
+  // A lib dir for gcc installation
+  SmallString<64> LibDir("/randomusr/lib/gcc/x86_64-linux-gnu");
+  llvm::sys::path::append(LibDir, Version);
+
+  // Put crtbegin.o into LibDir/64 to trick clang into thinking there's a gcc
+  // installation there.
+  SmallString<64> DummyLibFile;
+  llvm::sys::path::append(DummyLibFile, LibDir, "64", "crtbegin.o");
+  FS.Files[DummyLibFile] = "";
+
+  SmallString<64> IncludeDir("/randomusr/include/c++");
+  llvm::sys::path::append(IncludeDir, Version);
+
+  SmallString<64> StringPath;
+  llvm::sys::path::append(StringPath, IncludeDir, "string");
+  FS.Files[StringPath] = "class mock_string {};";
+
+  auto FooCpp = testPath("foo.cpp");
+  const auto SourceContents = R"cpp(
+#include <string>
+mock_string x;
+)cpp";
+  FS.Files[FooCpp] = SourceContents;
+
+  runAddDocument(Server, FooCpp, SourceContents);
+  EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+
+  const auto SourceContentsWithError = R"cpp(
+#include <string>
+std::string x;
+)cpp";
+  runAddDocument(Server, FooCpp, SourceContentsWithError);
+  EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
+}
+#endif // LLVM_ON_UNIX
+
+TEST_F(ClangdVFSTest, ForceReparseCompileCommand) {
+  MockFSProvider FS;
+  ErrorCheckingDiagConsumer DiagConsumer;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  auto FooCpp = testPath("foo.cpp");
+  const auto SourceContents1 = R"cpp(
+template <class T>
+struct foo { T x; };
+)cpp";
+  const auto SourceContents2 = R"cpp(
+template <class T>
+struct bar { T x; };
+)cpp";
+
+  FS.Files[FooCpp] = "";
+
+  // First parse files in C mode and check they produce errors.
+  CDB.ExtraClangFlags = {"-xc"};
+  runAddDocument(Server, FooCpp, SourceContents1);
+  EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
+  runAddDocument(Server, FooCpp, SourceContents2);
+  EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
+
+  // Now switch to C++ mode.
+  CDB.ExtraClangFlags = {"-xc++"};
+  runAddDocument(Server, FooCpp, SourceContents2, WantDiagnostics::Auto);
+  EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+  // Subsequent addDocument calls should finish without errors too.
+  runAddDocument(Server, FooCpp, SourceContents1);
+  EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+  runAddDocument(Server, FooCpp, SourceContents2);
+  EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+}
+
+TEST_F(ClangdVFSTest, ForceReparseCompileCommandDefines) {
+  MockFSProvider FS;
+  ErrorCheckingDiagConsumer DiagConsumer;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  auto FooCpp = testPath("foo.cpp");
+  const auto SourceContents = R"cpp(
+#ifdef WITH_ERROR
+this
+#endif
+
+int main() { return 0; }
+)cpp";
+  FS.Files[FooCpp] = "";
+
+  // Parse with define, we expect to see the errors.
+  CDB.ExtraClangFlags = {"-DWITH_ERROR"};
+  runAddDocument(Server, FooCpp, SourceContents);
+  EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
+
+  // Parse without the define, no errors should be produced.
+  CDB.ExtraClangFlags = {};
+  runAddDocument(Server, FooCpp, SourceContents, WantDiagnostics::Auto);
+  ASSERT_TRUE(Server.blockUntilIdleForTest());
+  EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+  // Subsequent addDocument call should finish without errors too.
+  runAddDocument(Server, FooCpp, SourceContents);
+  EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+}
+
+// Test ClangdServer.reparseOpenedFiles.
+TEST_F(ClangdVFSTest, ReparseOpenedFiles) {
+  Annotations FooSource(R"cpp(
+#ifdef MACRO
+static void $one[[bob]]() {}
+#else
+static void $two[[bob]]() {}
+#endif
+
+int main () { bo^b (); return 0; }
+)cpp");
+
+  Annotations BarSource(R"cpp(
+#ifdef MACRO
+this is an error
+#endif
+)cpp");
+
+  Annotations BazSource(R"cpp(
+int hello;
+)cpp");
+
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  MultipleErrorCheckingDiagConsumer DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  auto FooCpp = testPath("foo.cpp");
+  auto BarCpp = testPath("bar.cpp");
+  auto BazCpp = testPath("baz.cpp");
+
+  FS.Files[FooCpp] = "";
+  FS.Files[BarCpp] = "";
+  FS.Files[BazCpp] = "";
+
+  CDB.ExtraClangFlags = {"-DMACRO=1"};
+  Server.addDocument(FooCpp, FooSource.code());
+  Server.addDocument(BarCpp, BarSource.code());
+  Server.addDocument(BazCpp, BazSource.code());
+  ASSERT_TRUE(Server.blockUntilIdleForTest());
+
+  EXPECT_THAT(DiagConsumer.filesWithDiags(),
+              UnorderedElementsAre(Pair(FooCpp, false), Pair(BarCpp, true),
+                                   Pair(BazCpp, false)));
+
+  auto Locations = runFindDefinitions(Server, FooCpp, FooSource.point());
+  EXPECT_TRUE(bool(Locations));
+  EXPECT_THAT(*Locations, ElementsAre(Location{URIForFile{FooCpp},
+                                               FooSource.range("one")}));
+
+  // Undefine MACRO, close baz.cpp.
+  CDB.ExtraClangFlags.clear();
+  DiagConsumer.clear();
+  Server.removeDocument(BazCpp);
+  Server.addDocument(FooCpp, FooSource.code(), WantDiagnostics::Auto);
+  Server.addDocument(BarCpp, BarSource.code(), WantDiagnostics::Auto);
+  ASSERT_TRUE(Server.blockUntilIdleForTest());
+
+  EXPECT_THAT(DiagConsumer.filesWithDiags(),
+              UnorderedElementsAre(Pair(FooCpp, false), Pair(BarCpp, false)));
+
+  Locations = runFindDefinitions(Server, FooCpp, FooSource.point());
+  EXPECT_TRUE(bool(Locations));
+  EXPECT_THAT(*Locations, ElementsAre(Location{URIForFile{FooCpp},
+                                               FooSource.range("two")}));
+}
+
+TEST_F(ClangdVFSTest, MemoryUsage) {
+  MockFSProvider FS;
+  ErrorCheckingDiagConsumer DiagConsumer;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  Path FooCpp = testPath("foo.cpp");
+  const auto SourceContents = R"cpp(
+struct Something {
+  int method();
+};
+)cpp";
+  Path BarCpp = testPath("bar.cpp");
+
+  FS.Files[FooCpp] = "";
+  FS.Files[BarCpp] = "";
+
+  EXPECT_THAT(Server.getUsedBytesPerFile(), IsEmpty());
+
+  Server.addDocument(FooCpp, SourceContents);
+  Server.addDocument(BarCpp, SourceContents);
+  ASSERT_TRUE(Server.blockUntilIdleForTest());
+
+  EXPECT_THAT(Server.getUsedBytesPerFile(),
+              UnorderedElementsAre(Pair(FooCpp, Gt(0u)), Pair(BarCpp, Gt(0u))));
+
+  Server.removeDocument(FooCpp);
+  ASSERT_TRUE(Server.blockUntilIdleForTest());
+  EXPECT_THAT(Server.getUsedBytesPerFile(), ElementsAre(Pair(BarCpp, Gt(0u))));
+
+  Server.removeDocument(BarCpp);
+  ASSERT_TRUE(Server.blockUntilIdleForTest());
+  EXPECT_THAT(Server.getUsedBytesPerFile(), IsEmpty());
+}
+
+TEST_F(ClangdVFSTest, InvalidCompileCommand) {
+  MockFSProvider FS;
+  ErrorCheckingDiagConsumer DiagConsumer;
+  MockCompilationDatabase CDB;
+
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  auto FooCpp = testPath("foo.cpp");
+  // clang cannot create CompilerInvocation if we pass two files in the
+  // CompileCommand. We pass the file in ExtraFlags once and CDB adds another
+  // one in getCompileCommand().
+  CDB.ExtraClangFlags.push_back(FooCpp);
+
+  // Clang can't parse command args in that case, but we shouldn't crash.
+  runAddDocument(Server, FooCpp, "int main() {}");
+
+  EXPECT_EQ(runDumpAST(Server, FooCpp), "<no-ast>");
+  EXPECT_ERROR(runFindDefinitions(Server, FooCpp, Position()));
+  EXPECT_ERROR(runFindDocumentHighlights(Server, FooCpp, Position()));
+  EXPECT_ERROR(runRename(Server, FooCpp, Position(), "new_name"));
+  // FIXME: codeComplete and signatureHelp should also return errors when they
+  // can't parse the file.
+  EXPECT_THAT(cantFail(runCodeComplete(Server, FooCpp, Position(),
+                                       clangd::CodeCompleteOptions()))
+                  .Completions,
+              IsEmpty());
+  auto SigHelp = runSignatureHelp(Server, FooCpp, Position());
+  ASSERT_TRUE(bool(SigHelp)) << "signatureHelp returned an error";
+  EXPECT_THAT(SigHelp->signatures, IsEmpty());
+}
+
+class ClangdThreadingTest : public ClangdVFSTest {};
+
+TEST_F(ClangdThreadingTest, StressTest) {
+  // Without 'static' clang gives an error for a usage inside TestDiagConsumer.
+  static const unsigned FilesCount = 5;
+  const unsigned RequestsCount = 500;
+  // Blocking requests wait for the parsing to complete, they slow down the test
+  // dramatically, so they are issued rarely. Each
+  // BlockingRequestInterval-request will be a blocking one.
+  const unsigned BlockingRequestInterval = 40;
+
+  const auto SourceContentsWithoutErrors = R"cpp(
+int a;
+int b;
+int c;
+int d;
+)cpp";
+
+  const auto SourceContentsWithErrors = R"cpp(
+int a = x;
+int b;
+int c;
+int d;
+)cpp";
+
+  // Giving invalid line and column number should not crash ClangdServer, but
+  // just to make sure we're sometimes hitting the bounds inside the file we
+  // limit the intervals of line and column number that are generated.
+  unsigned MaxLineForFileRequests = 7;
+  unsigned MaxColumnForFileRequests = 10;
+
+  std::vector<std::string> FilePaths;
+  MockFSProvider FS;
+  for (unsigned I = 0; I < FilesCount; ++I) {
+    std::string Name = std::string("Foo") + std::to_string(I) + ".cpp";
+    FS.Files[Name] = "";
+    FilePaths.push_back(testPath(Name));
+  }
+
+  struct FileStat {
+    unsigned HitsWithoutErrors = 0;
+    unsigned HitsWithErrors = 0;
+    bool HadErrorsInLastDiags = false;
+  };
+
+  class TestDiagConsumer : public DiagnosticsConsumer {
+  public:
+    TestDiagConsumer() : Stats(FilesCount, FileStat()) {}
+
+    void onDiagnosticsReady(PathRef File,
+                            std::vector<Diag> Diagnostics) override {
+      StringRef FileIndexStr = llvm::sys::path::stem(File);
+      ASSERT_TRUE(FileIndexStr.consume_front("Foo"));
+
+      unsigned long FileIndex = std::stoul(FileIndexStr.str());
+
+      bool HadError = diagsContainErrors(Diagnostics);
+
+      std::lock_guard<std::mutex> Lock(Mutex);
+      if (HadError)
+        Stats[FileIndex].HitsWithErrors++;
+      else
+        Stats[FileIndex].HitsWithoutErrors++;
+      Stats[FileIndex].HadErrorsInLastDiags = HadError;
+    }
+
+    std::vector<FileStat> takeFileStats() {
+      std::lock_guard<std::mutex> Lock(Mutex);
+      return std::move(Stats);
+    }
+
+  private:
+    std::mutex Mutex;
+    std::vector<FileStat> Stats;
+  };
+
+  struct RequestStats {
+    unsigned RequestsWithoutErrors = 0;
+    unsigned RequestsWithErrors = 0;
+    bool LastContentsHadErrors = false;
+    bool FileIsRemoved = true;
+  };
+
+  std::vector<RequestStats> ReqStats;
+  ReqStats.reserve(FilesCount);
+  for (unsigned FileIndex = 0; FileIndex < FilesCount; ++FileIndex)
+    ReqStats.emplace_back();
+
+  TestDiagConsumer DiagConsumer;
+  {
+    MockCompilationDatabase CDB;
+    ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+    // Prepare some random distributions for the test.
+    std::random_device RandGen;
+
+    std::uniform_int_distribution<unsigned> FileIndexDist(0, FilesCount - 1);
+    // Pass a text that contains compiler errors to addDocument in about 20% of
+    // all requests.
+    std::bernoulli_distribution ShouldHaveErrorsDist(0.2);
+    // Line and Column numbers for requests that need them.
+    std::uniform_int_distribution<int> LineDist(0, MaxLineForFileRequests);
+    std::uniform_int_distribution<int> ColumnDist(0, MaxColumnForFileRequests);
+
+    // Some helpers.
+    auto UpdateStatsOnAddDocument = [&](unsigned FileIndex, bool HadErrors) {
+      auto &Stats = ReqStats[FileIndex];
+
+      if (HadErrors)
+        ++Stats.RequestsWithErrors;
+      else
+        ++Stats.RequestsWithoutErrors;
+      Stats.LastContentsHadErrors = HadErrors;
+      Stats.FileIsRemoved = false;
+    };
+
+    auto UpdateStatsOnRemoveDocument = [&](unsigned FileIndex) {
+      auto &Stats = ReqStats[FileIndex];
+
+      Stats.FileIsRemoved = true;
+    };
+
+    auto AddDocument = [&](unsigned FileIndex, bool SkipCache) {
+      bool ShouldHaveErrors = ShouldHaveErrorsDist(RandGen);
+      Server.addDocument(FilePaths[FileIndex],
+                         ShouldHaveErrors ? SourceContentsWithErrors
+                                          : SourceContentsWithoutErrors,
+                         WantDiagnostics::Auto);
+      UpdateStatsOnAddDocument(FileIndex, ShouldHaveErrors);
+    };
+
+    // Various requests that we would randomly run.
+    auto AddDocumentRequest = [&]() {
+      unsigned FileIndex = FileIndexDist(RandGen);
+      AddDocument(FileIndex, /*SkipCache=*/false);
+    };
+
+    auto ForceReparseRequest = [&]() {
+      unsigned FileIndex = FileIndexDist(RandGen);
+      AddDocument(FileIndex, /*SkipCache=*/true);
+    };
+
+    auto RemoveDocumentRequest = [&]() {
+      unsigned FileIndex = FileIndexDist(RandGen);
+      // Make sure we don't violate the ClangdServer's contract.
+      if (ReqStats[FileIndex].FileIsRemoved)
+        AddDocument(FileIndex, /*SkipCache=*/false);
+
+      Server.removeDocument(FilePaths[FileIndex]);
+      UpdateStatsOnRemoveDocument(FileIndex);
+    };
+
+    auto CodeCompletionRequest = [&]() {
+      unsigned FileIndex = FileIndexDist(RandGen);
+      // Make sure we don't violate the ClangdServer's contract.
+      if (ReqStats[FileIndex].FileIsRemoved)
+        AddDocument(FileIndex, /*SkipCache=*/false);
+
+      Position Pos;
+      Pos.line = LineDist(RandGen);
+      Pos.character = ColumnDist(RandGen);
+      // FIXME(ibiryukov): Also test async completion requests.
+      // Simply putting CodeCompletion into async requests now would make
+      // tests slow, since there's no way to cancel previous completion
+      // requests as opposed to AddDocument/RemoveDocument, which are implicitly
+      // cancelled by any subsequent AddDocument/RemoveDocument request to the
+      // same file.
+      cantFail(runCodeComplete(Server, FilePaths[FileIndex], Pos,
+                               clangd::CodeCompleteOptions()));
+    };
+
+    auto FindDefinitionsRequest = [&]() {
+      unsigned FileIndex = FileIndexDist(RandGen);
+      // Make sure we don't violate the ClangdServer's contract.
+      if (ReqStats[FileIndex].FileIsRemoved)
+        AddDocument(FileIndex, /*SkipCache=*/false);
+
+      Position Pos;
+      Pos.line = LineDist(RandGen);
+      Pos.character = ColumnDist(RandGen);
+
+      ASSERT_TRUE(!!runFindDefinitions(Server, FilePaths[FileIndex], Pos));
+    };
+
+    std::vector<std::function<void()>> AsyncRequests = {
+        AddDocumentRequest, ForceReparseRequest, RemoveDocumentRequest};
+    std::vector<std::function<void()>> BlockingRequests = {
+        CodeCompletionRequest, FindDefinitionsRequest};
+
+    // Bash requests to ClangdServer in a loop.
+    std::uniform_int_distribution<int> AsyncRequestIndexDist(
+        0, AsyncRequests.size() - 1);
+    std::uniform_int_distribution<int> BlockingRequestIndexDist(
+        0, BlockingRequests.size() - 1);
+    for (unsigned I = 1; I <= RequestsCount; ++I) {
+      if (I % BlockingRequestInterval != 0) {
+        // Issue an async request most of the time. It should be fast.
+        unsigned RequestIndex = AsyncRequestIndexDist(RandGen);
+        AsyncRequests[RequestIndex]();
+      } else {
+        // Issue a blocking request once in a while.
+        auto RequestIndex = BlockingRequestIndexDist(RandGen);
+        BlockingRequests[RequestIndex]();
+      }
+    }
+  } // Wait for ClangdServer to shutdown before proceeding.
+
+  // Check some invariants about the state of the program.
+  std::vector<FileStat> Stats = DiagConsumer.takeFileStats();
+  for (unsigned I = 0; I < FilesCount; ++I) {
+    if (!ReqStats[I].FileIsRemoved) {
+      ASSERT_EQ(Stats[I].HadErrorsInLastDiags,
+                ReqStats[I].LastContentsHadErrors);
+    }
+
+    ASSERT_LE(Stats[I].HitsWithErrors, ReqStats[I].RequestsWithErrors);
+    ASSERT_LE(Stats[I].HitsWithoutErrors, ReqStats[I].RequestsWithoutErrors);
+  }
+}
+
+TEST_F(ClangdVFSTest, CheckSourceHeaderSwitch) {
+  MockFSProvider FS;
+  ErrorCheckingDiagConsumer DiagConsumer;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  auto SourceContents = R"cpp(
+  #include "foo.h"
+  int b = a;
+  )cpp";
+
+  auto FooCpp = testPath("foo.cpp");
+  auto FooH = testPath("foo.h");
+  auto Invalid = testPath("main.cpp");
+
+  FS.Files[FooCpp] = SourceContents;
+  FS.Files[FooH] = "int a;";
+  FS.Files[Invalid] = "int main() { \n return 0; \n }";
+
+  llvm::Optional<Path> PathResult = Server.switchSourceHeader(FooCpp);
+  EXPECT_TRUE(PathResult.hasValue());
+  ASSERT_EQ(PathResult.getValue(), FooH);
+
+  PathResult = Server.switchSourceHeader(FooH);
+  EXPECT_TRUE(PathResult.hasValue());
+  ASSERT_EQ(PathResult.getValue(), FooCpp);
+
+  SourceContents = R"c(
+  #include "foo.HH"
+  int b = a;
+  )c";
+
+  // Test with header file in capital letters and different extension, source
+  // file with different extension
+  auto FooC = testPath("bar.c");
+  auto FooHH = testPath("bar.HH");
+
+  FS.Files[FooC] = SourceContents;
+  FS.Files[FooHH] = "int a;";
+
+  PathResult = Server.switchSourceHeader(FooC);
+  EXPECT_TRUE(PathResult.hasValue());
+  ASSERT_EQ(PathResult.getValue(), FooHH);
+
+  // Test with both capital letters
+  auto Foo2C = testPath("foo2.C");
+  auto Foo2HH = testPath("foo2.HH");
+  FS.Files[Foo2C] = SourceContents;
+  FS.Files[Foo2HH] = "int a;";
+
+  PathResult = Server.switchSourceHeader(Foo2C);
+  EXPECT_TRUE(PathResult.hasValue());
+  ASSERT_EQ(PathResult.getValue(), Foo2HH);
+
+  // Test with source file as capital letter and .hxx header file
+  auto Foo3C = testPath("foo3.C");
+  auto Foo3HXX = testPath("foo3.hxx");
+
+  SourceContents = R"c(
+  #include "foo3.hxx"
+  int b = a;
+  )c";
+
+  FS.Files[Foo3C] = SourceContents;
+  FS.Files[Foo3HXX] = "int a;";
+
+  PathResult = Server.switchSourceHeader(Foo3C);
+  EXPECT_TRUE(PathResult.hasValue());
+  ASSERT_EQ(PathResult.getValue(), Foo3HXX);
+
+  // Test if asking for a corresponding file that doesn't exist returns an empty
+  // string.
+  PathResult = Server.switchSourceHeader(Invalid);
+  EXPECT_FALSE(PathResult.hasValue());
+}
+
+TEST_F(ClangdThreadingTest, NoConcurrentDiagnostics) {
+  class NoConcurrentAccessDiagConsumer : public DiagnosticsConsumer {
+  public:
+    std::atomic<int> Count = {0};
+
+    NoConcurrentAccessDiagConsumer(std::promise<void> StartSecondReparse)
+        : StartSecondReparse(std::move(StartSecondReparse)) {}
+
+    void onDiagnosticsReady(PathRef, std::vector<Diag>) override {
+      ++Count;
+      std::unique_lock<std::mutex> Lock(Mutex, std::try_to_lock_t());
+      ASSERT_TRUE(Lock.owns_lock())
+          << "Detected concurrent onDiagnosticsReady calls for the same file.";
+
+      // If we started the second parse immediately, it might cancel the first.
+      // So we don't allow it to start until the first has delivered diags...
+      if (FirstRequest) {
+        FirstRequest = false;
+        StartSecondReparse.set_value();
+        // ... but then we wait long enough that the callbacks would overlap.
+        std::this_thread::sleep_for(std::chrono::milliseconds(50));
+      }
+    }
+
+  private:
+    std::mutex Mutex;
+    bool FirstRequest = true;
+    std::promise<void> StartSecondReparse;
+  };
+
+  const auto SourceContentsWithoutErrors = R"cpp(
+int a;
+int b;
+int c;
+int d;
+)cpp";
+
+  const auto SourceContentsWithErrors = R"cpp(
+int a = x;
+int b;
+int c;
+int d;
+)cpp";
+
+  auto FooCpp = testPath("foo.cpp");
+  MockFSProvider FS;
+  FS.Files[FooCpp] = "";
+
+  std::promise<void> StartSecondPromise;
+  std::future<void> StartSecond = StartSecondPromise.get_future();
+
+  NoConcurrentAccessDiagConsumer DiagConsumer(std::move(StartSecondPromise));
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+  Server.addDocument(FooCpp, SourceContentsWithErrors);
+  StartSecond.wait();
+  Server.addDocument(FooCpp, SourceContentsWithoutErrors);
+  ASSERT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for diagnostics";
+  ASSERT_EQ(DiagConsumer.Count, 2); // Sanity check - we actually ran both?
+}
+
+TEST_F(ClangdVFSTest, FormatCode) {
+  MockFSProvider FS;
+  ErrorCheckingDiagConsumer DiagConsumer;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  auto Path = testPath("foo.cpp");
+  std::string Code = R"cpp(
+#include "x.h"
+#include "y.h"
+
+void f(  )  {}
+)cpp";
+  std::string Expected = R"cpp(
+#include "x.h"
+#include "y.h"
+
+void f() {}
+)cpp";
+  FS.Files[Path] = Code;
+  runAddDocument(Server, Path, Code);
+
+  auto Replaces = Server.formatFile(Code, Path);
+  EXPECT_TRUE(static_cast<bool>(Replaces));
+  auto Changed = tooling::applyAllReplacements(Code, *Replaces);
+  EXPECT_TRUE(static_cast<bool>(Changed));
+  EXPECT_EQ(Expected, *Changed);
+}
+
+TEST_F(ClangdVFSTest, ChangedHeaderFromISystem) {
+  MockFSProvider FS;
+  ErrorCheckingDiagConsumer DiagConsumer;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  auto SourcePath = testPath("source/foo.cpp");
+  auto HeaderPath = testPath("headers/foo.h");
+  FS.Files[HeaderPath] = "struct X { int bar; };";
+  Annotations Code(R"cpp(
+    #include "foo.h"
+
+    int main() {
+      X().ba^
+    })cpp");
+  CDB.ExtraClangFlags.push_back("-xc++");
+  CDB.ExtraClangFlags.push_back("-isystem" + testPath("headers"));
+
+  runAddDocument(Server, SourcePath, Code.code());
+  auto Completions = cantFail(runCodeComplete(Server, SourcePath, Code.point(),
+                                              clangd::CodeCompleteOptions()))
+                         .Completions;
+  EXPECT_THAT(Completions, ElementsAre(Field(&CodeCompletion::Name, "bar")));
+  // Update the header and rerun addDocument to make sure we get the updated
+  // files.
+  FS.Files[HeaderPath] = "struct X { int bar; int baz; };";
+  runAddDocument(Server, SourcePath, Code.code());
+  Completions = cantFail(runCodeComplete(Server, SourcePath, Code.point(),
+                                         clangd::CodeCompleteOptions()))
+                    .Completions;
+  // We want to make sure we see the updated version.
+  EXPECT_THAT(Completions, ElementsAre(Field(&CodeCompletion::Name, "bar"),
+                                       Field(&CodeCompletion::Name, "baz")));
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/ClangdUnitTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/ClangdUnitTests.cpp
new file mode 100644
index 0000000..6843c9e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/ClangdUnitTests.cpp
@@ -0,0 +1,225 @@
+//===-- ClangdUnitTests.cpp - ClangdUnit tests ------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Annotations.h"
+#include "ClangdUnit.h"
+#include "SourceCode.h"
+#include "TestTU.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+using namespace llvm;
+
+namespace {
+using testing::ElementsAre;
+using testing::Field;
+using testing::IsEmpty;
+using testing::Pair;
+
+testing::Matcher<const Diag &> WithFix(testing::Matcher<Fix> FixMatcher) {
+  return Field(&Diag::Fixes, ElementsAre(FixMatcher));
+}
+
+testing::Matcher<const Diag &> WithNote(testing::Matcher<Note> NoteMatcher) {
+  return Field(&Diag::Notes, ElementsAre(NoteMatcher));
+}
+
+MATCHER_P2(Diag, Range, Message,
+           "Diag at " + llvm::to_string(Range) + " = [" + Message + "]") {
+  return arg.Range == Range && arg.Message == Message;
+}
+
+MATCHER_P3(Fix, Range, Replacement, Message,
+           "Fix " + llvm::to_string(Range) + " => " +
+               testing::PrintToString(Replacement) + " = [" + Message + "]") {
+  return arg.Message == Message && arg.Edits.size() == 1 &&
+         arg.Edits[0].range == Range && arg.Edits[0].newText == Replacement;
+}
+
+MATCHER_P(EqualToLSPDiag, LSPDiag,
+          "LSP diagnostic " + llvm::to_string(LSPDiag)) {
+  return std::tie(arg.range, arg.severity, arg.message) ==
+         std::tie(LSPDiag.range, LSPDiag.severity, LSPDiag.message);
+}
+
+MATCHER_P(EqualToFix, Fix, "LSP fix " + llvm::to_string(Fix)) {
+  if (arg.Message != Fix.Message)
+    return false;
+  if (arg.Edits.size() != Fix.Edits.size())
+    return false;
+  for (std::size_t I = 0; I < arg.Edits.size(); ++I) {
+    if (arg.Edits[I].range != Fix.Edits[I].range ||
+        arg.Edits[I].newText != Fix.Edits[I].newText)
+      return false;
+  }
+  return true;
+}
+
+// Helper function to make tests shorter.
+Position pos(int line, int character) {
+  Position Res;
+  Res.line = line;
+  Res.character = character;
+  return Res;
+}
+
+TEST(DiagnosticsTest, DiagnosticRanges) {
+  // Check we report correct ranges, including various edge-cases.
+  Annotations Test(R"cpp(
+    void $decl[[foo]]();
+    int main() {
+      $typo[[go\
+o]]();
+      foo()$semicolon[[]]
+      $unk[[unknown]]();
+    }
+  )cpp");
+  EXPECT_THAT(
+      TestTU::withCode(Test.code()).build().getDiagnostics(),
+      ElementsAre(
+          // This range spans lines.
+          AllOf(Diag(Test.range("typo"),
+                     "use of undeclared identifier 'goo'; did you mean 'foo'?"),
+                WithFix(
+                    Fix(Test.range("typo"), "foo", "change 'go\\ o' to 'foo'")),
+                // This is a pretty normal range.
+                WithNote(Diag(Test.range("decl"), "'foo' declared here"))),
+          // This range is zero-width, and at the end of a line.
+          AllOf(Diag(Test.range("semicolon"), "expected ';' after expression"),
+                WithFix(Fix(Test.range("semicolon"), ";", "insert ';'"))),
+          // This range isn't provided by clang, we expand to the token.
+          Diag(Test.range("unk"), "use of undeclared identifier 'unknown'")));
+}
+
+TEST(DiagnosticsTest, FlagsMatter) {
+  Annotations Test("[[void]] main() {}");
+  auto TU = TestTU::withCode(Test.code());
+  EXPECT_THAT(TU.build().getDiagnostics(),
+              ElementsAre(AllOf(Diag(Test.range(), "'main' must return 'int'"),
+                                WithFix(Fix(Test.range(), "int",
+                                            "change 'void' to 'int'")))));
+  // Same code built as C gets different diagnostics.
+  TU.Filename = "Plain.c";
+  EXPECT_THAT(
+      TU.build().getDiagnostics(),
+      ElementsAre(AllOf(
+          Diag(Test.range(), "return type of 'main' is not 'int'"),
+          WithFix(Fix(Test.range(), "int", "change return type to 'int'")))));
+}
+
+TEST(DiagnosticsTest, Preprocessor) {
+  // This looks like a preamble, but there's an #else in the middle!
+  // Check that:
+  //  - the #else doesn't generate diagnostics (we had this bug)
+  //  - we get diagnostics from the taken branch
+  //  - we get no diagnostics from the not taken branch
+  Annotations Test(R"cpp(
+    #ifndef FOO
+    #define FOO
+      int a = [[b]];
+    #else
+      int x = y;
+    #endif
+    )cpp");
+  EXPECT_THAT(
+      TestTU::withCode(Test.code()).build().getDiagnostics(),
+      ElementsAre(Diag(Test.range(), "use of undeclared identifier 'b'")));
+}
+
+TEST(DiagnosticsTest, ToLSP) {
+  clangd::Diag D;
+  D.Message = "something terrible happened";
+  D.Range = {pos(1, 2), pos(3, 4)};
+  D.InsideMainFile = true;
+  D.Severity = DiagnosticsEngine::Error;
+  D.File = "foo/bar/main.cpp";
+
+  clangd::Note NoteInMain;
+  NoteInMain.Message = "declared somewhere in the main file";
+  NoteInMain.Range = {pos(5, 6), pos(7, 8)};
+  NoteInMain.Severity = DiagnosticsEngine::Remark;
+  NoteInMain.File = "../foo/bar/main.cpp";
+  NoteInMain.InsideMainFile = true;
+  D.Notes.push_back(NoteInMain);
+
+  clangd::Note NoteInHeader;
+  NoteInHeader.Message = "declared somewhere in the header file";
+  NoteInHeader.Range = {pos(9, 10), pos(11, 12)};
+  NoteInHeader.Severity = DiagnosticsEngine::Note;
+  NoteInHeader.File = "../foo/baz/header.h";
+  NoteInHeader.InsideMainFile = false;
+  D.Notes.push_back(NoteInHeader);
+
+  clangd::Fix F;
+  F.Message = "do something";
+  D.Fixes.push_back(F);
+
+  auto MatchingLSP = [](const DiagBase &D, llvm::StringRef Message) {
+    clangd::Diagnostic Res;
+    Res.range = D.Range;
+    Res.severity = getSeverity(D.Severity);
+    Res.message = Message;
+    return Res;
+  };
+
+  // Diagnostics should turn into these:
+  clangd::Diagnostic MainLSP = MatchingLSP(D, R"(something terrible happened
+
+main.cpp:6:7: remark: declared somewhere in the main file
+
+../foo/baz/header.h:10:11:
+note: declared somewhere in the header file)");
+
+  clangd::Diagnostic NoteInMainLSP =
+      MatchingLSP(NoteInMain, R"(declared somewhere in the main file
+
+main.cpp:2:3: error: something terrible happened)");
+
+  // Transform dianostics and check the results.
+  std::vector<std::pair<clangd::Diagnostic, std::vector<clangd::Fix>>> LSPDiags;
+  toLSPDiags(D, [&](clangd::Diagnostic LSPDiag,
+                    llvm::ArrayRef<clangd::Fix> Fixes) {
+    LSPDiags.push_back({std::move(LSPDiag),
+                        std::vector<clangd::Fix>(Fixes.begin(), Fixes.end())});
+  });
+
+  EXPECT_THAT(
+      LSPDiags,
+      ElementsAre(Pair(EqualToLSPDiag(MainLSP), ElementsAre(EqualToFix(F))),
+                  Pair(EqualToLSPDiag(NoteInMainLSP), IsEmpty())));
+}
+
+TEST(ClangdUnitTest, GetBeginningOfIdentifier) {
+  // First ^ is the expected beginning, last is the search position.
+  for (const char *Text : {
+           "int ^f^oo();", // inside identifier
+           "int ^foo();",  // beginning of identifier
+           "int ^foo^();", // end of identifier
+           "int foo(^);",  // non-identifier
+           "^int foo();",  // beginning of file (can't back up)
+           "int ^f0^0();", // after a digit (lexing at N-1 is wrong)
+           "int ^λλ^λ();", // UTF-8 handled properly when backing up
+       }) {
+    Annotations TestCase(Text);
+    auto AST = TestTU::withCode(TestCase.code()).build();
+    const auto &SourceMgr = AST.getASTContext().getSourceManager();
+    SourceLocation Actual = getBeginningOfIdentifier(
+        AST, TestCase.points().back(), SourceMgr.getMainFileID());
+    Position ActualPos =
+        offsetToPosition(TestCase.code(), SourceMgr.getFileOffset(Actual));
+    EXPECT_EQ(TestCase.points().front(), ActualPos) << Text;
+  }
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp
new file mode 100644
index 0000000..2f04bef
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp
@@ -0,0 +1,1343 @@
+//===-- CodeCompleteTests.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Annotations.h"
+#include "ClangdServer.h"
+#include "CodeComplete.h"
+#include "Compiler.h"
+#include "Matchers.h"
+#include "Protocol.h"
+#include "Quality.h"
+#include "SourceCode.h"
+#include "SyncAPI.h"
+#include "TestFS.h"
+#include "index/MemIndex.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+
+namespace {
+using namespace llvm;
+using ::testing::AllOf;
+using ::testing::Contains;
+using ::testing::Each;
+using ::testing::ElementsAre;
+using ::testing::Field;
+using ::testing::HasSubstr;
+using ::testing::IsEmpty;
+using ::testing::Not;
+using ::testing::UnorderedElementsAre;
+
+class IgnoreDiagnostics : public DiagnosticsConsumer {
+  void onDiagnosticsReady(PathRef File,
+                          std::vector<Diag> Diagnostics) override {}
+};
+
+// GMock helpers for matching completion items.
+MATCHER_P(Named, Name, "") { return arg.Name == Name; }
+MATCHER_P(Scope, S, "") { return arg.Scope == S; }
+MATCHER_P(Qualifier, Q, "") { return arg.RequiredQualifier == Q; }
+MATCHER_P(Labeled, Label, "") {
+  return arg.RequiredQualifier + arg.Name + arg.Signature == Label;
+}
+MATCHER_P(SigHelpLabeled, Label, "") { return arg.label == Label; }
+MATCHER_P(Kind, K, "") { return arg.Kind == K; }
+MATCHER_P(Doc, D, "") { return arg.Documentation == D; }
+MATCHER_P(ReturnType, D, "") { return arg.ReturnType == D; }
+MATCHER_P(InsertInclude, IncludeHeader, "") {
+  return arg.Header == IncludeHeader && bool(arg.HeaderInsertion);
+}
+MATCHER(InsertInclude, "") { return bool(arg.HeaderInsertion); }
+MATCHER_P(SnippetSuffix, Text, "") { return arg.SnippetSuffix == Text; }
+MATCHER_P(Origin, OriginSet, "") { return arg.Origin == OriginSet; }
+
+// Shorthand for Contains(Named(Name)).
+Matcher<const std::vector<CodeCompletion> &> Has(std::string Name) {
+  return Contains(Named(std::move(Name)));
+}
+Matcher<const std::vector<CodeCompletion> &> Has(std::string Name,
+                                                 CompletionItemKind K) {
+  return Contains(AllOf(Named(std::move(Name)), Kind(K)));
+}
+MATCHER(IsDocumented, "") { return !arg.Documentation.empty(); }
+
+std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol> Symbols) {
+  SymbolSlab::Builder Slab;
+  for (const auto &Sym : Symbols)
+    Slab.insert(Sym);
+  return MemIndex::build(std::move(Slab).build());
+}
+
+CodeCompleteResult completions(ClangdServer &Server, StringRef Text,
+                               std::vector<Symbol> IndexSymbols = {},
+                               clangd::CodeCompleteOptions Opts = {}) {
+  std::unique_ptr<SymbolIndex> OverrideIndex;
+  if (!IndexSymbols.empty()) {
+    assert(!Opts.Index && "both Index and IndexSymbols given!");
+    OverrideIndex = memIndex(std::move(IndexSymbols));
+    Opts.Index = OverrideIndex.get();
+  }
+
+  auto File = testPath("foo.cpp");
+  Annotations Test(Text);
+  runAddDocument(Server, File, Test.code());
+  auto CompletionList =
+      cantFail(runCodeComplete(Server, File, Test.point(), Opts));
+  return CompletionList;
+}
+
+// Builds a server and runs code completion.
+// If IndexSymbols is non-empty, an index will be built and passed to opts.
+CodeCompleteResult completions(StringRef Text,
+                               std::vector<Symbol> IndexSymbols = {},
+                               clangd::CodeCompleteOptions Opts = {}) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+  return completions(Server, Text, std::move(IndexSymbols), std::move(Opts));
+}
+
+std::string replace(StringRef Haystack, StringRef Needle, StringRef Repl) {
+  std::string Result;
+  raw_string_ostream OS(Result);
+  std::pair<StringRef, StringRef> Split;
+  for (Split = Haystack.split(Needle); !Split.second.empty();
+       Split = Split.first.split(Needle))
+    OS << Split.first << Repl;
+  Result += Split.first;
+  OS.flush();
+  return Result;
+}
+
+// Helpers to produce fake index symbols for memIndex() or completions().
+// USRFormat is a regex replacement string for the unqualified part of the USR.
+Symbol sym(StringRef QName, index::SymbolKind Kind, StringRef USRFormat) {
+  Symbol Sym;
+  std::string USR = "c:"; // We synthesize a few simple cases of USRs by hand!
+  size_t Pos = QName.rfind("::");
+  if (Pos == llvm::StringRef::npos) {
+    Sym.Name = QName;
+    Sym.Scope = "";
+  } else {
+    Sym.Name = QName.substr(Pos + 2);
+    Sym.Scope = QName.substr(0, Pos + 2);
+    USR += "@N@" + replace(QName.substr(0, Pos), "::", "@N@"); // ns:: -> @N@ns
+  }
+  USR += Regex("^.*$").sub(USRFormat, Sym.Name); // e.g. func -> @F@func#
+  Sym.ID = SymbolID(USR);
+  Sym.SymInfo.Kind = Kind;
+  Sym.IsIndexedForCodeCompletion = true;
+  Sym.Origin = SymbolOrigin::Static;
+  return Sym;
+}
+Symbol func(StringRef Name) { // Assumes the function has no args.
+  return sym(Name, index::SymbolKind::Function, "@F@\\0#"); // no args
+}
+Symbol cls(StringRef Name) {
+  return sym(Name, index::SymbolKind::Class, "@S@\\0");
+}
+Symbol var(StringRef Name) {
+  return sym(Name, index::SymbolKind::Variable, "@\\0");
+}
+Symbol ns(StringRef Name) {
+  return sym(Name, index::SymbolKind::Namespace, "@N@\\0");
+}
+Symbol withReferences(int N, Symbol S) {
+  S.References = N;
+  return S;
+}
+
+TEST(CompletionTest, Limit) {
+  clangd::CodeCompleteOptions Opts;
+  Opts.Limit = 2;
+  auto Results = completions(R"cpp(
+struct ClassWithMembers {
+  int AAA();
+  int BBB();
+  int CCC();
+}
+int main() { ClassWithMembers().^ }
+      )cpp",
+                             /*IndexSymbols=*/{}, Opts);
+
+  EXPECT_TRUE(Results.HasMore);
+  EXPECT_THAT(Results.Completions, ElementsAre(Named("AAA"), Named("BBB")));
+}
+
+TEST(CompletionTest, Filter) {
+  std::string Body = R"cpp(
+    #define MotorCar
+    int Car;
+    struct S {
+      int FooBar;
+      int FooBaz;
+      int Qux;
+    };
+  )cpp";
+
+  // Only items matching the fuzzy query are returned.
+  EXPECT_THAT(completions(Body + "int main() { S().Foba^ }").Completions,
+              AllOf(Has("FooBar"), Has("FooBaz"), Not(Has("Qux"))));
+
+  // Macros require  prefix match.
+  EXPECT_THAT(completions(Body + "int main() { C^ }").Completions,
+              AllOf(Has("Car"), Not(Has("MotorCar"))));
+}
+
+void TestAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
+  auto Results = completions(
+      R"cpp(
+      #define MACRO X
+
+      int global_var;
+
+      int global_func();
+
+      struct GlobalClass {};
+
+      struct ClassWithMembers {
+        /// Doc for method.
+        int method();
+
+        int field;
+      private:
+        int private_field;
+      };
+
+      int test() {
+        struct LocalClass {};
+
+        /// Doc for local_var.
+        int local_var;
+
+        ClassWithMembers().^
+      }
+      )cpp",
+      {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
+
+  // Class members. The only items that must be present in after-dot
+  // completion.
+  EXPECT_THAT(Results.Completions,
+              AllOf(Has("method"), Has("field"), Not(Has("ClassWithMembers")),
+                    Not(Has("operator=")), Not(Has("~ClassWithMembers"))));
+  EXPECT_IFF(Opts.IncludeIneligibleResults, Results.Completions,
+             Has("private_field"));
+  // Global items.
+  EXPECT_THAT(
+      Results.Completions,
+      Not(AnyOf(Has("global_var"), Has("index_var"), Has("global_func"),
+                Has("global_func()"), Has("index_func"), Has("GlobalClass"),
+                Has("IndexClass"), Has("MACRO"), Has("LocalClass"))));
+  // There should be no code patterns (aka snippets) in after-dot
+  // completion. At least there aren't any we're aware of.
+  EXPECT_THAT(Results.Completions,
+              Not(Contains(Kind(CompletionItemKind::Snippet))));
+  // Check documentation.
+  EXPECT_IFF(Opts.IncludeComments, Results.Completions,
+             Contains(IsDocumented()));
+}
+
+void TestGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
+  auto Results = completions(
+      R"cpp(
+      #define MACRO X
+
+      int global_var;
+      int global_func();
+
+      struct GlobalClass {};
+
+      struct ClassWithMembers {
+        /// Doc for method.
+        int method();
+      };
+
+      int test() {
+        struct LocalClass {};
+
+        /// Doc for local_var.
+        int local_var;
+
+        ^
+      }
+      )cpp",
+      {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
+
+  // Class members. Should never be present in global completions.
+  EXPECT_THAT(Results.Completions,
+              Not(AnyOf(Has("method"), Has("method()"), Has("field"))));
+  // Global items.
+  EXPECT_THAT(Results.Completions,
+              AllOf(Has("global_var"), Has("index_var"), Has("global_func"),
+                    Has("index_func" /* our fake symbol doesn't include () */),
+                    Has("GlobalClass"), Has("IndexClass")));
+  // A macro.
+  EXPECT_IFF(Opts.IncludeMacros, Results.Completions, Has("MACRO"));
+  // Local items. Must be present always.
+  EXPECT_THAT(Results.Completions,
+              AllOf(Has("local_var"), Has("LocalClass"),
+                    Contains(Kind(CompletionItemKind::Snippet))));
+  // Check documentation.
+  EXPECT_IFF(Opts.IncludeComments, Results.Completions,
+             Contains(IsDocumented()));
+}
+
+TEST(CompletionTest, CompletionOptions) {
+  auto Test = [&](const clangd::CodeCompleteOptions &Opts) {
+    TestAfterDotCompletion(Opts);
+    TestGlobalScopeCompletion(Opts);
+  };
+  // We used to test every combination of options, but that got too slow (2^N).
+  auto Flags = {
+      &clangd::CodeCompleteOptions::IncludeMacros,
+      &clangd::CodeCompleteOptions::IncludeComments,
+      &clangd::CodeCompleteOptions::IncludeCodePatterns,
+      &clangd::CodeCompleteOptions::IncludeIneligibleResults,
+  };
+  // Test default options.
+  Test({});
+  // Test with one flag flipped.
+  for (auto &F : Flags) {
+    clangd::CodeCompleteOptions O;
+    O.*F ^= true;
+    Test(O);
+  }
+}
+
+TEST(CompletionTest, Priorities) {
+  auto Internal = completions(R"cpp(
+      class Foo {
+        public: void pub();
+        protected: void prot();
+        private: void priv();
+      };
+      void Foo::pub() { this->^ }
+  )cpp");
+  EXPECT_THAT(Internal.Completions,
+              HasSubsequence(Named("priv"), Named("prot"), Named("pub")));
+
+  auto External = completions(R"cpp(
+      class Foo {
+        public: void pub();
+        protected: void prot();
+        private: void priv();
+      };
+      void test() {
+        Foo F;
+        F.^
+      }
+  )cpp");
+  EXPECT_THAT(External.Completions,
+              AllOf(Has("pub"), Not(Has("prot")), Not(Has("priv"))));
+}
+
+TEST(CompletionTest, Qualifiers) {
+  auto Results = completions(R"cpp(
+      class Foo {
+        public: int foo() const;
+        int bar() const;
+      };
+      class Bar : public Foo {
+        int foo() const;
+      };
+      void test() { Bar().^ }
+  )cpp");
+  EXPECT_THAT(Results.Completions,
+              HasSubsequence(AllOf(Qualifier(""), Named("bar")),
+                             AllOf(Qualifier("Foo::"), Named("foo"))));
+  EXPECT_THAT(Results.Completions,
+              Not(Contains(AllOf(Qualifier(""), Named("foo"))))); // private
+}
+
+TEST(CompletionTest, InjectedTypename) {
+  // These are suppressed when accessed as a member...
+  EXPECT_THAT(completions("struct X{}; void foo(){ X().^ }").Completions,
+              Not(Has("X")));
+  EXPECT_THAT(completions("struct X{ void foo(){ this->^ } };").Completions,
+              Not(Has("X")));
+  // ...but accessible in other, more useful cases.
+  EXPECT_THAT(completions("struct X{ void foo(){ ^ } };").Completions,
+              Has("X"));
+  EXPECT_THAT(
+      completions("struct Y{}; struct X:Y{ void foo(){ ^ } };").Completions,
+      Has("Y"));
+  EXPECT_THAT(
+      completions(
+          "template<class> struct Y{}; struct X:Y<int>{ void foo(){ ^ } };")
+          .Completions,
+      Has("Y"));
+  // This case is marginal (`using X::X` is useful), we allow it for now.
+  EXPECT_THAT(completions("struct X{}; void foo(){ X::^ }").Completions,
+              Has("X"));
+}
+
+TEST(CompletionTest, Snippets) {
+  clangd::CodeCompleteOptions Opts;
+  auto Results = completions(
+      R"cpp(
+      struct fake {
+        int a;
+        int f(int i, const float f) const;
+      };
+      int main() {
+        fake f;
+        f.^
+      }
+      )cpp",
+      /*IndexSymbols=*/{}, Opts);
+  EXPECT_THAT(
+      Results.Completions,
+      HasSubsequence(Named("a"),
+                     SnippetSuffix("(${1:int i}, ${2:const float f})")));
+}
+
+TEST(CompletionTest, Kinds) {
+  auto Results = completions(
+      R"cpp(
+          #define MACRO X
+          int variable;
+          struct Struct {};
+          int function();
+          int X = ^
+      )cpp",
+      {func("indexFunction"), var("indexVariable"), cls("indexClass")});
+  EXPECT_THAT(Results.Completions,
+              AllOf(Has("function", CompletionItemKind::Function),
+                    Has("variable", CompletionItemKind::Variable),
+                    Has("int", CompletionItemKind::Keyword),
+                    Has("Struct", CompletionItemKind::Class),
+                    Has("MACRO", CompletionItemKind::Text),
+                    Has("indexFunction", CompletionItemKind::Function),
+                    Has("indexVariable", CompletionItemKind::Variable),
+                    Has("indexClass", CompletionItemKind::Class)));
+
+  Results = completions("nam^");
+  EXPECT_THAT(Results.Completions,
+              Has("namespace", CompletionItemKind::Snippet));
+}
+
+TEST(CompletionTest, NoDuplicates) {
+  auto Results = completions(
+      R"cpp(
+          class Adapter {
+          };
+
+          void f() {
+            Adapter^
+          }
+      )cpp",
+      {cls("Adapter")});
+
+  // Make sure there are no duplicate entries of 'Adapter'.
+  EXPECT_THAT(Results.Completions, ElementsAre(Named("Adapter")));
+}
+
+TEST(CompletionTest, ScopedNoIndex) {
+  auto Results = completions(
+      R"cpp(
+          namespace fake { int BigBang, Babble, Box; };
+          int main() { fake::ba^ }
+      ")cpp");
+  // Babble is a better match than BigBang. Box doesn't match at all.
+  EXPECT_THAT(Results.Completions,
+              ElementsAre(Named("Babble"), Named("BigBang")));
+}
+
+TEST(CompletionTest, Scoped) {
+  auto Results = completions(
+      R"cpp(
+          namespace fake { int Babble, Box; };
+          int main() { fake::ba^ }
+      ")cpp",
+      {var("fake::BigBang")});
+  EXPECT_THAT(Results.Completions,
+              ElementsAre(Named("Babble"), Named("BigBang")));
+}
+
+TEST(CompletionTest, ScopedWithFilter) {
+  auto Results = completions(
+      R"cpp(
+          void f() { ns::x^ }
+      )cpp",
+      {cls("ns::XYZ"), func("ns::foo")});
+  EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("XYZ")));
+}
+
+TEST(CompletionTest, ReferencesAffectRanking) {
+  auto Results = completions("int main() { abs^ }", {ns("absl"), func("absb")});
+  EXPECT_THAT(Results.Completions, HasSubsequence(Named("absb"), Named("absl")));
+  Results = completions("int main() { abs^ }",
+                        {withReferences(10000, ns("absl")), func("absb")});
+  EXPECT_THAT(Results.Completions,
+              HasSubsequence(Named("absl"), Named("absb")));
+}
+
+TEST(CompletionTest, GlobalQualified) {
+  auto Results = completions(
+      R"cpp(
+          void f() { ::^ }
+      )cpp",
+      {cls("XYZ")});
+  EXPECT_THAT(Results.Completions,
+              AllOf(Has("XYZ", CompletionItemKind::Class),
+                    Has("f", CompletionItemKind::Function)));
+}
+
+TEST(CompletionTest, FullyQualified) {
+  auto Results = completions(
+      R"cpp(
+          namespace ns { void bar(); }
+          void f() { ::ns::^ }
+      )cpp",
+      {cls("ns::XYZ")});
+  EXPECT_THAT(Results.Completions,
+              AllOf(Has("XYZ", CompletionItemKind::Class),
+                    Has("bar", CompletionItemKind::Function)));
+}
+
+TEST(CompletionTest, SemaIndexMerge) {
+  auto Results = completions(
+      R"cpp(
+          namespace ns { int local; void both(); }
+          void f() { ::ns::^ }
+      )cpp",
+      {func("ns::both"), cls("ns::Index")});
+  // We get results from both index and sema, with no duplicates.
+  EXPECT_THAT(Results.Completions,
+              UnorderedElementsAre(
+                  AllOf(Named("local"), Origin(SymbolOrigin::AST)),
+                  AllOf(Named("Index"), Origin(SymbolOrigin::Static)),
+                  AllOf(Named("both"),
+                        Origin(SymbolOrigin::AST | SymbolOrigin::Static))));
+}
+
+TEST(CompletionTest, SemaIndexMergeWithLimit) {
+  clangd::CodeCompleteOptions Opts;
+  Opts.Limit = 1;
+  auto Results = completions(
+      R"cpp(
+          namespace ns { int local; void both(); }
+          void f() { ::ns::^ }
+      )cpp",
+      {func("ns::both"), cls("ns::Index")}, Opts);
+  EXPECT_EQ(Results.Completions.size(), Opts.Limit);
+  EXPECT_TRUE(Results.HasMore);
+}
+
+TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  std::string Subdir = testPath("sub");
+  std::string SearchDirArg = (llvm::Twine("-I") + Subdir).str();
+  CDB.ExtraClangFlags = {SearchDirArg.c_str()};
+  std::string BarHeader = testPath("sub/bar.h");
+  FS.Files[BarHeader] = "";
+
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+  Symbol::Details Scratch;
+  auto BarURI = URI::createFile(BarHeader).toString();
+  Symbol Sym = cls("ns::X");
+  Sym.CanonicalDeclaration.FileURI = BarURI;
+  Scratch.IncludeHeader = BarURI;
+  Sym.Detail = &Scratch;
+  // Shoten include path based on search dirctory and insert.
+  auto Results = completions(Server,
+                             R"cpp(
+          int main() { ns::^ }
+      )cpp",
+                             {Sym});
+  EXPECT_THAT(Results.Completions,
+              ElementsAre(AllOf(Named("X"), InsertInclude("\"bar.h\""))));
+  // Duplicate based on inclusions in preamble.
+  Results = completions(Server,
+                        R"cpp(
+          #include "sub/bar.h"  // not shortest, so should only match resolved.
+          int main() { ns::^ }
+      )cpp",
+                        {Sym});
+  EXPECT_THAT(Results.Completions, ElementsAre(AllOf(Named("X"), Labeled("X"),
+                                                     Not(InsertInclude()))));
+}
+
+TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+  Symbol::Details Scratch;
+  Symbol SymX = cls("ns::X");
+  Symbol SymY = cls("ns::Y");
+  std::string BarHeader = testPath("bar.h");
+  auto BarURI = URI::createFile(BarHeader).toString();
+  SymX.CanonicalDeclaration.FileURI = BarURI;
+  SymY.CanonicalDeclaration.FileURI = BarURI;
+  Scratch.IncludeHeader = "<bar>";
+  SymX.Detail = &Scratch;
+  SymY.Detail = &Scratch;
+  // Shoten include path based on search dirctory and insert.
+  auto Results = completions(Server,
+                             R"cpp(
+          namespace ns {
+            class X;
+            class Y {}
+          }
+          int main() { ns::^ }
+      )cpp",
+                             {SymX, SymY});
+  EXPECT_THAT(Results.Completions,
+              ElementsAre(AllOf(Named("X"), Not(InsertInclude())),
+                          AllOf(Named("Y"), Not(InsertInclude()))));
+}
+
+TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  FS.Files[testPath("bar.h")] =
+      R"cpp(namespace ns { struct preamble { int member; }; })cpp";
+  auto File = testPath("foo.cpp");
+  Annotations Test(R"cpp(
+      #include "bar.h"
+      namespace ns { int local; }
+      void f() { ns::^; }
+      void f() { ns::preamble().$2^; }
+  )cpp");
+  runAddDocument(Server, File, Test.code());
+  clangd::CodeCompleteOptions Opts = {};
+
+  auto I = memIndex({var("ns::index")});
+  Opts.Index = I.get();
+  auto WithIndex = cantFail(runCodeComplete(Server, File, Test.point(), Opts));
+  EXPECT_THAT(WithIndex.Completions,
+              UnorderedElementsAre(Named("local"), Named("index")));
+  auto ClassFromPreamble =
+      cantFail(runCodeComplete(Server, File, Test.point("2"), Opts));
+  EXPECT_THAT(ClassFromPreamble.Completions, Contains(Named("member")));
+
+  Opts.Index = nullptr;
+  auto WithoutIndex =
+      cantFail(runCodeComplete(Server, File, Test.point(), Opts));
+  EXPECT_THAT(WithoutIndex.Completions,
+              UnorderedElementsAre(Named("local"), Named("preamble")));
+}
+
+TEST(CompletionTest, DynamicIndexMultiFile) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  auto Opts = ClangdServer::optsForTest();
+  Opts.BuildDynamicSymbolIndex = true;
+  ClangdServer Server(CDB, FS, DiagConsumer, Opts);
+
+  FS.Files[testPath("foo.h")] = R"cpp(
+      namespace ns { class XYZ {}; void foo(int x) {} }
+  )cpp";
+  runAddDocument(Server, testPath("foo.cpp"), R"cpp(
+      #include "foo.h"
+  )cpp");
+
+  auto File = testPath("bar.cpp");
+  Annotations Test(R"cpp(
+      namespace ns {
+      class XXX {};
+      /// Doooc
+      void fooooo() {}
+      }
+      void f() { ns::^ }
+  )cpp");
+  runAddDocument(Server, File, Test.code());
+
+  auto Results = cantFail(runCodeComplete(Server, File, Test.point(), {}));
+  // "XYZ" and "foo" are not included in the file being completed but are still
+  // visible through the index.
+  EXPECT_THAT(Results.Completions, Has("XYZ", CompletionItemKind::Class));
+  EXPECT_THAT(Results.Completions, Has("foo", CompletionItemKind::Function));
+  EXPECT_THAT(Results.Completions, Has("XXX", CompletionItemKind::Class));
+  EXPECT_THAT(Results.Completions,
+              Contains((Named("fooooo"), Kind(CompletionItemKind::Function),
+                        Doc("Doooc"), ReturnType("void"))));
+}
+
+TEST(CompletionTest, Documentation) {
+  auto Results = completions(
+      R"cpp(
+      // Non-doxygen comment.
+      int foo();
+      /// Doxygen comment.
+      /// \param int a
+      int bar(int a);
+      /* Multi-line
+         block comment
+      */
+      int baz();
+
+      int x = ^
+     )cpp");
+  EXPECT_THAT(Results.Completions,
+              Contains(AllOf(Named("foo"), Doc("Non-doxygen comment."))));
+  EXPECT_THAT(
+      Results.Completions,
+      Contains(AllOf(Named("bar"), Doc("Doxygen comment.\n\\param int a"))));
+  EXPECT_THAT(Results.Completions,
+              Contains(AllOf(Named("baz"), Doc("Multi-line\nblock comment"))));
+}
+
+TEST(CompletionTest, GlobalCompletionFiltering) {
+
+  Symbol Class = cls("XYZ");
+  Class.IsIndexedForCodeCompletion = false;
+  Symbol Func = func("XYZ::foooo");
+  Func.IsIndexedForCodeCompletion = false;
+
+  auto Results = completions(R"(//      void f() {
+      XYZ::foooo^
+      })",
+                             {Class, Func});
+  EXPECT_THAT(Results.Completions, IsEmpty());
+}
+
+TEST(CodeCompleteTest, DisableTypoCorrection) {
+  auto Results = completions(R"cpp(
+     namespace clang { int v; }
+     void f() { clangd::^
+  )cpp");
+  EXPECT_TRUE(Results.Completions.empty());
+}
+
+TEST(CodeCompleteTest, NoColonColonAtTheEnd) {
+  auto Results = completions(R"cpp(
+    namespace clang { }
+    void f() {
+      clan^
+    }
+  )cpp");
+
+  EXPECT_THAT(Results.Completions, Contains(Labeled("clang")));
+  EXPECT_THAT(Results.Completions, Not(Contains(Labeled("clang::"))));
+}
+
+TEST(CompletionTest, BacktrackCrashes) {
+  // Sema calls code completion callbacks twice in these cases.
+  auto Results = completions(R"cpp(
+      namespace ns {
+      struct FooBarBaz {};
+      } // namespace ns
+
+     int foo(ns::FooBar^
+  )cpp");
+
+  EXPECT_THAT(Results.Completions, ElementsAre(Labeled("FooBarBaz")));
+
+  // Check we don't crash in that case too.
+  completions(R"cpp(
+    struct FooBarBaz {};
+    void test() {
+      if (FooBarBaz * x^) {}
+    }
+)cpp");
+}
+
+TEST(CompletionTest, CompleteInMacroWithStringification) {
+  auto Results = completions(R"cpp(
+void f(const char *, int x);
+#define F(x) f(#x, x)
+
+namespace ns {
+int X;
+int Y;
+}  // namespace ns
+
+int f(int input_num) {
+  F(ns::^)
+}
+)cpp");
+
+  EXPECT_THAT(Results.Completions,
+              UnorderedElementsAre(Named("X"), Named("Y")));
+}
+
+TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
+  auto Results = completions(R"cpp(
+void f(const char *, int x);
+#define F(x) f(#x, x)
+
+namespace ns {
+int X;
+
+int f(int input_num) {
+  F(^)
+}
+}  // namespace ns
+)cpp");
+
+  EXPECT_THAT(Results.Completions, Contains(Named("X")));
+}
+
+TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {
+  auto Results = completions(R"cpp(
+    int bar(int param_in_bar) {
+    }
+
+    int foo(int param_in_foo) {
+#if 0
+  // In recorvery mode, "param_in_foo" will also be suggested among many other
+  // unrelated symbols; however, this is really a special case where this works.
+  // If the #if block is outside of the function, "param_in_foo" is still
+  // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't
+  // really provide useful results in excluded branches.
+  par^
+#endif
+    }
+)cpp");
+
+  EXPECT_TRUE(Results.Completions.empty());
+}
+
+SignatureHelp signatures(StringRef Text) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+  auto File = testPath("foo.cpp");
+  Annotations Test(Text);
+  runAddDocument(Server, File, Test.code());
+  return cantFail(runSignatureHelp(Server, File, Test.point()));
+}
+
+MATCHER_P(ParamsAre, P, "") {
+  if (P.size() != arg.parameters.size())
+    return false;
+  for (unsigned I = 0; I < P.size(); ++I)
+    if (P[I] != arg.parameters[I].label)
+      return false;
+  return true;
+}
+
+Matcher<SignatureInformation> Sig(std::string Label,
+                                  std::vector<std::string> Params) {
+  return AllOf(SigHelpLabeled(Label), ParamsAre(Params));
+}
+
+TEST(SignatureHelpTest, Overloads) {
+  auto Results = signatures(R"cpp(
+    void foo(int x, int y);
+    void foo(int x, float y);
+    void foo(float x, int y);
+    void foo(float x, float y);
+    void bar(int x, int y = 0);
+    int main() { foo(^); }
+  )cpp");
+  EXPECT_THAT(Results.signatures,
+              UnorderedElementsAre(
+                  Sig("foo(float x, float y) -> void", {"float x", "float y"}),
+                  Sig("foo(float x, int y) -> void", {"float x", "int y"}),
+                  Sig("foo(int x, float y) -> void", {"int x", "float y"}),
+                  Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+  // We always prefer the first signature.
+  EXPECT_EQ(0, Results.activeSignature);
+  EXPECT_EQ(0, Results.activeParameter);
+}
+
+TEST(SignatureHelpTest, DefaultArgs) {
+  auto Results = signatures(R"cpp(
+    void bar(int x, int y = 0);
+    void bar(float x = 0, int y = 42);
+    int main() { bar(^
+  )cpp");
+  EXPECT_THAT(Results.signatures,
+              UnorderedElementsAre(
+                  Sig("bar(int x, int y = 0) -> void", {"int x", "int y = 0"}),
+                  Sig("bar(float x = 0, int y = 42) -> void",
+                      {"float x = 0", "int y = 42"})));
+  EXPECT_EQ(0, Results.activeSignature);
+  EXPECT_EQ(0, Results.activeParameter);
+}
+
+TEST(SignatureHelpTest, ActiveArg) {
+  auto Results = signatures(R"cpp(
+    int baz(int a, int b, int c);
+    int main() { baz(baz(1,2,3), ^); }
+  )cpp");
+  EXPECT_THAT(Results.signatures,
+              ElementsAre(Sig("baz(int a, int b, int c) -> int",
+                              {"int a", "int b", "int c"})));
+  EXPECT_EQ(0, Results.activeSignature);
+  EXPECT_EQ(1, Results.activeParameter);
+}
+
+class IndexRequestCollector : public SymbolIndex {
+public:
+  bool
+  fuzzyFind(const FuzzyFindRequest &Req,
+            llvm::function_ref<void(const Symbol &)> Callback) const override {
+    Requests.push_back(Req);
+    return true;
+  }
+
+  void lookup(const LookupRequest &,
+              llvm::function_ref<void(const Symbol &)>) const override {}
+
+  const std::vector<FuzzyFindRequest> allRequests() const { return Requests; }
+
+private:
+  mutable std::vector<FuzzyFindRequest> Requests;
+};
+
+std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code) {
+  clangd::CodeCompleteOptions Opts;
+  IndexRequestCollector Requests;
+  Opts.Index = &Requests;
+  completions(Code, {}, Opts);
+  return Requests.allRequests();
+}
+
+TEST(CompletionTest, UnqualifiedIdQuery) {
+  auto Requests = captureIndexRequests(R"cpp(
+      namespace std {}
+      using namespace std;
+      namespace ns {
+      void f() {
+        vec^
+      }
+      }
+  )cpp");
+
+  EXPECT_THAT(Requests,
+              ElementsAre(Field(&FuzzyFindRequest::Scopes,
+                                UnorderedElementsAre("", "ns::", "std::"))));
+}
+
+TEST(CompletionTest, ResolvedQualifiedIdQuery) {
+  auto Requests = captureIndexRequests(R"cpp(
+      namespace ns1 {}
+      namespace ns2 {} // ignore
+      namespace ns3 { namespace nns3 {} }
+      namespace foo {
+      using namespace ns1;
+      using namespace ns3::nns3;
+      }
+      namespace ns {
+      void f() {
+        foo::^
+      }
+      }
+  )cpp");
+
+  EXPECT_THAT(Requests,
+              ElementsAre(Field(
+                  &FuzzyFindRequest::Scopes,
+                  UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::"))));
+}
+
+TEST(CompletionTest, UnresolvedQualifierIdQuery) {
+  auto Requests = captureIndexRequests(R"cpp(
+      namespace a {}
+      using namespace a;
+      namespace ns {
+      void f() {
+      bar::^
+      }
+      } // namespace ns
+  )cpp");
+
+  EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
+                                          UnorderedElementsAre("bar::"))));
+}
+
+TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
+  auto Requests = captureIndexRequests(R"cpp(
+      namespace a {}
+      using namespace a;
+      namespace ns {
+      void f() {
+      ::a::bar::^
+      }
+      } // namespace ns
+  )cpp");
+
+  EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
+                                          UnorderedElementsAre("a::bar::"))));
+}
+
+TEST(CompletionTest, EmptyQualifiedQuery) {
+  auto Requests = captureIndexRequests(R"cpp(
+      namespace ns {
+      void f() {
+      ^
+      }
+      } // namespace ns
+  )cpp");
+
+  EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
+                                          UnorderedElementsAre("", "ns::"))));
+}
+
+TEST(CompletionTest, GlobalQualifiedQuery) {
+  auto Requests = captureIndexRequests(R"cpp(
+      namespace ns {
+      void f() {
+      ::^
+      }
+      } // namespace ns
+  )cpp");
+
+  EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
+                                          UnorderedElementsAre(""))));
+}
+
+TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
+  auto Completions = completions(
+      R"cpp(
+    struct Foo {
+      int SomeNameOfField;
+      typedef int SomeNameOfTypedefField;
+    };
+
+    Foo::^)cpp",
+      {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")});
+
+  EXPECT_THAT(Completions.Completions,
+              AllOf(Contains(Labeled("SomeNameOfField")),
+                    Contains(Labeled("SomeNameOfTypedefField")),
+                    Not(Contains(Labeled("SomeNameInTheIndex")))));
+}
+
+TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
+  {
+    auto Completions = completions(
+        R"cpp(
+      template <class T>
+      void foo() {
+        T::^
+      }
+      )cpp",
+        {func("::SomeNameInTheIndex")});
+
+    EXPECT_THAT(Completions.Completions,
+                Not(Contains(Labeled("SomeNameInTheIndex"))));
+  }
+
+  {
+    auto Completions = completions(
+        R"cpp(
+      template <class T>
+      void foo() {
+        T::template Y<int>::^
+      }
+      )cpp",
+        {func("::SomeNameInTheIndex")});
+
+    EXPECT_THAT(Completions.Completions,
+                Not(Contains(Labeled("SomeNameInTheIndex"))));
+  }
+
+  {
+    auto Completions = completions(
+        R"cpp(
+      template <class T>
+      void foo() {
+        T::foo::^
+      }
+      )cpp",
+        {func("::SomeNameInTheIndex")});
+
+    EXPECT_THAT(Completions.Completions,
+                Not(Contains(Labeled("SomeNameInTheIndex"))));
+  }
+}
+
+TEST(CompletionTest, OverloadBundling) {
+  clangd::CodeCompleteOptions Opts;
+  Opts.BundleOverloads = true;
+
+  std::string Context = R"cpp(
+    struct X {
+      // Overload with int
+      int a(int);
+      // Overload with bool
+      int a(bool);
+      int b(float);
+    };
+    int GFuncC(int);
+    int GFuncD(int);
+  )cpp";
+
+  // Member completions are bundled.
+  EXPECT_THAT(completions(Context + "int y = X().^", {}, Opts).Completions,
+              UnorderedElementsAre(Labeled("a(…)"), Labeled("b(float)")));
+
+  // Non-member completions are bundled, including index+sema.
+  Symbol NoArgsGFunc = func("GFuncC");
+  EXPECT_THAT(
+      completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
+      UnorderedElementsAre(Labeled("GFuncC(…)"), Labeled("GFuncD(int)")));
+
+  // Differences in header-to-insert suppress bundling.
+  Symbol::Details Detail;
+  std::string DeclFile = URI::createFile(testPath("foo")).toString();
+  NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile;
+  Detail.IncludeHeader = "<foo>";
+  NoArgsGFunc.Detail = &Detail;
+  EXPECT_THAT(
+      completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
+      UnorderedElementsAre(AllOf(Named("GFuncC"), InsertInclude("<foo>")),
+                           Labeled("GFuncC(int)"), Labeled("GFuncD(int)")));
+
+  // Examine a bundled completion in detail.
+  auto A =
+      completions(Context + "int y = X().a^", {}, Opts).Completions.front();
+  EXPECT_EQ(A.Name, "a");
+  EXPECT_EQ(A.Signature, "(…)");
+  EXPECT_EQ(A.BundleSize, 2u);
+  EXPECT_EQ(A.Kind, CompletionItemKind::Method);
+  EXPECT_EQ(A.ReturnType, "int"); // All overloads return int.
+  // For now we just return one of the doc strings arbitrarily.
+  EXPECT_THAT(A.Documentation, AnyOf(HasSubstr("Overload with int"),
+                                     HasSubstr("Overload with bool")));
+  EXPECT_EQ(A.SnippetSuffix, "(${0})");
+}
+
+TEST(CompletionTest, DocumentationFromChangedFileCrash) {
+  MockFSProvider FS;
+  auto FooH = testPath("foo.h");
+  auto FooCpp = testPath("foo.cpp");
+  FS.Files[FooH] = R"cpp(
+    // this is my documentation comment.
+    int func();
+  )cpp";
+  FS.Files[FooCpp] = "";
+
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  Annotations Source(R"cpp(
+    #include "foo.h"
+    int func() {
+      // This makes sure we have func from header in the AST.
+    }
+    int a = fun^
+  )cpp");
+  Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes);
+  // We need to wait for preamble to build.
+  ASSERT_TRUE(Server.blockUntilIdleForTest());
+
+  // Change the header file. Completion will reuse the old preamble!
+  FS.Files[FooH] = R"cpp(
+    int func();
+  )cpp";
+
+  clangd::CodeCompleteOptions Opts;
+  Opts.IncludeComments = true;
+  CodeCompleteResult Completions =
+      cantFail(runCodeComplete(Server, FooCpp, Source.point(), Opts));
+  // We shouldn't crash. Unfortunately, current workaround is to not produce
+  // comments for symbols from headers.
+  EXPECT_THAT(Completions.Completions,
+              Contains(AllOf(Not(IsDocumented()), Named("func"))));
+}
+
+TEST(CompletionTest, NonDocComments) {
+  MockFSProvider FS;
+  auto FooCpp = testPath("foo.cpp");
+  FS.Files[FooCpp] = "";
+
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  Annotations Source(R"cpp(
+    // We ignore namespace comments, for rationale see CodeCompletionStrings.h.
+    namespace comments_ns {
+    }
+
+    // ------------------
+    int comments_foo();
+
+    // A comment and a decl are separated by newlines.
+    // Therefore, the comment shouldn't show up as doc comment.
+
+    int comments_bar();
+
+    // this comment should be in the results.
+    int comments_baz();
+
+
+    template <class T>
+    struct Struct {
+      int comments_qux();
+      int comments_quux();
+    };
+
+
+    // This comment should not be there.
+
+    template <class T>
+    int Struct<T>::comments_qux() {
+    }
+
+    // This comment **should** be in results.
+    template <class T>
+    int Struct<T>::comments_quux() {
+      int a = comments^;
+    }
+  )cpp");
+  // FIXME: Auto-completion in a template requires disabling delayed template
+  // parsing.
+  CDB.ExtraClangFlags.push_back("-fno-delayed-template-parsing");
+  Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes);
+  CodeCompleteResult Completions = cantFail(runCodeComplete(
+      Server, FooCpp, Source.point(), clangd::CodeCompleteOptions()));
+
+  // We should not get any of those comments in completion.
+  EXPECT_THAT(
+      Completions.Completions,
+      UnorderedElementsAre(AllOf(Not(IsDocumented()), Named("comments_foo")),
+                           AllOf(IsDocumented(), Named("comments_baz")),
+                           AllOf(IsDocumented(), Named("comments_quux")),
+                           AllOf(Not(IsDocumented()), Named("comments_ns")),
+                           // FIXME(ibiryukov): the following items should have
+                           // empty documentation, since they are separated from
+                           // a comment with an empty line. Unfortunately, I
+                           // couldn't make Sema tests pass if we ignore those.
+                           AllOf(IsDocumented(), Named("comments_bar")),
+                           AllOf(IsDocumented(), Named("comments_qux"))));
+}
+
+TEST(CompletionTest, CompleteOnInvalidLine) {
+  auto FooCpp = testPath("foo.cpp");
+
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  MockFSProvider FS;
+  FS.Files[FooCpp] = "// empty file";
+
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+  // Run completion outside the file range.
+  Position Pos;
+  Pos.line = 100;
+  Pos.character = 0;
+  EXPECT_THAT_EXPECTED(
+      runCodeComplete(Server, FooCpp, Pos, clangd::CodeCompleteOptions()),
+      Failed());
+}
+
+TEST(CompletionTest, QualifiedNames) {
+  auto Results = completions(
+      R"cpp(
+          namespace ns { int local; void both(); }
+          void f() { ::ns::^ }
+      )cpp",
+      {func("ns::both"), cls("ns::Index")});
+  // We get results from both index and sema, with no duplicates.
+  EXPECT_THAT(
+      Results.Completions,
+      UnorderedElementsAre(Scope("ns::"), Scope("ns::"), Scope("ns::")));
+}
+
+TEST(CompletionTest, Render) {
+  CodeCompletion C;
+  C.Name = "x";
+  C.Signature = "(bool) const";
+  C.SnippetSuffix = "(${0:bool})";
+  C.ReturnType = "int";
+  C.RequiredQualifier = "Foo::";
+  C.Scope = "ns::Foo::";
+  C.Documentation = "This is x().";
+  C.Header = "\"foo.h\"";
+  C.Kind = CompletionItemKind::Method;
+  C.Score.Total = 1.0;
+  C.Origin = SymbolOrigin::AST | SymbolOrigin::Static;
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeIndicator.Insert = "^";
+  Opts.IncludeIndicator.NoInsert = "";
+  Opts.EnableSnippets = false;
+
+  auto R = C.render(Opts);
+  EXPECT_EQ(R.label, "Foo::x(bool) const");
+  EXPECT_EQ(R.insertText, "Foo::x");
+  EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
+  EXPECT_EQ(R.filterText, "x");
+  EXPECT_EQ(R.detail, "int\n\"foo.h\"");
+  EXPECT_EQ(R.documentation, "This is x().");
+  EXPECT_THAT(R.additionalTextEdits, IsEmpty());
+  EXPECT_EQ(R.sortText, sortText(1.0, "x"));
+
+  Opts.EnableSnippets = true;
+  R = C.render(Opts);
+  EXPECT_EQ(R.insertText, "Foo::x(${0:bool})");
+  EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+
+  C.HeaderInsertion.emplace();
+  R = C.render(Opts);
+  EXPECT_EQ(R.label, "^Foo::x(bool) const");
+  EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
+
+  Opts.ShowOrigins = true;
+  R = C.render(Opts);
+  EXPECT_EQ(R.label, "^[AS]Foo::x(bool) const");
+
+  C.BundleSize = 2;
+  R = C.render(Opts);
+  EXPECT_EQ(R.detail, "[2 overloads]\n\"foo.h\"");
+}
+
+TEST(CompletionTest, IgnoreRecoveryResults) {
+  auto Results = completions(
+      R"cpp(
+          namespace ns { int NotRecovered() { return 0; } }
+          void f() {
+            // Sema enters recovery mode first and then normal mode.
+            if (auto x = ns::NotRecover^)
+          }
+      )cpp");
+  EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("NotRecovered")));
+}
+
+TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {
+  auto Results = completions(
+      R"cpp(
+        namespace ns {
+          class X { public: X(); int x_; };
+          X::X() : x_^(0) {}
+        }
+      )cpp");
+  EXPECT_THAT(Results.Completions,
+              UnorderedElementsAre(AllOf(Scope("ns::X::"), Named("x_"))));
+}
+
+TEST(CompletionTest, CodeCompletionContext) {
+  auto Results = completions(
+      R"cpp(
+        namespace ns {
+          class X { public: X(); int x_; };
+          void f() {
+            X x;
+            x.^;
+          }
+        }
+      )cpp");
+
+  EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/CodeCompletionStringsTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/CodeCompletionStringsTests.cpp
new file mode 100644
index 0000000..a6038a7
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/CodeCompletionStringsTests.cpp
@@ -0,0 +1,114 @@
+//===-- CodeCompletionStringsTests.cpp --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeCompletionStrings.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+class CompletionStringTest : public ::testing::Test {
+public:
+  CompletionStringTest()
+      : Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
+        CCTUInfo(Allocator), Builder(*Allocator, CCTUInfo) {}
+
+protected:
+  void computeSignature(const CodeCompletionString &CCS) {
+    Signature.clear();
+    Snippet.clear();
+    getSignature(CCS, &Signature, &Snippet);
+  }
+
+  std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
+  CodeCompletionTUInfo CCTUInfo;
+  CodeCompletionBuilder Builder;
+  std::string Signature;
+  std::string Snippet;
+};
+
+TEST_F(CompletionStringTest, ReturnType) {
+  Builder.AddResultTypeChunk("result");
+  Builder.AddResultTypeChunk("redundant result no no");
+  EXPECT_EQ(getReturnType(*Builder.TakeString()), "result");
+}
+
+TEST_F(CompletionStringTest, Documentation) {
+  Builder.addBriefComment("This is ignored");
+  EXPECT_EQ(formatDocumentation(*Builder.TakeString(), "Is this brief?"),
+            "Is this brief?");
+}
+
+TEST_F(CompletionStringTest, DocumentationWithAnnotation) {
+  Builder.addBriefComment("This is ignored");
+  Builder.AddAnnotation("Ano");
+  EXPECT_EQ(formatDocumentation(*Builder.TakeString(), "Is this brief?"),
+            "Annotation: Ano\n\nIs this brief?");
+}
+
+TEST_F(CompletionStringTest, MultipleAnnotations) {
+  Builder.AddAnnotation("Ano1");
+  Builder.AddAnnotation("Ano2");
+  Builder.AddAnnotation("Ano3");
+
+  EXPECT_EQ(formatDocumentation(*Builder.TakeString(), ""),
+            "Annotations: Ano1 Ano2 Ano3\n");
+}
+
+TEST_F(CompletionStringTest, EmptySignature) {
+  Builder.AddTypedTextChunk("X");
+  Builder.AddResultTypeChunk("result no no");
+  computeSignature(*Builder.TakeString());
+  EXPECT_EQ(Signature, "");
+  EXPECT_EQ(Snippet, "");
+}
+
+TEST_F(CompletionStringTest, Function) {
+  Builder.AddResultTypeChunk("result no no");
+  Builder.addBriefComment("This comment is ignored");
+  Builder.AddTypedTextChunk("Foo");
+  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+  Builder.AddPlaceholderChunk("p1");
+  Builder.AddChunk(CodeCompletionString::CK_Comma);
+  Builder.AddPlaceholderChunk("p2");
+  Builder.AddChunk(CodeCompletionString::CK_RightParen);
+
+  auto *CCS = Builder.TakeString();
+  computeSignature(*CCS);
+  EXPECT_EQ(Signature, "(p1, p2)");
+  EXPECT_EQ(Snippet, "(${1:p1}, ${2:p2})");
+  EXPECT_EQ(formatDocumentation(*CCS, "Foo's comment"), "Foo's comment");
+}
+
+TEST_F(CompletionStringTest, EscapeSnippet) {
+  Builder.AddTypedTextChunk("Foo");
+  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+  Builder.AddPlaceholderChunk("$p}1\\");
+  Builder.AddChunk(CodeCompletionString::CK_RightParen);
+
+  computeSignature(*Builder.TakeString());
+  EXPECT_EQ(Signature, "($p}1\\)");
+  EXPECT_EQ(Snippet, "(${1:\\$p\\}1\\\\})");
+}
+
+TEST_F(CompletionStringTest, IgnoreInformativeQualifier) {
+  Builder.AddTypedTextChunk("X");
+  Builder.AddInformativeChunk("info ok");
+  Builder.AddInformativeChunk("info no no::");
+  computeSignature(*Builder.TakeString());
+  EXPECT_EQ(Signature, "info ok");
+  EXPECT_EQ(Snippet, "");
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/ContextTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/ContextTests.cpp
new file mode 100644
index 0000000..d5cb3ce
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/ContextTests.cpp
@@ -0,0 +1,57 @@
+//===-- ContextTests.cpp - Context tests ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Context.h"
+
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+
+TEST(ContextTests, Simple) {
+  Key<int> IntParam;
+  Key<int> ExtraIntParam;
+
+  Context Ctx = Context::empty().derive(IntParam, 10).derive(ExtraIntParam, 20);
+
+  EXPECT_EQ(*Ctx.get(IntParam), 10);
+  EXPECT_EQ(*Ctx.get(ExtraIntParam), 20);
+}
+
+TEST(ContextTests, MoveOps) {
+  Key<std::unique_ptr<int>> Param;
+
+  Context Ctx = Context::empty().derive(Param, llvm::make_unique<int>(10));
+  EXPECT_EQ(**Ctx.get(Param), 10);
+
+  Context NewCtx = std::move(Ctx);
+  EXPECT_EQ(**NewCtx.get(Param), 10);
+}
+
+TEST(ContextTests, Builders) {
+  Key<int> ParentParam;
+  Key<int> ParentAndChildParam;
+  Key<int> ChildParam;
+
+  Context ParentCtx =
+      Context::empty().derive(ParentParam, 10).derive(ParentAndChildParam, 20);
+  Context ChildCtx =
+      ParentCtx.derive(ParentAndChildParam, 30).derive(ChildParam, 40);
+
+  EXPECT_EQ(*ParentCtx.get(ParentParam), 10);
+  EXPECT_EQ(*ParentCtx.get(ParentAndChildParam), 20);
+  EXPECT_EQ(ParentCtx.get(ChildParam), nullptr);
+
+  EXPECT_EQ(*ChildCtx.get(ParentParam), 10);
+  EXPECT_EQ(*ChildCtx.get(ParentAndChildParam), 30);
+  EXPECT_EQ(*ChildCtx.get(ChildParam), 40);
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/DexIndexTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/DexIndexTests.cpp
new file mode 100644
index 0000000..906d62a
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/DexIndexTests.cpp
@@ -0,0 +1,317 @@
+//===-- DexIndexTests.cpp  ----------------------------*- C++ -*-----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "index/dex/Iterator.h"
+#include "index/dex/Token.h"
+#include "index/dex/Trigram.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace clangd {
+namespace dex {
+
+using ::testing::ElementsAre;
+
+TEST(DexIndexIterators, DocumentIterator) {
+  const PostingList L = {4, 7, 8, 20, 42, 100};
+  auto DocIterator = create(L);
+
+  EXPECT_EQ(DocIterator->peek(), 4U);
+  EXPECT_EQ(DocIterator->reachedEnd(), false);
+
+  DocIterator->advance();
+  EXPECT_EQ(DocIterator->peek(), 7U);
+  EXPECT_EQ(DocIterator->reachedEnd(), false);
+
+  DocIterator->advanceTo(20);
+  EXPECT_EQ(DocIterator->peek(), 20U);
+  EXPECT_EQ(DocIterator->reachedEnd(), false);
+
+  DocIterator->advanceTo(65);
+  EXPECT_EQ(DocIterator->peek(), 100U);
+  EXPECT_EQ(DocIterator->reachedEnd(), false);
+
+  DocIterator->advanceTo(420);
+  EXPECT_EQ(DocIterator->reachedEnd(), true);
+}
+
+TEST(DexIndexIterators, AndWithEmpty) {
+  const PostingList L0;
+  const PostingList L1 = {0, 5, 7, 10, 42, 320, 9000};
+
+  auto AndEmpty = createAnd(create(L0));
+  EXPECT_EQ(AndEmpty->reachedEnd(), true);
+
+  auto AndWithEmpty = createAnd(create(L0), create(L1));
+  EXPECT_EQ(AndWithEmpty->reachedEnd(), true);
+
+  EXPECT_THAT(consume(*AndWithEmpty), ElementsAre());
+}
+
+TEST(DexIndexIterators, AndTwoLists) {
+  const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
+  const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
+
+  auto And = createAnd(create(L1), create(L0));
+
+  EXPECT_EQ(And->reachedEnd(), false);
+  EXPECT_THAT(consume(*And), ElementsAre(0U, 7U, 10U, 320U, 9000U));
+
+  And = createAnd(create(L0), create(L1));
+
+  And->advanceTo(0);
+  EXPECT_EQ(And->peek(), 0U);
+  And->advanceTo(5);
+  EXPECT_EQ(And->peek(), 7U);
+  And->advanceTo(10);
+  EXPECT_EQ(And->peek(), 10U);
+  And->advanceTo(42);
+  EXPECT_EQ(And->peek(), 320U);
+  And->advanceTo(8999);
+  EXPECT_EQ(And->peek(), 9000U);
+  And->advanceTo(9001);
+}
+
+TEST(DexIndexIterators, AndThreeLists) {
+  const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
+  const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
+  const PostingList L2 = {1, 4, 7, 11, 30, 60, 320, 9000};
+
+  auto And = createAnd(create(L0), create(L1), create(L2));
+  EXPECT_EQ(And->peek(), 7U);
+  And->advanceTo(300);
+  EXPECT_EQ(And->peek(), 320U);
+  And->advanceTo(100000);
+
+  EXPECT_EQ(And->reachedEnd(), true);
+}
+
+TEST(DexIndexIterators, OrWithEmpty) {
+  const PostingList L0;
+  const PostingList L1 = {0, 5, 7, 10, 42, 320, 9000};
+
+  auto OrEmpty = createOr(create(L0));
+  EXPECT_EQ(OrEmpty->reachedEnd(), true);
+
+  auto OrWithEmpty = createOr(create(L0), create(L1));
+  EXPECT_EQ(OrWithEmpty->reachedEnd(), false);
+
+  EXPECT_THAT(consume(*OrWithEmpty),
+              ElementsAre(0U, 5U, 7U, 10U, 42U, 320U, 9000U));
+}
+
+TEST(DexIndexIterators, OrTwoLists) {
+  const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
+  const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
+
+  auto Or = createOr(create(L0), create(L1));
+
+  EXPECT_EQ(Or->reachedEnd(), false);
+  EXPECT_EQ(Or->peek(), 0U);
+  Or->advance();
+  EXPECT_EQ(Or->peek(), 4U);
+  Or->advance();
+  EXPECT_EQ(Or->peek(), 5U);
+  Or->advance();
+  EXPECT_EQ(Or->peek(), 7U);
+  Or->advance();
+  EXPECT_EQ(Or->peek(), 10U);
+  Or->advance();
+  EXPECT_EQ(Or->peek(), 30U);
+  Or->advanceTo(42);
+  EXPECT_EQ(Or->peek(), 42U);
+  Or->advanceTo(300);
+  EXPECT_EQ(Or->peek(), 320U);
+  Or->advanceTo(9000);
+  EXPECT_EQ(Or->peek(), 9000U);
+  Or->advanceTo(9001);
+  EXPECT_EQ(Or->reachedEnd(), true);
+
+  Or = createOr(create(L0), create(L1));
+
+  EXPECT_THAT(consume(*Or),
+              ElementsAre(0U, 4U, 5U, 7U, 10U, 30U, 42U, 60U, 320U, 9000U));
+}
+
+TEST(DexIndexIterators, OrThreeLists) {
+  const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
+  const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
+  const PostingList L2 = {1, 4, 7, 11, 30, 60, 320, 9000};
+
+  auto Or = createOr(create(L0), create(L1), create(L2));
+
+  EXPECT_EQ(Or->reachedEnd(), false);
+  EXPECT_EQ(Or->peek(), 0U);
+
+  Or->advance();
+  EXPECT_EQ(Or->peek(), 1U);
+
+  Or->advance();
+  EXPECT_EQ(Or->peek(), 4U);
+
+  Or->advanceTo(7);
+
+  Or->advanceTo(59);
+  EXPECT_EQ(Or->peek(), 60U);
+
+  Or->advanceTo(9001);
+  EXPECT_EQ(Or->reachedEnd(), true);
+}
+
+// FIXME(kbobyrev): The testcase below is similar to what is expected in real
+// queries. It should be updated once new iterators (such as boosting, limiting,
+// etc iterators) appear. However, it is not exhaustive and it would be
+// beneficial to implement automatic generation of query trees for more
+// comprehensive testing.
+TEST(DexIndexIterators, QueryTree) {
+  // An example of more complicated query
+  //
+  //                      +-----------------+
+  //                      |And Iterator:1, 5|
+  //                      +--------+--------+
+  //                               |
+  //                               |
+  //                 +------------------------------------+
+  //                 |                                    |
+  //                 |                                    |
+  //      +----------v----------+              +----------v---------+
+  //      |And Iterator: 1, 5, 9|              |Or Iterator: 0, 1, 5|
+  //      +----------+----------+              +----------+---------+
+  //                 |                                    |
+  //          +------+-----+                    +---------+-----------+
+  //          |            |                    |         |           |
+  //  +-------v-----+ +----v-----+           +--v--+    +-V--+    +---v---+
+  //  |1, 3, 5, 8, 9| |1, 5, 7, 9|           |Empty|    |0, 5|    |0, 1, 5|
+  //  +-------------+ +----------+           +-----+    +----+    +-------+
+
+  const PostingList L0 = {1, 3, 5, 8, 9};
+  const PostingList L1 = {1, 5, 7, 9};
+  const PostingList L2 = {0, 5};
+  const PostingList L3 = {0, 1, 5};
+  const PostingList L4;
+
+  // Root of the query tree: [1, 5]
+  auto Root = createAnd(
+      // Lower And Iterator: [1, 5, 9]
+      createAnd(create(L0), create(L1)),
+      // Lower Or Iterator: [0, 1, 5]
+      createOr(create(L2), create(L3), create(L4)));
+
+  EXPECT_EQ(Root->reachedEnd(), false);
+  EXPECT_EQ(Root->peek(), 1U);
+  Root->advanceTo(0);
+  // Advance multiple times. Shouldn't do anything.
+  Root->advanceTo(1);
+  Root->advanceTo(0);
+  EXPECT_EQ(Root->peek(), 1U);
+  Root->advance();
+  EXPECT_EQ(Root->peek(), 5U);
+  Root->advanceTo(5);
+  EXPECT_EQ(Root->peek(), 5U);
+  Root->advanceTo(9000);
+  EXPECT_EQ(Root->reachedEnd(), true);
+}
+
+TEST(DexIndexIterators, StringRepresentation) {
+  const PostingList L0 = {4, 7, 8, 20, 42, 100};
+  const PostingList L1 = {1, 3, 5, 8, 9};
+  const PostingList L2 = {1, 5, 7, 9};
+  const PostingList L3 = {0, 5};
+  const PostingList L4 = {0, 1, 5};
+  const PostingList L5;
+
+  EXPECT_EQ(llvm::to_string(*(create(L0))), "[4, 7, 8, 20, 42, 100]");
+
+  auto Nested = createAnd(createAnd(create(L1), create(L2)),
+                          createOr(create(L3), create(L4), create(L5)));
+
+  EXPECT_EQ(llvm::to_string(*Nested),
+            "(& (& [1, 3, 5, 8, 9] [1, 5, 7, 9]) (| [0, 5] [0, 1, 5] []))");
+}
+
+testing::Matcher<std::vector<Token>>
+trigramsAre(std::initializer_list<std::string> Trigrams) {
+  std::vector<Token> Tokens;
+  for (const auto &Symbols : Trigrams) {
+    Tokens.push_back(Token(Token::Kind::Trigram, Symbols));
+  }
+  return testing::UnorderedElementsAreArray(Tokens);
+}
+
+TEST(DexIndexTrigrams, IdentifierTrigrams) {
+  EXPECT_THAT(generateIdentifierTrigrams("X86"), trigramsAre({"x86"}));
+
+  EXPECT_THAT(generateIdentifierTrigrams("nl"), trigramsAre({}));
+
+  EXPECT_THAT(generateIdentifierTrigrams("clangd"),
+              trigramsAre({"cla", "lan", "ang", "ngd"}));
+
+  EXPECT_THAT(generateIdentifierTrigrams("abc_def"),
+              trigramsAre({"abc", "abd", "ade", "bcd", "bde", "cde", "def"}));
+
+  EXPECT_THAT(
+      generateIdentifierTrigrams("a_b_c_d_e_"),
+      trigramsAre({"abc", "abd", "acd", "ace", "bcd", "bce", "bde", "cde"}));
+
+  EXPECT_THAT(
+      generateIdentifierTrigrams("unique_ptr"),
+      trigramsAre({"uni", "unp", "upt", "niq", "nip", "npt", "iqu", "iqp",
+                   "ipt", "que", "qup", "qpt", "uep", "ept", "ptr"}));
+
+  EXPECT_THAT(generateIdentifierTrigrams("TUDecl"),
+              trigramsAre({"tud", "tde", "ude", "dec", "ecl"}));
+
+  EXPECT_THAT(generateIdentifierTrigrams("IsOK"),
+              trigramsAre({"iso", "iok", "sok"}));
+
+  EXPECT_THAT(generateIdentifierTrigrams("abc_defGhij__klm"),
+              trigramsAre({
+                  "abc", "abd", "abg", "ade", "adg", "adk", "agh", "agk", "bcd",
+                  "bcg", "bde", "bdg", "bdk", "bgh", "bgk", "cde", "cdg", "cdk",
+                  "cgh", "cgk", "def", "deg", "dek", "dgh", "dgk", "dkl", "efg",
+                  "efk", "egh", "egk", "ekl", "fgh", "fgk", "fkl", "ghi", "ghk",
+                  "gkl", "hij", "hik", "hkl", "ijk", "ikl", "jkl", "klm",
+              }));
+}
+
+TEST(DexIndexTrigrams, QueryTrigrams) {
+  EXPECT_THAT(generateQueryTrigrams("X86"), trigramsAre({"x86"}));
+
+  EXPECT_THAT(generateQueryTrigrams("nl"), trigramsAre({}));
+
+  EXPECT_THAT(generateQueryTrigrams("clangd"),
+              trigramsAre({"cla", "lan", "ang", "ngd"}));
+
+  EXPECT_THAT(generateQueryTrigrams("abc_def"),
+              trigramsAre({"abc", "bcd", "cde", "def"}));
+
+  EXPECT_THAT(generateQueryTrigrams("a_b_c_d_e_"),
+              trigramsAre({"abc", "bcd", "cde"}));
+
+  EXPECT_THAT(generateQueryTrigrams("unique_ptr"),
+              trigramsAre({"uni", "niq", "iqu", "que", "uep", "ept", "ptr"}));
+
+  EXPECT_THAT(generateQueryTrigrams("TUDecl"),
+              trigramsAre({"tud", "ude", "dec", "ecl"}));
+
+  EXPECT_THAT(generateQueryTrigrams("IsOK"), trigramsAre({"iso", "sok"}));
+
+  EXPECT_THAT(generateQueryTrigrams("abc_defGhij__klm"),
+              trigramsAre({"abc", "bcd", "cde", "def", "efg", "fgh", "ghi",
+                           "hij", "ijk", "jkl", "klm"}));
+}
+
+} // namespace dex
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/DraftStoreTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/DraftStoreTests.cpp
new file mode 100644
index 0000000..ad723a3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/DraftStoreTests.cpp
@@ -0,0 +1,350 @@
+//===-- DraftStoreTests.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Annotations.h"
+#include "DraftStore.h"
+#include "SourceCode.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+struct IncrementalTestStep {
+  StringRef Src;
+  StringRef Contents;
+};
+
+int rangeLength(StringRef Code, const Range &Rng) {
+  llvm::Expected<size_t> Start = positionToOffset(Code, Rng.start);
+  llvm::Expected<size_t> End = positionToOffset(Code, Rng.end);
+  assert(Start);
+  assert(End);
+  return *End - *Start;
+}
+
+/// Send the changes one by one to updateDraft, verify the intermediate results.
+void stepByStep(llvm::ArrayRef<IncrementalTestStep> Steps) {
+  DraftStore DS;
+  Annotations InitialSrc(Steps.front().Src);
+  constexpr llvm::StringLiteral Path("/hello.cpp");
+
+  // Set the initial content.
+  DS.addDraft(Path, InitialSrc.code());
+
+  for (size_t i = 1; i < Steps.size(); i++) {
+    Annotations SrcBefore(Steps[i - 1].Src);
+    Annotations SrcAfter(Steps[i].Src);
+    StringRef Contents = Steps[i - 1].Contents;
+    TextDocumentContentChangeEvent Event{
+        SrcBefore.range(),
+        rangeLength(SrcBefore.code(), SrcBefore.range()),
+        Contents.str(),
+    };
+
+    llvm::Expected<std::string> Result = DS.updateDraft(Path, {Event});
+    ASSERT_TRUE(!!Result);
+    EXPECT_EQ(*Result, SrcAfter.code());
+    EXPECT_EQ(*DS.getDraft(Path), SrcAfter.code());
+  }
+}
+
+/// Send all the changes at once to updateDraft, check only the final result.
+void allAtOnce(llvm::ArrayRef<IncrementalTestStep> Steps) {
+  DraftStore DS;
+  Annotations InitialSrc(Steps.front().Src);
+  Annotations FinalSrc(Steps.back().Src);
+  constexpr llvm::StringLiteral Path("/hello.cpp");
+  std::vector<TextDocumentContentChangeEvent> Changes;
+
+  for (size_t i = 0; i < Steps.size() - 1; i++) {
+    Annotations Src(Steps[i].Src);
+    StringRef Contents = Steps[i].Contents;
+
+    Changes.push_back({
+        Src.range(),
+        rangeLength(Src.code(), Src.range()),
+        Contents.str(),
+    });
+  }
+
+  // Set the initial content.
+  DS.addDraft(Path, InitialSrc.code());
+
+  llvm::Expected<std::string> Result = DS.updateDraft(Path, Changes);
+
+  ASSERT_TRUE(!!Result) << llvm::toString(Result.takeError());
+  EXPECT_EQ(*Result, FinalSrc.code());
+  EXPECT_EQ(*DS.getDraft(Path), FinalSrc.code());
+}
+
+TEST(DraftStoreIncrementalUpdateTest, Simple) {
+  // clang-format off
+  IncrementalTestStep Steps[] =
+    {
+      // Replace a range
+      {
+R"cpp(static int
+hello[[World]]()
+{})cpp",
+        "Universe"
+      },
+      // Delete a range
+      {
+R"cpp(static int
+hello[[Universe]]()
+{})cpp",
+        ""
+      },
+      // Add a range
+      {
+R"cpp(static int
+hello[[]]()
+{})cpp",
+        "Monde"
+      },
+      {
+R"cpp(static int
+helloMonde()
+{})cpp",
+        ""
+      }
+    };
+  // clang-format on
+
+  stepByStep(Steps);
+  allAtOnce(Steps);
+}
+
+TEST(DraftStoreIncrementalUpdateTest, MultiLine) {
+  // clang-format off
+  IncrementalTestStep Steps[] =
+    {
+      // Replace a range
+      {
+R"cpp(static [[int
+helloWorld]]()
+{})cpp",
+R"cpp(char
+welcome)cpp"
+      },
+      // Delete a range
+      {
+R"cpp(static char[[
+welcome]]()
+{})cpp",
+        ""
+      },
+      // Add a range
+      {
+R"cpp(static char[[]]()
+{})cpp",
+        R"cpp(
+cookies)cpp"
+      },
+      // Replace the whole file
+      {
+R"cpp([[static char
+cookies()
+{}]])cpp",
+        R"cpp(#include <stdio.h>
+)cpp"
+      },
+      // Delete the whole file
+      {
+        R"cpp([[#include <stdio.h>
+]])cpp",
+        "",
+      },
+      // Add something to an empty file
+      {
+        "[[]]",
+        R"cpp(int main() {
+)cpp",
+      },
+      {
+        R"cpp(int main() {
+)cpp",
+        ""
+      }
+    };
+  // clang-format on
+
+  stepByStep(Steps);
+  allAtOnce(Steps);
+}
+
+TEST(DraftStoreIncrementalUpdateTest, WrongRangeLength) {
+  DraftStore DS;
+  Path File = "foo.cpp";
+
+  DS.addDraft(File, "int main() {}\n");
+
+  TextDocumentContentChangeEvent Change;
+  Change.range.emplace();
+  Change.range->start.line = 0;
+  Change.range->start.character = 0;
+  Change.range->end.line = 0;
+  Change.range->end.character = 2;
+  Change.rangeLength = 10;
+
+  llvm::Expected<std::string> Result = DS.updateDraft(File, {Change});
+
+  EXPECT_TRUE(!Result);
+  EXPECT_EQ(
+      llvm::toString(Result.takeError()),
+      "Change's rangeLength (10) doesn't match the computed range length (2).");
+}
+
+TEST(DraftStoreIncrementalUpdateTest, EndBeforeStart) {
+  DraftStore DS;
+  Path File = "foo.cpp";
+
+  DS.addDraft(File, "int main() {}\n");
+
+  TextDocumentContentChangeEvent Change;
+  Change.range.emplace();
+  Change.range->start.line = 0;
+  Change.range->start.character = 5;
+  Change.range->end.line = 0;
+  Change.range->end.character = 3;
+
+  llvm::Expected<std::string> Result = DS.updateDraft(File, {Change});
+
+  EXPECT_TRUE(!Result);
+  EXPECT_EQ(llvm::toString(Result.takeError()),
+            "Range's end position (0:3) is before start position (0:5)");
+}
+
+TEST(DraftStoreIncrementalUpdateTest, StartCharOutOfRange) {
+  DraftStore DS;
+  Path File = "foo.cpp";
+
+  DS.addDraft(File, "int main() {}\n");
+
+  TextDocumentContentChangeEvent Change;
+  Change.range.emplace();
+  Change.range->start.line = 0;
+  Change.range->start.character = 100;
+  Change.range->end.line = 0;
+  Change.range->end.character = 100;
+  Change.text = "foo";
+
+  llvm::Expected<std::string> Result = DS.updateDraft(File, {Change});
+
+  EXPECT_TRUE(!Result);
+  EXPECT_EQ(llvm::toString(Result.takeError()),
+            "UTF-16 offset 100 is invalid for line 0");
+}
+
+TEST(DraftStoreIncrementalUpdateTest, EndCharOutOfRange) {
+  DraftStore DS;
+  Path File = "foo.cpp";
+
+  DS.addDraft(File, "int main() {}\n");
+
+  TextDocumentContentChangeEvent Change;
+  Change.range.emplace();
+  Change.range->start.line = 0;
+  Change.range->start.character = 0;
+  Change.range->end.line = 0;
+  Change.range->end.character = 100;
+  Change.text = "foo";
+
+  llvm::Expected<std::string> Result = DS.updateDraft(File, {Change});
+
+  EXPECT_TRUE(!Result);
+  EXPECT_EQ(llvm::toString(Result.takeError()),
+            "UTF-16 offset 100 is invalid for line 0");
+}
+
+TEST(DraftStoreIncrementalUpdateTest, StartLineOutOfRange) {
+  DraftStore DS;
+  Path File = "foo.cpp";
+
+  DS.addDraft(File, "int main() {}\n");
+
+  TextDocumentContentChangeEvent Change;
+  Change.range.emplace();
+  Change.range->start.line = 100;
+  Change.range->start.character = 0;
+  Change.range->end.line = 100;
+  Change.range->end.character = 0;
+  Change.text = "foo";
+
+  llvm::Expected<std::string> Result = DS.updateDraft(File, {Change});
+
+  EXPECT_TRUE(!Result);
+  EXPECT_EQ(llvm::toString(Result.takeError()),
+            "Line value is out of range (100)");
+}
+
+TEST(DraftStoreIncrementalUpdateTest, EndLineOutOfRange) {
+  DraftStore DS;
+  Path File = "foo.cpp";
+
+  DS.addDraft(File, "int main() {}\n");
+
+  TextDocumentContentChangeEvent Change;
+  Change.range.emplace();
+  Change.range->start.line = 0;
+  Change.range->start.character = 0;
+  Change.range->end.line = 100;
+  Change.range->end.character = 0;
+  Change.text = "foo";
+
+  llvm::Expected<std::string> Result = DS.updateDraft(File, {Change});
+
+  EXPECT_TRUE(!Result);
+  EXPECT_EQ(llvm::toString(Result.takeError()),
+            "Line value is out of range (100)");
+}
+
+/// Check that if a valid change is followed by an invalid change, the original
+/// version of the document (prior to all changes) is kept.
+TEST(DraftStoreIncrementalUpdateTest, InvalidRangeInASequence) {
+  DraftStore DS;
+  Path File = "foo.cpp";
+
+  StringRef OriginalContents = "int main() {}\n";
+  DS.addDraft(File, OriginalContents);
+
+  // The valid change
+  TextDocumentContentChangeEvent Change1;
+  Change1.range.emplace();
+  Change1.range->start.line = 0;
+  Change1.range->start.character = 0;
+  Change1.range->end.line = 0;
+  Change1.range->end.character = 0;
+  Change1.text = "Hello ";
+
+  // The invalid change
+  TextDocumentContentChangeEvent Change2;
+  Change2.range.emplace();
+  Change2.range->start.line = 0;
+  Change2.range->start.character = 5;
+  Change2.range->end.line = 0;
+  Change2.range->end.character = 100;
+  Change2.text = "something";
+
+  llvm::Expected<std::string> Result = DS.updateDraft(File, {Change1, Change2});
+
+  EXPECT_TRUE(!Result);
+  EXPECT_EQ(llvm::toString(Result.takeError()),
+            "UTF-16 offset 100 is invalid for line 0");
+
+  llvm::Optional<std::string> Contents = DS.getDraft(File);
+  EXPECT_TRUE(Contents);
+  EXPECT_EQ(*Contents, OriginalContents);
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/FileDistanceTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/FileDistanceTests.cpp
new file mode 100644
index 0000000..0d5afc9
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/FileDistanceTests.cpp
@@ -0,0 +1,99 @@
+//===-- FileDistanceTests.cpp  ------------------------*- C++ -*-----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FileDistance.h"
+#include "TestFS.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(FileDistanceTests, Distance) {
+  FileDistanceOptions Opts;
+  Opts.UpCost = 5;
+  Opts.DownCost = 3;
+  SourceParams CostTwo;
+  CostTwo.Cost = 2;
+  FileDistance D(
+      {{"tools/clang/lib/Format/FormatToken.cpp", SourceParams()},
+       {"tools/clang/include/clang/Format/FormatToken.h", SourceParams()},
+       {"include/llvm/ADT/StringRef.h", CostTwo}},
+      Opts);
+
+  // Source
+  EXPECT_EQ(D.distance("tools/clang/lib/Format/FormatToken.cpp"), 0u);
+  EXPECT_EQ(D.distance("include/llvm/ADT/StringRef.h"), 2u);
+  // Parent
+  EXPECT_EQ(D.distance("tools/clang/lib/Format/"), 5u);
+  // Child
+  EXPECT_EQ(D.distance("tools/clang/lib/Format/FormatToken.cpp/Oops"), 3u);
+  // Ancestor (up+up+up+up)
+  EXPECT_EQ(D.distance("/"), 22u);
+  // Sibling (up+down)
+  EXPECT_EQ(D.distance("tools/clang/lib/Format/AnotherFile.cpp"), 8u);
+  // Cousin (up+up+down+down)
+  EXPECT_EQ(D.distance("include/llvm/Support/Allocator.h"), 18u);
+  // First cousin, once removed (up+up+up+down+down)
+  EXPECT_EQ(D.distance("include/llvm-c/Core.h"), 23u);
+}
+
+TEST(FileDistanceTests, BadSource) {
+  // We mustn't assume that paths above sources are best reached via them.
+  FileDistanceOptions Opts;
+  Opts.UpCost = 5;
+  Opts.DownCost = 3;
+  SourceParams CostLots;
+  CostLots.Cost = 100;
+  FileDistance D({{"a", SourceParams()}, {"b/b/b", CostLots}}, Opts);
+  EXPECT_EQ(D.distance("b"), 8u);        // a+up+down, not b+up+up
+  EXPECT_EQ(D.distance("b/b/b"), 14u);   // a+up+down+down+down, not b
+  EXPECT_EQ(D.distance("b/b/b/c"), 17u); // a+up+down+down+down+down, not b+down
+}
+
+auto UseUnittestScheme = UnittestSchemeAnchorSource;
+
+TEST(FileDistanceTests, URI) {
+  FileDistanceOptions Opts;
+  Opts.UpCost = 5;
+  Opts.DownCost = 3;
+  SourceParams CostLots;
+  CostLots.Cost = 1000;
+
+  URIDistance D({{testPath("foo"), CostLots},
+                 {"/not/a/testpath", SourceParams()},
+                 {"C:\\not\\a\\testpath", SourceParams()}},
+                Opts);
+#ifdef _WIN32
+  EXPECT_EQ(D.distance("file:///C%3a/not/a/testpath/either"), 3u);
+#else
+  EXPECT_EQ(D.distance("file:///not/a/testpath/either"), 3u);
+#endif
+  EXPECT_EQ(D.distance("unittest:///foo"), 1000u);
+  EXPECT_EQ(D.distance("unittest:///bar"), 1008u);
+}
+
+TEST(FileDistance, LimitUpTraversals) {
+  FileDistanceOptions Opts;
+  Opts.UpCost = Opts.DownCost = 1;
+  SourceParams CheapButLimited, CostLots;
+  CheapButLimited.MaxUpTraversals = 1;
+  CostLots.Cost = 100;
+
+  FileDistance D({{"/", CostLots}, {"/a/b/c", CheapButLimited}}, Opts);
+  EXPECT_EQ(D.distance("/a"), 101u);
+  EXPECT_EQ(D.distance("/a/z"), 102u);
+  EXPECT_EQ(D.distance("/a/b"), 1u);
+  EXPECT_EQ(D.distance("/a/b/z"), 2u);
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/FileIndexTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/FileIndexTests.cpp
new file mode 100644
index 0000000..08e8568
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/FileIndexTests.cpp
@@ -0,0 +1,275 @@
+//===-- FileIndexTests.cpp  ---------------------------*- C++ -*-----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangdUnit.h"
+#include "TestFS.h"
+#include "TestTU.h"
+#include "index/FileIndex.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using testing::UnorderedElementsAre;
+
+namespace clang {
+namespace clangd {
+
+namespace {
+
+Symbol symbol(llvm::StringRef ID) {
+  Symbol Sym;
+  Sym.ID = SymbolID(ID);
+  Sym.Name = ID;
+  return Sym;
+}
+
+std::unique_ptr<SymbolSlab> numSlab(int Begin, int End) {
+  SymbolSlab::Builder Slab;
+  for (int i = Begin; i <= End; i++)
+    Slab.insert(symbol(std::to_string(i)));
+  return llvm::make_unique<SymbolSlab>(std::move(Slab).build());
+}
+
+std::vector<std::string>
+getSymbolNames(const std::vector<const Symbol *> &Symbols) {
+  std::vector<std::string> Names;
+  for (const Symbol *Sym : Symbols)
+    Names.push_back(Sym->Name);
+  return Names;
+}
+
+TEST(FileSymbolsTest, UpdateAndGet) {
+  FileSymbols FS;
+  EXPECT_THAT(getSymbolNames(*FS.allSymbols()), UnorderedElementsAre());
+
+  FS.update("f1", numSlab(1, 3));
+  EXPECT_THAT(getSymbolNames(*FS.allSymbols()),
+              UnorderedElementsAre("1", "2", "3"));
+}
+
+TEST(FileSymbolsTest, Overlap) {
+  FileSymbols FS;
+  FS.update("f1", numSlab(1, 3));
+  FS.update("f2", numSlab(3, 5));
+  EXPECT_THAT(getSymbolNames(*FS.allSymbols()),
+              UnorderedElementsAre("1", "2", "3", "3", "4", "5"));
+}
+
+TEST(FileSymbolsTest, SnapshotAliveAfterRemove) {
+  FileSymbols FS;
+
+  FS.update("f1", numSlab(1, 3));
+
+  auto Symbols = FS.allSymbols();
+  EXPECT_THAT(getSymbolNames(*Symbols), UnorderedElementsAre("1", "2", "3"));
+
+  FS.update("f1", nullptr);
+  EXPECT_THAT(getSymbolNames(*FS.allSymbols()), UnorderedElementsAre());
+  EXPECT_THAT(getSymbolNames(*Symbols), UnorderedElementsAre("1", "2", "3"));
+}
+
+std::vector<std::string> match(const SymbolIndex &I,
+                               const FuzzyFindRequest &Req) {
+  std::vector<std::string> Matches;
+  I.fuzzyFind(Req, [&](const Symbol &Sym) {
+    Matches.push_back((Sym.Scope + Sym.Name).str());
+  });
+  return Matches;
+}
+
+// Adds Basename.cpp, which includes Basename.h, which contains Code.
+void update(FileIndex &M, llvm::StringRef Basename, llvm::StringRef Code) {
+  TestTU File;
+  File.Filename = (Basename + ".cpp").str();
+  File.HeaderFilename = (Basename + ".h").str();
+  File.HeaderCode = Code;
+  auto AST = File.build();
+  M.update(File.Filename, &AST.getASTContext(), AST.getPreprocessorPtr());
+}
+
+TEST(FileIndexTest, CustomizedURIScheme) {
+  FileIndex M({"unittest"});
+  update(M, "f", "class string {};");
+
+  FuzzyFindRequest Req;
+  Req.Query = "";
+  bool SeenSymbol = false;
+  M.fuzzyFind(Req, [&](const Symbol &Sym) {
+    EXPECT_EQ(Sym.CanonicalDeclaration.FileURI, "unittest:///f.h");
+    SeenSymbol = true;
+  });
+  EXPECT_TRUE(SeenSymbol);
+}
+
+TEST(FileIndexTest, IndexAST) {
+  FileIndex M;
+  update(M, "f1", "namespace ns { void f() {} class X {}; }");
+
+  FuzzyFindRequest Req;
+  Req.Query = "";
+  Req.Scopes = {"ns::"};
+  EXPECT_THAT(match(M, Req), UnorderedElementsAre("ns::f", "ns::X"));
+}
+
+TEST(FileIndexTest, NoLocal) {
+  FileIndex M;
+  update(M, "f1", "namespace ns { void f() { int local = 0; } class X {}; }");
+
+  FuzzyFindRequest Req;
+  Req.Query = "";
+  EXPECT_THAT(match(M, Req), UnorderedElementsAre("ns", "ns::f", "ns::X"));
+}
+
+TEST(FileIndexTest, IndexMultiASTAndDeduplicate) {
+  FileIndex M;
+  update(M, "f1", "namespace ns { void f() {} class X {}; }");
+  update(M, "f2", "namespace ns { void ff() {} class X {}; }");
+
+  FuzzyFindRequest Req;
+  Req.Query = "";
+  Req.Scopes = {"ns::"};
+  EXPECT_THAT(match(M, Req), UnorderedElementsAre("ns::f", "ns::X", "ns::ff"));
+}
+
+TEST(FileIndexTest, RemoveAST) {
+  FileIndex M;
+  update(M, "f1", "namespace ns { void f() {} class X {}; }");
+
+  FuzzyFindRequest Req;
+  Req.Query = "";
+  Req.Scopes = {"ns::"};
+  EXPECT_THAT(match(M, Req), UnorderedElementsAre("ns::f", "ns::X"));
+
+  M.update("f1.cpp", nullptr, nullptr);
+  EXPECT_THAT(match(M, Req), UnorderedElementsAre());
+}
+
+TEST(FileIndexTest, RemoveNonExisting) {
+  FileIndex M;
+  M.update("no.cpp", nullptr, nullptr);
+  EXPECT_THAT(match(M, FuzzyFindRequest()), UnorderedElementsAre());
+}
+
+TEST(FileIndexTest, ClassMembers) {
+  FileIndex M;
+  update(M, "f1", "class X { static int m1; int m2; static void f(); };");
+
+  FuzzyFindRequest Req;
+  Req.Query = "";
+  EXPECT_THAT(match(M, Req),
+              UnorderedElementsAre("X", "X::m1", "X::m2", "X::f"));
+}
+
+TEST(FileIndexTest, NoIncludeCollected) {
+  FileIndex M;
+  update(M, "f", "class string {};");
+
+  FuzzyFindRequest Req;
+  Req.Query = "";
+  bool SeenSymbol = false;
+  M.fuzzyFind(Req, [&](const Symbol &Sym) {
+    EXPECT_TRUE(Sym.Detail->IncludeHeader.empty());
+    SeenSymbol = true;
+  });
+  EXPECT_TRUE(SeenSymbol);
+}
+
+TEST(FileIndexTest, TemplateParamsInLabel) {
+  auto Source = R"cpp(
+template <class Ty>
+class vector {
+};
+
+template <class Ty, class Arg>
+vector<Ty> make_vector(Arg A) {}
+)cpp";
+
+  FileIndex M;
+  update(M, "f", Source);
+
+  FuzzyFindRequest Req;
+  Req.Query = "";
+  bool SeenVector = false;
+  bool SeenMakeVector = false;
+  M.fuzzyFind(Req, [&](const Symbol &Sym) {
+    if (Sym.Name == "vector") {
+      EXPECT_EQ(Sym.Signature, "<class Ty>");
+      EXPECT_EQ(Sym.CompletionSnippetSuffix, "<${1:class Ty}>");
+      SeenVector = true;
+      return;
+    }
+
+    if (Sym.Name == "make_vector") {
+      EXPECT_EQ(Sym.Signature, "<class Ty>(Arg A)");
+      EXPECT_EQ(Sym.CompletionSnippetSuffix, "<${1:class Ty}>(${2:Arg A})");
+      SeenMakeVector = true;
+    }
+  });
+  EXPECT_TRUE(SeenVector);
+  EXPECT_TRUE(SeenMakeVector);
+}
+
+TEST(FileIndexTest, RebuildWithPreamble) {
+  auto FooCpp = testPath("foo.cpp");
+  auto FooH = testPath("foo.h");
+  // Preparse ParseInputs.
+  ParseInputs PI;
+  PI.CompileCommand.Directory = testRoot();
+  PI.CompileCommand.Filename = FooCpp;
+  PI.CompileCommand.CommandLine = {"clang", "-xc++", FooCpp};
+
+  llvm::StringMap<std::string> Files;
+  Files[FooCpp] = "";
+  Files[FooH] = R"cpp(
+    namespace ns_in_header {
+      int func_in_header();
+    }
+  )cpp";
+  PI.FS = buildTestFS(std::move(Files));
+
+  PI.Contents = R"cpp(
+    #include "foo.h"
+    namespace ns_in_source {
+      int func_in_source();
+    }
+  )cpp";
+
+  // Rebuild the file.
+  auto CI = buildCompilerInvocation(PI);
+
+  FileIndex Index;
+  bool IndexUpdated = false;
+  buildPreamble(
+      FooCpp, *CI, /*OldPreamble=*/nullptr, tooling::CompileCommand(), PI,
+      std::make_shared<PCHContainerOperations>(), /*StoreInMemory=*/true,
+      [&Index, &IndexUpdated](PathRef FilePath, ASTContext &Ctx,
+                              std::shared_ptr<Preprocessor> PP) {
+        EXPECT_FALSE(IndexUpdated) << "Expected only a single index update";
+        IndexUpdated = true;
+        Index.update(FilePath, &Ctx, std::move(PP));
+      });
+  ASSERT_TRUE(IndexUpdated);
+
+  // Check the index contains symbols from the preamble, but not from the main
+  // file.
+  FuzzyFindRequest Req;
+  Req.Query = "";
+  Req.Scopes = {"", "ns_in_header::"};
+
+  EXPECT_THAT(
+      match(Index, Req),
+      UnorderedElementsAre("ns_in_header", "ns_in_header::func_in_header"));
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp
new file mode 100644
index 0000000..068660d
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp
@@ -0,0 +1,562 @@
+//===-- FindSymbolsTests.cpp -------------------------*- C++ -*------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "Annotations.h"
+#include "ClangdServer.h"
+#include "FindSymbols.h"
+#include "SyncAPI.h"
+#include "TestFS.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+
+namespace {
+
+using ::testing::AllOf;
+using ::testing::AnyOf;
+using ::testing::ElementsAre;
+using ::testing::ElementsAreArray;
+using ::testing::IsEmpty;
+using ::testing::UnorderedElementsAre;
+
+class IgnoreDiagnostics : public DiagnosticsConsumer {
+  void onDiagnosticsReady(PathRef File,
+                          std::vector<Diag> Diagnostics) override {}
+};
+
+// GMock helpers for matching SymbolInfos items.
+MATCHER_P(QName, Name, "") {
+  if (arg.containerName.empty())
+    return arg.name == Name;
+  return (arg.containerName + "::" + arg.name) == Name;
+}
+MATCHER_P(WithKind, Kind, "") { return arg.kind == Kind; }
+MATCHER_P(SymRange, Range, "") { return arg.location.range == Range; }
+
+ClangdServer::Options optsForTests() {
+  auto ServerOpts = ClangdServer::optsForTest();
+  ServerOpts.BuildDynamicSymbolIndex = true;
+  ServerOpts.URISchemes = {"unittest", "file"};
+  return ServerOpts;
+}
+
+class WorkspaceSymbolsTest : public ::testing::Test {
+public:
+  WorkspaceSymbolsTest()
+      : Server(CDB, FSProvider, DiagConsumer, optsForTests()) {
+    // Make sure the test root directory is created.
+    FSProvider.Files[testPath("unused")] = "";
+    Server.setRootPath(testRoot());
+  }
+
+protected:
+  MockFSProvider FSProvider;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server;
+  int Limit = 0;
+
+  std::vector<SymbolInformation> getSymbols(StringRef Query) {
+    EXPECT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for preamble";
+    auto SymbolInfos = runWorkspaceSymbols(Server, Query, Limit);
+    EXPECT_TRUE(bool(SymbolInfos)) << "workspaceSymbols returned an error";
+    return *SymbolInfos;
+  }
+
+  void addFile(StringRef FileName, StringRef Contents) {
+    auto Path = testPath(FileName);
+    FSProvider.Files[Path] = Contents;
+    Server.addDocument(Path, Contents);
+  }
+};
+
+} // namespace
+
+TEST_F(WorkspaceSymbolsTest, NoMacro) {
+  addFile("foo.cpp", R"cpp(
+      #define MACRO X
+      )cpp");
+
+  // Macros are not in the index.
+  EXPECT_THAT(getSymbols("macro"), IsEmpty());
+}
+
+TEST_F(WorkspaceSymbolsTest, NoLocals) {
+  addFile("foo.cpp", R"cpp(
+      void test(int FirstParam, int SecondParam) {
+        struct LocalClass {};
+        int local_var;
+      })cpp");
+  EXPECT_THAT(getSymbols("l"), IsEmpty());
+  EXPECT_THAT(getSymbols("p"), IsEmpty());
+}
+
+TEST_F(WorkspaceSymbolsTest, Globals) {
+  addFile("foo.h", R"cpp(
+      int global_var;
+
+      int global_func();
+
+      struct GlobalStruct {};)cpp");
+  addFile("foo.cpp", R"cpp(
+      #include "foo.h"
+      )cpp");
+  EXPECT_THAT(getSymbols("global"),
+              UnorderedElementsAre(
+                  AllOf(QName("GlobalStruct"), WithKind(SymbolKind::Struct)),
+                  AllOf(QName("global_func"), WithKind(SymbolKind::Function)),
+                  AllOf(QName("global_var"), WithKind(SymbolKind::Variable))));
+}
+
+TEST_F(WorkspaceSymbolsTest, Unnamed) {
+  addFile("foo.h", R"cpp(
+      struct {
+        int InUnnamed;
+      } UnnamedStruct;)cpp");
+  addFile("foo.cpp", R"cpp(
+      #include "foo.h"
+      )cpp");
+  EXPECT_THAT(getSymbols("UnnamedStruct"),
+              ElementsAre(AllOf(QName("UnnamedStruct"),
+                                WithKind(SymbolKind::Variable))));
+  EXPECT_THAT(getSymbols("InUnnamed"),
+              ElementsAre(AllOf(QName("(anonymous struct)::InUnnamed"),
+                                WithKind(SymbolKind::Field))));
+}
+
+TEST_F(WorkspaceSymbolsTest, InMainFile) {
+  addFile("foo.cpp", R"cpp(
+      int test() {
+      }
+      )cpp");
+  EXPECT_THAT(getSymbols("test"), IsEmpty());
+}
+
+TEST_F(WorkspaceSymbolsTest, Namespaces) {
+  addFile("foo.h", R"cpp(
+      namespace ans1 {
+        int ai1;
+      namespace ans2 {
+        int ai2;
+      }
+      }
+      )cpp");
+  addFile("foo.cpp", R"cpp(
+      #include "foo.h"
+      )cpp");
+  EXPECT_THAT(getSymbols("a"),
+              UnorderedElementsAre(QName("ans1"), QName("ans1::ai1"),
+                                   QName("ans1::ans2"),
+                                   QName("ans1::ans2::ai2")));
+  EXPECT_THAT(getSymbols("::"), ElementsAre(QName("ans1")));
+  EXPECT_THAT(getSymbols("::a"), ElementsAre(QName("ans1")));
+  EXPECT_THAT(getSymbols("ans1::"),
+              UnorderedElementsAre(QName("ans1::ai1"), QName("ans1::ans2")));
+  EXPECT_THAT(getSymbols("::ans1"), ElementsAre(QName("ans1")));
+  EXPECT_THAT(getSymbols("::ans1::"),
+              UnorderedElementsAre(QName("ans1::ai1"), QName("ans1::ans2")));
+  EXPECT_THAT(getSymbols("::ans1::ans2"), ElementsAre(QName("ans1::ans2")));
+  EXPECT_THAT(getSymbols("::ans1::ans2::"),
+              ElementsAre(QName("ans1::ans2::ai2")));
+}
+
+TEST_F(WorkspaceSymbolsTest, AnonymousNamespace) {
+  addFile("foo.h", R"cpp(
+      namespace {
+      void test() {}
+      }
+      )cpp");
+  addFile("foo.cpp", R"cpp(
+      #include "foo.h"
+      )cpp");
+  EXPECT_THAT(getSymbols("test"), IsEmpty());
+}
+
+TEST_F(WorkspaceSymbolsTest, MultiFile) {
+  addFile("foo.h", R"cpp(
+      int foo() {
+      }
+      )cpp");
+  addFile("foo2.h", R"cpp(
+      int foo2() {
+      }
+      )cpp");
+  addFile("foo.cpp", R"cpp(
+      #include "foo.h"
+      #include "foo2.h"
+      )cpp");
+  EXPECT_THAT(getSymbols("foo"),
+              UnorderedElementsAre(QName("foo"), QName("foo2")));
+}
+
+TEST_F(WorkspaceSymbolsTest, GlobalNamespaceQueries) {
+  addFile("foo.h", R"cpp(
+      int foo() {
+      }
+      class Foo {
+        int a;
+      };
+      namespace ns {
+      int foo2() {
+      }
+      }
+      )cpp");
+  addFile("foo.cpp", R"cpp(
+      #include "foo.h"
+      )cpp");
+  EXPECT_THAT(getSymbols("::"),
+              UnorderedElementsAre(
+                  AllOf(QName("Foo"), WithKind(SymbolKind::Class)),
+                  AllOf(QName("foo"), WithKind(SymbolKind::Function)),
+                  AllOf(QName("ns"), WithKind(SymbolKind::Namespace))));
+  EXPECT_THAT(getSymbols(":"), IsEmpty());
+  EXPECT_THAT(getSymbols(""), IsEmpty());
+}
+
+TEST_F(WorkspaceSymbolsTest, Enums) {
+  addFile("foo.h", R"cpp(
+    enum {
+      Red
+    };
+    enum Color {
+      Green
+    };
+    enum class Color2 {
+      Yellow
+    };
+    namespace ns {
+      enum {
+        Black
+      };
+      enum Color3 {
+        Blue
+      };
+      enum class Color4 {
+        White
+      };
+    }
+      )cpp");
+  addFile("foo.cpp", R"cpp(
+      #include "foo.h"
+      )cpp");
+  EXPECT_THAT(getSymbols("Red"), ElementsAre(QName("Red")));
+  EXPECT_THAT(getSymbols("::Red"), ElementsAre(QName("Red")));
+  EXPECT_THAT(getSymbols("Green"), ElementsAre(QName("Green")));
+  EXPECT_THAT(getSymbols("Green"), ElementsAre(QName("Green")));
+  EXPECT_THAT(getSymbols("Color2::Yellow"),
+              ElementsAre(QName("Color2::Yellow")));
+  EXPECT_THAT(getSymbols("Yellow"), ElementsAre(QName("Color2::Yellow")));
+
+  EXPECT_THAT(getSymbols("ns::Black"), ElementsAre(QName("ns::Black")));
+  EXPECT_THAT(getSymbols("ns::Blue"), ElementsAre(QName("ns::Blue")));
+  EXPECT_THAT(getSymbols("ns::Color4::White"),
+              ElementsAre(QName("ns::Color4::White")));
+}
+
+TEST_F(WorkspaceSymbolsTest, Ranking) {
+  addFile("foo.h", R"cpp(
+      namespace ns{}
+      function func();
+      )cpp");
+  addFile("foo.cpp", R"cpp(
+      #include "foo.h"
+      )cpp");
+  EXPECT_THAT(getSymbols("::"), ElementsAre(QName("func"), QName("ns")));
+}
+
+TEST_F(WorkspaceSymbolsTest, WithLimit) {
+  addFile("foo.h", R"cpp(
+      int foo;
+      int foo2;
+      )cpp");
+  addFile("foo.cpp", R"cpp(
+      #include "foo.h"
+      )cpp");
+  // Foo is higher ranked because of exact name match.
+  EXPECT_THAT(getSymbols("foo"),
+              UnorderedElementsAre(
+                  AllOf(QName("foo"), WithKind(SymbolKind::Variable)),
+                  AllOf(QName("foo2"), WithKind(SymbolKind::Variable))));
+
+  Limit = 1;
+  EXPECT_THAT(getSymbols("foo"), ElementsAre(QName("foo")));
+}
+
+namespace {
+class DocumentSymbolsTest : public ::testing::Test {
+public:
+  DocumentSymbolsTest()
+      : Server(CDB, FSProvider, DiagConsumer, optsForTests()) {}
+
+protected:
+  MockFSProvider FSProvider;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server;
+
+  std::vector<SymbolInformation> getSymbols(PathRef File) {
+    EXPECT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for preamble";
+    auto SymbolInfos = runDocumentSymbols(Server, File);
+    EXPECT_TRUE(bool(SymbolInfos)) << "documentSymbols returned an error";
+    return *SymbolInfos;
+  }
+
+  void addFile(StringRef FilePath, StringRef Contents) {
+    FSProvider.Files[FilePath] = Contents;
+    Server.addDocument(FilePath, Contents);
+  }
+};
+} // namespace
+
+TEST_F(DocumentSymbolsTest, BasicSymbols) {
+  std::string FilePath = testPath("foo.cpp");
+  Annotations Main(R"(
+      class Foo;
+      class Foo {
+        Foo() {}
+        Foo(int a) {}
+        void $decl[[f]]();
+        friend void f1();
+        friend class Friend;
+        Foo& operator=(const Foo&);
+        ~Foo();
+        class Nested {
+        void f();
+        };
+      };
+      class Friend {
+      };
+
+      void f1();
+      inline void f2() {}
+      static const int KInt = 2;
+      const char* kStr = "123";
+
+      void f1() {}
+
+      namespace foo {
+      // Type alias
+      typedef int int32;
+      using int32_t = int32;
+
+      // Variable
+      int v1;
+
+      // Namespace
+      namespace bar {
+      int v2;
+      }
+      // Namespace alias
+      namespace baz = bar;
+
+      // FIXME: using declaration is not supported as the IndexAction will ignore
+      // implicit declarations (the implicit using shadow declaration) by default,
+      // and there is no way to customize this behavior at the moment.
+      using bar::v2;
+      } // namespace foo
+    )");
+
+  addFile(FilePath, Main.code());
+  EXPECT_THAT(getSymbols(FilePath),
+              ElementsAreArray(
+                  {AllOf(QName("Foo"), WithKind(SymbolKind::Class)),
+                   AllOf(QName("Foo"), WithKind(SymbolKind::Class)),
+                   AllOf(QName("Foo::Foo"), WithKind(SymbolKind::Method)),
+                   AllOf(QName("Foo::Foo"), WithKind(SymbolKind::Method)),
+                   AllOf(QName("Foo::f"), WithKind(SymbolKind::Method)),
+                   AllOf(QName("f1"), WithKind(SymbolKind::Function)),
+                   AllOf(QName("Foo::operator="), WithKind(SymbolKind::Method)),
+                   AllOf(QName("Foo::~Foo"), WithKind(SymbolKind::Method)),
+                   AllOf(QName("Foo::Nested"), WithKind(SymbolKind::Class)),
+                   AllOf(QName("Foo::Nested::f"), WithKind(SymbolKind::Method)),
+                   AllOf(QName("Friend"), WithKind(SymbolKind::Class)),
+                   AllOf(QName("f1"), WithKind(SymbolKind::Function)),
+                   AllOf(QName("f2"), WithKind(SymbolKind::Function)),
+                   AllOf(QName("KInt"), WithKind(SymbolKind::Variable)),
+                   AllOf(QName("kStr"), WithKind(SymbolKind::Variable)),
+                   AllOf(QName("f1"), WithKind(SymbolKind::Function)),
+                   AllOf(QName("foo"), WithKind(SymbolKind::Namespace)),
+                   AllOf(QName("foo::int32"), WithKind(SymbolKind::Class)),
+                   AllOf(QName("foo::int32_t"), WithKind(SymbolKind::Class)),
+                   AllOf(QName("foo::v1"), WithKind(SymbolKind::Variable)),
+                   AllOf(QName("foo::bar"), WithKind(SymbolKind::Namespace)),
+                   AllOf(QName("foo::bar::v2"), WithKind(SymbolKind::Variable)),
+                   AllOf(QName("foo::baz"), WithKind(SymbolKind::Namespace))}));
+}
+
+TEST_F(DocumentSymbolsTest, DeclarationDefinition) {
+  std::string FilePath = testPath("foo.cpp");
+  Annotations Main(R"(
+      class Foo {
+        void $decl[[f]]();
+      };
+      void Foo::$def[[f]]() {
+      }
+    )");
+
+  addFile(FilePath, Main.code());
+  EXPECT_THAT(getSymbols(FilePath),
+              ElementsAre(AllOf(QName("Foo"), WithKind(SymbolKind::Class)),
+                          AllOf(QName("Foo::f"), WithKind(SymbolKind::Method),
+                                SymRange(Main.range("decl"))),
+                          AllOf(QName("Foo::f"), WithKind(SymbolKind::Method),
+                                SymRange(Main.range("def")))));
+}
+
+TEST_F(DocumentSymbolsTest, ExternSymbol) {
+  std::string FilePath = testPath("foo.cpp");
+  addFile(testPath("foo.h"), R"cpp(
+      extern int var = 2;
+      )cpp");
+  addFile(FilePath, R"cpp(
+      #include "foo.h"
+      )cpp");
+
+  EXPECT_THAT(getSymbols(FilePath), IsEmpty());
+}
+
+TEST_F(DocumentSymbolsTest, NoLocals) {
+  std::string FilePath = testPath("foo.cpp");
+  addFile(FilePath,
+          R"cpp(
+      void test(int FirstParam, int SecondParam) {
+        struct LocalClass {};
+        int local_var;
+      })cpp");
+  EXPECT_THAT(getSymbols(FilePath), ElementsAre(QName("test")));
+}
+
+TEST_F(DocumentSymbolsTest, Unnamed) {
+  std::string FilePath = testPath("foo.h");
+  addFile(FilePath,
+          R"cpp(
+      struct {
+        int InUnnamed;
+      } UnnamedStruct;
+      )cpp");
+  EXPECT_THAT(
+      getSymbols(FilePath),
+      ElementsAre(AllOf(QName("UnnamedStruct"), WithKind(SymbolKind::Variable)),
+                  AllOf(QName("(anonymous struct)::InUnnamed"),
+                        WithKind(SymbolKind::Field))));
+}
+
+TEST_F(DocumentSymbolsTest, InHeaderFile) {
+  addFile("bar.h", R"cpp(
+      int foo() {
+      }
+      )cpp");
+  std::string FilePath = testPath("foo.h");
+  addFile(FilePath, R"cpp(
+      #include "bar.h"
+      int test() {
+      }
+      )cpp");
+  addFile("foo.cpp", R"cpp(
+      #include "foo.h"
+      )cpp");
+  EXPECT_THAT(getSymbols(FilePath), ElementsAre(QName("test")));
+}
+
+TEST_F(DocumentSymbolsTest, Template) {
+  std::string FilePath = testPath("foo.cpp");
+  addFile(FilePath, R"(
+    // Primary templates and specializations are included but instantiations
+    // are not.
+    template <class T> struct Tmpl {T x = 0;};
+    template <> struct Tmpl<int> {};
+    extern template struct Tmpl<float>;
+    template struct Tmpl<double>;
+  )");
+  EXPECT_THAT(getSymbols(FilePath),
+              ElementsAre(AllOf(QName("Tmpl"), WithKind(SymbolKind::Struct)),
+                          AllOf(QName("Tmpl::x"), WithKind(SymbolKind::Field)),
+                          AllOf(QName("Tmpl"), WithKind(SymbolKind::Struct))));
+}
+
+TEST_F(DocumentSymbolsTest, Namespaces) {
+  std::string FilePath = testPath("foo.cpp");
+  addFile(FilePath, R"cpp(
+      namespace ans1 {
+        int ai1;
+      namespace ans2 {
+        int ai2;
+      }
+      }
+      namespace {
+      void test() {}
+      }
+
+      namespace na {
+      inline namespace nb {
+      class Foo {};
+      }
+      }
+      namespace na {
+      // This is still inlined.
+      namespace nb {
+      class Bar {};
+      }
+      }
+      )cpp");
+  EXPECT_THAT(
+      getSymbols(FilePath),
+      ElementsAreArray({QName("ans1"), QName("ans1::ai1"), QName("ans1::ans2"),
+                        QName("ans1::ans2::ai2"), QName("test"), QName("na"),
+                        QName("na::nb"), QName("na::Foo"), QName("na"),
+                        QName("na::nb"), QName("na::Bar")}));
+}
+
+TEST_F(DocumentSymbolsTest, Enums) {
+  std::string FilePath = testPath("foo.cpp");
+  addFile(FilePath, R"(
+      enum {
+        Red
+      };
+      enum Color {
+        Green
+      };
+      enum class Color2 {
+        Yellow
+      };
+      namespace ns {
+      enum {
+        Black
+      };
+      }
+    )");
+  EXPECT_THAT(getSymbols(FilePath),
+              ElementsAre(QName("Red"), QName("Color"), QName("Green"),
+                          QName("Color2"), QName("Color2::Yellow"), QName("ns"),
+                          QName("ns::Black")));
+}
+
+TEST_F(DocumentSymbolsTest, FromMacro) {
+  std::string FilePath = testPath("foo.cpp");
+  Annotations Main(R"(
+    #define FF(name) \
+      class name##_Test {};
+
+    $expansion[[FF]](abc);
+
+    #define FF2() \
+      class $spelling[[Test]] {};
+
+    FF2();
+  )");
+  addFile(FilePath, Main.code());
+  EXPECT_THAT(
+      getSymbols(FilePath),
+      ElementsAre(AllOf(QName("abc_Test"), SymRange(Main.range("expansion"))),
+                  AllOf(QName("Test"), SymRange(Main.range("spelling")))));
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/FuzzyMatchTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/FuzzyMatchTests.cpp
new file mode 100644
index 0000000..c03f8f3
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/FuzzyMatchTests.cpp
@@ -0,0 +1,301 @@
+//===-- FuzzyMatchTests.cpp - String fuzzy matcher tests --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FuzzyMatch.h"
+
+#include "llvm/ADT/StringExtras.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+using namespace llvm;
+using testing::Not;
+
+struct ExpectedMatch {
+  // Annotations are optional, and will not be asserted if absent.
+  ExpectedMatch(StringRef Match) : Word(Match), Annotated(Match) {
+    for (char C : "[]")
+      Word.erase(std::remove(Word.begin(), Word.end(), C), Word.end());
+    if (Word.size() == Annotated->size())
+      Annotated = None;
+  }
+  bool accepts(StringRef ActualAnnotated) const {
+    return !Annotated || ActualAnnotated == *Annotated;
+  }
+
+  friend raw_ostream &operator<<(raw_ostream &OS, const ExpectedMatch &M) {
+    OS << "'" << M.Word;
+    if (M.Annotated)
+      OS << "' as " << *M.Annotated;
+    return OS;
+  }
+
+  std::string Word;
+
+private:
+  Optional<StringRef> Annotated;
+};
+
+struct MatchesMatcher : public testing::MatcherInterface<StringRef> {
+  ExpectedMatch Candidate;
+  Optional<float> Score;
+  MatchesMatcher(ExpectedMatch Candidate, Optional<float> Score)
+      : Candidate(std::move(Candidate)), Score(Score) {}
+
+  void DescribeTo(::std::ostream *OS) const override {
+    raw_os_ostream(*OS) << "Matches " << Candidate;
+    if (Score)
+      *OS << " with score " << *Score;
+  }
+
+  bool MatchAndExplain(StringRef Pattern,
+                       testing::MatchResultListener *L) const override {
+    std::unique_ptr<raw_ostream> OS(
+        L->stream() ? (raw_ostream *)(new raw_os_ostream(*L->stream()))
+                    : new raw_null_ostream());
+    FuzzyMatcher Matcher(Pattern);
+    auto Result = Matcher.match(Candidate.Word);
+    auto AnnotatedMatch = Matcher.dumpLast(*OS << "\n");
+    return Result && Candidate.accepts(AnnotatedMatch) &&
+           (!Score || testing::Value(*Result, testing::FloatEq(*Score)));
+  }
+};
+
+// Accepts patterns that match a given word, optionally requiring a score.
+// Dumps the debug tables on match failure.
+testing::Matcher<StringRef> matches(StringRef M, Optional<float> Score = {}) {
+  return testing::MakeMatcher<StringRef>(new MatchesMatcher(M, Score));
+}
+
+TEST(FuzzyMatch, Matches) {
+  EXPECT_THAT("", matches("unique_ptr"));
+  EXPECT_THAT("u_p", matches("[u]nique[_p]tr"));
+  EXPECT_THAT("up", matches("[u]nique_[p]tr"));
+  EXPECT_THAT("uq", Not(matches("unique_ptr")));
+  EXPECT_THAT("qp", Not(matches("unique_ptr")));
+  EXPECT_THAT("log", Not(matches("SVGFEMorphologyElement")));
+
+  EXPECT_THAT("tit", matches("win.[tit]"));
+  EXPECT_THAT("title", matches("win.[title]"));
+  EXPECT_THAT("WordCla", matches("[Word]Character[Cla]ssifier"));
+  EXPECT_THAT("WordCCla", matches("[WordC]haracter[Cla]ssifier"));
+
+  EXPECT_THAT("dete", Not(matches("editor.quickSuggestionsDelay")));
+
+  EXPECT_THAT("highlight", matches("editorHover[Highlight]"));
+  EXPECT_THAT("hhighlight", matches("editor[H]over[Highlight]"));
+  EXPECT_THAT("dhhighlight", Not(matches("editorHoverHighlight")));
+
+  EXPECT_THAT("-moz", matches("[-moz]-foo"));
+  EXPECT_THAT("moz", matches("-[moz]-foo"));
+  EXPECT_THAT("moza", matches("-[moz]-[a]nimation"));
+
+  EXPECT_THAT("ab", matches("[ab]A"));
+  EXPECT_THAT("ccm", Not(matches("cacmelCase")));
+  EXPECT_THAT("bti", Not(matches("the_black_knight")));
+  EXPECT_THAT("ccm", Not(matches("camelCase")));
+  EXPECT_THAT("cmcm", Not(matches("camelCase")));
+  EXPECT_THAT("BK", matches("the_[b]lack_[k]night"));
+  EXPECT_THAT("KeyboardLayout=", Not(matches("KeyboardLayout")));
+  EXPECT_THAT("LLL", matches("SVisual[L]ogger[L]ogs[L]ist"));
+  EXPECT_THAT("LLLL", Not(matches("SVilLoLosLi")));
+  EXPECT_THAT("LLLL", Not(matches("SVisualLoggerLogsList")));
+  EXPECT_THAT("TEdit", matches("[T]ext[Edit]"));
+  EXPECT_THAT("TEdit", matches("[T]ext[Edit]or"));
+  EXPECT_THAT("TEdit", Not(matches("[T]ext[edit]")));
+  EXPECT_THAT("TEdit", matches("[t]ext_[edit]"));
+  EXPECT_THAT("TEditDt", matches("[T]ext[Edit]or[D]ecoration[T]ype"));
+  EXPECT_THAT("TEdit", matches("[T]ext[Edit]orDecorationType"));
+  EXPECT_THAT("Tedit", matches("[T]ext[Edit]"));
+  EXPECT_THAT("ba", Not(matches("?AB?")));
+  EXPECT_THAT("bkn", matches("the_[b]lack_[kn]ight"));
+  EXPECT_THAT("bt", Not(matches("the_[b]lack_knigh[t]")));
+  EXPECT_THAT("ccm", Not(matches("[c]amelCase[cm]")));
+  EXPECT_THAT("fdm", Not(matches("[f]in[dM]odel")));
+  EXPECT_THAT("fob", Not(matches("[fo]o[b]ar")));
+  EXPECT_THAT("fobz", Not(matches("foobar")));
+  EXPECT_THAT("foobar", matches("[foobar]"));
+  EXPECT_THAT("form", matches("editor.[form]atOnSave"));
+  EXPECT_THAT("g p", matches("[G]it:[ P]ull"));
+  EXPECT_THAT("g p", matches("[G]it:[ P]ull"));
+  EXPECT_THAT("gip", matches("[Gi]t: [P]ull"));
+  EXPECT_THAT("gip", matches("[Gi]t: [P]ull"));
+  EXPECT_THAT("gp", matches("[G]it: [P]ull"));
+  EXPECT_THAT("gp", matches("[G]it_Git_[P]ull"));
+  EXPECT_THAT("is", matches("[I]mport[S]tatement"));
+  EXPECT_THAT("is", matches("[is]Valid"));
+  EXPECT_THAT("lowrd", Not(matches("[low]Wo[rd]")));
+  EXPECT_THAT("myvable", Not(matches("[myva]ria[ble]")));
+  EXPECT_THAT("no", Not(matches("")));
+  EXPECT_THAT("no", Not(matches("match")));
+  EXPECT_THAT("ob", Not(matches("foobar")));
+  EXPECT_THAT("sl", matches("[S]Visual[L]oggerLogsList"));
+  EXPECT_THAT("sllll", matches("[S]Visua[L]ogger[Ll]ama[L]ist"));
+  EXPECT_THAT("THRE", matches("H[T]ML[HRE]lement"));
+  EXPECT_THAT("b", Not(matches("NDEBUG")));
+  EXPECT_THAT("Three", matches("[Three]"));
+  EXPECT_THAT("fo", Not(matches("barfoo")));
+  EXPECT_THAT("fo", matches("bar_[fo]o"));
+  EXPECT_THAT("fo", matches("bar_[Fo]o"));
+  EXPECT_THAT("fo", matches("bar [fo]o"));
+  EXPECT_THAT("fo", matches("bar.[fo]o"));
+  EXPECT_THAT("fo", matches("bar/[fo]o"));
+  EXPECT_THAT("fo", matches("bar\\[fo]o"));
+
+  EXPECT_THAT(
+      "aaaaaa",
+      matches("[aaaaaa]aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+              "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
+  EXPECT_THAT("baba", Not(matches("ababababab")));
+  EXPECT_THAT("fsfsfs", Not(matches("dsafdsafdsafdsafdsafdsafdsafasdfdsa")));
+  EXPECT_THAT("fsfsfsfsfsfsfsf",
+              Not(matches("dsafdsafdsafdsafdsafdsafdsafasdfdsafdsafdsafdsafdsfd"
+                          "safdsfdfdfasdnfdsajfndsjnafjndsajlknfdsa")));
+
+  EXPECT_THAT("  g", matches("[  g]roup"));
+  EXPECT_THAT("g", matches("  [g]roup"));
+  EXPECT_THAT("g g", Not(matches("  groupGroup")));
+  EXPECT_THAT("g g", matches("  [g]roup[ G]roup"));
+  EXPECT_THAT(" g g", matches("[ ] [g]roup[ G]roup"));
+  EXPECT_THAT("zz", matches("[zz]Group"));
+  EXPECT_THAT("zzg", matches("[zzG]roup"));
+  EXPECT_THAT("g", matches("zz[G]roup"));
+
+  EXPECT_THAT("aaaa", matches("_a_[aaaa]")); // Prefer consecutive.
+  // These would ideally match, but would need special segmentation rules.
+  EXPECT_THAT("printf", Not(matches("s[printf]")));
+  EXPECT_THAT("str", Not(matches("o[str]eam")));
+  EXPECT_THAT("strcpy", Not(matches("strncpy")));
+  EXPECT_THAT("std", Not(matches("PTHREAD_MUTEX_STALLED")));
+  EXPECT_THAT("std", Not(matches("pthread_condattr_setpshared")));
+}
+
+struct RankMatcher : public testing::MatcherInterface<StringRef> {
+  std::vector<ExpectedMatch> RankedStrings;
+  RankMatcher(std::initializer_list<ExpectedMatch> RankedStrings)
+      : RankedStrings(RankedStrings) {}
+
+  void DescribeTo(::std::ostream *OS) const override {
+    raw_os_ostream O(*OS);
+    O << "Ranks strings in order: [";
+    for (const auto &Str : RankedStrings)
+      O << "\n\t" << Str;
+    O << "\n]";
+  }
+
+  bool MatchAndExplain(StringRef Pattern,
+                       testing::MatchResultListener *L) const override {
+    std::unique_ptr<raw_ostream> OS(
+        L->stream() ? (raw_ostream *)(new raw_os_ostream(*L->stream()))
+                    : new raw_null_ostream());
+    FuzzyMatcher Matcher(Pattern);
+    const ExpectedMatch *LastMatch;
+    Optional<float> LastScore;
+    bool Ok = true;
+    for (const auto &Str : RankedStrings) {
+      auto Score = Matcher.match(Str.Word);
+      if (!Score) {
+        *OS << "\nDoesn't match '" << Str.Word << "'";
+        Matcher.dumpLast(*OS << "\n");
+        Ok = false;
+      } else {
+        std::string Buf;
+        llvm::raw_string_ostream Info(Buf);
+        auto AnnotatedMatch = Matcher.dumpLast(Info);
+
+        if (!Str.accepts(AnnotatedMatch)) {
+          *OS << "\nDoesn't match " << Str << ", but " << AnnotatedMatch << "\n"
+              << Info.str();
+          Ok = false;
+        } else if (LastScore && *LastScore < *Score) {
+          *OS << "\nRanks '" << Str.Word << "'=" << *Score << " above '"
+              << LastMatch->Word << "'=" << *LastScore << "\n"
+              << Info.str();
+          Matcher.match(LastMatch->Word);
+          Matcher.dumpLast(*OS << "\n");
+          Ok = false;
+        }
+      }
+      LastMatch = &Str;
+      LastScore = Score;
+    }
+    return Ok;
+  }
+};
+
+// Accepts patterns that match all the strings and rank them in the given order.
+// Dumps the debug tables on match failure.
+template <typename... T> testing::Matcher<StringRef> ranks(T... RankedStrings) {
+  return testing::MakeMatcher<StringRef>(
+      new RankMatcher{ExpectedMatch(RankedStrings)...});
+}
+
+TEST(FuzzyMatch, Ranking) {
+  EXPECT_THAT("cons",
+              ranks("[cons]ole", "[Cons]ole", "ArrayBuffer[Cons]tructor"));
+  EXPECT_THAT("foo", ranks("[foo]", "[Foo]"));
+  EXPECT_THAT("onMes",
+              ranks("[onMes]sage", "[onmes]sage", "[on]This[M]ega[Es]capes"));
+  EXPECT_THAT("CC", ranks("[C]amel[C]ase", "[c]amel[C]ase"));
+  EXPECT_THAT("cC", ranks("[c]amel[C]ase", "[C]amel[C]ase"));
+  EXPECT_THAT("p", ranks("[p]", "[p]arse", "[p]osix", "[p]afdsa", "[p]ath"));
+  EXPECT_THAT("pa", ranks("[pa]rse", "[pa]th", "[pa]fdsa"));
+  EXPECT_THAT("log", ranks("[log]", "Scroll[Log]icalPosition"));
+  EXPECT_THAT("e", ranks("[e]lse", "Abstract[E]lement"));
+  EXPECT_THAT("workbench.sideb",
+              ranks("[workbench.sideB]ar.location",
+                    "[workbench.]editor.default[SideB]ySideLayout"));
+  EXPECT_THAT("editor.r", ranks("[editor.r]enderControlCharacter",
+                                "[editor.]overview[R]ulerlanes",
+                                "diff[Editor.r]enderSideBySide"));
+  EXPECT_THAT("-mo", ranks("[-mo]z-columns", "[-]ms-ime-[mo]de"));
+  EXPECT_THAT("convertModelPosition",
+              ranks("[convertModelPosition]ToViewPosition",
+                    "[convert]ViewTo[ModelPosition]"));
+  EXPECT_THAT("is", ranks("[is]ValidViewletId", "[i]mport [s]tatement"));
+  EXPECT_THAT("strcpy", ranks("[strcpy]", "[strcpy]_s"));
+}
+
+// Verify some bounds so we know scores fall in the right range.
+// Testing exact scores is fragile, so we prefer Ranking tests.
+TEST(FuzzyMatch, Scoring) {
+  EXPECT_THAT("abs", matches("[a]w[B]xYz[S]", 0.f));
+  EXPECT_THAT("abs", matches("[abs]l", 1.f));
+  EXPECT_THAT("abs", matches("[abs]", 2.f));
+  EXPECT_THAT("Abs", matches("[abs]", 2.f));
+}
+
+// Returns pretty-printed segmentation of Text.
+// e.g. std::basic_string --> +--  +---- +-----
+std::string segment(StringRef Text) {
+  std::vector<CharRole> Roles(Text.size());
+  calculateRoles(Text, Roles);
+  std::string Printed;
+  for (unsigned I = 0; I < Text.size(); ++I)
+    Printed.push_back("?-+ "[static_cast<unsigned>(Roles[I])]);
+  return Printed;
+}
+
+// this is a no-op hack so clang-format will vertically align our testcases.
+StringRef returns(StringRef Text) { return Text; }
+
+TEST(FuzzyMatch, Segmentation) {
+  EXPECT_THAT(segment("std::basic_string"), //
+              returns("+--  +---- +-----"));
+  EXPECT_THAT(segment("XMLHttpRequest"), //
+              returns("+--+---+------"));
+  EXPECT_THAT(segment("t3h PeNgU1N oF d00m!!!!!!!!"), //
+              returns("+-- +-+-+-+ ++ +---        "));
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/GlobalCompilationDatabaseTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/GlobalCompilationDatabaseTests.cpp
new file mode 100644
index 0000000..18190c2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/GlobalCompilationDatabaseTests.cpp
@@ -0,0 +1,37 @@
+//===-- GlobalCompilationDatabaseTests.cpp ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GlobalCompilationDatabase.h"
+
+#include "TestFS.h"
+#include "llvm/ADT/StringExtras.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+using ::testing::ElementsAre;
+
+TEST(GlobalCompilationDatabaseTest, FallbackCommand) {
+  DirectoryBasedGlobalCompilationDatabase DB(llvm::None);
+  auto Cmd = DB.getFallbackCommand(testPath("foo/bar.cc"));
+  EXPECT_EQ(Cmd.Directory, testPath("foo"));
+  EXPECT_THAT(Cmd.CommandLine, ElementsAre("clang", testPath("foo/bar.cc")));
+  EXPECT_EQ(Cmd.Output, "");
+
+  // .h files have unknown language, so they are parsed liberally as obj-c++.
+  Cmd = DB.getFallbackCommand(testPath("foo/bar.h"));
+  EXPECT_THAT(Cmd.CommandLine, ElementsAre("clang", "-xobjective-c++-header",
+                                           testPath("foo/bar.h")));
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/HeadersTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/HeadersTests.cpp
new file mode 100644
index 0000000..21046c0
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/HeadersTests.cpp
@@ -0,0 +1,245 @@
+//===-- HeadersTests.cpp - Include headers unit tests -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Headers.h"
+
+#include "Compiler.h"
+#include "TestFS.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+using ::testing::AllOf;
+using ::testing::UnorderedElementsAre;
+
+class HeadersTest : public ::testing::Test {
+public:
+  HeadersTest() {
+    CDB.ExtraClangFlags = {SearchDirArg.c_str()};
+    FS.Files[MainFile] = "";
+    // Make sure directory sub/ exists.
+    FS.Files[testPath("sub/EMPTY")] = "";
+  }
+
+private:
+  std::unique_ptr<CompilerInstance> setupClang() {
+    auto Cmd = CDB.getCompileCommand(MainFile);
+    assert(static_cast<bool>(Cmd));
+    auto VFS = FS.getFileSystem();
+    VFS->setCurrentWorkingDirectory(Cmd->Directory);
+
+    std::vector<const char *> Argv;
+    for (const auto &S : Cmd->CommandLine)
+      Argv.push_back(S.c_str());
+    auto CI = clang::createInvocationFromCommandLine(
+        Argv,
+        CompilerInstance::createDiagnostics(new DiagnosticOptions(),
+                                            &IgnoreDiags, false),
+        VFS);
+    EXPECT_TRUE(static_cast<bool>(CI));
+    CI->getFrontendOpts().DisableFree = false;
+
+    // The diagnostic options must be set before creating a CompilerInstance.
+    CI->getDiagnosticOpts().IgnoreWarnings = true;
+    auto Clang = prepareCompilerInstance(
+        std::move(CI), /*Preamble=*/nullptr,
+        llvm::MemoryBuffer::getMemBuffer(FS.Files[MainFile], MainFile),
+        std::make_shared<PCHContainerOperations>(), VFS, IgnoreDiags);
+
+    EXPECT_FALSE(Clang->getFrontendOpts().Inputs.empty());
+    return Clang;
+  }
+
+protected:
+  IncludeStructure collectIncludes() {
+    auto Clang = setupClang();
+    PreprocessOnlyAction Action;
+    EXPECT_TRUE(
+        Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]));
+    IncludeStructure Includes;
+    Clang->getPreprocessor().addPPCallbacks(
+        collectIncludeStructureCallback(Clang->getSourceManager(), &Includes));
+    EXPECT_TRUE(Action.Execute());
+    Action.EndSourceFile();
+    return Includes;
+  }
+
+  // Calculates the include path, or returns "" on error or header should not be
+  // inserted.
+  std::string calculate(PathRef Original, PathRef Preferred = "",
+                        const std::vector<Inclusion> &Inclusions = {}) {
+    auto Clang = setupClang();
+    PreprocessOnlyAction Action;
+    EXPECT_TRUE(
+        Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]));
+
+    if (Preferred.empty())
+      Preferred = Original;
+    auto ToHeaderFile = [](llvm::StringRef Header) {
+      return HeaderFile{Header,
+                        /*Verbatim=*/!llvm::sys::path::is_absolute(Header)};
+    };
+
+    IncludeInserter Inserter(MainFile, /*Code=*/"", format::getLLVMStyle(),
+                             CDB.getCompileCommand(MainFile)->Directory,
+                             Clang->getPreprocessor().getHeaderSearchInfo());
+    for (const auto &Inc : Inclusions)
+      Inserter.addExisting(Inc);
+    auto Declaring = ToHeaderFile(Original);
+    auto Inserted = ToHeaderFile(Preferred);
+    if (!Inserter.shouldInsertInclude(Declaring, Inserted))
+      return "";
+    std::string Path = Inserter.calculateIncludePath(Declaring, Inserted);
+    Action.EndSourceFile();
+    return Path;
+  }
+
+  Optional<TextEdit> insert(StringRef VerbatimHeader) {
+    auto Clang = setupClang();
+    PreprocessOnlyAction Action;
+    EXPECT_TRUE(
+        Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]));
+
+    IncludeInserter Inserter(MainFile, /*Code=*/"", format::getLLVMStyle(),
+                             CDB.getCompileCommand(MainFile)->Directory,
+                             Clang->getPreprocessor().getHeaderSearchInfo());
+    auto Edit = Inserter.insert(VerbatimHeader);
+    Action.EndSourceFile();
+    return Edit;
+  }
+
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  std::string MainFile = testPath("main.cpp");
+  std::string Subdir = testPath("sub");
+  std::string SearchDirArg = (llvm::Twine("-I") + Subdir).str();
+  IgnoringDiagConsumer IgnoreDiags;
+};
+
+MATCHER_P(Written, Name, "") { return arg.Written == Name; }
+MATCHER_P(Resolved, Name, "") { return arg.Resolved == Name; }
+
+MATCHER_P2(Distance, File, D, "") {
+  if (arg.getKey() != File)
+    *result_listener << "file =" << arg.getKey().str();
+  if (arg.getValue() != D)
+    *result_listener << "distance =" << arg.getValue();
+  return arg.getKey() == File && arg.getValue() == D;
+}
+
+TEST_F(HeadersTest, CollectRewrittenAndResolved) {
+  FS.Files[MainFile] = R"cpp(
+#include "sub/bar.h" // not shortest
+)cpp";
+  std::string BarHeader = testPath("sub/bar.h");
+  FS.Files[BarHeader] = "";
+
+  EXPECT_THAT(collectIncludes().MainFileIncludes,
+              UnorderedElementsAre(
+                  AllOf(Written("\"sub/bar.h\""), Resolved(BarHeader))));
+  EXPECT_THAT(collectIncludes().includeDepth(MainFile),
+              UnorderedElementsAre(Distance(MainFile, 0u),
+                                   Distance(testPath("sub/bar.h"), 1u)));
+}
+
+TEST_F(HeadersTest, OnlyCollectInclusionsInMain) {
+  std::string BazHeader = testPath("sub/baz.h");
+  FS.Files[BazHeader] = "";
+  std::string BarHeader = testPath("sub/bar.h");
+  FS.Files[BarHeader] = R"cpp(
+#include "baz.h"
+)cpp";
+  FS.Files[MainFile] = R"cpp(
+#include "bar.h"
+)cpp";
+  EXPECT_THAT(
+      collectIncludes().MainFileIncludes,
+      UnorderedElementsAre(AllOf(Written("\"bar.h\""), Resolved(BarHeader))));
+  EXPECT_THAT(collectIncludes().includeDepth(MainFile),
+              UnorderedElementsAre(Distance(MainFile, 0u),
+                                   Distance(testPath("sub/bar.h"), 1u),
+                                   Distance(testPath("sub/baz.h"), 2u)));
+  // includeDepth() also works for non-main files.
+  EXPECT_THAT(collectIncludes().includeDepth(testPath("sub/bar.h")),
+              UnorderedElementsAre(Distance(testPath("sub/bar.h"), 0u),
+                                   Distance(testPath("sub/baz.h"), 1u)));
+}
+
+TEST_F(HeadersTest, UnResolvedInclusion) {
+  FS.Files[MainFile] = R"cpp(
+#include "foo.h"
+)cpp";
+
+  EXPECT_THAT(collectIncludes().MainFileIncludes,
+              UnorderedElementsAre(AllOf(Written("\"foo.h\""), Resolved(""))));
+  EXPECT_THAT(collectIncludes().includeDepth(MainFile),
+              UnorderedElementsAre(Distance(MainFile, 0u)));
+}
+
+TEST_F(HeadersTest, InsertInclude) {
+  std::string Path = testPath("sub/bar.h");
+  FS.Files[Path] = "";
+  EXPECT_EQ(calculate(Path), "\"bar.h\"");
+}
+
+TEST_F(HeadersTest, DoNotInsertIfInSameFile) {
+  MainFile = testPath("main.h");
+  EXPECT_EQ(calculate(MainFile), "");
+}
+
+TEST_F(HeadersTest, ShortenedInclude) {
+  std::string BarHeader = testPath("sub/bar.h");
+  EXPECT_EQ(calculate(BarHeader), "\"bar.h\"");
+}
+
+TEST_F(HeadersTest, NotShortenedInclude) {
+  std::string BarHeader = testPath("sub-2/bar.h");
+  EXPECT_EQ(calculate(BarHeader, ""), "\"" + BarHeader + "\"");
+}
+
+TEST_F(HeadersTest, PreferredHeader) {
+  std::string BarHeader = testPath("sub/bar.h");
+  EXPECT_EQ(calculate(BarHeader, "<bar>"), "<bar>");
+
+  std::string BazHeader = testPath("sub/baz.h");
+  EXPECT_EQ(calculate(BarHeader, BazHeader), "\"baz.h\"");
+}
+
+TEST_F(HeadersTest, DontInsertDuplicatePreferred) {
+  std::vector<Inclusion> Inclusions = {
+      {Range(), /*Written*/ "\"bar.h\"", /*Resolved*/ ""}};
+  EXPECT_EQ(calculate(testPath("sub/bar.h"), "\"bar.h\"", Inclusions), "");
+  EXPECT_EQ(calculate("\"x.h\"", "\"bar.h\"", Inclusions), "");
+}
+
+TEST_F(HeadersTest, DontInsertDuplicateResolved) {
+  std::string BarHeader = testPath("sub/bar.h");
+  std::vector<Inclusion> Inclusions = {
+      {Range(), /*Written*/ "fake-bar.h", /*Resolved*/ BarHeader}};
+  EXPECT_EQ(calculate(BarHeader, "", Inclusions), "");
+  // Do not insert preferred.
+  EXPECT_EQ(calculate(BarHeader, "\"BAR.h\"", Inclusions), "");
+}
+
+TEST_F(HeadersTest, PreferInserted) {
+  auto Edit = insert("<y>");
+  EXPECT_TRUE(Edit.hasValue());
+  EXPECT_TRUE(llvm::StringRef(Edit->newText).contains("<y>"));
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/IndexTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/IndexTests.cpp
new file mode 100644
index 0000000..3ddf2d2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/IndexTests.cpp
@@ -0,0 +1,326 @@
+//===-- IndexTests.cpp  -------------------------------*- C++ -*-----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "index/Index.h"
+#include "index/MemIndex.h"
+#include "index/Merge.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using testing::UnorderedElementsAre;
+using testing::Pointee;
+
+namespace clang {
+namespace clangd {
+namespace {
+
+Symbol symbol(llvm::StringRef QName) {
+  Symbol Sym;
+  Sym.ID = SymbolID(QName.str());
+  size_t Pos = QName.rfind("::");
+  if (Pos == llvm::StringRef::npos) {
+    Sym.Name = QName;
+    Sym.Scope = "";
+  } else {
+    Sym.Name = QName.substr(Pos + 2);
+    Sym.Scope = QName.substr(0, Pos + 2);
+  }
+  return Sym;
+}
+
+MATCHER_P(Named, N, "") { return arg.Name == N; }
+
+TEST(SymbolSlab, FindAndIterate) {
+  SymbolSlab::Builder B;
+  B.insert(symbol("Z"));
+  B.insert(symbol("Y"));
+  B.insert(symbol("X"));
+  EXPECT_EQ(nullptr, B.find(SymbolID("W")));
+  for (const char *Sym : {"X", "Y", "Z"})
+    EXPECT_THAT(B.find(SymbolID(Sym)), Pointee(Named(Sym)));
+
+  SymbolSlab S = std::move(B).build();
+  EXPECT_THAT(S, UnorderedElementsAre(Named("X"), Named("Y"), Named("Z")));
+  EXPECT_EQ(S.end(), S.find(SymbolID("W")));
+  for (const char *Sym : {"X", "Y", "Z"})
+    EXPECT_THAT(*S.find(SymbolID(Sym)), Named(Sym));
+}
+
+struct SlabAndPointers {
+  SymbolSlab Slab;
+  std::vector<const Symbol *> Pointers;
+};
+
+// Create a slab of symbols with the given qualified names as both IDs and
+// names. The life time of the slab is managed by the returned shared pointer.
+// If \p WeakSymbols is provided, it will be pointed to the managed object in
+// the returned shared pointer.
+std::shared_ptr<std::vector<const Symbol *>>
+generateSymbols(std::vector<std::string> QualifiedNames,
+                std::weak_ptr<SlabAndPointers> *WeakSymbols = nullptr) {
+  SymbolSlab::Builder Slab;
+  for (llvm::StringRef QName : QualifiedNames)
+    Slab.insert(symbol(QName));
+
+  auto Storage = std::make_shared<SlabAndPointers>();
+  Storage->Slab = std::move(Slab).build();
+  for (const auto &Sym : Storage->Slab)
+    Storage->Pointers.push_back(&Sym);
+  if (WeakSymbols)
+    *WeakSymbols = Storage;
+  auto *Pointers = &Storage->Pointers;
+  return {std::move(Storage), Pointers};
+}
+
+// Create a slab of symbols with IDs and names [Begin, End], otherwise identical
+// to the `generateSymbols` above.
+std::shared_ptr<std::vector<const Symbol *>>
+generateNumSymbols(int Begin, int End,
+                   std::weak_ptr<SlabAndPointers> *WeakSymbols = nullptr) {
+  std::vector<std::string> Names;
+  for (int i = Begin; i <= End; i++)
+    Names.push_back(std::to_string(i));
+  return generateSymbols(Names, WeakSymbols);
+}
+
+std::string getQualifiedName(const Symbol &Sym) {
+  return (Sym.Scope + Sym.Name).str();
+}
+
+std::vector<std::string> match(const SymbolIndex &I,
+                               const FuzzyFindRequest &Req,
+                               bool *Incomplete = nullptr) {
+  std::vector<std::string> Matches;
+  bool IsIncomplete = I.fuzzyFind(Req, [&](const Symbol &Sym) {
+    Matches.push_back(getQualifiedName(Sym));
+  });
+  if (Incomplete)
+    *Incomplete = IsIncomplete;
+  return Matches;
+}
+
+TEST(MemIndexTest, MemIndexSymbolsRecycled) {
+  MemIndex I;
+  std::weak_ptr<SlabAndPointers> Symbols;
+  I.build(generateNumSymbols(0, 10, &Symbols));
+  FuzzyFindRequest Req;
+  Req.Query = "7";
+  EXPECT_THAT(match(I, Req), UnorderedElementsAre("7"));
+
+  EXPECT_FALSE(Symbols.expired());
+  // Release old symbols.
+  I.build(generateNumSymbols(0, 0));
+  EXPECT_TRUE(Symbols.expired());
+}
+
+TEST(MemIndexTest, MemIndexDeduplicate) {
+  auto Symbols = generateNumSymbols(0, 10);
+
+  // Inject some duplicates and make sure we only match the same symbol once.
+  auto Sym = symbol("7");
+  Symbols->push_back(&Sym);
+  Symbols->push_back(&Sym);
+  Symbols->push_back(&Sym);
+
+  FuzzyFindRequest Req;
+  Req.Query = "7";
+  MemIndex I;
+  I.build(std::move(Symbols));
+  auto Matches = match(I, Req);
+  EXPECT_EQ(Matches.size(), 1u);
+}
+
+TEST(MemIndexTest, MemIndexLimitedNumMatches) {
+  MemIndex I;
+  I.build(generateNumSymbols(0, 100));
+  FuzzyFindRequest Req;
+  Req.Query = "5";
+  Req.MaxCandidateCount = 3;
+  bool Incomplete;
+  auto Matches = match(I, Req, &Incomplete);
+  EXPECT_EQ(Matches.size(), Req.MaxCandidateCount);
+  EXPECT_TRUE(Incomplete);
+}
+
+TEST(MemIndexTest, FuzzyMatch) {
+  MemIndex I;
+  I.build(
+      generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}));
+  FuzzyFindRequest Req;
+  Req.Query = "lol";
+  Req.MaxCandidateCount = 2;
+  EXPECT_THAT(match(I, Req),
+              UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
+}
+
+TEST(MemIndexTest, MatchQualifiedNamesWithoutSpecificScope) {
+  MemIndex I;
+  I.build(generateSymbols({"a::y1", "b::y2", "y3"}));
+  FuzzyFindRequest Req;
+  Req.Query = "y";
+  EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1", "b::y2", "y3"));
+}
+
+TEST(MemIndexTest, MatchQualifiedNamesWithGlobalScope) {
+  MemIndex I;
+  I.build(generateSymbols({"a::y1", "b::y2", "y3"}));
+  FuzzyFindRequest Req;
+  Req.Query = "y";
+  Req.Scopes = {""};
+  EXPECT_THAT(match(I, Req), UnorderedElementsAre("y3"));
+}
+
+TEST(MemIndexTest, MatchQualifiedNamesWithOneScope) {
+  MemIndex I;
+  I.build(generateSymbols({"a::y1", "a::y2", "a::x", "b::y2", "y3"}));
+  FuzzyFindRequest Req;
+  Req.Query = "y";
+  Req.Scopes = {"a::"};
+  EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1", "a::y2"));
+}
+
+TEST(MemIndexTest, MatchQualifiedNamesWithMultipleScopes) {
+  MemIndex I;
+  I.build(generateSymbols({"a::y1", "a::y2", "a::x", "b::y3", "y3"}));
+  FuzzyFindRequest Req;
+  Req.Query = "y";
+  Req.Scopes = {"a::", "b::"};
+  EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1", "a::y2", "b::y3"));
+}
+
+TEST(MemIndexTest, NoMatchNestedScopes) {
+  MemIndex I;
+  I.build(generateSymbols({"a::y1", "a::b::y2"}));
+  FuzzyFindRequest Req;
+  Req.Query = "y";
+  Req.Scopes = {"a::"};
+  EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1"));
+}
+
+TEST(MemIndexTest, IgnoreCases) {
+  MemIndex I;
+  I.build(generateSymbols({"ns::ABC", "ns::abc"}));
+  FuzzyFindRequest Req;
+  Req.Query = "AB";
+  Req.Scopes = {"ns::"};
+  EXPECT_THAT(match(I, Req), UnorderedElementsAre("ns::ABC", "ns::abc"));
+}
+
+// Returns qualified names of symbols with any of IDs in the index.
+std::vector<std::string> lookup(const SymbolIndex &I,
+                                llvm::ArrayRef<SymbolID> IDs) {
+  LookupRequest Req;
+  Req.IDs.insert(IDs.begin(), IDs.end());
+  std::vector<std::string> Results;
+  I.lookup(Req, [&](const Symbol &Sym) {
+    Results.push_back(getQualifiedName(Sym));
+  });
+  return Results;
+}
+
+TEST(MemIndexTest, Lookup) {
+  MemIndex I;
+  I.build(generateSymbols({"ns::abc", "ns::xyz"}));
+  EXPECT_THAT(lookup(I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
+  EXPECT_THAT(lookup(I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
+              UnorderedElementsAre("ns::abc", "ns::xyz"));
+  EXPECT_THAT(lookup(I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
+              UnorderedElementsAre("ns::xyz"));
+  EXPECT_THAT(lookup(I, SymbolID("ns::nonono")), UnorderedElementsAre());
+}
+
+TEST(MergeIndexTest, Lookup) {
+  MemIndex I, J;
+  I.build(generateSymbols({"ns::A", "ns::B"}));
+  J.build(generateSymbols({"ns::B", "ns::C"}));
+  EXPECT_THAT(lookup(*mergeIndex(&I, &J), SymbolID("ns::A")),
+              UnorderedElementsAre("ns::A"));
+  EXPECT_THAT(lookup(*mergeIndex(&I, &J), SymbolID("ns::B")),
+              UnorderedElementsAre("ns::B"));
+  EXPECT_THAT(lookup(*mergeIndex(&I, &J), SymbolID("ns::C")),
+              UnorderedElementsAre("ns::C"));
+  EXPECT_THAT(
+      lookup(*mergeIndex(&I, &J), {SymbolID("ns::A"), SymbolID("ns::B")}),
+      UnorderedElementsAre("ns::A", "ns::B"));
+  EXPECT_THAT(
+      lookup(*mergeIndex(&I, &J), {SymbolID("ns::A"), SymbolID("ns::C")}),
+      UnorderedElementsAre("ns::A", "ns::C"));
+  EXPECT_THAT(lookup(*mergeIndex(&I, &J), SymbolID("ns::D")),
+              UnorderedElementsAre());
+  EXPECT_THAT(lookup(*mergeIndex(&I, &J), {}), UnorderedElementsAre());
+}
+
+TEST(MergeIndexTest, FuzzyFind) {
+  MemIndex I, J;
+  I.build(generateSymbols({"ns::A", "ns::B"}));
+  J.build(generateSymbols({"ns::B", "ns::C"}));
+  FuzzyFindRequest Req;
+  Req.Scopes = {"ns::"};
+  EXPECT_THAT(match(*mergeIndex(&I, &J), Req),
+              UnorderedElementsAre("ns::A", "ns::B", "ns::C"));
+}
+
+TEST(MergeTest, Merge) {
+  Symbol L, R;
+  L.ID = R.ID = SymbolID("hello");
+  L.Name = R.Name = "Foo";                    // same in both
+  L.CanonicalDeclaration.FileURI = "file:///left.h"; // differs
+  R.CanonicalDeclaration.FileURI = "file:///right.h";
+  L.References = 1;
+  R.References = 2;
+  L.Signature = "()";                   // present in left only
+  R.CompletionSnippetSuffix = "{$1:0}"; // present in right only
+  Symbol::Details DetL, DetR;
+  DetL.ReturnType = "DetL";
+  DetR.ReturnType = "DetR";
+  DetR.Documentation = "--doc--";
+  L.Detail = &DetL;
+  R.Detail = &DetR;
+  L.Origin = SymbolOrigin::Dynamic;
+  R.Origin = SymbolOrigin::Static;
+
+  Symbol::Details Scratch;
+  Symbol M = mergeSymbol(L, R, &Scratch);
+  EXPECT_EQ(M.Name, "Foo");
+  EXPECT_EQ(M.CanonicalDeclaration.FileURI, "file:///left.h");
+  EXPECT_EQ(M.References, 3u);
+  EXPECT_EQ(M.Signature, "()");
+  EXPECT_EQ(M.CompletionSnippetSuffix, "{$1:0}");
+  ASSERT_TRUE(M.Detail);
+  EXPECT_EQ(M.Detail->ReturnType, "DetL");
+  EXPECT_EQ(M.Detail->Documentation, "--doc--");
+  EXPECT_EQ(M.Origin,
+            SymbolOrigin::Dynamic | SymbolOrigin::Static | SymbolOrigin::Merge);
+}
+
+TEST(MergeTest, PreferSymbolWithDefn) {
+  Symbol L, R;
+  Symbol::Details Scratch;
+
+  L.ID = R.ID = SymbolID("hello");
+  L.CanonicalDeclaration.FileURI = "file:/left.h";
+  R.CanonicalDeclaration.FileURI = "file:/right.h";
+  L.Name = "left";
+  R.Name = "right";
+
+  Symbol M = mergeSymbol(L, R, &Scratch);
+  EXPECT_EQ(M.CanonicalDeclaration.FileURI, "file:/left.h");
+  EXPECT_EQ(M.Definition.FileURI, "");
+  EXPECT_EQ(M.Name, "left");
+
+  R.Definition.FileURI = "file:/right.cpp"; // Now right will be favored.
+  M = mergeSymbol(L, R, &Scratch);
+  EXPECT_EQ(M.CanonicalDeclaration.FileURI, "file:/right.h");
+  EXPECT_EQ(M.Definition.FileURI, "file:/right.cpp");
+  EXPECT_EQ(M.Name, "right");
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/Matchers.h b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/Matchers.h
new file mode 100644
index 0000000..ed44464
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/Matchers.h
@@ -0,0 +1,135 @@
+//===-- Matchers.h ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// GMock matchers that aren't specific to particular tests.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_MATCHERS_H
+#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_MATCHERS_H
+#include "Protocol.h"
+#include "gmock/gmock.h"
+
+namespace clang {
+namespace clangd {
+using ::testing::Matcher;
+
+// EXPECT_IFF expects matcher if condition is true, and Not(matcher) if false.
+// This is hard to write as a function, because matchers may be polymorphic.
+#define EXPECT_IFF(condition, value, matcher)                                  \
+  do {                                                                         \
+    if (condition)                                                             \
+      EXPECT_THAT(value, matcher);                                             \
+    else                                                                       \
+      EXPECT_THAT(value, ::testing::Not(matcher));                             \
+  } while (0)
+
+// HasSubsequence(m1, m2, ...) matches a vector containing elements that match
+// m1, m2 ... in that order.
+//
+// SubsequenceMatcher implements this once the type of vector is known.
+template <typename T>
+class SubsequenceMatcher
+    : public ::testing::MatcherInterface<const std::vector<T> &> {
+  std::vector<Matcher<T>> Matchers;
+
+public:
+  SubsequenceMatcher(std::vector<Matcher<T>> M) : Matchers(M) {}
+
+  void DescribeTo(std::ostream *OS) const override {
+    *OS << "Contains the subsequence [";
+    const char *Sep = "";
+    for (const auto &M : Matchers) {
+      *OS << Sep;
+      M.DescribeTo(OS);
+      Sep = ", ";
+    }
+    *OS << "]";
+  }
+
+  bool MatchAndExplain(const std::vector<T> &V,
+                       ::testing::MatchResultListener *L) const override {
+    std::vector<int> Matches(Matchers.size());
+    size_t I = 0;
+    for (size_t J = 0; I < Matchers.size() && J < V.size(); ++J)
+      if (Matchers[I].Matches(V[J]))
+        Matches[I++] = J;
+    if (I == Matchers.size()) // We exhausted all matchers.
+      return true;
+    if (L->IsInterested()) {
+      *L << "\n  Matched:";
+      for (size_t K = 0; K < I; ++K) {
+        *L << "\n\t";
+        Matchers[K].DescribeTo(L->stream());
+        *L << " ==> " << ::testing::PrintToString(V[Matches[K]]);
+      }
+      *L << "\n\t";
+      Matchers[I].DescribeTo(L->stream());
+      *L << " ==> no subsequent match";
+    }
+    return false;
+  }
+};
+
+// PolySubsequenceMatcher implements a "polymorphic" SubsequenceMatcher.
+// It captures the types of the element matchers, and can be converted to
+// Matcher<vector<T>> if each matcher can be converted to Matcher<T>.
+// This allows HasSubsequence() to accept polymorphic matchers like Not().
+template <typename... M> class PolySubsequenceMatcher {
+  std::tuple<M...> Matchers;
+
+public:
+  PolySubsequenceMatcher(M &&... Args)
+      : Matchers(std::make_tuple(std::forward<M>(Args)...)) {}
+
+  template <typename T> operator Matcher<const std::vector<T> &>() const {
+    return ::testing::MakeMatcher(new SubsequenceMatcher<T>(
+        TypedMatchers<T>(llvm::index_sequence_for<M...>{})));
+  }
+
+private:
+  template <typename T, size_t... I>
+  std::vector<Matcher<T>> TypedMatchers(llvm::index_sequence<I...>) const {
+    return {std::get<I>(Matchers)...};
+  }
+};
+
+// HasSubsequence(m1, m2, ...) matches a vector containing elements that match
+// m1, m2 ... in that order.
+// The real implementation is in SubsequenceMatcher.
+template <typename... Args>
+PolySubsequenceMatcher<Args...> HasSubsequence(Args &&... M) {
+  return PolySubsequenceMatcher<Args...>(std::forward<Args>(M)...);
+}
+
+// EXPECT_ERROR seems like a pretty generic name, make sure it's not defined
+// already.
+#ifdef EXPECT_ERROR
+#error "Refusing to redefine EXPECT_ERROR"
+#endif
+
+// Consumes llvm::Expected<T>, checks it contains an error and marks it as
+// handled.
+#define EXPECT_ERROR(expectedValue)                                            \
+  do {                                                                         \
+    auto &&ComputedValue = (expectedValue);                                    \
+    if (ComputedValue) {                                                       \
+      ADD_FAILURE() << "expected an error from " << #expectedValue             \
+                    << " but got "                                             \
+                    << ::testing::PrintToString(*ComputedValue);               \
+      break;                                                                   \
+    }                                                                          \
+    handleAllErrors(ComputedValue.takeError(),                                 \
+                    [](const llvm::ErrorInfoBase &) {});                       \
+                                                                               \
+  } while (false)
+
+} // namespace clangd
+} // namespace clang
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/QualityTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/QualityTests.cpp
new file mode 100644
index 0000000..153eef4
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/QualityTests.cpp
@@ -0,0 +1,351 @@
+//===-- SourceCodeTests.cpp  ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Evaluating scoring functions isn't a great fit for assert-based tests.
+// For interesting cases, both exact scores and "X beats Y" are too brittle to
+// make good hard assertions.
+//
+// Here we test the signal extraction and sanity-check that signals point in
+// the right direction. This should be supplemented by quality metrics which
+// we can compute from a corpus of queries and preferred rankings.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FileDistance.h"
+#include "Quality.h"
+#include "TestFS.h"
+#include "TestTU.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "llvm/Support/Casting.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+
+// Force the unittest URI scheme to be linked,
+static int LLVM_ATTRIBUTE_UNUSED UnittestSchemeAnchorDest =
+    UnittestSchemeAnchorSource;
+
+namespace {
+
+TEST(QualityTests, SymbolQualitySignalExtraction) {
+  auto Header = TestTU::withHeaderCode(R"cpp(
+    int _X;
+
+    [[deprecated]]
+    int _f() { return _X; }
+  )cpp");
+  auto Symbols = Header.headerSymbols();
+  auto AST = Header.build();
+
+  SymbolQualitySignals Quality;
+  Quality.merge(findSymbol(Symbols, "_X"));
+  EXPECT_FALSE(Quality.Deprecated);
+  EXPECT_TRUE(Quality.ReservedName);
+  EXPECT_EQ(Quality.References, SymbolQualitySignals().References);
+  EXPECT_EQ(Quality.Category, SymbolQualitySignals::Variable);
+
+  Symbol F = findSymbol(Symbols, "_f");
+  F.References = 24; // TestTU doesn't count references, so fake it.
+  Quality = {};
+  Quality.merge(F);
+  EXPECT_FALSE(Quality.Deprecated); // FIXME: Include deprecated bit in index.
+  EXPECT_FALSE(Quality.ReservedName);
+  EXPECT_EQ(Quality.References, 24u);
+  EXPECT_EQ(Quality.Category, SymbolQualitySignals::Function);
+
+  Quality = {};
+  Quality.merge(CodeCompletionResult(&findDecl(AST, "_f"), /*Priority=*/42));
+  EXPECT_TRUE(Quality.Deprecated);
+  EXPECT_FALSE(Quality.ReservedName);
+  EXPECT_EQ(Quality.References, SymbolQualitySignals().References);
+  EXPECT_EQ(Quality.Category, SymbolQualitySignals::Function);
+
+  Quality = {};
+  Quality.merge(CodeCompletionResult("if"));
+  EXPECT_EQ(Quality.Category, SymbolQualitySignals::Keyword);
+}
+
+TEST(QualityTests, SymbolRelevanceSignalExtraction) {
+  TestTU Test;
+  Test.HeaderCode = R"cpp(
+  int header();
+  int header_main();
+
+  namespace hdr { class Bar {}; } // namespace hdr
+
+  #define DEFINE_FLAG(X) \
+  namespace flags { \
+  int FLAGS_##X; \
+  } \
+
+  DEFINE_FLAG(FOO)
+  )cpp";
+  Test.Code = R"cpp(
+  using hdr::Bar;
+
+  using flags::FLAGS_FOO;
+
+  int ::header_main() {}
+  int main();
+
+  [[deprecated]]
+  int deprecated() { return 0; }
+
+  namespace { struct X { void y() { int z; } }; }
+  struct S{}
+  )cpp";
+  auto AST = Test.build();
+
+  SymbolRelevanceSignals Relevance;
+  Relevance.merge(CodeCompletionResult(&findDecl(AST, "deprecated"),
+                                       /*Priority=*/42, nullptr, false,
+                                       /*Accessible=*/false));
+  EXPECT_EQ(Relevance.NameMatch, SymbolRelevanceSignals().NameMatch);
+  EXPECT_TRUE(Relevance.Forbidden);
+  EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::GlobalScope);
+
+  Relevance = {};
+  Relevance.merge(CodeCompletionResult(&findDecl(AST, "main"), 42));
+  EXPECT_FLOAT_EQ(Relevance.SemaProximityScore, 1.0f) << "Decl in current file";
+  Relevance = {};
+  Relevance.merge(CodeCompletionResult(&findDecl(AST, "header"), 42));
+  EXPECT_FLOAT_EQ(Relevance.SemaProximityScore, 0.6f) << "Decl from header";
+  Relevance = {};
+  Relevance.merge(CodeCompletionResult(&findDecl(AST, "header_main"), 42));
+  EXPECT_FLOAT_EQ(Relevance.SemaProximityScore, 1.0f)
+      << "Current file and header";
+
+  auto constructShadowDeclCompletionResult = [&](const std::string DeclName) {
+    auto *Shadow =
+        *dyn_cast<UsingDecl>(
+             &findAnyDecl(AST,
+                          [&](const NamedDecl &ND) {
+                            if (const UsingDecl *Using =
+                                    dyn_cast<UsingDecl>(&ND))
+                              if (Using->shadow_size() &&
+                                  Using->getQualifiedNameAsString() == DeclName)
+                                return true;
+                            return false;
+                          }))
+             ->shadow_begin();
+    CodeCompletionResult Result(Shadow->getTargetDecl(), 42);
+    Result.ShadowDecl = Shadow;
+    return Result;
+  };
+
+  Relevance = {};
+  Relevance.merge(constructShadowDeclCompletionResult("Bar"));
+  EXPECT_FLOAT_EQ(Relevance.SemaProximityScore, 1.0f)
+      << "Using declaration in main file";
+  Relevance.merge(constructShadowDeclCompletionResult("FLAGS_FOO"));
+  EXPECT_FLOAT_EQ(Relevance.SemaProximityScore, 1.0f)
+      << "Using declaration in main file";
+
+  Relevance = {};
+  Relevance.merge(CodeCompletionResult(&findAnyDecl(AST, "X"), 42));
+  EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FileScope);
+  Relevance = {};
+  Relevance.merge(CodeCompletionResult(&findAnyDecl(AST, "y"), 42));
+  EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::ClassScope);
+  Relevance = {};
+  Relevance.merge(CodeCompletionResult(&findAnyDecl(AST, "z"), 42));
+  EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FunctionScope);
+  // The injected class name is treated as the outer class name.
+  Relevance = {};
+  Relevance.merge(CodeCompletionResult(&findDecl(AST, "S::S"), 42));
+  EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::GlobalScope);
+}
+
+// Do the signals move the scores in the direction we expect?
+TEST(QualityTests, SymbolQualitySignalsSanity) {
+  SymbolQualitySignals Default;
+  EXPECT_EQ(Default.evaluate(), 1);
+
+  SymbolQualitySignals Deprecated;
+  Deprecated.Deprecated = true;
+  EXPECT_LT(Deprecated.evaluate(), Default.evaluate());
+
+  SymbolQualitySignals ReservedName;
+  ReservedName.ReservedName = true;
+  EXPECT_LT(ReservedName.evaluate(), Default.evaluate());
+
+  SymbolQualitySignals WithReferences, ManyReferences;
+  WithReferences.References = 20;
+  ManyReferences.References = 1000;
+  EXPECT_GT(WithReferences.evaluate(), Default.evaluate());
+  EXPECT_GT(ManyReferences.evaluate(), WithReferences.evaluate());
+
+  SymbolQualitySignals Keyword, Variable, Macro, Constructor, Function;
+  Keyword.Category = SymbolQualitySignals::Keyword;
+  Variable.Category = SymbolQualitySignals::Variable;
+  Macro.Category = SymbolQualitySignals::Macro;
+  Constructor.Category = SymbolQualitySignals::Constructor;
+  Function.Category = SymbolQualitySignals::Function;
+  EXPECT_GT(Variable.evaluate(), Default.evaluate());
+  EXPECT_GT(Keyword.evaluate(), Variable.evaluate());
+  EXPECT_LT(Macro.evaluate(), Default.evaluate());
+  EXPECT_LT(Constructor.evaluate(), Function.evaluate());
+}
+
+TEST(QualityTests, SymbolRelevanceSignalsSanity) {
+  SymbolRelevanceSignals Default;
+  EXPECT_EQ(Default.evaluate(), 1);
+
+  SymbolRelevanceSignals Forbidden;
+  Forbidden.Forbidden = true;
+  EXPECT_LT(Forbidden.evaluate(), Default.evaluate());
+
+  SymbolRelevanceSignals PoorNameMatch;
+  PoorNameMatch.NameMatch = 0.2f;
+  EXPECT_LT(PoorNameMatch.evaluate(), Default.evaluate());
+
+  SymbolRelevanceSignals WithSemaProximity;
+  WithSemaProximity.SemaProximityScore = 0.2f;
+  EXPECT_GT(WithSemaProximity.evaluate(), Default.evaluate());
+
+  SymbolRelevanceSignals IndexProximate;
+  IndexProximate.SymbolURI = "unittest:/foo/bar.h";
+  llvm::StringMap<SourceParams> ProxSources;
+  ProxSources.try_emplace(testPath("foo/baz.h"));
+  URIDistance Distance(ProxSources);
+  IndexProximate.FileProximityMatch = &Distance;
+  EXPECT_GT(IndexProximate.evaluate(), Default.evaluate());
+  SymbolRelevanceSignals IndexDistant = IndexProximate;
+  IndexDistant.SymbolURI = "unittest:/elsewhere/path.h";
+  EXPECT_GT(IndexProximate.evaluate(), IndexDistant.evaluate())
+      << IndexProximate << IndexDistant;
+  EXPECT_GT(IndexDistant.evaluate(), Default.evaluate());
+
+  SymbolRelevanceSignals Scoped;
+  Scoped.Scope = SymbolRelevanceSignals::FileScope;
+  EXPECT_EQ(Scoped.evaluate(), Default.evaluate());
+  Scoped.Query = SymbolRelevanceSignals::CodeComplete;
+  EXPECT_GT(Scoped.evaluate(), Default.evaluate());
+
+  SymbolRelevanceSignals Instance;
+  Instance.IsInstanceMember = false;
+  EXPECT_EQ(Instance.evaluate(), Default.evaluate());
+  Instance.Context = CodeCompletionContext::CCC_DotMemberAccess;
+  EXPECT_LT(Instance.evaluate(), Default.evaluate());
+  Instance.IsInstanceMember = true;
+  EXPECT_EQ(Instance.evaluate(), Default.evaluate());
+}
+
+TEST(QualityTests, SortText) {
+  EXPECT_LT(sortText(std::numeric_limits<float>::infinity()),
+            sortText(1000.2f));
+  EXPECT_LT(sortText(1000.2f), sortText(1));
+  EXPECT_LT(sortText(1), sortText(0.3f));
+  EXPECT_LT(sortText(0.3f), sortText(0));
+  EXPECT_LT(sortText(0), sortText(-10));
+  EXPECT_LT(sortText(-10), sortText(-std::numeric_limits<float>::infinity()));
+
+  EXPECT_LT(sortText(1, "z"), sortText(0, "a"));
+  EXPECT_LT(sortText(0, "a"), sortText(0, "z"));
+}
+
+TEST(QualityTests, NoBoostForClassConstructor) {
+  auto Header = TestTU::withHeaderCode(R"cpp(
+    class Foo {
+    public:
+      Foo(int);
+    };
+  )cpp");
+  auto Symbols = Header.headerSymbols();
+  auto AST = Header.build();
+
+  const NamedDecl *Foo = &findDecl(AST, "Foo");
+  SymbolRelevanceSignals Cls;
+  Cls.merge(CodeCompletionResult(Foo, /*Priority=*/0));
+
+  const NamedDecl *CtorDecl = &findAnyDecl(AST, [](const NamedDecl &ND) {
+    return (ND.getQualifiedNameAsString() == "Foo::Foo") &&
+           llvm::isa<CXXConstructorDecl>(&ND);
+  });
+  SymbolRelevanceSignals Ctor;
+  Ctor.merge(CodeCompletionResult(CtorDecl, /*Priority=*/0));
+
+  EXPECT_EQ(Cls.Scope, SymbolRelevanceSignals::GlobalScope);
+  EXPECT_EQ(Ctor.Scope, SymbolRelevanceSignals::GlobalScope);
+}
+
+TEST(QualityTests, IsInstanceMember) {
+  auto Header = TestTU::withHeaderCode(R"cpp(
+    class Foo {
+    public:
+      static void foo() {}
+
+      template <typename T> void tpl(T *t) {}
+
+      void bar() {}
+    };
+  )cpp");
+  auto Symbols = Header.headerSymbols();
+
+  SymbolRelevanceSignals Rel;
+  const Symbol &FooSym = findSymbol(Symbols, "Foo::foo");
+  Rel.merge(FooSym);
+  EXPECT_FALSE(Rel.IsInstanceMember);
+  const Symbol &BarSym = findSymbol(Symbols, "Foo::bar");
+  Rel.merge(BarSym);
+  EXPECT_TRUE(Rel.IsInstanceMember);
+
+  Rel.IsInstanceMember =false;
+  const Symbol &TplSym = findSymbol(Symbols, "Foo::tpl");
+  Rel.merge(TplSym);
+  EXPECT_TRUE(Rel.IsInstanceMember);
+
+  auto AST = Header.build();
+  const NamedDecl *Foo = &findDecl(AST, "Foo::foo");
+  const NamedDecl *Bar = &findDecl(AST, "Foo::bar");
+  const NamedDecl *Tpl = &findDecl(AST, "Foo::tpl");
+
+  Rel.IsInstanceMember = false;
+  Rel.merge(CodeCompletionResult(Foo, /*Priority=*/0));
+  EXPECT_FALSE(Rel.IsInstanceMember);
+  Rel.merge(CodeCompletionResult(Bar, /*Priority=*/0));
+  EXPECT_TRUE(Rel.IsInstanceMember);
+  Rel.IsInstanceMember = false;
+  Rel.merge(CodeCompletionResult(Tpl, /*Priority=*/0));
+  EXPECT_TRUE(Rel.IsInstanceMember);
+}
+
+TEST(QualityTests, ConstructorQuality) {
+  auto Header = TestTU::withHeaderCode(R"cpp(
+    class Foo {
+    public:
+      Foo(int);
+    };
+  )cpp");
+  auto Symbols = Header.headerSymbols();
+  auto AST = Header.build();
+
+  const NamedDecl *CtorDecl = &findAnyDecl(AST, [](const NamedDecl &ND) {
+    return (ND.getQualifiedNameAsString() == "Foo::Foo") &&
+           llvm::isa<CXXConstructorDecl>(&ND);
+  });
+
+  SymbolQualitySignals Q;
+  Q.merge(CodeCompletionResult(CtorDecl, /*Priority=*/0));
+  EXPECT_EQ(Q.Category, SymbolQualitySignals::Constructor);
+
+  Q.Category = SymbolQualitySignals::Unknown;
+  const Symbol &CtorSym = findSymbol(Symbols, "Foo::Foo");
+  Q.merge(CtorSym);
+  EXPECT_EQ(Q.Category, SymbolQualitySignals::Constructor);
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/SourceCodeTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/SourceCodeTests.cpp
new file mode 100644
index 0000000..57276af
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/SourceCodeTests.cpp
@@ -0,0 +1,124 @@
+//===-- SourceCodeTests.cpp  ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "SourceCode.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_os_ostream.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang{
+namespace clangd {
+namespace {
+
+using llvm::Failed;
+using llvm::HasValue;
+
+MATCHER_P2(Pos, Line, Col, "") {
+  return arg.line == Line && arg.character == Col;
+}
+
+// The = → 🡆 below are ASCII (1 byte), BMP (3 bytes), and astral (4 bytes).
+const char File[] = R"(0:0 = 0
+1:0 → 8
+2:0 🡆 18)";
+
+/// A helper to make tests easier to read.
+Position position(int line, int character) {
+  Position Pos;
+  Pos.line = line;
+  Pos.character = character;
+  return Pos;
+}
+
+TEST(SourceCodeTests, PositionToOffset) {
+  // line out of bounds
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), Failed());
+  // first line
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, -1)),
+                       Failed()); // out of range
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 0)),
+                       HasValue(0)); // first character
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 3)),
+                       HasValue(3)); // middle character
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 6)),
+                       HasValue(6)); // last character
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7)),
+                       HasValue(7)); // the newline itself
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7), false),
+                       HasValue(7));
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8)),
+                       HasValue(7)); // out of range
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8), false),
+                       Failed()); // out of range
+  // middle line
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, -1)),
+                       Failed()); // out of range
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 0)),
+                       HasValue(8)); // first character
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3)),
+                       HasValue(11)); // middle character
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3), false),
+                       HasValue(11));
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 6)),
+                       HasValue(16)); // last character
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 7)),
+                       HasValue(17)); // the newline itself
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8)),
+                       HasValue(17)); // out of range
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8), false),
+                       Failed()); // out of range
+  // last line
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, -1)),
+                       Failed()); // out of range
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 0)),
+                       HasValue(18)); // first character
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 3)),
+                       HasValue(21)); // middle character
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5), false),
+                       Failed()); // middle of surrogate pair
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5)),
+                       HasValue(26)); // middle of surrogate pair
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 6), false),
+                       HasValue(26)); // end of surrogate pair
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 8)),
+                       HasValue(28)); // last character
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 9)),
+                       HasValue(29)); // EOF
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 10), false),
+                       Failed()); // out of range
+  // line out of bounds
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), Failed());
+  EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 1)), Failed());
+}
+
+TEST(SourceCodeTests, OffsetToPosition) {
+  EXPECT_THAT(offsetToPosition(File, 0), Pos(0, 0)) << "start of file";
+  EXPECT_THAT(offsetToPosition(File, 3), Pos(0, 3)) << "in first line";
+  EXPECT_THAT(offsetToPosition(File, 6), Pos(0, 6)) << "end of first line";
+  EXPECT_THAT(offsetToPosition(File, 7), Pos(0, 7)) << "first newline";
+  EXPECT_THAT(offsetToPosition(File, 8), Pos(1, 0)) << "start of second line";
+  EXPECT_THAT(offsetToPosition(File, 12), Pos(1, 4)) << "before BMP char";
+  EXPECT_THAT(offsetToPosition(File, 13), Pos(1, 5)) << "in BMP char";
+  EXPECT_THAT(offsetToPosition(File, 15), Pos(1, 5)) << "after BMP char";
+  EXPECT_THAT(offsetToPosition(File, 16), Pos(1, 6)) << "end of second line";
+  EXPECT_THAT(offsetToPosition(File, 17), Pos(1, 7)) << "second newline";
+  EXPECT_THAT(offsetToPosition(File, 18), Pos(2, 0)) << "start of last line";
+  EXPECT_THAT(offsetToPosition(File, 21), Pos(2, 3)) << "in last line";
+  EXPECT_THAT(offsetToPosition(File, 22), Pos(2, 4)) << "before astral char";
+  EXPECT_THAT(offsetToPosition(File, 24), Pos(2, 6)) << "in astral char";
+  EXPECT_THAT(offsetToPosition(File, 26), Pos(2, 6)) << "after astral char";
+  EXPECT_THAT(offsetToPosition(File, 28), Pos(2, 8)) << "end of last line";
+  EXPECT_THAT(offsetToPosition(File, 29), Pos(2, 9)) << "EOF";
+  EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 9)) << "out of bounds";
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp
new file mode 100644
index 0000000..666d0bb
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp
@@ -0,0 +1,1023 @@
+//===-- SymbolCollectorTests.cpp  -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Annotations.h"
+#include "TestFS.h"
+#include "TestTU.h"
+#include "index/SymbolCollector.h"
+#include "index/SymbolYAML.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Index/IndexingAction.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <memory>
+#include <string>
+
+using testing::AllOf;
+using testing::Eq;
+using testing::Field;
+using testing::Not;
+using testing::UnorderedElementsAre;
+using testing::UnorderedElementsAreArray;
+
+// GMock helpers for matching Symbol.
+MATCHER_P(Labeled, Label, "") {
+  return (arg.Name + arg.Signature).str() == Label;
+}
+MATCHER(HasReturnType, "") {
+  return arg.Detail && !arg.Detail->ReturnType.empty();
+}
+MATCHER_P(ReturnType, D, "") {
+  return arg.Detail && arg.Detail->ReturnType == D;
+}
+MATCHER_P(Doc, D, "") { return arg.Detail && arg.Detail->Documentation == D; }
+MATCHER_P(Snippet, S, "") {
+  return (arg.Name + arg.CompletionSnippetSuffix).str() == S;
+}
+MATCHER_P(QName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
+MATCHER_P(DeclURI, P, "") { return arg.CanonicalDeclaration.FileURI == P; }
+MATCHER_P(DefURI, P, "") { return arg.Definition.FileURI == P; }
+MATCHER_P(IncludeHeader, P, "") {
+  return arg.Detail && arg.Detail->IncludeHeader == P;
+}
+MATCHER_P(DeclRange, Pos, "") {
+  return std::tie(arg.CanonicalDeclaration.Start.Line,
+                  arg.CanonicalDeclaration.Start.Column,
+                  arg.CanonicalDeclaration.End.Line,
+                  arg.CanonicalDeclaration.End.Column) ==
+         std::tie(Pos.start.line, Pos.start.character, Pos.end.line,
+                  Pos.end.character);
+}
+MATCHER_P(DefRange, Pos, "") {
+  return std::tie(arg.Definition.Start.Line,
+                  arg.Definition.Start.Column, arg.Definition.End.Line,
+                  arg.Definition.End.Column) ==
+         std::tie(Pos.start.line, Pos.start.character, Pos.end.line,
+                  Pos.end.character);
+}
+MATCHER_P(Refs, R, "") { return int(arg.References) == R; }
+MATCHER_P(ForCodeCompletion, IsIndexedForCodeCompletion, "") {
+  return arg.IsIndexedForCodeCompletion == IsIndexedForCodeCompletion;
+}
+
+namespace clang {
+namespace clangd {
+
+namespace {
+
+class ShouldCollectSymbolTest : public ::testing::Test {
+public:
+  void build(StringRef HeaderCode, StringRef Code = "") {
+    File.HeaderFilename = HeaderName;
+    File.Filename = FileName;
+    File.HeaderCode = HeaderCode;
+    File.Code = Code;
+    AST = File.build();
+  }
+
+  // build() must have been called.
+  bool shouldCollect(StringRef Name, bool Qualified = true) {
+    assert(AST.hasValue());
+    return SymbolCollector::shouldCollectSymbol(
+        Qualified ? findDecl(*AST, Name) : findAnyDecl(*AST, Name),
+        AST->getASTContext(), SymbolCollector::Options());
+  }
+
+protected:
+  std::string HeaderName = "f.h";
+  std::string FileName = "f.cpp";
+  TestTU File;
+  Optional<ParsedAST> AST;  // Initialized after build.
+};
+
+TEST_F(ShouldCollectSymbolTest, ShouldCollectSymbol) {
+  build(R"(
+    namespace nx {
+    class X{}
+    void f() { int Local; }
+    struct { int x } var;
+    namespace { class InAnonymous {}; }
+    }
+  )",
+        "class InMain {};");
+  auto AST = File.build();
+  EXPECT_TRUE(shouldCollect("nx"));
+  EXPECT_TRUE(shouldCollect("nx::X"));
+  EXPECT_TRUE(shouldCollect("nx::f"));
+
+  EXPECT_FALSE(shouldCollect("InMain"));
+  EXPECT_FALSE(shouldCollect("Local", /*Qualified=*/false));
+  EXPECT_FALSE(shouldCollect("InAnonymous", /*Qualified=*/false));
+}
+
+TEST_F(ShouldCollectSymbolTest, NoPrivateProtoSymbol) {
+  HeaderName = "f.proto.h";
+  build(
+      R"(// Generated by the protocol buffer compiler.  DO NOT EDIT!
+         namespace nx {
+           class Top_Level {};
+           class TopLevel {};
+           enum Kind {
+             KIND_OK,
+             Kind_Not_Ok,
+           };
+         })");
+  EXPECT_TRUE(shouldCollect("nx::TopLevel"));
+  EXPECT_TRUE(shouldCollect("nx::Kind::KIND_OK"));
+  EXPECT_TRUE(shouldCollect("nx::Kind"));
+
+  EXPECT_FALSE(shouldCollect("nx::Top_Level"));
+  EXPECT_FALSE(shouldCollect("nx::Kind::Kind_Not_Ok"));
+}
+
+TEST_F(ShouldCollectSymbolTest, DoubleCheckProtoHeaderComment) {
+  HeaderName = "f.proto.h";
+  build(R"(
+    namespace nx {
+      class Top_Level {};
+      enum Kind {
+        Kind_Fine
+      };
+    }
+  )");
+  EXPECT_TRUE(shouldCollect("nx::Top_Level"));
+  EXPECT_TRUE(shouldCollect("nx::Kind_Fine"));
+}
+
+class SymbolIndexActionFactory : public tooling::FrontendActionFactory {
+public:
+  SymbolIndexActionFactory(SymbolCollector::Options COpts,
+                           CommentHandler *PragmaHandler)
+      : COpts(std::move(COpts)), PragmaHandler(PragmaHandler) {}
+
+  clang::FrontendAction *create() override {
+    class WrappedIndexAction : public WrapperFrontendAction {
+    public:
+      WrappedIndexAction(std::shared_ptr<SymbolCollector> C,
+                         const index::IndexingOptions &Opts,
+                         CommentHandler *PragmaHandler)
+          : WrapperFrontendAction(
+                index::createIndexingAction(C, Opts, nullptr)),
+            PragmaHandler(PragmaHandler) {}
+
+      std::unique_ptr<ASTConsumer>
+      CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override {
+        if (PragmaHandler)
+          CI.getPreprocessor().addCommentHandler(PragmaHandler);
+        return WrapperFrontendAction::CreateASTConsumer(CI, InFile);
+      }
+
+    private:
+      index::IndexingOptions IndexOpts;
+      CommentHandler *PragmaHandler;
+    };
+    index::IndexingOptions IndexOpts;
+    IndexOpts.SystemSymbolFilter =
+        index::IndexingOptions::SystemSymbolFilterKind::All;
+    IndexOpts.IndexFunctionLocals = false;
+    Collector = std::make_shared<SymbolCollector>(COpts);
+    return new WrappedIndexAction(Collector, std::move(IndexOpts),
+                                  PragmaHandler);
+  }
+
+  std::shared_ptr<SymbolCollector> Collector;
+  SymbolCollector::Options COpts;
+  CommentHandler *PragmaHandler;
+};
+
+class SymbolCollectorTest : public ::testing::Test {
+public:
+  SymbolCollectorTest()
+      : InMemoryFileSystem(new vfs::InMemoryFileSystem),
+        TestHeaderName(testPath("symbol.h")),
+        TestFileName(testPath("symbol.cc")) {
+    TestHeaderURI = URI::createFile(TestHeaderName).toString();
+    TestFileURI = URI::createFile(TestFileName).toString();
+  }
+
+  bool runSymbolCollector(StringRef HeaderCode, StringRef MainCode,
+                          const std::vector<std::string> &ExtraArgs = {}) {
+    llvm::IntrusiveRefCntPtr<FileManager> Files(
+        new FileManager(FileSystemOptions(), InMemoryFileSystem));
+
+    auto Factory = llvm::make_unique<SymbolIndexActionFactory>(
+        CollectorOpts, PragmaHandler.get());
+
+    std::vector<std::string> Args = {
+        "symbol_collector", "-fsyntax-only", "-xc++",
+        "-std=c++11",       "-include",      TestHeaderName};
+    Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
+    // This allows to override the "-xc++" with something else, i.e.
+    // -xobjective-c++.
+    Args.push_back(TestFileName);
+
+    tooling::ToolInvocation Invocation(
+        Args,
+        Factory->create(), Files.get(),
+        std::make_shared<PCHContainerOperations>());
+
+    InMemoryFileSystem->addFile(TestHeaderName, 0,
+                                llvm::MemoryBuffer::getMemBuffer(HeaderCode));
+    InMemoryFileSystem->addFile(TestFileName, 0,
+                                llvm::MemoryBuffer::getMemBuffer(MainCode));
+    Invocation.run();
+    Symbols = Factory->Collector->takeSymbols();
+    return true;
+  }
+
+protected:
+  llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
+  std::string TestHeaderName;
+  std::string TestHeaderURI;
+  std::string TestFileName;
+  std::string TestFileURI;
+  SymbolSlab Symbols;
+  SymbolCollector::Options CollectorOpts;
+  std::unique_ptr<CommentHandler> PragmaHandler;
+};
+
+TEST_F(SymbolCollectorTest, CollectSymbols) {
+  const std::string Header = R"(
+    class Foo {
+      Foo() {}
+      Foo(int a) {}
+      void f();
+      friend void f1();
+      friend class Friend;
+      Foo& operator=(const Foo&);
+      ~Foo();
+      class Nested {
+      void f();
+      };
+    };
+    class Friend {
+    };
+
+    void f1();
+    inline void f2() {}
+    static const int KInt = 2;
+    const char* kStr = "123";
+
+    namespace {
+    void ff() {} // ignore
+    }
+
+    void f1() {}
+
+    namespace foo {
+    // Type alias
+    typedef int int32;
+    using int32_t = int32;
+
+    // Variable
+    int v1;
+
+    // Namespace
+    namespace bar {
+    int v2;
+    }
+    // Namespace alias
+    namespace baz = bar;
+
+    // FIXME: using declaration is not supported as the IndexAction will ignore
+    // implicit declarations (the implicit using shadow declaration) by default,
+    // and there is no way to customize this behavior at the moment.
+    using bar::v2;
+    } // namespace foo
+  )";
+  runSymbolCollector(Header, /*Main=*/"");
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAreArray(
+                  {AllOf(QName("Foo"), ForCodeCompletion(true)),
+                   AllOf(QName("Foo::Foo"), ForCodeCompletion(false)),
+                   AllOf(QName("Foo::Foo"), ForCodeCompletion(false)),
+                   AllOf(QName("Foo::f"), ForCodeCompletion(false)),
+                   AllOf(QName("Foo::~Foo"), ForCodeCompletion(false)),
+                   AllOf(QName("Foo::operator="), ForCodeCompletion(false)),
+                   AllOf(QName("Foo::Nested"), ForCodeCompletion(false)),
+                   AllOf(QName("Foo::Nested::f"), ForCodeCompletion(false)),
+
+                   AllOf(QName("Friend"), ForCodeCompletion(true)),
+                   AllOf(QName("f1"), ForCodeCompletion(true)),
+                   AllOf(QName("f2"), ForCodeCompletion(true)),
+                   AllOf(QName("KInt"), ForCodeCompletion(true)),
+                   AllOf(QName("kStr"), ForCodeCompletion(true)),
+                   AllOf(QName("foo"), ForCodeCompletion(true)),
+                   AllOf(QName("foo::bar"), ForCodeCompletion(true)),
+                   AllOf(QName("foo::int32"), ForCodeCompletion(true)),
+                   AllOf(QName("foo::int32_t"), ForCodeCompletion(true)),
+                   AllOf(QName("foo::v1"), ForCodeCompletion(true)),
+                   AllOf(QName("foo::bar::v2"), ForCodeCompletion(true)),
+                   AllOf(QName("foo::baz"), ForCodeCompletion(true))}));
+}
+
+TEST_F(SymbolCollectorTest, Template) {
+  Annotations Header(R"(
+    // Template is indexed, specialization and instantiation is not.
+    template <class T> struct [[Tmpl]] {T $xdecl[[x]] = 0;};
+    template <> struct Tmpl<int> {};
+    extern template struct Tmpl<float>;
+    template struct Tmpl<double>;
+  )");
+  runSymbolCollector(Header.code(), /*Main=*/"");
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAreArray(
+                  {AllOf(QName("Tmpl"), DeclRange(Header.range())),
+                   AllOf(QName("Tmpl::x"), DeclRange(Header.range("xdecl")))}));
+}
+
+TEST_F(SymbolCollectorTest, ObjCSymbols) {
+  const std::string Header = R"(
+    @interface Person
+    - (void)someMethodName:(void*)name1 lastName:(void*)lName;
+    @end
+
+    @implementation Person
+    - (void)someMethodName:(void*)name1 lastName:(void*)lName{
+      int foo;
+      ^(int param){ int bar; };
+    }
+    @end
+
+    @interface Person (MyCategory)
+    - (void)someMethodName2:(void*)name2;
+    @end
+
+    @implementation Person (MyCategory)
+    - (void)someMethodName2:(void*)name2 {
+      int foo2;
+    }
+    @end
+
+    @protocol MyProtocol
+    - (void)someMethodName3:(void*)name3;
+    @end
+  )";
+  TestFileName = "test.m";
+  runSymbolCollector(Header, /*Main=*/"", {"-fblocks", "-xobjective-c++"});
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(
+                  QName("Person"), QName("Person::someMethodName:lastName:"),
+                  QName("MyCategory"), QName("Person::someMethodName2:"),
+                  QName("MyProtocol"), QName("MyProtocol::someMethodName3:")));
+}
+
+TEST_F(SymbolCollectorTest, Locations) {
+  Annotations Header(R"cpp(
+    // Declared in header, defined in main.
+    extern int $xdecl[[X]];
+    class $clsdecl[[Cls]];
+    void $printdecl[[print]]();
+
+    // Declared in header, defined nowhere.
+    extern int $zdecl[[Z]];
+
+    void $foodecl[[fo\
+o]]();
+  )cpp");
+  Annotations Main(R"cpp(
+    int $xdef[[X]] = 42;
+    class $clsdef[[Cls]] {};
+    void $printdef[[print]]() {}
+
+    // Declared/defined in main only.
+    int Y;
+  )cpp");
+  runSymbolCollector(Header.code(), Main.code());
+  EXPECT_THAT(
+      Symbols,
+      UnorderedElementsAre(
+          AllOf(QName("X"), DeclRange(Header.range("xdecl")),
+                DefRange(Main.range("xdef"))),
+          AllOf(QName("Cls"), DeclRange(Header.range("clsdecl")),
+                DefRange(Main.range("clsdef"))),
+          AllOf(QName("print"), DeclRange(Header.range("printdecl")),
+                DefRange(Main.range("printdef"))),
+          AllOf(QName("Z"), DeclRange(Header.range("zdecl"))),
+          AllOf(QName("foo"), DeclRange(Header.range("foodecl")))
+          ));
+}
+
+TEST_F(SymbolCollectorTest, References) {
+  const std::string Header = R"(
+    class W;
+    class X {};
+    class Y;
+    class Z {}; // not used anywhere
+    Y* y = nullptr;  // used in header doesn't count
+    #define GLOBAL_Z(name) Z name;
+  )";
+  const std::string Main = R"(
+    W* w = nullptr;
+    W* w2 = nullptr; // only one usage counts
+    X x();
+    class V;
+    V* v = nullptr; // Used, but not eligible for indexing.
+    class Y{}; // definition doesn't count as a reference
+    GLOBAL_Z(z); // Not a reference to Z, we don't spell the type.
+  )";
+  CollectorOpts.CountReferences = true;
+  runSymbolCollector(Header, Main);
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(AllOf(QName("W"), Refs(1)),
+                                   AllOf(QName("X"), Refs(1)),
+                                   AllOf(QName("Y"), Refs(0)),
+                                   AllOf(QName("Z"), Refs(0)), QName("y")));
+}
+
+TEST_F(SymbolCollectorTest, SymbolRelativeNoFallback) {
+  runSymbolCollector("class Foo {};", /*Main=*/"");
+  EXPECT_THAT(Symbols, UnorderedElementsAre(
+                           AllOf(QName("Foo"), DeclURI(TestHeaderURI))));
+}
+
+TEST_F(SymbolCollectorTest, SymbolRelativeWithFallback) {
+  TestHeaderName = "x.h";
+  TestFileName = "x.cpp";
+  TestHeaderURI = URI::createFile(testPath(TestHeaderName)).toString();
+  CollectorOpts.FallbackDir = testRoot();
+  runSymbolCollector("class Foo {};", /*Main=*/"");
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(AllOf(QName("Foo"), DeclURI(TestHeaderURI))));
+}
+
+TEST_F(SymbolCollectorTest, CustomURIScheme) {
+  // Use test URI scheme from URITests.cpp
+  CollectorOpts.URISchemes.insert(CollectorOpts.URISchemes.begin(), "unittest");
+  TestHeaderName = testPath("x.h");
+  TestFileName = testPath("x.cpp");
+  runSymbolCollector("class Foo {};", /*Main=*/"");
+  EXPECT_THAT(Symbols, UnorderedElementsAre(
+                           AllOf(QName("Foo"), DeclURI("unittest:///x.h"))));
+}
+
+TEST_F(SymbolCollectorTest, InvalidURIScheme) {
+  // Use test URI scheme from URITests.cpp
+  CollectorOpts.URISchemes = {"invalid"};
+  runSymbolCollector("class Foo {};", /*Main=*/"");
+  EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("Foo"), DeclURI(""))));
+}
+
+TEST_F(SymbolCollectorTest, FallbackToFileURI) {
+  // Use test URI scheme from URITests.cpp
+  CollectorOpts.URISchemes = {"invalid", "file"};
+  runSymbolCollector("class Foo {};", /*Main=*/"");
+  EXPECT_THAT(Symbols, UnorderedElementsAre(
+                           AllOf(QName("Foo"), DeclURI(TestHeaderURI))));
+}
+
+TEST_F(SymbolCollectorTest, IncludeEnums) {
+  const std::string Header = R"(
+    enum {
+      Red
+    };
+    enum Color {
+      Green
+    };
+    enum class Color2 {
+      Yellow
+    };
+    namespace ns {
+    enum {
+      Black
+    };
+    }
+  )";
+  runSymbolCollector(Header, /*Main=*/"");
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(
+                  AllOf(QName("Red"), ForCodeCompletion(true)),
+                  AllOf(QName("Color"), ForCodeCompletion(true)),
+                  AllOf(QName("Green"), ForCodeCompletion(true)),
+                  AllOf(QName("Color2"), ForCodeCompletion(true)),
+                  AllOf(QName("Color2::Yellow"), ForCodeCompletion(false)),
+                  AllOf(QName("ns"), ForCodeCompletion(true)),
+                  AllOf(QName("ns::Black"), ForCodeCompletion(true))));
+}
+
+TEST_F(SymbolCollectorTest, NamelessSymbols) {
+  const std::string Header = R"(
+    struct {
+      int a;
+    } Foo;
+  )";
+  runSymbolCollector(Header, /*Main=*/"");
+  EXPECT_THAT(Symbols, UnorderedElementsAre(QName("Foo"),
+                                            QName("(anonymous struct)::a")));
+}
+
+TEST_F(SymbolCollectorTest, SymbolFormedFromMacro) {
+
+  Annotations Header(R"(
+    #define FF(name) \
+      class name##_Test {};
+
+    $expansion[[FF]](abc);
+
+    #define FF2() \
+      class $spelling[[Test]] {};
+
+    FF2();
+  )");
+
+  runSymbolCollector(Header.code(), /*Main=*/"");
+  EXPECT_THAT(
+      Symbols,
+      UnorderedElementsAre(
+          AllOf(QName("abc_Test"), DeclRange(Header.range("expansion")),
+                DeclURI(TestHeaderURI)),
+          AllOf(QName("Test"), DeclRange(Header.range("spelling")),
+                DeclURI(TestHeaderURI))));
+}
+
+TEST_F(SymbolCollectorTest, SymbolFormedByCLI) {
+  Annotations Header(R"(
+    #ifdef NAME
+    class $expansion[[NAME]] {};
+    #endif
+  )");
+
+  runSymbolCollector(Header.code(), /*Main=*/"",
+                     /*ExtraArgs=*/{"-DNAME=name"});
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(AllOf(
+                  QName("name"),
+                  DeclRange(Header.range("expansion")),
+                  DeclURI(TestHeaderURI))));
+}
+
+TEST_F(SymbolCollectorTest, IgnoreSymbolsInMainFile) {
+  const std::string Header = R"(
+    class Foo {};
+    void f1();
+    inline void f2() {}
+  )";
+  const std::string Main = R"(
+    namespace {
+    void ff() {} // ignore
+    }
+    void main_f() {} // ignore
+    void f1() {}
+  )";
+  runSymbolCollector(Header, Main);
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(QName("Foo"), QName("f1"), QName("f2")));
+}
+
+TEST_F(SymbolCollectorTest, ClassMembers) {
+  const std::string Header = R"(
+    class Foo {
+      void f() {}
+      void g();
+      static void sf() {}
+      static void ssf();
+      static int x;
+    };
+  )";
+  const std::string Main = R"(
+    void Foo::g() {}
+    void Foo::ssf() {}
+  )";
+  runSymbolCollector(Header, Main);
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(QName("Foo"), QName("Foo::f"),
+                                   QName("Foo::g"), QName("Foo::sf"),
+                                   QName("Foo::ssf"), QName("Foo::x")));
+}
+
+TEST_F(SymbolCollectorTest, Scopes) {
+  const std::string Header = R"(
+    namespace na {
+    class Foo {};
+    namespace nb {
+    class Bar {};
+    }
+    }
+  )";
+  runSymbolCollector(Header, /*Main=*/"");
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(QName("na"), QName("na::nb"),
+                                   QName("na::Foo"), QName("na::nb::Bar")));
+}
+
+TEST_F(SymbolCollectorTest, ExternC) {
+  const std::string Header = R"(
+    extern "C" { class Foo {}; }
+    namespace na {
+    extern "C" { class Bar {}; }
+    }
+  )";
+  runSymbolCollector(Header, /*Main=*/"");
+  EXPECT_THAT(Symbols, UnorderedElementsAre(QName("na"), QName("Foo"),
+                                            QName("na::Bar")));
+}
+
+TEST_F(SymbolCollectorTest, SkipInlineNamespace) {
+  const std::string Header = R"(
+    namespace na {
+    inline namespace nb {
+    class Foo {};
+    }
+    }
+    namespace na {
+    // This is still inlined.
+    namespace nb {
+    class Bar {};
+    }
+    }
+  )";
+  runSymbolCollector(Header, /*Main=*/"");
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(QName("na"), QName("na::nb"),
+                                   QName("na::Foo"), QName("na::Bar")));
+}
+
+TEST_F(SymbolCollectorTest, SymbolWithDocumentation) {
+  const std::string Header = R"(
+    namespace nx {
+    /// Foo comment.
+    int ff(int x, double y) { return 0; }
+    }
+  )";
+  runSymbolCollector(Header, /*Main=*/"");
+  EXPECT_THAT(
+      Symbols,
+      UnorderedElementsAre(
+          QName("nx"), AllOf(QName("nx::ff"), Labeled("ff(int x, double y)"),
+                             ReturnType("int"), Doc("Foo comment."))));
+}
+
+TEST_F(SymbolCollectorTest, Snippet) {
+  const std::string Header = R"(
+    namespace nx {
+    void f() {}
+    int ff(int x, double y) { return 0; }
+    }
+  )";
+  runSymbolCollector(Header, /*Main=*/"");
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(
+                  QName("nx"),
+                  AllOf(QName("nx::f"), Labeled("f()"), Snippet("f()")),
+                  AllOf(QName("nx::ff"), Labeled("ff(int x, double y)"),
+                        Snippet("ff(${1:int x}, ${2:double y})"))));
+}
+
+TEST_F(SymbolCollectorTest, YAMLConversions) {
+  const std::string YAML1 = R"(
+---
+ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF856
+Name:   'Foo1'
+Scope:   'clang::'
+SymInfo:
+  Kind:            Function
+  Lang:            Cpp
+CanonicalDeclaration:
+  FileURI:        file:///path/foo.h
+  Start:
+    Line: 1
+    Column: 0
+  End:
+    Line: 1
+    Column: 1
+IsIndexedForCodeCompletion:    true
+Detail:
+  Documentation:    'Foo doc'
+  ReturnType:    'int'
+...
+)";
+  const std::string YAML2 = R"(
+---
+ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF858
+Name:   'Foo2'
+Scope:   'clang::'
+SymInfo:
+  Kind:            Function
+  Lang:            Cpp
+CanonicalDeclaration:
+  FileURI:        file:///path/bar.h
+  Start:
+    Line: 1
+    Column: 0
+  End:
+    Line: 1
+    Column: 1
+IsIndexedForCodeCompletion:    false
+Signature:    '-sig'
+CompletionSnippetSuffix:    '-snippet'
+...
+)";
+
+  auto Symbols1 = symbolsFromYAML(YAML1);
+
+  EXPECT_THAT(Symbols1,
+              UnorderedElementsAre(AllOf(QName("clang::Foo1"), Labeled("Foo1"),
+                                         Doc("Foo doc"), ReturnType("int"),
+                                         DeclURI("file:///path/foo.h"),
+                                         ForCodeCompletion(true))));
+  auto Symbols2 = symbolsFromYAML(YAML2);
+  EXPECT_THAT(Symbols2, UnorderedElementsAre(AllOf(
+                            QName("clang::Foo2"), Labeled("Foo2-sig"),
+                            Not(HasReturnType()), DeclURI("file:///path/bar.h"),
+                            ForCodeCompletion(false))));
+
+  std::string ConcatenatedYAML;
+  {
+    llvm::raw_string_ostream OS(ConcatenatedYAML);
+    SymbolsToYAML(Symbols1, OS);
+    SymbolsToYAML(Symbols2, OS);
+  }
+  auto ConcatenatedSymbols = symbolsFromYAML(ConcatenatedYAML);
+  EXPECT_THAT(ConcatenatedSymbols,
+              UnorderedElementsAre(QName("clang::Foo1"),
+                                   QName("clang::Foo2")));
+}
+
+TEST_F(SymbolCollectorTest, IncludeHeaderSameAsFileURI) {
+  CollectorOpts.CollectIncludePath = true;
+  runSymbolCollector("class Foo {};", /*Main=*/"");
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(AllOf(QName("Foo"), DeclURI(TestHeaderURI),
+                                         IncludeHeader(TestHeaderURI))));
+}
+
+#ifndef _WIN32
+TEST_F(SymbolCollectorTest, CanonicalSTLHeader) {
+  CollectorOpts.CollectIncludePath = true;
+  CanonicalIncludes Includes;
+  addSystemHeadersMapping(&Includes);
+  CollectorOpts.Includes = &Includes;
+  // bits/basic_string.h$ should be mapped to <string>
+  TestHeaderName = "/nasty/bits/basic_string.h";
+  TestFileName = "/nasty/bits/basic_string.cpp";
+  TestHeaderURI = URI::createFile(TestHeaderName).toString();
+  runSymbolCollector("class string {};", /*Main=*/"");
+  EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("string"),
+                                                  DeclURI(TestHeaderURI),
+                                                  IncludeHeader("<string>"))));
+}
+#endif
+
+TEST_F(SymbolCollectorTest, STLiosfwd) {
+  CollectorOpts.CollectIncludePath = true;
+  CanonicalIncludes Includes;
+  addSystemHeadersMapping(&Includes);
+  CollectorOpts.Includes = &Includes;
+  // Symbols from <iosfwd> should be mapped individually.
+  TestHeaderName = testPath("iosfwd");
+  TestFileName = testPath("iosfwd.cpp");
+  std::string Header = R"(
+    namespace std {
+      class no_map {};
+      class ios {};
+      class ostream {};
+      class filebuf {};
+    } // namespace std
+  )";
+  runSymbolCollector(Header, /*Main=*/"");
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(
+                  QName("std"),
+                  AllOf(QName("std::no_map"), IncludeHeader("<iosfwd>")),
+                  AllOf(QName("std::ios"), IncludeHeader("<ios>")),
+                  AllOf(QName("std::ostream"), IncludeHeader("<ostream>")),
+                  AllOf(QName("std::filebuf"), IncludeHeader("<fstream>"))));
+}
+
+TEST_F(SymbolCollectorTest, IWYUPragma) {
+  CollectorOpts.CollectIncludePath = true;
+  CanonicalIncludes Includes;
+  PragmaHandler = collectIWYUHeaderMaps(&Includes);
+  CollectorOpts.Includes = &Includes;
+  const std::string Header = R"(
+    // IWYU pragma: private, include the/good/header.h
+    class Foo {};
+  )";
+  runSymbolCollector(Header, /*Main=*/"");
+  EXPECT_THAT(Symbols, UnorderedElementsAre(
+                           AllOf(QName("Foo"), DeclURI(TestHeaderURI),
+                                 IncludeHeader("\"the/good/header.h\""))));
+}
+
+TEST_F(SymbolCollectorTest, IWYUPragmaWithDoubleQuotes) {
+  CollectorOpts.CollectIncludePath = true;
+  CanonicalIncludes Includes;
+  PragmaHandler = collectIWYUHeaderMaps(&Includes);
+  CollectorOpts.Includes = &Includes;
+  const std::string Header = R"(
+    // IWYU pragma: private, include "the/good/header.h"
+    class Foo {};
+  )";
+  runSymbolCollector(Header, /*Main=*/"");
+  EXPECT_THAT(Symbols, UnorderedElementsAre(
+                           AllOf(QName("Foo"), DeclURI(TestHeaderURI),
+                                 IncludeHeader("\"the/good/header.h\""))));
+}
+
+TEST_F(SymbolCollectorTest, SkipIncFileWhenCanonicalizeHeaders) {
+  CollectorOpts.CollectIncludePath = true;
+  CanonicalIncludes Includes;
+  Includes.addMapping(TestHeaderName, "<canonical>");
+  CollectorOpts.Includes = &Includes;
+  auto IncFile = testPath("test.inc");
+  auto IncURI = URI::createFile(IncFile).toString();
+  InMemoryFileSystem->addFile(IncFile, 0,
+                              llvm::MemoryBuffer::getMemBuffer("class X {};"));
+  runSymbolCollector("#include \"test.inc\"\nclass Y {};", /*Main=*/"",
+                     /*ExtraArgs=*/{"-I", testRoot()});
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
+                                         IncludeHeader("<canonical>")),
+                                   AllOf(QName("Y"), DeclURI(TestHeaderURI),
+                                         IncludeHeader("<canonical>"))));
+}
+
+TEST_F(SymbolCollectorTest, MainFileIsHeaderWhenSkipIncFile) {
+  CollectorOpts.CollectIncludePath = true;
+  CanonicalIncludes Includes;
+  CollectorOpts.Includes = &Includes;
+  TestFileName = testPath("main.h");
+  TestFileURI = URI::createFile(TestFileName).toString();
+  auto IncFile = testPath("test.inc");
+  auto IncURI = URI::createFile(IncFile).toString();
+  InMemoryFileSystem->addFile(IncFile, 0,
+                              llvm::MemoryBuffer::getMemBuffer("class X {};"));
+  runSymbolCollector("", /*Main=*/"#include \"test.inc\"",
+                     /*ExtraArgs=*/{"-I", testRoot()});
+  EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
+                                                  IncludeHeader(TestFileURI))));
+}
+
+TEST_F(SymbolCollectorTest, MainFileIsHeaderWithoutExtensionWhenSkipIncFile) {
+  CollectorOpts.CollectIncludePath = true;
+  CanonicalIncludes Includes;
+  CollectorOpts.Includes = &Includes;
+  TestFileName = testPath("no_ext_main");
+  TestFileURI = URI::createFile(TestFileName).toString();
+  auto IncFile = testPath("test.inc");
+  auto IncURI = URI::createFile(IncFile).toString();
+  InMemoryFileSystem->addFile(IncFile, 0,
+                              llvm::MemoryBuffer::getMemBuffer("class X {};"));
+  runSymbolCollector("", /*Main=*/"#include \"test.inc\"",
+                     /*ExtraArgs=*/{"-I", testRoot()});
+  EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
+                                                  IncludeHeader(TestFileURI))));
+}
+
+TEST_F(SymbolCollectorTest, FallbackToIncFileWhenIncludingFileIsCC) {
+  CollectorOpts.CollectIncludePath = true;
+  CanonicalIncludes Includes;
+  CollectorOpts.Includes = &Includes;
+  auto IncFile = testPath("test.inc");
+  auto IncURI = URI::createFile(IncFile).toString();
+  InMemoryFileSystem->addFile(IncFile, 0,
+                              llvm::MemoryBuffer::getMemBuffer("class X {};"));
+  runSymbolCollector("", /*Main=*/"#include \"test.inc\"",
+                     /*ExtraArgs=*/{"-I", testRoot()});
+  EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
+                                                  IncludeHeader(IncURI))));
+}
+
+TEST_F(SymbolCollectorTest, AvoidUsingFwdDeclsAsCanonicalDecls) {
+  CollectorOpts.CollectIncludePath = true;
+  Annotations Header(R"(
+    // Forward declarations of TagDecls.
+    class C;
+    struct S;
+    union U;
+
+    // Canonical declarations.
+    class $cdecl[[C]] {};
+    struct $sdecl[[S]] {};
+    union $udecl[[U]] {int $xdecl[[x]]; bool $ydecl[[y]];};
+  )");
+  runSymbolCollector(Header.code(), /*Main=*/"");
+  EXPECT_THAT(
+      Symbols,
+      UnorderedElementsAre(
+          AllOf(QName("C"), DeclURI(TestHeaderURI),
+                DeclRange(Header.range("cdecl")), IncludeHeader(TestHeaderURI),
+                DefURI(TestHeaderURI), DefRange(Header.range("cdecl"))),
+          AllOf(QName("S"), DeclURI(TestHeaderURI),
+                DeclRange(Header.range("sdecl")), IncludeHeader(TestHeaderURI),
+                DefURI(TestHeaderURI), DefRange(Header.range("sdecl"))),
+          AllOf(QName("U"), DeclURI(TestHeaderURI),
+                DeclRange(Header.range("udecl")), IncludeHeader(TestHeaderURI),
+                DefURI(TestHeaderURI), DefRange(Header.range("udecl"))),
+          AllOf(QName("U::x"), DeclURI(TestHeaderURI),
+                DeclRange(Header.range("xdecl")), DefURI(TestHeaderURI),
+                DefRange(Header.range("xdecl"))),
+          AllOf(QName("U::y"), DeclURI(TestHeaderURI),
+                DeclRange(Header.range("ydecl")), DefURI(TestHeaderURI),
+                DefRange(Header.range("ydecl")))));
+}
+
+TEST_F(SymbolCollectorTest, ClassForwardDeclarationIsCanonical) {
+  CollectorOpts.CollectIncludePath = true;
+  runSymbolCollector(/*Header=*/"class X;", /*Main=*/"class X {};");
+  EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(
+                           QName("X"), DeclURI(TestHeaderURI),
+                           IncludeHeader(TestHeaderURI), DefURI(TestFileURI))));
+}
+
+TEST_F(SymbolCollectorTest, UTF16Character) {
+  // ö is 2-bytes.
+  Annotations Header(/*Header=*/"class [[pörk]] {};");
+  runSymbolCollector(Header.code(), /*Main=*/"");
+  EXPECT_THAT(Symbols, UnorderedElementsAre(
+                           AllOf(QName("pörk"), DeclRange(Header.range()))));
+}
+
+TEST_F(SymbolCollectorTest, DoNotIndexSymbolsInFriendDecl) {
+  Annotations Header(R"(
+    namespace nx {
+      class $z[[Z]] {};
+      class X {
+        friend class Y;
+        friend class Z;
+        friend void foo();
+        friend void $bar[[bar]]() {}
+      };
+      class $y[[Y]] {};
+      void $foo[[foo]]();
+    }
+  )");
+  runSymbolCollector(Header.code(), /*Main=*/"");
+
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(
+                  QName("nx"), QName("nx::X"),
+                  AllOf(QName("nx::Y"), DeclRange(Header.range("y"))),
+                  AllOf(QName("nx::Z"), DeclRange(Header.range("z"))),
+                  AllOf(QName("nx::foo"), DeclRange(Header.range("foo"))),
+                  AllOf(QName("nx::bar"), DeclRange(Header.range("bar")))));
+}
+
+TEST_F(SymbolCollectorTest, ReferencesInFriendDecl) {
+  const std::string Header = R"(
+    class X;
+    class Y;
+  )";
+  const std::string Main = R"(
+    class C {
+      friend ::X;
+      friend class Y;
+    };
+  )";
+  CollectorOpts.CountReferences = true;
+  runSymbolCollector(Header, Main);
+  EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), Refs(1)),
+                                            AllOf(QName("Y"), Refs(1))));
+}
+
+TEST_F(SymbolCollectorTest, Origin) {
+  CollectorOpts.Origin = SymbolOrigin::Static;
+  runSymbolCollector("class Foo {};", /*Main=*/"");
+  EXPECT_THAT(Symbols, UnorderedElementsAre(
+                           Field(&Symbol::Origin, SymbolOrigin::Static)));
+}
+
+TEST_F(SymbolCollectorTest, CollectMacros) {
+  CollectorOpts.CollectIncludePath = true;
+  Annotations Header(R"(
+    #define X 1
+    #define $mac[[MAC]](x) int x
+    #define $used[[USED]](y) float y;
+
+    MAC(p);
+  )");
+  const std::string Main = R"(
+    #define MAIN 1  // not indexed
+    USED(t);
+  )";
+  CollectorOpts.CountReferences = true;
+  CollectorOpts.CollectMacro = true;
+  runSymbolCollector(Header.code(), Main);
+  EXPECT_THAT(
+      Symbols,
+      UnorderedElementsAre(
+          QName("p"),
+          AllOf(QName("X"), DeclURI(TestHeaderURI),
+                IncludeHeader(TestHeaderURI)),
+          AllOf(Labeled("MAC(x)"), Refs(0), DeclRange(Header.range("mac"))),
+          AllOf(Labeled("USED(y)"), Refs(1), DeclRange(Header.range("used")))));
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/SyncAPI.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/SyncAPI.cpp
new file mode 100644
index 0000000..ae9ece5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/SyncAPI.cpp
@@ -0,0 +1,128 @@
+//===--- SyncAPI.cpp - Sync version of ClangdServer's API --------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+#include "SyncAPI.h"
+
+namespace clang {
+namespace clangd {
+
+void runAddDocument(ClangdServer &Server, PathRef File, StringRef Contents,
+                    WantDiagnostics WantDiags) {
+  Server.addDocument(File, Contents, WantDiags);
+  if (!Server.blockUntilIdleForTest())
+    llvm_unreachable("not idle after addDocument");
+}
+
+namespace {
+/// A helper that waits for async callbacks to fire and exposes their result in
+/// the output variable. Intended to be used in the following way:
+///    T Result;
+///    someAsyncFunc(Param1, Param2, /*Callback=*/capture(Result));
+template <typename T> struct CaptureProxy {
+  CaptureProxy(llvm::Optional<T> &Target) : Target(&Target) {
+    assert(!Target.hasValue());
+  }
+
+  CaptureProxy(const CaptureProxy &) = delete;
+  CaptureProxy &operator=(const CaptureProxy &) = delete;
+  // We need move ctor to return a value from the 'capture' helper.
+  CaptureProxy(CaptureProxy &&Other) : Target(Other.Target) {
+    Other.Target = nullptr;
+  }
+  CaptureProxy &operator=(CaptureProxy &&) = delete;
+
+  operator llvm::unique_function<void(T)>() && {
+    assert(!Future.valid() && "conversion to callback called multiple times");
+    Future = Promise.get_future();
+    return Bind(
+        [](std::promise<std::shared_ptr<T>> Promise, T Value) {
+          Promise.set_value(std::make_shared<T>(std::move(Value)));
+        },
+        std::move(Promise));
+  }
+
+  ~CaptureProxy() {
+    if (!Target)
+      return;
+    assert(Future.valid() && "conversion to callback was not called");
+    assert(!Target->hasValue());
+    Target->emplace(std::move(*Future.get()));
+  }
+
+private:
+  llvm::Optional<T> *Target;
+  // Using shared_ptr to workaround compilation errors with MSVC.
+  // MSVC only allows default-construcitble and copyable objects as future<>
+  // arguments.
+  std::promise<std::shared_ptr<T>> Promise;
+  std::future<std::shared_ptr<T>> Future;
+};
+
+template <typename T> CaptureProxy<T> capture(llvm::Optional<T> &Target) {
+  return CaptureProxy<T>(Target);
+}
+} // namespace
+
+llvm::Expected<CodeCompleteResult>
+runCodeComplete(ClangdServer &Server, PathRef File, Position Pos,
+                clangd::CodeCompleteOptions Opts) {
+  llvm::Optional<llvm::Expected<CodeCompleteResult>> Result;
+  Server.codeComplete(File, Pos, Opts, capture(Result));
+  return std::move(*Result);
+}
+
+llvm::Expected<SignatureHelp> runSignatureHelp(ClangdServer &Server,
+                                               PathRef File, Position Pos) {
+  llvm::Optional<llvm::Expected<SignatureHelp>> Result;
+  Server.signatureHelp(File, Pos, capture(Result));
+  return std::move(*Result);
+}
+
+llvm::Expected<std::vector<Location>>
+runFindDefinitions(ClangdServer &Server, PathRef File, Position Pos) {
+  llvm::Optional<llvm::Expected<std::vector<Location>>> Result;
+  Server.findDefinitions(File, Pos, capture(Result));
+  return std::move(*Result);
+}
+
+llvm::Expected<std::vector<DocumentHighlight>>
+runFindDocumentHighlights(ClangdServer &Server, PathRef File, Position Pos) {
+  llvm::Optional<llvm::Expected<std::vector<DocumentHighlight>>> Result;
+  Server.findDocumentHighlights(File, Pos, capture(Result));
+  return std::move(*Result);
+}
+
+llvm::Expected<std::vector<tooling::Replacement>>
+runRename(ClangdServer &Server, PathRef File, Position Pos, StringRef NewName) {
+  llvm::Optional<llvm::Expected<std::vector<tooling::Replacement>>> Result;
+  Server.rename(File, Pos, NewName, capture(Result));
+  return std::move(*Result);
+}
+
+std::string runDumpAST(ClangdServer &Server, PathRef File) {
+  llvm::Optional<std::string> Result;
+  Server.dumpAST(File, capture(Result));
+  return std::move(*Result);
+}
+
+llvm::Expected<std::vector<SymbolInformation>>
+runWorkspaceSymbols(ClangdServer &Server, StringRef Query, int Limit) {
+  llvm::Optional<llvm::Expected<std::vector<SymbolInformation>>> Result;
+  Server.workspaceSymbols(Query, Limit, capture(Result));
+  return std::move(*Result);
+}
+
+llvm::Expected<std::vector<SymbolInformation>>
+runDocumentSymbols(ClangdServer &Server, PathRef File) {
+  llvm::Optional<llvm::Expected<std::vector<SymbolInformation>>> Result;
+  Server.documentSymbols(File, capture(Result));
+  return std::move(*Result);
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/SyncAPI.h b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/SyncAPI.h
new file mode 100644
index 0000000..ddf90d8
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/SyncAPI.h
@@ -0,0 +1,52 @@
+//===--- SyncAPI.h - Sync version of ClangdServer's API ----------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// This file contains synchronous versions of ClangdServer's async API. We
+// deliberately don't expose the sync API outside tests to encourage using the
+// async versions in clangd code.
+#ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_SYNCAPI_H
+#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_SYNCAPI_H
+
+#include "ClangdServer.h"
+#include <future>
+
+namespace clang {
+namespace clangd {
+
+// Calls addDocument and then blockUntilIdleForTest.
+void runAddDocument(ClangdServer &Server, PathRef File, StringRef Contents,
+                    WantDiagnostics WantDiags = WantDiagnostics::Auto);
+
+llvm::Expected<CodeCompleteResult>
+runCodeComplete(ClangdServer &Server, PathRef File, Position Pos,
+                clangd::CodeCompleteOptions Opts);
+
+llvm::Expected<SignatureHelp> runSignatureHelp(ClangdServer &Server,
+                                               PathRef File, Position Pos);
+
+llvm::Expected<std::vector<Location>>
+runFindDefinitions(ClangdServer &Server, PathRef File, Position Pos);
+
+llvm::Expected<std::vector<DocumentHighlight>>
+runFindDocumentHighlights(ClangdServer &Server, PathRef File, Position Pos);
+
+llvm::Expected<std::vector<tooling::Replacement>>
+runRename(ClangdServer &Server, PathRef File, Position Pos, StringRef NewName);
+
+std::string runDumpAST(ClangdServer &Server, PathRef File);
+
+llvm::Expected<std::vector<SymbolInformation>>
+runWorkspaceSymbols(ClangdServer &Server, StringRef Query, int Limit);
+
+llvm::Expected<std::vector<SymbolInformation>>
+runDocumentSymbols(ClangdServer &Server, PathRef File);
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TUSchedulerTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TUSchedulerTests.cpp
new file mode 100644
index 0000000..138a4e2
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TUSchedulerTests.cpp
@@ -0,0 +1,428 @@
+//===-- TUSchedulerTests.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Context.h"
+#include "TUScheduler.h"
+#include "TestFS.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <algorithm>
+#include <utility>
+
+namespace clang {
+namespace clangd {
+
+using ::testing::_;
+using ::testing::Each;
+using ::testing::AnyOf;
+using ::testing::Pair;
+using ::testing::Pointee;
+using ::testing::UnorderedElementsAre;
+
+void ignoreUpdate(llvm::Optional<std::vector<Diag>>) {}
+void ignoreError(llvm::Error Err) {
+  handleAllErrors(std::move(Err), [](const llvm::ErrorInfoBase &) {});
+}
+
+class TUSchedulerTests : public ::testing::Test {
+protected:
+  ParseInputs getInputs(PathRef File, std::string Contents) {
+    return ParseInputs{*CDB.getCompileCommand(File),
+                       buildTestFS(Files, Timestamps), std::move(Contents)};
+  }
+
+  llvm::StringMap<std::string> Files;
+  llvm::StringMap<time_t> Timestamps;
+  MockCompilationDatabase CDB;
+};
+
+TEST_F(TUSchedulerTests, MissingFiles) {
+  TUScheduler S(getDefaultAsyncThreadsCount(),
+                /*StorePreamblesInMemory=*/true,
+                /*PreambleParsedCallback=*/nullptr,
+                /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
+                ASTRetentionPolicy());
+
+  auto Added = testPath("added.cpp");
+  Files[Added] = "";
+
+  auto Missing = testPath("missing.cpp");
+  Files[Missing] = "";
+
+  S.update(Added, getInputs(Added, ""), WantDiagnostics::No, ignoreUpdate);
+
+  // Assert each operation for missing file is an error (even if it's available
+  // in VFS).
+  S.runWithAST("", Missing, [&](llvm::Expected<InputsAndAST> AST) {
+    ASSERT_FALSE(bool(AST));
+    ignoreError(AST.takeError());
+  });
+  S.runWithPreamble("", Missing,
+                    [&](llvm::Expected<InputsAndPreamble> Preamble) {
+                      ASSERT_FALSE(bool(Preamble));
+                      ignoreError(Preamble.takeError());
+                    });
+  // remove() shouldn't crash on missing files.
+  S.remove(Missing);
+
+  // Assert there aren't any errors for added file.
+  S.runWithAST("", Added, [&](llvm::Expected<InputsAndAST> AST) {
+    EXPECT_TRUE(bool(AST));
+  });
+  S.runWithPreamble("", Added, [&](llvm::Expected<InputsAndPreamble> Preamble) {
+    EXPECT_TRUE(bool(Preamble));
+  });
+  S.remove(Added);
+
+  // Assert that all operations fail after removing the file.
+  S.runWithAST("", Added, [&](llvm::Expected<InputsAndAST> AST) {
+    ASSERT_FALSE(bool(AST));
+    ignoreError(AST.takeError());
+  });
+  S.runWithPreamble("", Added, [&](llvm::Expected<InputsAndPreamble> Preamble) {
+    ASSERT_FALSE(bool(Preamble));
+    ignoreError(Preamble.takeError());
+  });
+  // remove() shouldn't crash on missing files.
+  S.remove(Added);
+}
+
+TEST_F(TUSchedulerTests, WantDiagnostics) {
+  std::atomic<int> CallbackCount(0);
+  {
+    // To avoid a racy test, don't allow tasks to actualy run on the worker
+    // thread until we've scheduled them all.
+    Notification Ready;
+    TUScheduler S(
+        getDefaultAsyncThreadsCount(),
+        /*StorePreamblesInMemory=*/true,
+        /*PreambleParsedCallback=*/nullptr,
+        /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
+        ASTRetentionPolicy());
+    auto Path = testPath("foo.cpp");
+    S.update(Path, getInputs(Path, ""), WantDiagnostics::Yes,
+             [&](std::vector<Diag>) { Ready.wait(); });
+
+    S.update(Path, getInputs(Path, "request diags"), WantDiagnostics::Yes,
+             [&](std::vector<Diag> Diags) { ++CallbackCount; });
+    S.update(Path, getInputs(Path, "auto (clobbered)"), WantDiagnostics::Auto,
+             [&](std::vector<Diag> Diags) {
+               ADD_FAILURE() << "auto should have been cancelled by auto";
+             });
+    S.update(Path, getInputs(Path, "request no diags"), WantDiagnostics::No,
+             [&](std::vector<Diag> Diags) {
+               ADD_FAILURE() << "no diags should not be called back";
+             });
+    S.update(Path, getInputs(Path, "auto (produces)"), WantDiagnostics::Auto,
+             [&](std::vector<Diag> Diags) { ++CallbackCount; });
+    Ready.notify();
+  }
+  EXPECT_EQ(2, CallbackCount);
+}
+
+TEST_F(TUSchedulerTests, Debounce) {
+  std::atomic<int> CallbackCount(0);
+  {
+    TUScheduler S(getDefaultAsyncThreadsCount(),
+                  /*StorePreamblesInMemory=*/true,
+                  /*PreambleParsedCallback=*/nullptr,
+                  /*UpdateDebounce=*/std::chrono::seconds(1),
+                  ASTRetentionPolicy());
+    // FIXME: we could probably use timeouts lower than 1 second here.
+    auto Path = testPath("foo.cpp");
+    S.update(Path, getInputs(Path, "auto (debounced)"), WantDiagnostics::Auto,
+             [&](std::vector<Diag> Diags) {
+               ADD_FAILURE() << "auto should have been debounced and canceled";
+             });
+    std::this_thread::sleep_for(std::chrono::milliseconds(200));
+    S.update(Path, getInputs(Path, "auto (timed out)"), WantDiagnostics::Auto,
+             [&](std::vector<Diag> Diags) { ++CallbackCount; });
+    std::this_thread::sleep_for(std::chrono::seconds(2));
+    S.update(Path, getInputs(Path, "auto (shut down)"), WantDiagnostics::Auto,
+             [&](std::vector<Diag> Diags) { ++CallbackCount; });
+  }
+  EXPECT_EQ(2, CallbackCount);
+}
+
+TEST_F(TUSchedulerTests, ManyUpdates) {
+  const int FilesCount = 3;
+  const int UpdatesPerFile = 10;
+
+  std::mutex Mut;
+  int TotalASTReads = 0;
+  int TotalPreambleReads = 0;
+  int TotalUpdates = 0;
+
+  // Run TUScheduler and collect some stats.
+  {
+    TUScheduler S(getDefaultAsyncThreadsCount(),
+                  /*StorePreamblesInMemory=*/true,
+                  /*PreambleParsedCallback=*/nullptr,
+                  /*UpdateDebounce=*/std::chrono::milliseconds(50),
+                  ASTRetentionPolicy());
+
+    std::vector<std::string> Files;
+    for (int I = 0; I < FilesCount; ++I) {
+      std::string Name = "foo" + std::to_string(I) + ".cpp";
+      Files.push_back(testPath(Name));
+      this->Files[Files.back()] = "";
+    }
+
+    llvm::StringRef Contents1 = R"cpp(int a;)cpp";
+    llvm::StringRef Contents2 = R"cpp(int main() { return 1; })cpp";
+    llvm::StringRef Contents3 =
+        R"cpp(int a; int b; int sum() { return a + b; })cpp";
+
+    llvm::StringRef AllContents[] = {Contents1, Contents2, Contents3};
+    const int AllContentsSize = 3;
+
+    // Scheduler may run tasks asynchronously, but should propagate the context.
+    // We stash a nonce in the context, and verify it in the task.
+    static Key<int> NonceKey;
+    int Nonce = 0;
+
+    for (int FileI = 0; FileI < FilesCount; ++FileI) {
+      for (int UpdateI = 0; UpdateI < UpdatesPerFile; ++UpdateI) {
+        auto Contents = AllContents[(FileI + UpdateI) % AllContentsSize];
+
+        auto File = Files[FileI];
+        auto Inputs = getInputs(File, Contents.str());
+
+        {
+          WithContextValue WithNonce(NonceKey, ++Nonce);
+          S.update(File, Inputs, WantDiagnostics::Auto,
+                   [Nonce, &Mut,
+                    &TotalUpdates](llvm::Optional<std::vector<Diag>> Diags) {
+                     EXPECT_THAT(Context::current().get(NonceKey),
+                                 Pointee(Nonce));
+
+                     std::lock_guard<std::mutex> Lock(Mut);
+                     ++TotalUpdates;
+                   });
+        }
+
+        {
+          WithContextValue WithNonce(NonceKey, ++Nonce);
+          S.runWithAST("CheckAST", File,
+                       [Inputs, Nonce, &Mut,
+                        &TotalASTReads](llvm::Expected<InputsAndAST> AST) {
+                         EXPECT_THAT(Context::current().get(NonceKey),
+                                     Pointee(Nonce));
+
+                         ASSERT_TRUE((bool)AST);
+                         EXPECT_EQ(AST->Inputs.FS, Inputs.FS);
+                         EXPECT_EQ(AST->Inputs.Contents, Inputs.Contents);
+
+                         std::lock_guard<std::mutex> Lock(Mut);
+                         ++TotalASTReads;
+                       });
+        }
+
+        {
+          WithContextValue WithNonce(NonceKey, ++Nonce);
+          S.runWithPreamble("CheckPreamble", File,
+                            [Inputs, Nonce, &Mut, &TotalPreambleReads](
+                                llvm::Expected<InputsAndPreamble> Preamble) {
+                              EXPECT_THAT(Context::current().get(NonceKey),
+                                          Pointee(Nonce));
+
+                              ASSERT_TRUE((bool)Preamble);
+                              EXPECT_EQ(Preamble->Contents, Inputs.Contents);
+
+                              std::lock_guard<std::mutex> Lock(Mut);
+                              ++TotalPreambleReads;
+                            });
+        }
+      }
+    }
+  } // TUScheduler destructor waits for all operations to finish.
+
+  std::lock_guard<std::mutex> Lock(Mut);
+  EXPECT_EQ(TotalUpdates, FilesCount * UpdatesPerFile);
+  EXPECT_EQ(TotalASTReads, FilesCount * UpdatesPerFile);
+  EXPECT_EQ(TotalPreambleReads, FilesCount * UpdatesPerFile);
+}
+
+TEST_F(TUSchedulerTests, EvictedAST) {
+  std::atomic<int> BuiltASTCounter(0);
+  ASTRetentionPolicy Policy;
+  Policy.MaxRetainedASTs = 2;
+  TUScheduler S(
+      /*AsyncThreadsCount=*/1, /*StorePreambleInMemory=*/true,
+      PreambleParsedCallback(),
+      /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(), Policy);
+
+  llvm::StringLiteral SourceContents = R"cpp(
+    int* a;
+    double* b = a;
+  )cpp";
+  llvm::StringLiteral OtherSourceContents = R"cpp(
+    int* a;
+    double* b = a + 0;
+  )cpp";
+
+  auto Foo = testPath("foo.cpp");
+  auto Bar = testPath("bar.cpp");
+  auto Baz = testPath("baz.cpp");
+
+  // Build one file in advance. We will not access it later, so it will be the
+  // one that the cache will evict.
+  S.update(Foo, getInputs(Foo, SourceContents), WantDiagnostics::Yes,
+           [&BuiltASTCounter](std::vector<Diag> Diags) { ++BuiltASTCounter; });
+  ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(1)));
+  ASSERT_EQ(BuiltASTCounter.load(), 1);
+
+  // Build two more files. Since we can retain only 2 ASTs, these should be the
+  // ones we see in the cache later.
+  S.update(Bar, getInputs(Bar, SourceContents), WantDiagnostics::Yes,
+           [&BuiltASTCounter](std::vector<Diag> Diags) { ++BuiltASTCounter; });
+  S.update(Baz, getInputs(Baz, SourceContents), WantDiagnostics::Yes,
+           [&BuiltASTCounter](std::vector<Diag> Diags) { ++BuiltASTCounter; });
+  ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(1)));
+  ASSERT_EQ(BuiltASTCounter.load(), 3);
+
+  // Check only the last two ASTs are retained.
+  ASSERT_THAT(S.getFilesWithCachedAST(), UnorderedElementsAre(Bar, Baz));
+
+  // Access the old file again.
+  S.update(Foo, getInputs(Foo, OtherSourceContents), WantDiagnostics::Yes,
+           [&BuiltASTCounter](std::vector<Diag> Diags) { ++BuiltASTCounter; });
+  ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(1)));
+  ASSERT_EQ(BuiltASTCounter.load(), 4);
+
+  // Check the AST for foo.cpp is retained now and one of the others got
+  // evicted.
+  EXPECT_THAT(S.getFilesWithCachedAST(),
+              UnorderedElementsAre(Foo, AnyOf(Bar, Baz)));
+}
+
+TEST_F(TUSchedulerTests, RunWaitsForPreamble) {
+  // Testing strategy: we update the file and schedule a few preamble reads at
+  // the same time. All reads should get the same non-null preamble.
+  TUScheduler S(
+      /*AsyncThreadsCount=*/4, /*StorePreambleInMemory=*/true,
+      PreambleParsedCallback(),
+      /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
+      ASTRetentionPolicy());
+  auto Foo = testPath("foo.cpp");
+  auto NonEmptyPreamble = R"cpp(
+    #define FOO 1
+    #define BAR 2
+
+    int main() {}
+  )cpp";
+  constexpr int ReadsToSchedule = 10;
+  std::mutex PreamblesMut;
+  std::vector<const void *> Preambles(ReadsToSchedule, nullptr);
+  S.update(Foo, getInputs(Foo, NonEmptyPreamble), WantDiagnostics::Auto,
+           [](std::vector<Diag>) {});
+  for (int I = 0; I < ReadsToSchedule; ++I) {
+    S.runWithPreamble(
+        "test", Foo,
+        [I, &PreamblesMut, &Preambles](llvm::Expected<InputsAndPreamble> IP) {
+          std::lock_guard<std::mutex> Lock(PreamblesMut);
+          Preambles[I] = cantFail(std::move(IP)).Preamble;
+        });
+  }
+  ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(10)));
+  // Check all actions got the same non-null preamble.
+  std::lock_guard<std::mutex> Lock(PreamblesMut);
+  ASSERT_NE(Preambles[0], nullptr);
+  ASSERT_THAT(Preambles, Each(Preambles[0]));
+}
+
+TEST_F(TUSchedulerTests, NoopOnEmptyChanges) {
+  TUScheduler S(
+      /*AsyncThreadsCount=*/getDefaultAsyncThreadsCount(),
+      /*StorePreambleInMemory=*/true, PreambleParsedCallback(),
+      /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
+      ASTRetentionPolicy());
+
+  auto Source = testPath("foo.cpp");
+  auto Header = testPath("foo.h");
+
+  Files[Header] = "int a;";
+  Timestamps[Header] = time_t(0);
+
+  auto SourceContents = R"cpp(
+      #include "foo.h"
+      int b = a;
+    )cpp";
+
+  // Return value indicates if the updated callback was received.
+  auto DoUpdate = [&](ParseInputs Inputs) -> bool {
+    std::atomic<bool> Updated(false);
+    Updated = false;
+    S.update(Source, std::move(Inputs), WantDiagnostics::Yes,
+             [&Updated](std::vector<Diag>) { Updated = true; });
+    bool UpdateFinished = S.blockUntilIdle(timeoutSeconds(1));
+    if (!UpdateFinished)
+      ADD_FAILURE() << "Updated has not finished in one second. Threading bug?";
+    return Updated;
+  };
+
+  // Test that subsequent updates with the same inputs do not cause rebuilds.
+  ASSERT_TRUE(DoUpdate(getInputs(Source, SourceContents)));
+  ASSERT_FALSE(DoUpdate(getInputs(Source, SourceContents)));
+
+  // Update to a header should cause a rebuild, though.
+  Files[Header] = time_t(1);
+  ASSERT_TRUE(DoUpdate(getInputs(Source, SourceContents)));
+  ASSERT_FALSE(DoUpdate(getInputs(Source, SourceContents)));
+
+  // Update to the contents should cause a rebuild.
+  auto OtherSourceContents = R"cpp(
+      #include "foo.h"
+      int c = d;
+    )cpp";
+  ASSERT_TRUE(DoUpdate(getInputs(Source, OtherSourceContents)));
+  ASSERT_FALSE(DoUpdate(getInputs(Source, OtherSourceContents)));
+
+  // Update to the compile commands should also cause a rebuild.
+  CDB.ExtraClangFlags.push_back("-DSOMETHING");
+  ASSERT_TRUE(DoUpdate(getInputs(Source, OtherSourceContents)));
+  ASSERT_FALSE(DoUpdate(getInputs(Source, OtherSourceContents)));
+}
+
+TEST_F(TUSchedulerTests, NoChangeDiags) {
+  TUScheduler S(
+      /*AsyncThreadsCount=*/getDefaultAsyncThreadsCount(),
+      /*StorePreambleInMemory=*/true, PreambleParsedCallback(),
+      /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
+      ASTRetentionPolicy());
+
+  auto FooCpp = testPath("foo.cpp");
+  auto Contents = "int a; int b;";
+
+  S.update(FooCpp, getInputs(FooCpp, Contents), WantDiagnostics::No,
+           [](std::vector<Diag>) { ADD_FAILURE() << "Should not be called."; });
+  S.runWithAST("touchAST", FooCpp, [](llvm::Expected<InputsAndAST> IA) {
+    // Make sure the AST was actually built.
+    cantFail(std::move(IA));
+  });
+  ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(1)));
+
+  // Even though the inputs didn't change and AST can be reused, we need to
+  // report the diagnostics, as they were not reported previously.
+  std::atomic<bool> SeenDiags(false);
+  S.update(FooCpp, getInputs(FooCpp, Contents), WantDiagnostics::Auto,
+           [&](std::vector<Diag>) { SeenDiags = true; });
+  ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(1)));
+  ASSERT_TRUE(SeenDiags);
+
+  // Subsequent request does not get any diagnostics callback because the same
+  // diags have previously been reported and the inputs didn't change.
+  S.update(
+      FooCpp, getInputs(FooCpp, Contents), WantDiagnostics::Auto,
+      [&](std::vector<Diag>) { ADD_FAILURE() << "Should not be called."; });
+  ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(1)));
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TestFS.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TestFS.cpp
new file mode 100644
index 0000000..b3081d6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TestFS.cpp
@@ -0,0 +1,111 @@
+//===-- TestFS.cpp ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "TestFS.h"
+#include "URI.h"
+#include "clang/AST/DeclCXX.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Path.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+using namespace llvm;
+
+IntrusiveRefCntPtr<vfs::FileSystem>
+buildTestFS(llvm::StringMap<std::string> const &Files,
+            llvm::StringMap<time_t> const &Timestamps) {
+  IntrusiveRefCntPtr<vfs::InMemoryFileSystem> MemFS(
+      new vfs::InMemoryFileSystem);
+  for (auto &FileAndContents : Files) {
+    StringRef File = FileAndContents.first();
+    MemFS->addFile(
+        File, Timestamps.lookup(File),
+        MemoryBuffer::getMemBufferCopy(FileAndContents.second, File));
+  }
+  return MemFS;
+}
+
+MockCompilationDatabase::MockCompilationDatabase(bool UseRelPaths)
+    : ExtraClangFlags({"-ffreestanding"}), UseRelPaths(UseRelPaths) {
+  // -ffreestanding avoids implicit stdc-predef.h.
+}
+
+Optional<tooling::CompileCommand>
+MockCompilationDatabase::getCompileCommand(PathRef File) const {
+  if (ExtraClangFlags.empty())
+    return None;
+
+  auto CommandLine = ExtraClangFlags;
+  auto FileName = sys::path::filename(File);
+  CommandLine.insert(CommandLine.begin(), "clang");
+  CommandLine.insert(CommandLine.end(), UseRelPaths ? FileName : File);
+  return {tooling::CompileCommand(sys::path::parent_path(File), FileName,
+                                  std::move(CommandLine), "")};
+}
+
+const char *testRoot() {
+#ifdef _WIN32
+  return "C:\\clangd-test";
+#else
+  return "/clangd-test";
+#endif
+}
+
+std::string testPath(PathRef File) {
+  assert(sys::path::is_relative(File) && "FileName should be relative");
+
+  SmallString<32> NativeFile = File;
+  sys::path::native(NativeFile);
+  SmallString<32> Path;
+  sys::path::append(Path, testRoot(), NativeFile);
+  return Path.str();
+}
+
+/// unittest: is a scheme that refers to files relative to testRoot().
+/// URI body is a path relative to testRoot() e.g. unittest:///x.h for
+/// /clangd-test/x.h.
+class TestScheme : public URIScheme {
+public:
+  static const char *Scheme;
+
+  llvm::Expected<std::string>
+  getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body,
+                  llvm::StringRef HintPath) const override {
+    assert(HintPath.startswith(testRoot()));
+    if (!Body.consume_front("/"))
+      return llvm::make_error<llvm::StringError>(
+          "Body of an unittest: URI must start with '/'",
+          llvm::inconvertibleErrorCode());
+    llvm::SmallString<16> Path(Body.begin(), Body.end());
+    llvm::sys::path::native(Path);
+    return testPath(Path);
+  }
+
+  llvm::Expected<URI>
+  uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override {
+    llvm::StringRef Body = AbsolutePath;
+    if (!Body.consume_front(testRoot()))
+      return llvm::make_error<llvm::StringError>(
+          AbsolutePath + "does not start with " + testRoot(),
+          llvm::inconvertibleErrorCode());
+
+    return URI(Scheme, /*Authority=*/"",
+               llvm::sys::path::convert_to_slash(Body));
+  }
+};
+
+const char *TestScheme::Scheme = "unittest";
+
+static URISchemeRegistry::Add<TestScheme> X(TestScheme::Scheme, "Test schema");
+
+volatile int UnittestSchemeAnchorSource = 0;
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TestFS.h b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TestFS.h
new file mode 100644
index 0000000..9c2a15e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TestFS.h
@@ -0,0 +1,67 @@
+//===-- TestFS.h ------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Allows setting up fake filesystem environments for tests.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTFS_H
+#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTFS_H
+#include "ClangdServer.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/Path.h"
+
+namespace clang {
+namespace clangd {
+
+// Builds a VFS that provides access to the provided files, plus temporary
+// directories.
+llvm::IntrusiveRefCntPtr<vfs::FileSystem>
+buildTestFS(llvm::StringMap<std::string> const &Files,
+            llvm::StringMap<time_t> const &Timestamps = {});
+
+// A VFS provider that returns TestFSes containing a provided set of files.
+class MockFSProvider : public FileSystemProvider {
+public:
+  IntrusiveRefCntPtr<vfs::FileSystem> getFileSystem() override {
+    return buildTestFS(Files);
+  }
+
+  // If relative paths are used, they are resolved with testPath().
+  llvm::StringMap<std::string> Files;
+};
+
+// A Compilation database that returns a fixed set of compile flags.
+class MockCompilationDatabase : public GlobalCompilationDatabase {
+public:
+  /// When \p UseRelPaths is true, uses relative paths in compile commands.
+  /// When \p UseRelPaths is false, uses absoulte paths.
+  MockCompilationDatabase(bool UseRelPaths = false);
+
+  llvm::Optional<tooling::CompileCommand>
+  getCompileCommand(PathRef File) const override;
+
+  std::vector<std::string> ExtraClangFlags;
+  const bool UseRelPaths;
+};
+
+// Returns an absolute (fake) test directory for this OS.
+const char *testRoot();
+
+// Returns a suitable absolute path for this OS.
+std::string testPath(PathRef File);
+
+// unittest: is a scheme that refers to files relative to testRoot()
+// This anchor is used to force the linker to link in the generated object file
+// and thus register unittest: URI scheme plugin.
+extern volatile int UnittestSchemeAnchorSource;
+
+} // namespace clangd
+} // namespace clang
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TestScheme.h b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TestScheme.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TestScheme.h
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TestTU.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TestTU.cpp
new file mode 100644
index 0000000..b47d944
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TestTU.cpp
@@ -0,0 +1,127 @@
+//===--- TestTU.cpp - Scratch source files for testing --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+#include "TestTU.h"
+#include "TestFS.h"
+#include "index/FileIndex.h"
+#include "index/MemIndex.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Frontend/Utils.h"
+
+namespace clang {
+namespace clangd {
+using namespace llvm;
+
+ParsedAST TestTU::build() const {
+  std::string FullFilename = testPath(Filename),
+              FullHeaderName = testPath(HeaderFilename);
+  std::vector<const char *> Cmd = {"clang", FullFilename.c_str()};
+  // FIXME: this shouldn't need to be conditional, but it breaks a
+  // GoToDefinition test for some reason (getMacroArgExpandedLocation fails).
+  if (!HeaderCode.empty()) {
+    Cmd.push_back("-include");
+    Cmd.push_back(FullHeaderName.c_str());
+  }
+  Cmd.insert(Cmd.end(), ExtraArgs.begin(), ExtraArgs.end());
+  auto AST = ParsedAST::build(
+      createInvocationFromCommandLine(Cmd), nullptr,
+      MemoryBuffer::getMemBufferCopy(Code),
+      std::make_shared<PCHContainerOperations>(),
+      buildTestFS({{FullFilename, Code}, {FullHeaderName, HeaderCode}}));
+  if (!AST.hasValue()) {
+    ADD_FAILURE() << "Failed to build code:\n" << Code;
+    llvm_unreachable("Failed to build TestTU!");
+  }
+  return std::move(*AST);
+}
+
+SymbolSlab TestTU::headerSymbols() const {
+  auto AST = build();
+  return indexAST(AST.getASTContext(), AST.getPreprocessorPtr());
+}
+
+std::unique_ptr<SymbolIndex> TestTU::index() const {
+  return MemIndex::build(headerSymbols());
+}
+
+const Symbol &findSymbol(const SymbolSlab &Slab, llvm::StringRef QName) {
+  const Symbol *Result = nullptr;
+  for (const Symbol &S : Slab) {
+    if (QName != (S.Scope + S.Name).str())
+      continue;
+    if (Result) {
+      ADD_FAILURE() << "Multiple symbols named " << QName << ":\n"
+                    << *Result << "\n---\n"
+                    << S;
+      assert(false && "QName is not unique");
+    }
+    Result = &S;
+  }
+  if (!Result) {
+    ADD_FAILURE() << "No symbol named " << QName << " in "
+                  << ::testing::PrintToString(Slab);
+    assert(false && "No symbol with QName");
+  }
+  return *Result;
+}
+
+const NamedDecl &findDecl(ParsedAST &AST, llvm::StringRef QName) {
+  llvm::SmallVector<llvm::StringRef, 4> Components;
+  QName.split(Components, "::");
+
+  auto &Ctx = AST.getASTContext();
+  auto LookupDecl = [&Ctx](const DeclContext &Scope,
+                           llvm::StringRef Name) -> const NamedDecl & {
+    auto LookupRes = Scope.lookup(DeclarationName(&Ctx.Idents.get(Name)));
+    assert(!LookupRes.empty() && "Lookup failed");
+    assert(LookupRes.size() == 1 && "Lookup returned multiple results");
+    return *LookupRes.front();
+  };
+
+  const DeclContext *Scope = Ctx.getTranslationUnitDecl();
+  for (auto NameIt = Components.begin(), End = Components.end() - 1;
+       NameIt != End; ++NameIt) {
+    Scope = &cast<DeclContext>(LookupDecl(*Scope, *NameIt));
+  }
+  return LookupDecl(*Scope, Components.back());
+}
+
+const NamedDecl &findAnyDecl(ParsedAST &AST,
+                             std::function<bool(const NamedDecl &)> Callback) {
+  struct Visitor : RecursiveASTVisitor<Visitor> {
+    decltype(Callback) CB;
+    llvm::SmallVector<const NamedDecl *, 1> Decls;
+    bool VisitNamedDecl(const NamedDecl *ND) {
+      if (CB(*ND))
+        Decls.push_back(ND);
+      return true;
+    }
+  } Visitor;
+  Visitor.CB = Callback;
+  for (Decl *D : AST.getLocalTopLevelDecls())
+    Visitor.TraverseDecl(D);
+  if (Visitor.Decls.size() != 1) {
+    ADD_FAILURE() << Visitor.Decls.size() << " symbols matched.";
+    assert(Visitor.Decls.size() == 1);
+  }
+  return *Visitor.Decls.front();
+}
+
+const NamedDecl &findAnyDecl(ParsedAST &AST, llvm::StringRef Name) {
+  return findAnyDecl(AST, [Name](const NamedDecl &ND) {
+    if (auto *ID = ND.getIdentifier())
+      if (ID->getName() == Name)
+        return true;
+    return false;
+  });
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TestTU.h b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TestTU.h
new file mode 100644
index 0000000..b66159e
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TestTU.h
@@ -0,0 +1,67 @@
+//===--- TestTU.h - Scratch source files for testing ------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// Many tests for indexing, code completion etc are most naturally expressed
+// using code examples.
+// TestTU lets test define these examples in a common way without dealing with
+// the mechanics of VFS and compiler interactions, and then easily grab the
+// AST, particular symbols, etc.
+//
+//===---------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTTU_H
+#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTTU_H
+#include "ClangdUnit.h"
+#include "index/Index.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+
+struct TestTU {
+  static TestTU withCode(llvm::StringRef Code) {
+    TestTU TU;
+    TU.Code = Code;
+    return TU;
+  }
+
+  static TestTU withHeaderCode(llvm::StringRef HeaderCode) {
+    TestTU TU;
+    TU.HeaderCode = HeaderCode;
+    return TU;
+  }
+
+  // The code to be compiled.
+  std::string Code;
+  std::string Filename = "TestTU.cpp";
+
+  // Define contents of a header which will be implicitly included by Code.
+  std::string HeaderCode;
+  std::string HeaderFilename = "TestTU.h";
+
+  // Extra arguments for the compiler invocation.
+  std::vector<const char *> ExtraArgs;
+
+  ParsedAST build() const;
+  SymbolSlab headerSymbols() const;
+  std::unique_ptr<SymbolIndex> index() const;
+};
+
+// Look up an index symbol by qualified name, which must be unique.
+const Symbol &findSymbol(const SymbolSlab &, llvm::StringRef QName);
+// Look up an AST symbol by qualified name, which must be unique and top-level.
+const NamedDecl &findDecl(ParsedAST &AST, llvm::StringRef QName);
+// Look up a main-file AST symbol that satisfies \p Filter.
+const NamedDecl &findAnyDecl(ParsedAST &AST,
+                             std::function<bool(const NamedDecl &)> Filter);
+// Look up a main-file AST symbol by unqualified name, which must be unique.
+const NamedDecl &findAnyDecl(ParsedAST &AST, llvm::StringRef Name);
+
+} // namespace clangd
+} // namespace clang
+#endif
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/ThreadingTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/ThreadingTests.cpp
new file mode 100644
index 0000000..dd27dcc
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/ThreadingTests.cpp
@@ -0,0 +1,65 @@
+//===-- ThreadingTests.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Threading.h"
+#include "gtest/gtest.h"
+#include <mutex>
+
+namespace clang {
+namespace clangd {
+class ThreadingTest : public ::testing::Test {};
+
+TEST_F(ThreadingTest, TaskRunner) {
+  const int TasksCnt = 100;
+  // This should be const, but MSVC does not allow to use const vars in lambdas
+  // without capture. On the other hand, clang gives a warning that capture of
+  // const var is not required.
+  // Making it non-const makes both compilers happy.
+  int IncrementsPerTask = 1000;
+
+  std::mutex Mutex;
+  int Counter(0); /* GUARDED_BY(Mutex) */
+  {
+    AsyncTaskRunner Tasks;
+    auto scheduleIncrements = [&]() {
+      for (int TaskI = 0; TaskI < TasksCnt; ++TaskI) {
+        Tasks.runAsync("task", [&Counter, &Mutex, IncrementsPerTask]() {
+          for (int Increment = 0; Increment < IncrementsPerTask; ++Increment) {
+            std::lock_guard<std::mutex> Lock(Mutex);
+            ++Counter;
+          }
+        });
+      }
+    };
+
+    {
+      // Make sure runAsync is not running tasks synchronously on the same
+      // thread by locking the Mutex used for increments.
+      std::lock_guard<std::mutex> Lock(Mutex);
+      scheduleIncrements();
+    }
+
+    Tasks.wait();
+    {
+      std::lock_guard<std::mutex> Lock(Mutex);
+      ASSERT_EQ(Counter, TasksCnt * IncrementsPerTask);
+    }
+
+    {
+      std::lock_guard<std::mutex> Lock(Mutex);
+      Counter = 0;
+      scheduleIncrements();
+    }
+  }
+  // Check that destructor has waited for tasks to finish.
+  std::lock_guard<std::mutex> Lock(Mutex);
+  ASSERT_EQ(Counter, TasksCnt * IncrementsPerTask);
+}
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TraceTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TraceTests.cpp
new file mode 100644
index 0000000..02fe7da
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/TraceTests.cpp
@@ -0,0 +1,127 @@
+//===-- TraceTests.cpp - Tracing unit tests ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Trace.h"
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/Threading.h"
+#include "llvm/Support/YAMLParser.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+using namespace llvm;
+
+MATCHER_P(StringNode, Val, "") {
+  if (arg->getType() != yaml::Node::NK_Scalar) {
+    *result_listener << "is a " << arg->getVerbatimTag();
+    return false;
+  }
+  SmallString<32> S;
+  return Val == static_cast<yaml::ScalarNode *>(arg)->getValue(S);
+}
+
+// Checks that N is a Mapping (JS object) with the expected scalar properties.
+// The object must have all the Expected properties, but may have others.
+bool VerifyObject(yaml::Node &N, std::map<std::string, std::string> Expected) {
+  auto *M = dyn_cast<yaml::MappingNode>(&N);
+  if (!M) {
+    ADD_FAILURE() << "Not an object";
+    return false;
+  }
+  bool Match = true;
+  SmallString<32> Tmp;
+  for (auto &Prop : *M) {
+    auto *K = dyn_cast_or_null<yaml::ScalarNode>(Prop.getKey());
+    if (!K)
+      continue;
+    std::string KS = K->getValue(Tmp).str();
+    auto I = Expected.find(KS);
+    if (I == Expected.end())
+      continue; // Ignore properties with no assertion.
+
+    auto *V = dyn_cast_or_null<yaml::ScalarNode>(Prop.getValue());
+    if (!V) {
+      ADD_FAILURE() << KS << " is not a string";
+      Match = false;
+    }
+    std::string VS = V->getValue(Tmp).str();
+    if (VS != I->second) {
+      ADD_FAILURE() << KS << " expected " << I->second << " but actual " << VS;
+      Match = false;
+    }
+    Expected.erase(I);
+  }
+  for (const auto &P : Expected) {
+    ADD_FAILURE() << P.first << " missing, expected " << P.second;
+    Match = false;
+  }
+  return Match;
+}
+
+TEST(TraceTest, SmokeTest) {
+  // Capture some events.
+  std::string JSON;
+  {
+    raw_string_ostream OS(JSON);
+    auto JSONTracer = trace::createJSONTracer(OS);
+    trace::Session Session(*JSONTracer);
+    {
+      trace::Span Tracer("A");
+      trace::log("B");
+    }
+  }
+
+  // Get the root JSON object using the YAML parser.
+  SourceMgr SM;
+  yaml::Stream Stream(JSON, SM);
+  auto Doc = Stream.begin();
+  ASSERT_NE(Doc, Stream.end());
+  auto *Root = dyn_cast_or_null<yaml::MappingNode>(Doc->getRoot());
+  ASSERT_NE(Root, nullptr) << "Root should be an object";
+
+  // Check whether we expect thread name events on this platform.
+  SmallString<32> ThreadName;
+  llvm::get_thread_name(ThreadName);
+  bool ThreadsHaveNames = !ThreadName.empty();
+
+  // We expect in order:
+  //   displayTimeUnit: "ns"
+  //   traceEvents: [process name, thread name, start span, log, end span]
+  // (The order doesn't matter, but the YAML parser is awkward to use otherwise)
+  auto Prop = Root->begin();
+  ASSERT_NE(Prop, Root->end()) << "Expected displayTimeUnit property";
+  ASSERT_THAT(Prop->getKey(), StringNode("displayTimeUnit"));
+  EXPECT_THAT(Prop->getValue(), StringNode("ns"));
+  ASSERT_NE(++Prop, Root->end()) << "Expected traceEvents property";
+  EXPECT_THAT(Prop->getKey(), StringNode("traceEvents"));
+  auto *Events = dyn_cast_or_null<yaml::SequenceNode>(Prop->getValue());
+  ASSERT_NE(Events, nullptr) << "traceEvents should be an array";
+  auto Event = Events->begin();
+  ASSERT_NE(Event, Events->end()) << "Expected process name";
+  EXPECT_TRUE(VerifyObject(*Event, {{"ph", "M"}, {"name", "process_name"}}));
+  if (ThreadsHaveNames) {
+    ASSERT_NE(++Event, Events->end()) << "Expected thread name";
+    EXPECT_TRUE(VerifyObject(*Event, {{"ph", "M"}, {"name", "thread_name"}}));
+  }
+  ASSERT_NE(++Event, Events->end()) << "Expected log message";
+  EXPECT_TRUE(VerifyObject(*Event, {{"ph", "i"}, {"name", "Log"}}));
+  ASSERT_NE(++Event, Events->end()) << "Expected span end";
+  EXPECT_TRUE(VerifyObject(*Event, {{"ph", "X"}, {"name", "A"}}));
+  ASSERT_EQ(++Event, Events->end());
+  ASSERT_EQ(++Prop, Root->end());
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/URITests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/URITests.cpp
new file mode 100644
index 0000000..84d5ca1
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/URITests.cpp
@@ -0,0 +1,176 @@
+//===-- URITests.cpp  ---------------------------------*- C++ -*-----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestFS.h"
+#include "URI.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+
+// Force the unittest URI scheme to be linked,
+static int LLVM_ATTRIBUTE_UNUSED UnittestSchemeAnchorDest =
+    UnittestSchemeAnchorSource;
+
+namespace {
+
+using ::testing::AllOf;
+
+MATCHER_P(Scheme, S, "") { return arg.scheme() == S; }
+MATCHER_P(Authority, A, "") { return arg.authority() == A; }
+MATCHER_P(Body, B, "") { return arg.body() == B; }
+
+std::string createOrDie(llvm::StringRef AbsolutePath,
+                        llvm::StringRef Scheme = "file") {
+  auto Uri = URI::create(AbsolutePath, Scheme);
+  if (!Uri)
+    llvm_unreachable(llvm::toString(Uri.takeError()).c_str());
+  return Uri->toString();
+}
+
+URI parseOrDie(llvm::StringRef Uri) {
+  auto U = URI::parse(Uri);
+  if (!U)
+    llvm_unreachable(llvm::toString(U.takeError()).c_str());
+  return *U;
+}
+
+TEST(PercentEncodingTest, Encode) {
+  EXPECT_EQ(URI("x", /*Authority=*/"", "a/b/c").toString(), "x:a/b/c");
+  EXPECT_EQ(URI("x", /*Authority=*/"", "a!b;c~").toString(), "x:a%21b%3bc~");
+  EXPECT_EQ(URI("x", /*Authority=*/"", "a123b").toString(), "x:a123b");
+}
+
+TEST(PercentEncodingTest, Decode) {
+  EXPECT_EQ(parseOrDie("x:a/b/c").body(), "a/b/c");
+
+  EXPECT_EQ(parseOrDie("%3a://%3a/%3").scheme(), ":");
+  EXPECT_EQ(parseOrDie("%3a://%3a/%3").authority(), ":");
+  EXPECT_EQ(parseOrDie("%3a://%3a/%3").body(), "/%3");
+
+  EXPECT_EQ(parseOrDie("x:a%21b%3ac~").body(), "a!b:c~");
+}
+
+std::string resolveOrDie(const URI &U, llvm::StringRef HintPath = "") {
+  auto Path = URI::resolve(U, HintPath);
+  if (!Path)
+    llvm_unreachable(llvm::toString(Path.takeError()).c_str());
+  return *Path;
+}
+
+TEST(URITest, Create) {
+#ifdef _WIN32
+  EXPECT_THAT(createOrDie("c:\\x\\y\\z"), "file:///c%3a/x/y/z");
+#else
+  EXPECT_THAT(createOrDie("/x/y/z"), "file:///x/y/z");
+  EXPECT_THAT(createOrDie("/(x)/y/\\ z"), "file:///%28x%29/y/%5c%20z");
+#endif
+}
+
+TEST(URITest, FailedCreate) {
+  auto Fail = [](llvm::Expected<URI> U) {
+    if (!U) {
+      llvm::consumeError(U.takeError());
+      return true;
+    }
+    return false;
+  };
+  EXPECT_TRUE(Fail(URI::create("/x/y/z", "no")));
+  // Path has to be absolute.
+  EXPECT_TRUE(Fail(URI::create("x/y/z", "file")));
+}
+
+TEST(URITest, Parse) {
+  EXPECT_THAT(parseOrDie("file://auth/x/y/z"),
+              AllOf(Scheme("file"), Authority("auth"), Body("/x/y/z")));
+
+  EXPECT_THAT(parseOrDie("file://au%3dth/%28x%29/y/%5c%20z"),
+              AllOf(Scheme("file"), Authority("au=th"), Body("/(x)/y/\\ z")));
+
+  EXPECT_THAT(parseOrDie("file:///%28x%29/y/%5c%20z"),
+              AllOf(Scheme("file"), Authority(""), Body("/(x)/y/\\ z")));
+  EXPECT_THAT(parseOrDie("file:///x/y/z"),
+              AllOf(Scheme("file"), Authority(""), Body("/x/y/z")));
+  EXPECT_THAT(parseOrDie("file:"),
+              AllOf(Scheme("file"), Authority(""), Body("")));
+  EXPECT_THAT(parseOrDie("file:///x/y/z%2"),
+              AllOf(Scheme("file"), Authority(""), Body("/x/y/z%2")));
+  EXPECT_THAT(parseOrDie("http://llvm.org"),
+              AllOf(Scheme("http"), Authority("llvm.org"), Body("")));
+  EXPECT_THAT(parseOrDie("http://llvm.org/"),
+              AllOf(Scheme("http"), Authority("llvm.org"), Body("/")));
+  EXPECT_THAT(parseOrDie("http://llvm.org/D"),
+              AllOf(Scheme("http"), Authority("llvm.org"), Body("/D")));
+  EXPECT_THAT(parseOrDie("http:/"),
+              AllOf(Scheme("http"), Authority(""), Body("/")));
+  EXPECT_THAT(parseOrDie("urn:isbn:0451450523"),
+              AllOf(Scheme("urn"), Authority(""), Body("isbn:0451450523")));
+  EXPECT_THAT(
+      parseOrDie("file:///c:/windows/system32/"),
+      AllOf(Scheme("file"), Authority(""), Body("/c:/windows/system32/")));
+}
+
+TEST(URITest, ParseFailed) {
+  auto FailedParse = [](llvm::StringRef U) {
+    auto URI = URI::parse(U);
+    if (!URI) {
+      llvm::consumeError(URI.takeError());
+      return true;
+    }
+    return false;
+  };
+
+  // Expect ':' in URI.
+  EXPECT_TRUE(FailedParse("file//x/y/z"));
+  // Empty.
+  EXPECT_TRUE(FailedParse(""));
+  EXPECT_TRUE(FailedParse(":/a/b/c"));
+}
+
+TEST(URITest, Resolve) {
+#ifdef _WIN32
+  EXPECT_THAT(resolveOrDie(parseOrDie("file:///c%3a/x/y/z")), "c:\\x\\y\\z");
+#else
+  EXPECT_EQ(resolveOrDie(parseOrDie("file:/a/b/c")), "/a/b/c");
+  EXPECT_EQ(resolveOrDie(parseOrDie("file://auth/a/b/c")), "/a/b/c");
+  EXPECT_THAT(resolveOrDie(parseOrDie("file://au%3dth/%28x%29/y/%20z")),
+              "/(x)/y/ z");
+  EXPECT_THAT(resolveOrDie(parseOrDie("file:///c:/x/y/z")), "c:/x/y/z");
+#endif
+  EXPECT_EQ(resolveOrDie(parseOrDie("unittest:///a"), testPath("x")),
+            testPath("a"));
+}
+
+TEST(URITest, Platform) {
+  auto Path = testPath("x");
+  auto U = URI::create(Path, "file");
+  EXPECT_TRUE(static_cast<bool>(U));
+  EXPECT_THAT(resolveOrDie(*U), Path);
+}
+
+TEST(URITest, ResolveFailed) {
+  auto FailedResolve = [](llvm::StringRef Uri) {
+    auto Path = URI::resolve(parseOrDie(Uri));
+    if (!Path) {
+      llvm::consumeError(Path.takeError());
+      return true;
+    }
+    return false;
+  };
+
+  // Invalid scheme.
+  EXPECT_TRUE(FailedResolve("no:/a/b/c"));
+  // File path needs to be absolute.
+  EXPECT_TRUE(FailedResolve("file:a/b/c"));
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/XRefsTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/XRefsTests.cpp
new file mode 100644
index 0000000..3383dd5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/clangd/XRefsTests.cpp
@@ -0,0 +1,988 @@
+//===-- XRefsTests.cpp  ---------------------------*- C++ -*--------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "Annotations.h"
+#include "ClangdUnit.h"
+#include "Compiler.h"
+#include "Matchers.h"
+#include "SyncAPI.h"
+#include "TestFS.h"
+#include "TestTU.h"
+#include "XRefs.h"
+#include "index/FileIndex.h"
+#include "index/SymbolCollector.h"
+#include "clang/Index/IndexingAction.h"
+#include "llvm/Support/Path.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+using namespace llvm;
+
+namespace {
+using testing::ElementsAre;
+using testing::Field;
+using testing::IsEmpty;
+using testing::Matcher;
+using testing::UnorderedElementsAreArray;
+
+class IgnoreDiagnostics : public DiagnosticsConsumer {
+  void onDiagnosticsReady(PathRef File,
+                          std::vector<Diag> Diagnostics) override {}
+};
+
+// Extracts ranges from an annotated example, and constructs a matcher for a
+// highlight set. Ranges should be named $read/$write as appropriate.
+Matcher<const std::vector<DocumentHighlight> &>
+HighlightsFrom(const Annotations &Test) {
+  std::vector<DocumentHighlight> Expected;
+  auto Add = [&](const Range &R, DocumentHighlightKind K) {
+    Expected.emplace_back();
+    Expected.back().range = R;
+    Expected.back().kind = K;
+  };
+  for (const auto &Range : Test.ranges())
+    Add(Range, DocumentHighlightKind::Text);
+  for (const auto &Range : Test.ranges("read"))
+    Add(Range, DocumentHighlightKind::Read);
+  for (const auto &Range : Test.ranges("write"))
+    Add(Range, DocumentHighlightKind::Write);
+  return UnorderedElementsAreArray(Expected);
+}
+
+TEST(HighlightsTest, All) {
+  const char *Tests[] = {
+      R"cpp(// Local variable
+        int main() {
+          int [[bonjour]];
+          $write[[^bonjour]] = 2;
+          int test1 = $read[[bonjour]];
+        }
+      )cpp",
+
+      R"cpp(// Struct
+        namespace ns1 {
+        struct [[MyClass]] {
+          static void foo([[MyClass]]*) {}
+        };
+        } // namespace ns1
+        int main() {
+          ns1::[[My^Class]]* Params;
+        }
+      )cpp",
+
+      R"cpp(// Function
+        int [[^foo]](int) {}
+        int main() {
+          [[foo]]([[foo]](42));
+          auto *X = &[[foo]];
+        }
+      )cpp",
+  };
+  for (const char *Test : Tests) {
+    Annotations T(Test);
+    auto AST = TestTU::withCode(T.code()).build();
+    EXPECT_THAT(findDocumentHighlights(AST, T.point()), HighlightsFrom(T))
+        << Test;
+  }
+}
+
+MATCHER_P(RangeIs, R, "") { return arg.range == R; }
+
+TEST(GoToDefinition, WithIndex) {
+  Annotations SymbolHeader(R"cpp(
+        class $forward[[Forward]];
+        class $foo[[Foo]] {};
+
+        void $f1[[f1]]();
+
+        inline void $f2[[f2]]() {}
+      )cpp");
+  Annotations SymbolCpp(R"cpp(
+      class $forward[[forward]] {};
+      void  $f1[[f1]]() {}
+    )cpp");
+
+  TestTU TU;
+  TU.Code = SymbolCpp.code();
+  TU.HeaderCode = SymbolHeader.code();
+  auto Index = TU.index();
+  auto runFindDefinitionsWithIndex = [&Index](const Annotations &Main) {
+    auto AST = TestTU::withCode(Main.code()).build();
+    return clangd::findDefinitions(AST, Main.point(), Index.get());
+  };
+
+  Annotations Test(R"cpp(// only declaration in AST.
+        void [[f1]]();
+        int main() {
+          ^f1();
+        }
+      )cpp");
+  EXPECT_THAT(runFindDefinitionsWithIndex(Test),
+              testing::ElementsAreArray(
+                  {RangeIs(SymbolCpp.range("f1")), RangeIs(Test.range())}));
+
+  Test = Annotations(R"cpp(// definition in AST.
+        void [[f1]]() {}
+        int main() {
+          ^f1();
+        }
+      )cpp");
+  EXPECT_THAT(runFindDefinitionsWithIndex(Test),
+              testing::ElementsAreArray(
+                  {RangeIs(Test.range()), RangeIs(SymbolHeader.range("f1"))}));
+
+  Test = Annotations(R"cpp(// forward declaration in AST.
+        class [[Foo]];
+        F^oo* create();
+      )cpp");
+  EXPECT_THAT(runFindDefinitionsWithIndex(Test),
+              testing::ElementsAreArray(
+                  {RangeIs(SymbolHeader.range("foo")), RangeIs(Test.range())}));
+
+  Test = Annotations(R"cpp(// defintion in AST.
+        class [[Forward]] {};
+        F^orward create();
+      )cpp");
+  EXPECT_THAT(runFindDefinitionsWithIndex(Test),
+              testing::ElementsAreArray({
+                  RangeIs(Test.range()), RangeIs(SymbolHeader.range("forward")),
+              }));
+}
+
+TEST(GoToDefinition, All) {
+  const char *Tests[] = {
+      R"cpp(// Local variable
+        int main() {
+          int [[bonjour]];
+          ^bonjour = 2;
+          int test1 = bonjour;
+        }
+      )cpp",
+
+      R"cpp(// Struct
+        namespace ns1 {
+        struct [[MyClass]] {};
+        } // namespace ns1
+        int main() {
+          ns1::My^Class* Params;
+        }
+      )cpp",
+
+      R"cpp(// Function definition via pointer
+        int [[foo]](int) {}
+        int main() {
+          auto *X = &^foo;
+        }
+      )cpp",
+
+      R"cpp(// Function declaration via call
+        int [[foo]](int);
+        int main() {
+          return ^foo(42);
+        }
+      )cpp",
+
+      R"cpp(// Field
+        struct Foo { int [[x]]; };
+        int main() {
+          Foo bar;
+          bar.^x;
+        }
+      )cpp",
+
+      R"cpp(// Field, member initializer
+        struct Foo {
+          int [[x]];
+          Foo() : ^x(0) {}
+        };
+      )cpp",
+
+      R"cpp(// Field, GNU old-style field designator
+        struct Foo { int [[x]]; };
+        int main() {
+          Foo bar = { ^x : 1 };
+        }
+      )cpp",
+
+      R"cpp(// Field, field designator
+        struct Foo { int [[x]]; };
+        int main() {
+          Foo bar = { .^x = 2 };
+        }
+      )cpp",
+
+      R"cpp(// Method call
+        struct Foo { int [[x]](); };
+        int main() {
+          Foo bar;
+          bar.^x();
+        }
+      )cpp",
+
+      R"cpp(// Typedef
+        typedef int [[Foo]];
+        int main() {
+          ^Foo bar;
+        }
+      )cpp",
+
+      /* FIXME: clangIndex doesn't handle template type parameters
+      R"cpp(// Template type parameter
+        template <[[typename T]]>
+        void foo() { ^T t; }
+      )cpp", */
+
+      R"cpp(// Namespace
+        namespace [[ns]] {
+        struct Foo { static void bar(); }
+        } // namespace ns
+        int main() { ^ns::Foo::bar(); }
+      )cpp",
+
+      R"cpp(// Macro
+        #define MACRO 0
+        #define [[MACRO]] 1
+        int main() { return ^MACRO; }
+        #define MACRO 2
+        #undef macro
+      )cpp",
+
+      R"cpp(// Macro
+       class TTT { public: int a; };
+       #define [[FF]](S) if (int b = S.a) {}
+       void f() {
+         TTT t;
+         F^F(t);
+       }
+      )cpp",
+
+      R"cpp(// Macro argument
+       int [[i]];
+       #define ADDRESSOF(X) &X;
+       int *j = ADDRESSOF(^i);
+      )cpp",
+
+      R"cpp(// Symbol concatenated inside macro (not supported)
+       int *pi;
+       #define POINTER(X) p # X;
+       int i = *POINTER(^i);
+      )cpp",
+
+      R"cpp(// Forward class declaration
+        class Foo;
+        class [[Foo]] {};
+        F^oo* foo();
+      )cpp",
+
+      R"cpp(// Function declaration
+        void foo();
+        void g() { f^oo(); }
+        void [[foo]]() {}
+      )cpp",
+
+      R"cpp(
+        #define FF(name) class name##_Test {};
+        [[FF]](my);
+        void f() { my^_Test a; }
+      )cpp",
+
+      R"cpp(
+         #define FF() class [[Test]] {};
+         FF();
+         void f() { T^est a; }
+      )cpp",
+  };
+  for (const char *Test : Tests) {
+    Annotations T(Test);
+    auto AST = TestTU::withCode(T.code()).build();
+    std::vector<Matcher<Location>> ExpectedLocations;
+    for (const auto &R : T.ranges())
+      ExpectedLocations.push_back(RangeIs(R));
+    EXPECT_THAT(findDefinitions(AST, T.point()),
+                ElementsAreArray(ExpectedLocations))
+        << Test;
+  }
+}
+
+TEST(GoToDefinition, RelPathsInCompileCommand) {
+  Annotations SourceAnnotations(R"cpp(
+int [[foo]];
+int baz = f^oo;
+)cpp");
+
+  IgnoreDiagnostics DiagConsumer;
+  MockCompilationDatabase CDB(/*UseRelPaths=*/true);
+  MockFSProvider FS;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  auto FooCpp = testPath("foo.cpp");
+  FS.Files[FooCpp] = "";
+
+  Server.addDocument(FooCpp, SourceAnnotations.code());
+  runAddDocument(Server, FooCpp, SourceAnnotations.code());
+  auto Locations =
+      runFindDefinitions(Server, FooCpp, SourceAnnotations.point());
+  EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
+
+  EXPECT_THAT(*Locations, ElementsAre(Location{URIForFile{FooCpp},
+                                               SourceAnnotations.range()}));
+}
+
+TEST(Hover, All) {
+  struct OneTest {
+    StringRef Input;
+    StringRef ExpectedHover;
+  };
+
+  OneTest Tests[] = {
+      {
+          R"cpp(// No hover
+            ^int main() {
+            }
+          )cpp",
+          "",
+      },
+      {
+          R"cpp(// Local variable
+            int main() {
+              int bonjour;
+              ^bonjour = 2;
+              int test1 = bonjour;
+            }
+          )cpp",
+          "Declared in function main\n\nint bonjour",
+      },
+      {
+          R"cpp(// Local variable in method
+            struct s {
+              void method() {
+                int bonjour;
+                ^bonjour = 2;
+              }
+            };
+          )cpp",
+          "Declared in function s::method\n\nint bonjour",
+      },
+      {
+          R"cpp(// Struct
+            namespace ns1 {
+              struct MyClass {};
+            } // namespace ns1
+            int main() {
+              ns1::My^Class* Params;
+            }
+          )cpp",
+          "Declared in namespace ns1\n\nstruct MyClass {}",
+      },
+      {
+          R"cpp(// Class
+            namespace ns1 {
+              class MyClass {};
+            } // namespace ns1
+            int main() {
+              ns1::My^Class* Params;
+            }
+          )cpp",
+          "Declared in namespace ns1\n\nclass MyClass {}",
+      },
+      {
+          R"cpp(// Union
+            namespace ns1 {
+              union MyUnion { int x; int y; };
+            } // namespace ns1
+            int main() {
+              ns1::My^Union Params;
+            }
+          )cpp",
+          "Declared in namespace ns1\n\nunion MyUnion {}",
+      },
+      {
+          R"cpp(// Function definition via pointer
+            int foo(int) {}
+            int main() {
+              auto *X = &^foo;
+            }
+          )cpp",
+          "Declared in global namespace\n\nint foo(int)",
+      },
+      {
+          R"cpp(// Function declaration via call
+            int foo(int);
+            int main() {
+              return ^foo(42);
+            }
+          )cpp",
+          "Declared in global namespace\n\nint foo(int)",
+      },
+      {
+          R"cpp(// Field
+            struct Foo { int x; };
+            int main() {
+              Foo bar;
+              bar.^x;
+            }
+          )cpp",
+          "Declared in struct Foo\n\nint x",
+      },
+      {
+          R"cpp(// Field with initialization
+            struct Foo { int x = 5; };
+            int main() {
+              Foo bar;
+              bar.^x;
+            }
+          )cpp",
+          "Declared in struct Foo\n\nint x = 5",
+      },
+      {
+          R"cpp(// Static field
+            struct Foo { static int x; };
+            int main() {
+              Foo::^x;
+            }
+          )cpp",
+          "Declared in struct Foo\n\nstatic int x",
+      },
+      {
+          R"cpp(// Field, member initializer
+            struct Foo {
+              int x;
+              Foo() : ^x(0) {}
+            };
+          )cpp",
+          "Declared in struct Foo\n\nint x",
+      },
+      {
+          R"cpp(// Field, GNU old-style field designator
+            struct Foo { int x; };
+            int main() {
+              Foo bar = { ^x : 1 };
+            }
+          )cpp",
+          "Declared in struct Foo\n\nint x",
+      },
+      {
+          R"cpp(// Field, field designator
+            struct Foo { int x; };
+            int main() {
+              Foo bar = { .^x = 2 };
+            }
+          )cpp",
+          "Declared in struct Foo\n\nint x",
+      },
+      {
+          R"cpp(// Method call
+            struct Foo { int x(); };
+            int main() {
+              Foo bar;
+              bar.^x();
+            }
+          )cpp",
+          "Declared in struct Foo\n\nint x()",
+      },
+      {
+          R"cpp(// Static method call
+            struct Foo { static int x(); };
+            int main() {
+              Foo::^x();
+            }
+          )cpp",
+          "Declared in struct Foo\n\nstatic int x()",
+      },
+      {
+          R"cpp(// Typedef
+            typedef int Foo;
+            int main() {
+              ^Foo bar;
+            }
+          )cpp",
+          "Declared in global namespace\n\ntypedef int Foo",
+      },
+      {
+          R"cpp(// Namespace
+            namespace ns {
+            struct Foo { static void bar(); }
+            } // namespace ns
+            int main() { ^ns::Foo::bar(); }
+          )cpp",
+          "Declared in global namespace\n\nnamespace ns {\n}",
+      },
+      {
+          R"cpp(// Anonymous namespace
+            namespace ns {
+              namespace {
+                int foo;
+              } // anonymous namespace
+            } // namespace ns
+            int main() { ns::f^oo++; }
+          )cpp",
+          "Declared in namespace ns::(anonymous)\n\nint foo",
+      },
+      {
+          R"cpp(// Macro
+            #define MACRO 0
+            #define MACRO 1
+            int main() { return ^MACRO; }
+            #define MACRO 2
+            #undef macro
+          )cpp",
+          "#define MACRO",
+      },
+      {
+          R"cpp(// Forward class declaration
+            class Foo;
+            class Foo {};
+            F^oo* foo();
+          )cpp",
+          "Declared in global namespace\n\nclass Foo {}",
+      },
+      {
+          R"cpp(// Function declaration
+            void foo();
+            void g() { f^oo(); }
+            void foo() {}
+          )cpp",
+          "Declared in global namespace\n\nvoid foo()",
+      },
+      {
+          R"cpp(// Enum declaration
+            enum Hello {
+              ONE, TWO, THREE,
+            };
+            void foo() {
+              Hel^lo hello = ONE;
+            }
+          )cpp",
+          "Declared in global namespace\n\nenum Hello {\n}",
+      },
+      {
+          R"cpp(// Enumerator
+            enum Hello {
+              ONE, TWO, THREE,
+            };
+            void foo() {
+              Hello hello = O^NE;
+            }
+          )cpp",
+          "Declared in enum Hello\n\nONE",
+      },
+      {
+          R"cpp(// Enumerator in anonymous enum
+            enum {
+              ONE, TWO, THREE,
+            };
+            void foo() {
+              int hello = O^NE;
+            }
+          )cpp",
+          "Declared in enum (anonymous)\n\nONE",
+      },
+      {
+          R"cpp(// Global variable
+            static int hey = 10;
+            void foo() {
+              he^y++;
+            }
+          )cpp",
+          "Declared in global namespace\n\nstatic int hey = 10",
+      },
+      {
+          R"cpp(// Global variable in namespace
+            namespace ns1 {
+              static int hey = 10;
+            }
+            void foo() {
+              ns1::he^y++;
+            }
+          )cpp",
+          "Declared in namespace ns1\n\nstatic int hey = 10",
+      },
+      {
+          R"cpp(// Field in anonymous struct
+            static struct {
+              int hello;
+            } s;
+            void foo() {
+              s.he^llo++;
+            }
+          )cpp",
+          "Declared in struct (anonymous)\n\nint hello",
+      },
+      {
+          R"cpp(// Templated function
+            template <typename T>
+            T foo() {
+              return 17;
+            }
+            void g() { auto x = f^oo<int>(); }
+          )cpp",
+          "Declared in global namespace\n\ntemplate <typename T> T foo()",
+      },
+      {
+          R"cpp(// Anonymous union
+            struct outer {
+              union {
+                int abc, def;
+              } v;
+            };
+            void g() { struct outer o; o.v.d^ef++; }
+          )cpp",
+          "Declared in union outer::(anonymous)\n\nint def",
+      },
+      {
+          R"cpp(// Nothing
+            void foo() {
+              ^
+            }
+          )cpp",
+          "",
+      },
+      {
+          R"cpp(// Simple initialization with auto
+            void foo() {
+              ^auto i = 1;
+            }
+          )cpp",
+          "int",
+      },
+      {
+          R"cpp(// Simple initialization with const auto
+            void foo() {
+              const ^auto i = 1;
+            }
+          )cpp",
+          "int",
+      },
+      {
+          R"cpp(// Simple initialization with const auto&
+            void foo() {
+              const ^auto& i = 1;
+            }
+          )cpp",
+          "int",
+      },
+      {
+          R"cpp(// Simple initialization with auto&
+            void foo() {
+              ^auto& i = 1;
+            }
+          )cpp",
+          "int",
+      },
+      {
+          R"cpp(// Auto with initializer list.
+            namespace std
+            {
+              template<class _E>
+              class initializer_list {};
+            }
+            void foo() {
+              ^auto i = {1,2};
+            }
+          )cpp",
+          "class std::initializer_list<int>",
+      },
+      {
+          R"cpp(// User defined conversion to auto
+            struct Bar {
+              operator ^auto() const { return 10; }
+            };
+          )cpp",
+          "int",
+      },
+      {
+          R"cpp(// Simple initialization with decltype(auto)
+            void foo() {
+              ^decltype(auto) i = 1;
+            }
+          )cpp",
+          "int",
+      },
+      {
+          R"cpp(// Simple initialization with const decltype(auto)
+            void foo() {
+              const int j = 0;
+              ^decltype(auto) i = j;
+            }
+          )cpp",
+          "const int",
+      },
+      {
+          R"cpp(// Simple initialization with const& decltype(auto)
+            void foo() {
+              int k = 0;
+              const int& j = k;
+              ^decltype(auto) i = j;
+            }
+          )cpp",
+          "const int &",
+      },
+      {
+          R"cpp(// Simple initialization with & decltype(auto)
+            void foo() {
+              int k = 0;
+              int& j = k;
+              ^decltype(auto) i = j;
+            }
+          )cpp",
+          "int &",
+      },
+      {
+          R"cpp(// decltype with initializer list: nothing
+            namespace std
+            {
+              template<class _E>
+              class initializer_list {};
+            }
+            void foo() {
+              ^decltype(auto) i = {1,2};
+            }
+          )cpp",
+          "",
+      },
+      {
+          R"cpp(// auto function return with trailing type
+            struct Bar {};
+            ^auto test() -> decltype(Bar()) {
+              return Bar();
+            }
+          )cpp",
+          "struct Bar",
+      },
+      {
+          R"cpp(// trailing return type
+            struct Bar {};
+            auto test() -> ^decltype(Bar()) {
+              return Bar();
+            }
+          )cpp",
+          "struct Bar",
+      },
+      {
+          R"cpp(// auto in function return
+            struct Bar {};
+            ^auto test() {
+              return Bar();
+            }
+          )cpp",
+          "struct Bar",
+      },
+      {
+          R"cpp(// auto& in function return
+            struct Bar {};
+            ^auto& test() {
+              return Bar();
+            }
+          )cpp",
+          "struct Bar",
+      },
+      {
+          R"cpp(// const auto& in function return
+            struct Bar {};
+            const ^auto& test() {
+              return Bar();
+            }
+          )cpp",
+          "struct Bar",
+      },
+      {
+          R"cpp(// decltype(auto) in function return
+            struct Bar {};
+            ^decltype(auto) test() {
+              return Bar();
+            }
+          )cpp",
+          "struct Bar",
+      },
+      {
+          R"cpp(// decltype(auto) reference in function return
+            struct Bar {};
+            ^decltype(auto) test() {
+              int a;
+              return (a);
+            }
+          )cpp",
+          "int &",
+      },
+      {
+          R"cpp(// decltype lvalue reference
+            void foo() {
+              int I = 0;
+              ^decltype(I) J = I;
+            }
+          )cpp",
+          "int",
+      },
+      {
+          R"cpp(// decltype lvalue reference
+            void foo() {
+              int I= 0;
+              int &K = I;
+              ^decltype(K) J = I;
+            }
+          )cpp",
+          "int &",
+      },
+      {
+          R"cpp(// decltype lvalue reference parenthesis
+            void foo() {
+              int I = 0;
+              ^decltype((I)) J = I;
+            }
+          )cpp",
+          "int &",
+      },
+      {
+          R"cpp(// decltype rvalue reference
+            void foo() {
+              int I = 0;
+              ^decltype(static_cast<int&&>(I)) J = static_cast<int&&>(I);
+            }
+          )cpp",
+          "int &&",
+      },
+      {
+          R"cpp(// decltype rvalue reference function call
+            int && bar();
+            void foo() {
+              int I = 0;
+              ^decltype(bar()) J = bar();
+            }
+          )cpp",
+          "int &&",
+      },
+      {
+          R"cpp(// decltype of function with trailing return type.
+            struct Bar {};
+            auto test() -> decltype(Bar()) {
+              return Bar();
+            }
+            void foo() {
+              ^decltype(test()) i = test();
+            }
+          )cpp",
+          "struct Bar",
+      },
+      {
+          R"cpp(// decltype of var with decltype.
+            void foo() {
+              int I = 0;
+              decltype(I) J = I;
+              ^decltype(J) K = J;
+            }
+          )cpp",
+          "int",
+      },
+      {
+          R"cpp(// structured binding. Not supported yet
+            struct Bar {};
+            void foo() {
+              Bar a[2];
+              ^auto [x,y] = a;
+            }
+          )cpp",
+          "",
+      },
+      {
+          R"cpp(// Template auto parameter. Nothing (Not useful).
+            template<^auto T>
+            void func() {
+            }
+            void foo() {
+               func<1>();
+            }
+          )cpp",
+          "",
+      },
+  };
+
+  for (const OneTest &Test : Tests) {
+    Annotations T(Test.Input);
+    TestTU TU = TestTU::withCode(T.code());
+    TU.ExtraArgs.push_back("-std=c++17");
+    auto AST = TU.build();
+    if (auto H = getHover(AST, T.point())) {
+      EXPECT_NE("", Test.ExpectedHover) << Test.Input;
+      EXPECT_EQ(H->contents.value, Test.ExpectedHover.str()) << Test.Input;
+    } else
+      EXPECT_EQ("", Test.ExpectedHover.str()) << Test.Input;
+  }
+}
+
+TEST(GoToInclude, All) {
+  MockFSProvider FS;
+  IgnoreDiagnostics DiagConsumer;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  auto FooCpp = testPath("foo.cpp");
+  const char *SourceContents = R"cpp(
+  #include ^"$2^foo.h$3^"
+  #include "$4^invalid.h"
+  int b = a;
+  // test
+  int foo;
+  #in$5^clude "$6^foo.h"$7^
+  )cpp";
+  Annotations SourceAnnotations(SourceContents);
+  FS.Files[FooCpp] = SourceAnnotations.code();
+  auto FooH = testPath("foo.h");
+  auto FooHUri = URIForFile{FooH};
+
+  const char *HeaderContents = R"cpp([[]]#pragma once
+                                     int a;
+                                     )cpp";
+  Annotations HeaderAnnotations(HeaderContents);
+  FS.Files[FooH] = HeaderAnnotations.code();
+
+  Server.addDocument(FooH, HeaderAnnotations.code());
+  Server.addDocument(FooCpp, SourceAnnotations.code());
+
+  // Test include in preamble.
+  auto Locations =
+      runFindDefinitions(Server, FooCpp, SourceAnnotations.point());
+  ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
+  EXPECT_THAT(*Locations,
+              ElementsAre(Location{FooHUri, HeaderAnnotations.range()}));
+
+  // Test include in preamble, last char.
+  Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("2"));
+  ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
+  EXPECT_THAT(*Locations,
+              ElementsAre(Location{FooHUri, HeaderAnnotations.range()}));
+
+  Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("3"));
+  ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
+  EXPECT_THAT(*Locations,
+              ElementsAre(Location{FooHUri, HeaderAnnotations.range()}));
+
+  // Test include outside of preamble.
+  Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("6"));
+  ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
+  EXPECT_THAT(*Locations,
+              ElementsAre(Location{FooHUri, HeaderAnnotations.range()}));
+
+  // Test a few positions that do not result in Locations.
+  Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("4"));
+  ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
+  EXPECT_THAT(*Locations, IsEmpty());
+
+  Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("5"));
+  ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
+  EXPECT_THAT(*Locations, IsEmpty());
+
+  Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("7"));
+  ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
+  EXPECT_THAT(*Locations, IsEmpty());
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/include-fixer/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/unittests/include-fixer/CMakeLists.txt
new file mode 100644
index 0000000..80284a6
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/include-fixer/CMakeLists.txt
@@ -0,0 +1,31 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  )
+
+get_filename_component(INCLUDE_FIXER_SOURCE_DIR
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../include-fixer REALPATH)
+include_directories(
+  ${INCLUDE_FIXER_SOURCE_DIR}
+  )
+
+# We'd like to clang/unittests/Tooling/RewriterTestContext.h in the test.
+include_directories(${CLANG_SOURCE_DIR})
+
+add_extra_unittest(IncludeFixerTests
+  IncludeFixerTest.cpp
+  FuzzySymbolIndexTests.cpp
+  )
+
+target_link_libraries(IncludeFixerTests
+  PRIVATE
+  clangBasic
+  clangFormat
+  clangFrontend
+  clangIncludeFixer
+  clangRewrite
+  clangTooling
+  clangToolingCore
+  findAllSymbols
+  )
+
+add_subdirectory(find-all-symbols)
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/include-fixer/FuzzySymbolIndexTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/include-fixer/FuzzySymbolIndexTests.cpp
new file mode 100644
index 0000000..17679c5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/include-fixer/FuzzySymbolIndexTests.cpp
@@ -0,0 +1,61 @@
+//===-- FuzzySymbolIndexTests.cpp - Fuzzy symbol index unit tests ---------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FuzzySymbolIndex.h"
+#include "gmock/gmock.h"
+#include "llvm/Support/Regex.h"
+#include "gtest/gtest.h"
+
+using testing::ElementsAre;
+using testing::Not;
+
+namespace clang {
+namespace include_fixer {
+namespace {
+
+TEST(FuzzySymbolIndexTest, Tokenize) {
+  EXPECT_THAT(FuzzySymbolIndex::tokenize("URLHandlerCallback"),
+              ElementsAre("url", "handler", "callback"));
+  EXPECT_THAT(FuzzySymbolIndex::tokenize("snake_case11"),
+              ElementsAre("snake", "case", "11"));
+  EXPECT_THAT(FuzzySymbolIndex::tokenize("__$42!!BOB\nbob"),
+              ElementsAre("42", "bob", "bob"));
+}
+
+MATCHER_P(MatchesSymbol, Identifier, "") {
+  llvm::Regex Pattern("^" + arg);
+  std::string err;
+  if (!Pattern.isValid(err)) {
+    *result_listener << "invalid regex: " << err;
+    return false;
+  }
+  auto Tokens = FuzzySymbolIndex::tokenize(Identifier);
+  std::string Target = llvm::join(Tokens.begin(), Tokens.end(), " ");
+  *result_listener << "matching against '" << Target << "'";
+  return llvm::Regex("^" + arg).match(Target);
+}
+
+TEST(FuzzySymbolIndexTest, QueryRegexp) {
+  auto QueryRegexp = [](const std::string &query) {
+    return FuzzySymbolIndex::queryRegexp(FuzzySymbolIndex::tokenize(query));
+  };
+  EXPECT_THAT(QueryRegexp("uhc"), MatchesSymbol("URLHandlerCallback"));
+  EXPECT_THAT(QueryRegexp("urhaca"), MatchesSymbol("URLHandlerCallback"));
+  EXPECT_THAT(QueryRegexp("uhcb"), Not(MatchesSymbol("URLHandlerCallback")))
+      << "Non-prefix";
+  EXPECT_THAT(QueryRegexp("uc"), Not(MatchesSymbol("URLHandlerCallback")))
+      << "Skip token";
+
+  EXPECT_THAT(QueryRegexp("uptr"), MatchesSymbol("unique_ptr"));
+  EXPECT_THAT(QueryRegexp("UniP"), MatchesSymbol("unique_ptr"));
+}
+
+} // namespace
+} // namespace include_fixer
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/include-fixer/IncludeFixerTest.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/include-fixer/IncludeFixerTest.cpp
new file mode 100644
index 0000000..4da14f5
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/include-fixer/IncludeFixerTest.cpp
@@ -0,0 +1,372 @@
+//===-- IncludeFixerTest.cpp - Include fixer unit tests -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InMemorySymbolIndex.h"
+#include "IncludeFixer.h"
+#include "SymbolIndexManager.h"
+#include "unittests/Tooling/RewriterTestContext.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace include_fixer {
+namespace {
+
+using find_all_symbols::SymbolInfo;
+using find_all_symbols::SymbolAndSignals;
+
+static bool runOnCode(tooling::ToolAction *ToolAction, StringRef Code,
+                      StringRef FileName,
+                      const std::vector<std::string> &ExtraArgs) {
+  llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+      new vfs::InMemoryFileSystem);
+  llvm::IntrusiveRefCntPtr<FileManager> Files(
+      new FileManager(FileSystemOptions(), InMemoryFileSystem));
+  // FIXME: Investigate why -fms-compatibility breaks tests.
+  std::vector<std::string> Args = {"include_fixer", "-fsyntax-only",
+                                   "-fno-ms-compatibility", FileName};
+  Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
+  tooling::ToolInvocation Invocation(
+      Args, ToolAction, Files.get(),
+      std::make_shared<PCHContainerOperations>());
+
+  InMemoryFileSystem->addFile(FileName, 0,
+                              llvm::MemoryBuffer::getMemBuffer(Code));
+
+  InMemoryFileSystem->addFile("foo.h", 0,
+                              llvm::MemoryBuffer::getMemBuffer("\n"));
+  InMemoryFileSystem->addFile("dir/bar.h", 0,
+                              llvm::MemoryBuffer::getMemBuffer("\n"));
+  InMemoryFileSystem->addFile("dir/otherdir/qux.h", 0,
+                              llvm::MemoryBuffer::getMemBuffer("\n"));
+  InMemoryFileSystem->addFile("header.h", 0,
+                              llvm::MemoryBuffer::getMemBuffer("bar b;"));
+  return Invocation.run();
+}
+
+static std::string runIncludeFixer(
+    StringRef Code,
+    const std::vector<std::string> &ExtraArgs = std::vector<std::string>()) {
+  std::vector<SymbolAndSignals> Symbols = {
+      {SymbolInfo("string", SymbolInfo::SymbolKind::Class, "<string>",
+                  {{SymbolInfo::ContextType::Namespace, "std"}}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("sting", SymbolInfo::SymbolKind::Class, "\"sting\"",
+                  {{SymbolInfo::ContextType::Namespace, "std"}}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("foo", SymbolInfo::SymbolKind::Class,
+                  "\"dir/otherdir/qux.h\"",
+                  {{SymbolInfo::ContextType::Namespace, "b"},
+                   {SymbolInfo::ContextType::Namespace, "a"}}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("bar", SymbolInfo::SymbolKind::Class, "\"bar.h\"",
+                  {{SymbolInfo::ContextType::Namespace, "b"},
+                   {SymbolInfo::ContextType::Namespace, "a"}}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("bar", SymbolInfo::SymbolKind::Class, "\"bar2.h\"",
+                  {{SymbolInfo::ContextType::Namespace, "c"},
+                   {SymbolInfo::ContextType::Namespace, "a"}}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("Green", SymbolInfo::SymbolKind::Class, "\"color.h\"",
+                  {{SymbolInfo::ContextType::EnumDecl, "Color"},
+                   {SymbolInfo::ContextType::Namespace, "b"},
+                   {SymbolInfo::ContextType::Namespace, "a"}}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("Vector", SymbolInfo::SymbolKind::Class, "\"Vector.h\"",
+                  {{SymbolInfo::ContextType::Namespace, "__a"},
+                   {SymbolInfo::ContextType::Namespace, "a"}}),
+       SymbolInfo::Signals{/*Seen=*/2, 0}},
+      {SymbolInfo("Vector", SymbolInfo::SymbolKind::Class, "\"Vector.h\"",
+                  {{SymbolInfo::ContextType::Namespace, "a"}}),
+       SymbolInfo::Signals{/*Seen=*/2, 0}},
+      {SymbolInfo("StrCat", SymbolInfo::SymbolKind::Class, "\"strcat.h\"",
+                  {{SymbolInfo::ContextType::Namespace, "str"}}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("str", SymbolInfo::SymbolKind::Class, "\"str.h\"", {}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("foo2", SymbolInfo::SymbolKind::Class, "\"foo2.h\"", {}),
+       SymbolInfo::Signals{}},
+  };
+  auto SymbolIndexMgr = llvm::make_unique<SymbolIndexManager>();
+  SymbolIndexMgr->addSymbolIndex(
+      [=]() { return llvm::make_unique<InMemorySymbolIndex>(Symbols); });
+
+  std::vector<IncludeFixerContext> FixerContexts;
+  IncludeFixerActionFactory Factory(*SymbolIndexMgr, FixerContexts, "llvm");
+  std::string FakeFileName = "input.cc";
+  runOnCode(&Factory, Code, FakeFileName, ExtraArgs);
+  assert(FixerContexts.size() == 1);
+  if (FixerContexts.front().getHeaderInfos().empty())
+    return Code;
+  auto Replaces = createIncludeFixerReplacements(Code, FixerContexts.front());
+  EXPECT_TRUE(static_cast<bool>(Replaces))
+      << llvm::toString(Replaces.takeError()) << "\n";
+  if (!Replaces)
+    return "";
+  RewriterTestContext Context;
+  FileID ID = Context.createInMemoryFile(FakeFileName, Code);
+  tooling::applyAllReplacements(*Replaces, Context.Rewrite);
+  return Context.getRewrittenText(ID);
+}
+
+TEST(IncludeFixer, Typo) {
+  EXPECT_EQ("#include <string>\nstd::string foo;\n",
+            runIncludeFixer("std::string foo;\n"));
+
+  EXPECT_EQ("// comment\n#include \"foo.h\"\n#include <string>\n"
+            "std::string foo;\n#include \"dir/bar.h\"\n",
+            runIncludeFixer("// comment\n#include \"foo.h\"\nstd::string foo;\n"
+                            "#include \"dir/bar.h\"\n"));
+
+  EXPECT_EQ("#include \"foo.h\"\n#include <string>\nstd::string foo;\n",
+            runIncludeFixer("#include \"foo.h\"\nstd::string foo;\n"));
+
+  EXPECT_EQ(
+      "#include \"foo.h\"\n#include <string>\nstd::string::size_type foo;\n",
+      runIncludeFixer("#include \"foo.h\"\nstd::string::size_type foo;\n"));
+
+  EXPECT_EQ("#include <string>\nstd::string foo;\n",
+            runIncludeFixer("string foo;\n"));
+
+  // Should not match std::string.
+  EXPECT_EQ("::string foo;\n", runIncludeFixer("::string foo;\n"));
+}
+
+TEST(IncludeFixer, IncompleteType) {
+  EXPECT_EQ(
+      "#include \"foo.h\"\n#include <string>\n"
+      "namespace std {\nclass string;\n}\nstd::string foo;\n",
+      runIncludeFixer("#include \"foo.h\"\n"
+                      "namespace std {\nclass string;\n}\nstring foo;\n"));
+
+  EXPECT_EQ("#include <string>\n"
+            "class string;\ntypedef string foo;\nfoo f;\n",
+            runIncludeFixer("class string;\ntypedef string foo;\nfoo f;\n"));
+}
+
+TEST(IncludeFixer, MinimizeInclude) {
+  std::vector<std::string> IncludePath = {"-Idir/"};
+  EXPECT_EQ("#include \"otherdir/qux.h\"\na::b::foo bar;\n",
+            runIncludeFixer("a::b::foo bar;\n", IncludePath));
+
+  IncludePath = {"-isystemdir"};
+  EXPECT_EQ("#include <otherdir/qux.h>\na::b::foo bar;\n",
+            runIncludeFixer("a::b::foo bar;\n", IncludePath));
+
+  IncludePath = {"-iquotedir"};
+  EXPECT_EQ("#include \"otherdir/qux.h\"\na::b::foo bar;\n",
+            runIncludeFixer("a::b::foo bar;\n", IncludePath));
+
+  IncludePath = {"-Idir", "-Idir/otherdir"};
+  EXPECT_EQ("#include \"qux.h\"\na::b::foo bar;\n",
+            runIncludeFixer("a::b::foo bar;\n", IncludePath));
+}
+
+TEST(IncludeFixer, NestedName) {
+  EXPECT_EQ("#include \"dir/otherdir/qux.h\"\n"
+            "int x = a::b::foo(0);\n",
+            runIncludeFixer("int x = a::b::foo(0);\n"));
+
+  // FIXME: Handle simple macros.
+  EXPECT_EQ("#define FOO a::b::foo\nint x = FOO;\n",
+            runIncludeFixer("#define FOO a::b::foo\nint x = FOO;\n"));
+  EXPECT_EQ("#define FOO(x) a::##x\nint x = FOO(b::foo);\n",
+            runIncludeFixer("#define FOO(x) a::##x\nint x = FOO(b::foo);\n"));
+
+  // The empty namespace is cleaned up by clang-format after include-fixer
+  // finishes.
+  EXPECT_EQ("#include \"dir/otherdir/qux.h\"\n"
+            "\nint a = a::b::foo(0);\n",
+            runIncludeFixer("namespace a {}\nint a = a::b::foo(0);\n"));
+}
+
+TEST(IncludeFixer, MultipleMissingSymbols) {
+  EXPECT_EQ("#include <string>\nstd::string bar;\nstd::sting foo;\n",
+            runIncludeFixer("std::string bar;\nstd::sting foo;\n"));
+}
+
+TEST(IncludeFixer, ScopedNamespaceSymbols) {
+  EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar b;\n}",
+            runIncludeFixer("namespace a {\nb::bar b;\n}"));
+  EXPECT_EQ("#include \"bar.h\"\nnamespace A {\na::b::bar b;\n}",
+            runIncludeFixer("namespace A {\na::b::bar b;\n}"));
+  EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nvoid func() { b::bar b; }\n} "
+            "// namespace a",
+            runIncludeFixer("namespace a {\nvoid func() { b::bar b; }\n}"));
+  EXPECT_EQ("namespace A { c::b::bar b; }\n",
+            runIncludeFixer("namespace A { c::b::bar b; }\n"));
+  // FIXME: The header should not be added here. Remove this after we support
+  // full match.
+  EXPECT_EQ("#include \"bar.h\"\nnamespace A {\na::b::bar b;\n}",
+            runIncludeFixer("namespace A {\nb::bar b;\n}"));
+
+  // Finds candidates for "str::StrCat".
+  EXPECT_EQ("#include \"strcat.h\"\nnamespace foo2 {\nstr::StrCat b;\n}",
+            runIncludeFixer("namespace foo2 {\nstr::StrCat b;\n}"));
+  // str::StrCat2 doesn't exist.
+  // In these two cases, StrCat2 is a nested class of class str.
+  EXPECT_EQ("#include \"str.h\"\nnamespace foo2 {\nstr::StrCat2 b;\n}",
+            runIncludeFixer("namespace foo2 {\nstr::StrCat2 b;\n}"));
+  EXPECT_EQ("#include \"str.h\"\nnamespace ns {\nstr::StrCat2 b;\n}",
+            runIncludeFixer("namespace ns {\nstr::StrCat2 b;\n}"));
+}
+
+TEST(IncludeFixer, EnumConstantSymbols) {
+  EXPECT_EQ("#include \"color.h\"\nint test = a::b::Green;\n",
+            runIncludeFixer("int test = a::b::Green;\n"));
+}
+
+TEST(IncludeFixer, IgnoreSymbolFromHeader) {
+  std::string Code = "#include \"header.h\"";
+  EXPECT_EQ(Code, runIncludeFixer(Code));
+}
+
+// FIXME: add test cases for inserting and sorting multiple headers when
+// include-fixer supports multiple headers insertion.
+TEST(IncludeFixer, InsertAndSortSingleHeader) {
+  // Insert one header.
+  std::string Code = "#include \"a.h\"\n"
+                     "#include \"foo.h\"\n"
+                     "\n"
+                     "namespace a {\nb::bar b;\n}\n";
+  std::string Expected = "#include \"a.h\"\n"
+                         "#include \"bar.h\"\n"
+                         "#include \"foo.h\"\n"
+                         "\n"
+                         "namespace a {\nb::bar b;\n}\n";
+  EXPECT_EQ(Expected, runIncludeFixer(Code));
+}
+
+TEST(IncludeFixer, DoNotDeleteMatchedSymbol) {
+  EXPECT_EQ("#include \"Vector.h\"\na::Vector v;",
+            runIncludeFixer("a::Vector v;"));
+}
+
+TEST(IncludeFixer, FixNamespaceQualifiers) {
+  EXPECT_EQ("#include \"bar.h\"\na::b::bar b;\n",
+            runIncludeFixer("b::bar b;\n"));
+  EXPECT_EQ("#include \"bar.h\"\na::b::bar b;\n",
+            runIncludeFixer("a::b::bar b;\n"));
+  EXPECT_EQ("#include \"bar.h\"\na::b::bar b;\n",
+            runIncludeFixer("bar b;\n"));
+  EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar b;\n}\n",
+            runIncludeFixer("namespace a {\nb::bar b;\n}\n"));
+  EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar b;\n}\n",
+            runIncludeFixer("namespace a {\nbar b;\n}\n"));
+  EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nnamespace b{\nbar b;\n}\n} "
+            "// namespace a\n",
+            runIncludeFixer("namespace a {\nnamespace b{\nbar b;\n}\n}\n"));
+  EXPECT_EQ("c::b::bar b;\n",
+            runIncludeFixer("c::b::bar b;\n"));
+  EXPECT_EQ("#include \"bar.h\"\nnamespace d {\na::b::bar b;\n}\n",
+            runIncludeFixer("namespace d {\nbar b;\n}\n"));
+  EXPECT_EQ("#include \"bar2.h\"\nnamespace c {\na::c::bar b;\n}\n",
+            runIncludeFixer("namespace c {\nbar b;\n}\n"));
+
+  // Test common qualifers reduction.
+  EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nnamespace d {\nb::bar b;\n}\n} "
+            "// namespace a\n",
+            runIncludeFixer("namespace a {\nnamespace d {\nbar b;\n}\n}\n"));
+  EXPECT_EQ("#include \"bar.h\"\nnamespace d {\nnamespace a {\na::b::bar "
+            "b;\n}\n} // namespace d\n",
+            runIncludeFixer("namespace d {\nnamespace a {\nbar b;\n}\n}\n"));
+
+  // Test nested classes.
+  EXPECT_EQ("#include \"bar.h\"\nnamespace d {\na::b::bar::t b;\n}\n",
+            runIncludeFixer("namespace d {\nbar::t b;\n}\n"));
+  EXPECT_EQ("#include \"bar.h\"\nnamespace c {\na::b::bar::t b;\n}\n",
+            runIncludeFixer("namespace c {\nbar::t b;\n}\n"));
+  EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar::t b;\n}\n",
+            runIncludeFixer("namespace a {\nbar::t b;\n}\n"));
+
+  EXPECT_EQ("#include \"color.h\"\nint test = a::b::Green;\n",
+            runIncludeFixer("int test = Green;\n"));
+  EXPECT_EQ("#include \"color.h\"\nnamespace d {\nint test = a::b::Green;\n}\n",
+            runIncludeFixer("namespace d {\nint test = Green;\n}\n"));
+  EXPECT_EQ("#include \"color.h\"\nnamespace a {\nint test = b::Green;\n}\n",
+            runIncludeFixer("namespace a {\nint test = Green;\n}\n"));
+
+  // Test global scope operator.
+  EXPECT_EQ("#include \"bar.h\"\n::a::b::bar b;\n",
+            runIncludeFixer("::a::b::bar b;\n"));
+  EXPECT_EQ("#include \"bar.h\"\nnamespace a {\n::a::b::bar b;\n}\n",
+            runIncludeFixer("namespace a {\n::a::b::bar b;\n}\n"));
+}
+
+TEST(IncludeFixer, FixNamespaceQualifiersForAllInstances) {
+  const char TestCode[] = R"(
+namespace a {
+bar b;
+int func1() {
+  bar a;
+                                                             bar *p = new bar();
+  return 0;
+}
+} // namespace a
+
+namespace a {
+bar func2() {
+  bar f;
+  return f;
+}
+} // namespace a
+
+// Non-fixed cases:
+void f() {
+  bar b;
+}
+
+namespace a {
+namespace c {
+  bar b;
+} // namespace c
+} // namespace a
+)";
+
+  const char ExpectedCode[] = R"(
+#include "bar.h"
+namespace a {
+b::bar b;
+int func1() {
+  b::bar a;
+  b::bar *p = new b::bar();
+  return 0;
+}
+} // namespace a
+
+namespace a {
+b::bar func2() {
+  b::bar f;
+  return f;
+}
+} // namespace a
+
+// Non-fixed cases:
+void f() {
+  bar b;
+}
+
+namespace a {
+namespace c {
+  bar b;
+} // namespace c
+} // namespace a
+)";
+
+  EXPECT_EQ(ExpectedCode, runIncludeFixer(TestCode));
+}
+
+TEST(IncludeFixer, DontAddQualifiersForMissingCompleteType) {
+  EXPECT_EQ("#include \"bar.h\"\nclass bar;\nvoid f() {\nbar* b;\nb->f();\n}",
+            runIncludeFixer("class bar;\nvoid f() {\nbar* b;\nb->f();\n}"));
+}
+
+} // namespace
+} // namespace include_fixer
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/include-fixer/find-all-symbols/CMakeLists.txt b/src/third_party/llvm-project/clang-tools-extra/unittests/include-fixer/find-all-symbols/CMakeLists.txt
new file mode 100644
index 0000000..5689285
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/include-fixer/find-all-symbols/CMakeLists.txt
@@ -0,0 +1,24 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  )
+
+get_filename_component(INCLUDE_FIXER_SOURCE_DIR
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../../include-fixer/find-all-symbols REALPATH)
+include_directories(
+  ${INCLUDE_FIXER_SOURCE_DIR}
+  )
+
+add_extra_unittest(FindAllSymbolsTests
+  FindAllSymbolsTests.cpp
+  )
+
+target_link_libraries(FindAllSymbolsTests
+  PRIVATE
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFrontend
+  clangLex
+  clangTooling
+  findAllSymbols
+  )
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp b/src/third_party/llvm-project/clang-tools-extra/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
new file mode 100644
index 0000000..760a253
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
@@ -0,0 +1,578 @@
+//===-- FindAllSymbolsTests.cpp - find all symbols unit tests ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FindAllSymbolsAction.h"
+#include "HeaderMapCollector.h"
+#include "SymbolInfo.h"
+#include "SymbolReporter.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "gtest/gtest.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace find_all_symbols {
+
+static const char HeaderName[] = "symbols.h";
+
+class TestSymbolReporter : public SymbolReporter {
+public:
+  ~TestSymbolReporter() override {}
+
+  void reportSymbols(llvm::StringRef FileName,
+                     const SymbolInfo::SignalMap &NewSymbols) override {
+    for (const auto &Entry : NewSymbols)
+      Symbols[Entry.first] += Entry.second;
+  }
+
+  int seen(const SymbolInfo &Symbol) const {
+    auto it = Symbols.find(Symbol);
+    return it == Symbols.end() ? 0 : it->second.Seen;
+  }
+
+  int used(const SymbolInfo &Symbol) const {
+    auto it = Symbols.find(Symbol);
+    return it == Symbols.end() ? 0 : it->second.Used;
+  }
+
+private:
+  SymbolInfo::SignalMap Symbols;
+};
+
+class FindAllSymbolsTest : public ::testing::Test {
+public:
+  int seen(const SymbolInfo &Symbol) { return Reporter.seen(Symbol); }
+
+  int used(const SymbolInfo &Symbol) { return Reporter.used(Symbol); }
+
+  bool runFindAllSymbols(StringRef HeaderCode, StringRef MainCode) {
+    llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+        new vfs::InMemoryFileSystem);
+    llvm::IntrusiveRefCntPtr<FileManager> Files(
+        new FileManager(FileSystemOptions(), InMemoryFileSystem));
+
+    std::string FileName = "symbol.cc";
+
+    const std::string InternalHeader = "internal/internal_header.h";
+    const std::string TopHeader = "<top>";
+    // Test .inc header path. The header for `IncHeaderClass` should be
+    // internal.h, which will eventually be mapped to <top>.
+    std::string IncHeader = "internal/private.inc";
+    std::string IncHeaderCode = "class IncHeaderClass {};";
+
+    HeaderMapCollector::RegexHeaderMap RegexMap = {
+        {R"(internal_.*\.h$)", TopHeader.c_str()},
+    };
+
+    std::string InternalCode =
+        "#include \"private.inc\"\nclass Internal {};";
+    SymbolInfo InternalSymbol("Internal", SymbolInfo::SymbolKind::Class,
+                              TopHeader, {});
+    SymbolInfo IncSymbol("IncHeaderClass", SymbolInfo::SymbolKind::Class,
+                         TopHeader, {});
+    InMemoryFileSystem->addFile(
+        IncHeader, 0, llvm::MemoryBuffer::getMemBuffer(IncHeaderCode));
+    InMemoryFileSystem->addFile(InternalHeader, 0,
+                                llvm::MemoryBuffer::getMemBuffer(InternalCode));
+
+    std::unique_ptr<tooling::FrontendActionFactory> Factory(
+        new FindAllSymbolsActionFactory(&Reporter, &RegexMap));
+
+    tooling::ToolInvocation Invocation(
+        {std::string("find_all_symbols"), std::string("-fsyntax-only"),
+         std::string("-std=c++11"), FileName},
+        Factory->create(), Files.get(),
+        std::make_shared<PCHContainerOperations>());
+
+    InMemoryFileSystem->addFile(HeaderName, 0,
+                                llvm::MemoryBuffer::getMemBuffer(HeaderCode));
+
+    std::string Content = "#include\"" + std::string(HeaderName) +
+                          "\"\n"
+                          "#include \"" +
+                          InternalHeader + "\"";
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+    // Test path cleaning for both decls and macros.
+    const std::string DirtyHeader = "./internal/./a/b.h";
+    Content += "\n#include \"" + DirtyHeader + "\"";
+    const std::string CleanHeader = "internal/a/b.h";
+    const std::string DirtyHeaderContent =
+        "#define INTERNAL 1\nclass ExtraInternal {};";
+    InMemoryFileSystem->addFile(
+        DirtyHeader, 0, llvm::MemoryBuffer::getMemBuffer(DirtyHeaderContent));
+    SymbolInfo DirtyMacro("INTERNAL", SymbolInfo::SymbolKind::Macro,
+                          CleanHeader, {});
+    SymbolInfo DirtySymbol("ExtraInternal", SymbolInfo::SymbolKind::Class,
+                           CleanHeader, {});
+#endif // _MSC_VER && __MINGW32__
+    Content += "\n" + MainCode.str();
+    InMemoryFileSystem->addFile(FileName, 0,
+                                llvm::MemoryBuffer::getMemBuffer(Content));
+    Invocation.run();
+    EXPECT_EQ(1, seen(InternalSymbol));
+    EXPECT_EQ(1, seen(IncSymbol));
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+    EXPECT_EQ(1, seen(DirtySymbol));
+    EXPECT_EQ(1, seen(DirtyMacro));
+#endif  // _MSC_VER && __MINGW32__
+    return true;
+  }
+
+protected:
+  TestSymbolReporter Reporter;
+};
+
+TEST_F(FindAllSymbolsTest, VariableSymbols) {
+  static const char Header[] = R"(
+      extern int xargc;
+      namespace na {
+      static bool SSSS = false;
+      namespace nb { const long long *XXXX; }
+      })";
+  static const char Main[] = R"(
+      auto y = &na::nb::XXXX;
+      int main() { if (na::SSSS) return xargc; }
+  )";
+  runFindAllSymbols(Header, Main);
+
+  SymbolInfo Symbol =
+      SymbolInfo("xargc", SymbolInfo::SymbolKind::Variable, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("SSSS", SymbolInfo::SymbolKind::Variable, HeaderName,
+                      {{SymbolInfo::ContextType::Namespace, "na"}});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("XXXX", SymbolInfo::SymbolKind::Variable, HeaderName,
+                      {{SymbolInfo::ContextType::Namespace, "nb"},
+                       {SymbolInfo::ContextType::Namespace, "na"}});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+}
+
+TEST_F(FindAllSymbolsTest, ExternCSymbols) {
+  static const char Header[] = R"(
+      extern "C" {
+      int C_Func() { return 0; }
+      struct C_struct {
+        int Member;
+      };
+      })";
+  static const char Main[] = R"(
+      C_struct q() {
+        int(*ptr)() = C_Func;
+        return {0};
+      }
+  )";
+  runFindAllSymbols(Header, Main);
+
+  SymbolInfo Symbol =
+      SymbolInfo("C_Func", SymbolInfo::SymbolKind::Function, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol =
+      SymbolInfo("C_struct", SymbolInfo::SymbolKind::Class, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+}
+
+TEST_F(FindAllSymbolsTest, CXXRecordSymbols) {
+  static const char Header[] = R"(
+      struct Glob {};
+      struct A; // Not a defintion, ignored.
+      class NOP; // Not a defintion, ignored
+      namespace na {
+      struct A {
+        struct AAAA {};
+        int x;
+        int y;
+        void f() {}
+      };
+      };  //
+      )";
+  static const char Main[] = R"(
+      static Glob glob;
+      static na::A::AAAA* a;
+  )";
+  runFindAllSymbols(Header, Main);
+
+  SymbolInfo Symbol =
+      SymbolInfo("Glob", SymbolInfo::SymbolKind::Class, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("A", SymbolInfo::SymbolKind::Class, HeaderName,
+                      {{SymbolInfo::ContextType::Namespace, "na"}});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("AAA", SymbolInfo::SymbolKind::Class, HeaderName,
+                      {{SymbolInfo::ContextType::Record, "A"},
+                       {SymbolInfo::ContextType::Namespace, "na"}});
+  EXPECT_EQ(0, seen(Symbol));
+  EXPECT_EQ(0, used(Symbol));
+}
+
+TEST_F(FindAllSymbolsTest, CXXRecordSymbolsTemplate) {
+  static const char Header[] = R"(
+      template <typename T>
+      struct T_TEMP {
+        template <typename _Tp1>
+        struct rebind { typedef T_TEMP<_Tp1> other; };
+      };
+      // Ignore specialization.
+      template class T_TEMP<char>;
+
+      template <typename T>
+      class Observer {
+      };
+      // Ignore specialization.
+      template <> class Observer<int> {};
+      )";
+  static const char Main[] = R"(
+      extern T_TEMP<int>::rebind<char> weirdo;
+  )";
+  runFindAllSymbols(Header, Main);
+
+  SymbolInfo Symbol =
+      SymbolInfo("T_TEMP", SymbolInfo::SymbolKind::Class, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+}
+
+TEST_F(FindAllSymbolsTest, DontIgnoreTemplatePartialSpecialization) {
+  static const char Code[] = R"(
+      template<class> class Class; // undefined
+      template<class R, class... ArgTypes>
+      class Class<R(ArgTypes...)> {
+      };
+
+      template<class T> void f() {};
+      template<> void f<int>() {};
+      )";
+  runFindAllSymbols(Code, "");
+  SymbolInfo Symbol =
+      SymbolInfo("Class", SymbolInfo::SymbolKind::Class, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  Symbol = SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+}
+
+TEST_F(FindAllSymbolsTest, FunctionSymbols) {
+  static const char Header[] = R"(
+      namespace na {
+      int gg(int);
+      int f(const int &a) { int Local; static int StaticLocal; return 0; }
+      static void SSSFFF() {}
+      }  // namespace na
+      namespace na {
+      namespace nb {
+      template<typename T>
+      void fun(T t) {};
+      } // namespace nb
+      } // namespace na";
+      )";
+  static const char Main[] = R"(
+      int(*gg)(int) = &na::gg;
+      int main() {
+        (void)na::SSSFFF;
+        na::nb::fun(0);
+        return na::f(gg(0));
+      }
+  )";
+  runFindAllSymbols(Header, Main);
+
+  SymbolInfo Symbol =
+      SymbolInfo("gg", SymbolInfo::SymbolKind::Function, HeaderName,
+                 {{SymbolInfo::ContextType::Namespace, "na"}});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName,
+                      {{SymbolInfo::ContextType::Namespace, "na"}});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("SSSFFF", SymbolInfo::SymbolKind::Function, HeaderName,
+                      {{SymbolInfo::ContextType::Namespace, "na"}});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("fun", SymbolInfo::SymbolKind::Function, HeaderName,
+                      {{SymbolInfo::ContextType::Namespace, "nb"},
+                       {SymbolInfo::ContextType::Namespace, "na"}});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+}
+
+TEST_F(FindAllSymbolsTest, NamespaceTest) {
+  static const char Header[] = R"(
+      int X1;
+      namespace { int X2; }
+      namespace { namespace { int X3; } }
+      namespace { namespace nb { int X4; } }
+      namespace na { inline namespace __1 { int X5; } }
+      )";
+  static const char Main[] = R"(
+      using namespace nb;
+      int main() {
+        X1 = X2;
+        X3 = X4;
+        (void)na::X5;
+      }
+  )";
+  runFindAllSymbols(Header, Main);
+
+  SymbolInfo Symbol =
+      SymbolInfo("X1", SymbolInfo::SymbolKind::Variable, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("X2", SymbolInfo::SymbolKind::Variable, HeaderName,
+                      {{SymbolInfo::ContextType::Namespace, ""}});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("X3", SymbolInfo::SymbolKind::Variable, HeaderName,
+                      {{SymbolInfo::ContextType::Namespace, ""},
+                       {SymbolInfo::ContextType::Namespace, ""}});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("X4", SymbolInfo::SymbolKind::Variable, HeaderName,
+                      {{SymbolInfo::ContextType::Namespace, "nb"},
+                       {SymbolInfo::ContextType::Namespace, ""}});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("X5", SymbolInfo::SymbolKind::Variable, HeaderName,
+                      {{SymbolInfo::ContextType::Namespace, "na"}});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+}
+
+TEST_F(FindAllSymbolsTest, DecayedTypeTest) {
+  static const char Header[] = "void DecayedFunc(int x[], int y[10]) {}";
+  static const char Main[] = R"(int main() { DecayedFunc(nullptr, nullptr); })";
+  runFindAllSymbols(Header, Main);
+  SymbolInfo Symbol = SymbolInfo(
+      "DecayedFunc", SymbolInfo::SymbolKind::Function, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+}
+
+TEST_F(FindAllSymbolsTest, CTypedefTest) {
+  static const char Header[] = R"(
+      typedef unsigned size_t_;
+      typedef struct { int x; } X;
+      using XX = X;
+      )";
+  static const char Main[] = R"(
+      size_t_ f;
+      template<typename T> struct vector{};
+      vector<X> list;
+      void foo(const XX&){}
+  )";
+  runFindAllSymbols(Header, Main);
+
+  SymbolInfo Symbol = SymbolInfo("size_t_", SymbolInfo::SymbolKind::TypedefName,
+                                 HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("X", SymbolInfo::SymbolKind::TypedefName, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol =
+      SymbolInfo("XX", SymbolInfo::SymbolKind::TypedefName, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+}
+
+TEST_F(FindAllSymbolsTest, EnumTest) {
+  static const char Header[] = R"(
+      enum Glob_E { G1, G2 };
+      enum class Altitude { high='h', low='l'};
+      enum { A1, A2 };
+      class A {
+      public:
+        enum A_ENUM { X1, X2 };
+      };
+      enum DECL : int;
+      )";
+  static const char Main[] = R"(
+      static auto flags = G1 | G2;
+      static auto alt = Altitude::high;
+      static auto nested = A::X1;
+      extern DECL whatever;
+      static auto flags2 = A1 | A2;
+  )";
+  runFindAllSymbols(Header, Main);
+
+  SymbolInfo Symbol =
+      SymbolInfo("Glob_E", SymbolInfo::SymbolKind::EnumDecl, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(0, used(Symbol));
+
+  Symbol =
+      SymbolInfo("G1", SymbolInfo::SymbolKind::EnumConstantDecl, HeaderName,
+                 {{SymbolInfo::ContextType::EnumDecl, "Glob_E"}});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol =
+      SymbolInfo("G2", SymbolInfo::SymbolKind::EnumConstantDecl, HeaderName,
+                 {{SymbolInfo::ContextType::EnumDecl, "Glob_E"}});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol =
+      SymbolInfo("Altitude", SymbolInfo::SymbolKind::EnumDecl, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+  Symbol =
+      SymbolInfo("high", SymbolInfo::SymbolKind::EnumConstantDecl, HeaderName,
+                 {{SymbolInfo::ContextType::EnumDecl, "Altitude"}});
+  EXPECT_EQ(0, seen(Symbol));
+  EXPECT_EQ(0, used(Symbol));
+
+  Symbol = SymbolInfo("A1", SymbolInfo::SymbolKind::EnumConstantDecl,
+                      HeaderName, {{SymbolInfo::ContextType::EnumDecl, ""}});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+  Symbol = SymbolInfo("A2", SymbolInfo::SymbolKind::EnumConstantDecl,
+                      HeaderName, {{SymbolInfo::ContextType::EnumDecl, ""}});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+  Symbol = SymbolInfo("", SymbolInfo::SymbolKind::EnumDecl, HeaderName, {});
+  EXPECT_EQ(0, seen(Symbol));
+  EXPECT_EQ(0, used(Symbol));
+
+  Symbol = SymbolInfo("A_ENUM", SymbolInfo::SymbolKind::EnumDecl, HeaderName,
+                      {{SymbolInfo::ContextType::Record, "A"}});
+  EXPECT_EQ(0, seen(Symbol));
+  EXPECT_EQ(0, used(Symbol));
+
+  Symbol = SymbolInfo("X1", SymbolInfo::SymbolKind::EnumDecl, HeaderName,
+                      {{SymbolInfo::ContextType::EnumDecl, "A_ENUM"},
+                       {SymbolInfo::ContextType::Record, "A"}});
+  EXPECT_EQ(0, seen(Symbol));
+
+  Symbol = SymbolInfo("DECL", SymbolInfo::SymbolKind::EnumDecl, HeaderName, {});
+  EXPECT_EQ(0, seen(Symbol));
+}
+
+TEST_F(FindAllSymbolsTest, IWYUPrivatePragmaTest) {
+  static const char Header[] = R"(
+    // IWYU pragma: private, include "bar.h"
+    struct Bar {
+    };
+  )";
+  static const char Main[] = R"(
+    Bar bar;
+  )";
+  runFindAllSymbols(Header, Main);
+
+  SymbolInfo Symbol =
+      SymbolInfo("Bar", SymbolInfo::SymbolKind::Class, "bar.h", {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+}
+
+TEST_F(FindAllSymbolsTest, MacroTest) {
+  static const char Header[] = R"(
+    #define X
+    #define Y 1
+    #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
+  )";
+  static const char Main[] = R"(
+    #ifdef X
+    int main() { return MAX(0,Y); }
+    #endif
+  )";
+  runFindAllSymbols(Header, Main);
+  SymbolInfo Symbol =
+      SymbolInfo("X", SymbolInfo::SymbolKind::Macro, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("Y", SymbolInfo::SymbolKind::Macro, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("MAX", SymbolInfo::SymbolKind::Macro, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+}
+
+TEST_F(FindAllSymbolsTest, MacroTestWithIWYU) {
+  static const char Header[] = R"(
+    // IWYU pragma: private, include "bar.h"
+    #define X 1
+    #define Y 1
+    #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
+  )";
+  static const char Main[] = R"(
+    #ifdef X
+    int main() { return MAX(0,Y); }
+    #endif
+  )";
+  runFindAllSymbols(Header, Main);
+  SymbolInfo Symbol =
+      SymbolInfo("X", SymbolInfo::SymbolKind::Macro, "bar.h", {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("Y", SymbolInfo::SymbolKind::Macro, "bar.h", {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+
+  Symbol = SymbolInfo("MAX", SymbolInfo::SymbolKind::Macro, "bar.h", {});
+  EXPECT_EQ(1, seen(Symbol));
+  EXPECT_EQ(1, used(Symbol));
+}
+
+TEST_F(FindAllSymbolsTest, NoFriendTest) {
+  static const char Header[] = R"(
+    class WorstFriend {
+      friend void Friend();
+      friend class BestFriend;
+    };
+  )";
+  runFindAllSymbols(Header, "");
+  SymbolInfo Symbol =
+      SymbolInfo("WorstFriend", SymbolInfo::SymbolKind::Class, HeaderName, {});
+  EXPECT_EQ(1, seen(Symbol));
+
+  Symbol =
+      SymbolInfo("Friend", SymbolInfo::SymbolKind::Function, HeaderName, {});
+  EXPECT_EQ(0, seen(Symbol));
+
+  Symbol =
+      SymbolInfo("BestFriend", SymbolInfo::SymbolKind::Class, HeaderName, {});
+  EXPECT_EQ(0, seen(Symbol));
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/src/third_party/llvm-project/clang-tools-extra/unittests/include/common/VirtualFileHelper.h b/src/third_party/llvm-project/clang-tools-extra/unittests/include/common/VirtualFileHelper.h
new file mode 100644
index 0000000..5fa4d53
--- /dev/null
+++ b/src/third_party/llvm-project/clang-tools-extra/unittests/include/common/VirtualFileHelper.h
@@ -0,0 +1,82 @@
+//===--- VirtualFileHelper.h ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \brief This file defines an utility class for tests that needs a source
+/// manager for a virtual file with customizable content.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_MODERNIZE_VIRTUAL_FILE_HELPER_H
+#define CLANG_MODERNIZE_VIRTUAL_FILE_HELPER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+
+namespace clang {
+
+/// \brief Class that provides easy access to a SourceManager and that allows to
+/// map virtual files conveniently.
+class VirtualFileHelper {
+  struct VirtualFile {
+    std::string FileName;
+    std::string Code;
+  };
+
+public:
+  VirtualFileHelper()
+      : DiagOpts(new DiagnosticOptions()),
+        Diagnostics(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
+                    &*DiagOpts),
+        DiagnosticPrinter(llvm::outs(), &*DiagOpts),
+        Files((FileSystemOptions())) {}
+
+  /// \brief Create a virtual file \p FileName, with content \p Code.
+  void mapFile(llvm::StringRef FileName, llvm::StringRef Code) {
+    VirtualFile VF = { FileName, Code };
+    VirtualFiles.push_back(VF);
+  }
+
+  /// \brief Create a new \c SourceManager with the virtual files and contents
+  /// mapped to it.
+  SourceManager &getNewSourceManager() {
+    Sources.reset(new SourceManager(Diagnostics, Files));
+    mapVirtualFiles(*Sources);
+    return *Sources;
+  }
+
+  /// \brief Map the virtual file contents in the given \c SourceManager.
+  void mapVirtualFiles(SourceManager &SM) const {
+    for (llvm::SmallVectorImpl<VirtualFile>::const_iterator
+             I = VirtualFiles.begin(),
+             E = VirtualFiles.end();
+         I != E; ++I) {
+      std::unique_ptr<llvm::MemoryBuffer> Buf =
+          llvm::MemoryBuffer::getMemBuffer(I->Code);
+      const FileEntry *Entry = SM.getFileManager().getVirtualFile(
+          I->FileName, Buf->getBufferSize(), /*ModificationTime=*/0);
+      SM.overrideFileContents(Entry, std::move(Buf));
+    }
+  }
+
+private:
+  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
+  DiagnosticsEngine Diagnostics;
+  TextDiagnosticPrinter DiagnosticPrinter;
+  FileManager Files;
+  // most tests don't need more than one file
+  llvm::SmallVector<VirtualFile, 1> VirtualFiles;
+  std::unique_ptr<SourceManager> Sources;
+};
+
+} // end namespace clang
+
+#endif // CLANG_MODERNIZE_VIRTUAL_FILE_HELPER_H