[clang] [Clang] [NFC] Introduce `DynamicRecursiveASTVisitor` (PR #105195)

via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 20 11:08:59 PDT 2024


https://github.com/Sirraide created https://github.com/llvm/llvm-project/pull/105195

First, please see #93462 if you’re not already familiar w/ what this is about.

This introduces a variant of `RecursiveASTVisitor` (RAV), called `DynamicRecursiveASTVisitor` (DRAV), that uses virtual functions instead of CRTP in an attempt to combat long compile times and increasing binary size incurred by stamping out dozens of RAV instantiations.

This pr may look big, but most of the changes are very repetitive (it’s mostly just adding `override` like 200 places or so and changing `: RecursiveASTVisitor<Foo>` to `: DynamicRecursiveASTVisitor`).

This pr does NOT remove the old RAV, because
1. Downstream forks may be reliant on it, and
2. There are some things that the DRAV currently does not support, mostly because they are either
    1. complicated or impossible to implement using virtual functions (post-order traversal); or
    2. basically no-one is using them (e.g. overriding `WalkUpFromX` or `getStmtChildren()`; there are about 5 or so visitors 
     in the entire codebase that override those functions; also post-order traversal) and making them `virtual` might have a negative impact on performance; or
    3. I candidly have no idea what to do with them (`LexicallyOrderedRecursiveASTVisitor`; I’m still not sure I understand how that one works).

There is TableGen support for traversing attributes, but for the same reasons as 2ii and 2iii above, it isn’t currently supported.

## Implementation
The DRAV is currently based on the RAV, mostly using a bunch of X macros. This means that, when a new AST node is added, the code for traversing it only needs to be added to the CRTP-based RAV.

The DRAV is based on the principle that no template instantiation (of the RAV) should be necessary to use it (otherwise, that wouldn’t really solve the problem as the problem *is* all the template instantiation). To that end, the DRAV is customised using virtual functions instead. 

The inner workings of the DRAV are a bit arcane (at least it took me a while to figure out a way to get this to work; I’ll be adding some more comments for this soon. Also, if anyone can think of a better approach, please let me know): The `.cpp` file for the DRAV contains a struct called `Impl` that derives from the RAV like usual using CTRP. This `Impl` struct contains a pointer to an instance of (a derived class of) the DRAV and overrides every member function of the RAV that is marked virtual in the DRAV to delegate to it instead via a virtual call. 

This will then either execute the implementation of that function in the derived class; if the base class function of DRAV itself is called (either by the derived class or because the derived class doesn’t override it), then it will statically create a new `Impl` instance, passing in itself (which is a no-op because it has a single reference member and the constructor does nothing), and then call the RAV’s base implementation of the corresponding function (which then executes the code in the old RAV and so on).

## Results
To see how effective this would be, a lot of visitors all over the codebase have been migrated to use the dynamic visitor. The results of this refactor can be viewed [here](https://llvm-compile-time-tracker.com/compare.php?from=27e5f505e5eee3da27c1515d6ed95d66fbe543ea&to=8f7d61923b414085d5d1e419cebd46500cef2662&stat=instructions%3Au) (if you look at the branch in llvm-compile-time-tracker and see that there are a few commits where *everything* got magically faster; those are merge commits, so please ignore those; the link here compares the current state of this branch to the commit on trunk that it is based on to eliminate any effects that unrelated changes might have had).

However, it is worth noting that using virtual functions for this *does* seem to be measurably slower than using CRTP. I have more or less indiscriminately migrated visitors regardless of how often they are used to see how much of a slowdown this would incur. Furthermore, I also checked how often each visitor is being instantiated when compiling Clang itself. The results of that are shown below.

I’ve only checked how often a few select functions were being called; reverting one of the most commonly used visitors (by any of the three tables below) doesn’t really seem to change anything, though (the only thing it does is make Clang’s binary size go up). If anyone has a better idea as to how to determine what visitors are causing (most of) the performance loss, please let me know.


Visitor                                | Instances created
-------------------------------------- | ---------------------
MarkReferencedDecls                    | 142,088,373
FindCXXThisExpr                        |  82,500,552
CollectUnexpandedParameterPacksVisitor |  67,408,408
FallthroughMapper                      |  30,640,329
ImmediateCallVisitor                   |   2,779,953
LocalTypedefNameReferencer             |     841,018
MarkUsedTemplateParameterVisitor       |       2,448


Visitor                                | Calls to `TraverseStmt()`
-------------------------------------- | ---------------------
FallthroughMapper                      | 426,518,146
CollectUnexpandedParameterPacksVisitor |  31,363,671
ImmediateCallVisitor                   |   8,163,769
FindCXXThisExpr                        |   3,776,540
MarkReferencedDecls                    |     105,877
LocalTypedefNameReferencer             |       2,529
MarkUsedTemplateParameterVisitor       |       2,448


Visitor                                | Calls to `TraverseType()`
-------------------------------------- | ---------------------
MarkReferencedDecls                    | 232,417,799
CollectUnexpandedParameterPacksVisitor |  21,681,491
FallthroughMapper                      |  14,102,937
LocalTypedefNameReferencer             |   2,163,902
ImmediateCallVisitor                   |     935,887
FindCXXThisExpr                        |          36
MarkUsedTemplateParameterVisitor       |           0


>From a43092cd2a63f141e80fa914f4a0f5845f768154 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Thu, 6 Jun 2024 16:43:19 +0200
Subject: [PATCH 01/25] [Clang] Introduce DynamicRecursiveASTVisitor

---
 .../clang/AST/DynamicRecursiveASTVisitor.h    | 174 ++++++++++++
 clang/include/clang/AST/RecursiveASTVisitor.h |   8 +-
 clang/lib/AST/CMakeLists.txt                  |   1 +
 clang/lib/AST/DynamicRecursiveASTVisitor.cpp  | 267 ++++++++++++++++++
 clang/lib/Sema/SemaDeclCXX.cpp                |  53 ++--
 clang/lib/Sema/SemaExpr.cpp                   |  49 ++--
 clang/lib/Sema/SemaExprCXX.cpp                |   6 +-
 clang/lib/Sema/SemaStmt.cpp                   |  10 +-
 clang/lib/Sema/SemaTemplate.cpp               |  45 ++-
 clang/utils/TableGen/ClangAttrEmitter.cpp     |  42 ++-
 10 files changed, 563 insertions(+), 92 deletions(-)
 create mode 100644 clang/include/clang/AST/DynamicRecursiveASTVisitor.h
 create mode 100644 clang/lib/AST/DynamicRecursiveASTVisitor.cpp

diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
new file mode 100644
index 00000000000000..58797d9e19fe43
--- /dev/null
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -0,0 +1,174 @@
+#ifndef LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H
+#define LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H
+
+#include "clang/AST/Attr.h"
+#include "clang/AST/ExprConcepts.h"
+#include "clang/AST/TypeLoc.h"
+
+namespace clang {
+class ASTContext;
+
+/// Recursive AST visitor that supports extension via dynamic dispatch.
+///
+/// \see RecursiveASTVisitor
+class DynamicRecursiveASTVisitor {
+public:
+  using DataRecursionQueue =
+      SmallVectorImpl<llvm::PointerIntPair<Stmt *, 1, bool>>;
+
+  /// Whether this visitor should recurse into template instantiations.
+  bool ShouldVisitTemplateInstantiations = false;
+
+  /// Whether this visitor should recurse into the types of TypeLocs.
+  bool ShouldWalkTypesOfTypeLocs = true;
+
+  /// Whether this visitor should recurse into implicit code, e.g.
+  /// implicit constructors and destructors.
+  bool ShouldVisitImplicitCode = false;
+
+  /// Whether this visitor should recurse into lambda body
+  bool ShouldVisitLambdaBody = true;
+
+  /// Return whether this visitor should traverse post-order.
+  bool ShouldTraversePostOrder = false;
+
+protected:
+  DynamicRecursiveASTVisitor() = default;
+
+public:
+  // Copying/moving a polymorphic type is a bad idea.
+  DynamicRecursiveASTVisitor(DynamicRecursiveASTVisitor &&) = delete;
+  DynamicRecursiveASTVisitor(const DynamicRecursiveASTVisitor &) = delete;
+  DynamicRecursiveASTVisitor &operator=(DynamicRecursiveASTVisitor &&) = delete;
+  DynamicRecursiveASTVisitor &
+  operator=(const DynamicRecursiveASTVisitor &) = delete;
+
+  // Declared out of line as a vtable anchor.
+  virtual ~DynamicRecursiveASTVisitor();
+
+  /// Recursively visits an entire AST, starting from the TranslationUnitDecl.
+  /// \returns false if visitation was terminated early.
+  virtual bool TraverseAST(ASTContext &AST);
+
+  /// Recursively visit an attribute, by dispatching to
+  /// Traverse*Attr() based on the argument's dynamic type.
+  ///
+  /// \returns false if the visitation was terminated early, true
+  /// otherwise (including when the argument is a Null type location).
+  virtual bool TraverseAttr(Attr *At);
+
+  /// Recursively visit a constructor initializer.  This
+  /// automatically dispatches to another visitor for the initializer
+  /// expression, but not for the name of the initializer, so may
+  /// be overridden for clients that need access to the name.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
+
+  /// Recursively visit a declaration, by dispatching to
+  /// Traverse*Decl() based on the argument's dynamic type.
+  ///
+  /// \returns false if the visitation was terminated early, true
+  /// otherwise (including when the argument is NULL).
+  virtual bool TraverseDecl(Decl *D);
+
+  /// Recursively visit a statement or expression, by
+  /// dispatching to Traverse*() based on the argument's dynamic type.
+  ///
+  /// \returns false if the visitation was terminated early, true
+  /// otherwise (including when the argument is nullptr).
+  virtual bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr);
+
+  /// Recursively visit a template argument and dispatch to the
+  /// appropriate method for the argument type.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  // FIXME: migrate callers to TemplateArgumentLoc instead.
+  virtual bool TraverseTemplateArgument(const TemplateArgument &Arg);
+
+  /// Recursively visit a set of template arguments.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead.
+  bool
+  TraverseTemplateArguments(ArrayRef<TemplateArgument> Args); // NOT virtual
+
+  /// Recursively visit a template name and dispatch to the
+  /// appropriate method.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseTemplateName(TemplateName Template);
+
+  /// Recursively visit a type, by dispatching to
+  /// Traverse*Type() based on the argument's getTypeClass() property.
+  ///
+  /// \returns false if the visitation was terminated early, true
+  /// otherwise (including when the argument is a Null type).
+  virtual bool TraverseType(QualType T);
+
+  /// Recursively visit a type with location, by dispatching to
+  /// Traverse*TypeLoc() based on the argument type's getTypeClass() property.
+  ///
+  /// \returns false if the visitation was terminated early, true
+  /// otherwise (including when the argument is a Null type location).
+  virtual bool TraverseTypeLoc(TypeLoc TL);
+
+  /// Traverse a concept (requirement).
+  virtual bool TraverseTypeConstraint(const TypeConstraint *C);
+  virtual bool TraverseConceptRequirement(concepts::Requirement *R);
+  virtual bool TraverseConceptTypeRequirement(concepts::TypeRequirement *R);
+  virtual bool TraverseConceptExprRequirement(concepts::ExprRequirement *R);
+  virtual bool TraverseConceptNestedRequirement(concepts::NestedRequirement *R);
+
+  /// Visit a node.
+  virtual bool VisitAttr(Attr *A) { return true; }
+  virtual bool VisitDecl(Decl *D) { return true; }
+  virtual bool VisitStmt(Stmt *S) { return true; }
+  virtual bool VisitType(Type *T) { return true; }
+  virtual bool VisitTypeLoc(TypeLoc TL) { return true; }
+
+  /// Walk up from a node.
+  virtual bool WalkUpFromDecl(Decl *D) { return VisitDecl(D); }
+  virtual bool WalkUpFromStmt(Stmt *S) { return VisitStmt(S); }
+  virtual bool WalkUpFromType(Type *T) { return VisitType(T); }
+  virtual bool WalkUpFromTypeLoc(TypeLoc TL) { return VisitTypeLoc(TL); }
+
+  /*// Declare Traverse*() and friends for attributes.
+#define DYNAMIC_ATTR_VISITOR_DECLS
+#include "clang/AST/AttrVisitor.inc"
+#undef DYNAMIC_ATTR_VISITOR_DECLS*/
+
+  // Declare Traverse*() for and friends all concrete Decl classes.
+#define ABSTRACT_DECL(DECL)
+#define DECL(CLASS, BASE)                                                      \
+  virtual bool Traverse##CLASS##Decl(CLASS##Decl *D);                          \
+  virtual bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D);                        \
+  virtual bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; }
+#include "clang/AST/DeclNodes.inc"
+
+  // Declare Traverse*() and friends for all concrete Stmt classes.
+#define ABSTRACT_STMT(STMT)
+#define STMT(CLASS, PARENT)                                                    \
+  virtual bool Traverse##CLASS(CLASS *S);                                      \
+  virtual bool WalkUpFrom##CLASS(CLASS *S);                                    \
+  virtual bool Visit##CLASS(CLASS *S) { return true; }
+#include "clang/AST/StmtNodes.inc"
+
+  // Declare Traverse*() and friends for all concrete Type classes.
+#define ABSTRACT_TYPE(CLASS, BASE)
+#define TYPE(CLASS, BASE)                                                      \
+  virtual bool Traverse##CLASS##Type(CLASS##Type *T);                          \
+  virtual bool WalkUpFrom##CLASS##Type(CLASS##Type *T);                        \
+  virtual bool Visit##CLASS##Type(CLASS##Type *T) { return true; }
+#include "clang/AST/TypeNodes.inc"
+
+#define ABSTRACT_TYPELOC(CLASS, BASE)
+#define TYPELOC(CLASS, BASE)                                                   \
+  virtual bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL);                    \
+  virtual bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL);                  \
+  virtual bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; }
+#include "clang/AST/TypeLocNodes.def"
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 4bbb4380cdd7fd..d91e54c555297d 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -327,11 +327,11 @@ template <typename Derived> class RecursiveASTVisitor {
   bool VisitAttr(Attr *A) { return true; }
 
 // Declare Traverse* and empty Visit* for all Attr classes.
-#define ATTR_VISITOR_DECLS_ONLY
+#define ATTR_VISITOR_DECLS
 #include "clang/AST/AttrVisitor.inc"
-#undef ATTR_VISITOR_DECLS_ONLY
+#undef ATTR_VISITOR_DECLS
 
-// ---- Methods on Stmts ----
+  // ---- Methods on Stmts ----
 
   Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); }
 
@@ -727,9 +727,11 @@ bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) {
 }
 
 // Define the Traverse*Attr(Attr* A) methods
+#define ATTR_VISITOR_IMPL
 #define VISITORCLASS RecursiveASTVisitor
 #include "clang/AST/AttrVisitor.inc"
 #undef VISITORCLASS
+#undef ATTR_VISITOR_IMPL
 
 template <typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt
index 3faefb54f599fb..dcae3b6f8fedf2 100644
--- a/clang/lib/AST/CMakeLists.txt
+++ b/clang/lib/AST/CMakeLists.txt
@@ -53,6 +53,7 @@ add_clang_library(clangAST
   DeclOpenMP.cpp
   DeclPrinter.cpp
   DeclTemplate.cpp
+  DynamicRecursiveASTVisitor.cpp
   ParentMapContext.cpp
   Expr.cpp
   ExprClassification.cpp
diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
new file mode 100644
index 00000000000000..b9994f31a0730e
--- /dev/null
+++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
@@ -0,0 +1,267 @@
+//=== DynamicRecursiveASTVisitor.cpp - Dynamic AST Visitor Implementation -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements an AST visitor that does not require any template
+// instantiation to allow users to override this behaviour.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+
+using namespace clang;
+
+namespace {
+struct Impl : RecursiveASTVisitor<Impl> {
+  DynamicRecursiveASTVisitor &Visitor;
+  Impl(DynamicRecursiveASTVisitor &Visitor) : Visitor(Visitor) {}
+
+  bool shouldVisitTemplateInstantiations() const {
+    return Visitor.ShouldVisitTemplateInstantiations;
+  }
+
+  bool shouldWalkTypesOfTypeLocs() const {
+    return Visitor.ShouldWalkTypesOfTypeLocs;
+  }
+
+  bool shouldVisitImplicitCode() const {
+    return Visitor.ShouldVisitImplicitCode;
+  }
+
+  bool shouldVisitLambdaBody() const { return Visitor.ShouldVisitLambdaBody; }
+
+  bool shouldTraversePostOrder() const {
+    return Visitor.ShouldTraversePostOrder;
+  }
+
+  bool TraverseAST(ASTContext &AST) { return Visitor.TraverseAST(AST); }
+  bool TraverseAttr(Attr *At) { return Visitor.TraverseAttr(At); }
+  bool TraverseDecl(Decl *D) { return Visitor.TraverseDecl(D); }
+  bool TraverseType(QualType T) { return Visitor.TraverseType(T); }
+  bool TraverseTypeLoc(TypeLoc TL) { return Visitor.TraverseTypeLoc(TL); }
+  bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr) {
+    return Visitor.TraverseStmt(S, Queue);
+  }
+
+  bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
+    return Visitor.TraverseConstructorInitializer(Init);
+  }
+
+  bool TraverseTemplateArgument(const TemplateArgument &Arg) {
+    return Visitor.TraverseTemplateArgument(Arg);
+  }
+
+  bool TraverseTemplateName(TemplateName Template) {
+    return Visitor.TraverseTemplateName(Template);
+  }
+
+  bool TraverseTypeConstraint(const TypeConstraint *C) {
+    return Visitor.TraverseTypeConstraint(C);
+  }
+  bool TraverseConceptRequirement(concepts::Requirement *R) {
+    return Visitor.TraverseConceptRequirement(R);
+  }
+  bool TraverseConceptTypeRequirement(concepts::TypeRequirement *R) {
+    return Visitor.TraverseConceptTypeRequirement(R);
+  }
+  bool TraverseConceptExprRequirement(concepts::ExprRequirement *R) {
+    return Visitor.TraverseConceptExprRequirement(R);
+  }
+  bool TraverseConceptNestedRequirement(concepts::NestedRequirement *R) {
+    return Visitor.TraverseConceptNestedRequirement(R);
+  }
+
+  /// Visit a node.
+  bool VisitAttr(Attr *A) { return Visitor.VisitAttr(A); }
+  bool VisitDecl(Decl *D) { return Visitor.VisitDecl(D); }
+  bool VisitStmt(Stmt *S) { return Visitor.VisitStmt(S); }
+  bool VisitType(Type *T) { return Visitor.VisitType(T); }
+  bool VisitTypeLoc(TypeLoc TL) { return Visitor.VisitTypeLoc(TL); }
+
+  /// Walk up from a node.
+  bool WalkUpFromDecl(Decl *D) { return Visitor.WalkUpFromDecl(D); }
+  bool WalkUpFromStmt(Stmt *S) { return Visitor.WalkUpFromStmt(S); }
+  bool WalkUpFromType(Type *T) { return Visitor.WalkUpFromType(T); }
+  bool WalkUpFromTypeLoc(TypeLoc TL) { return Visitor.WalkUpFromTypeLoc(TL); }
+
+  /*#define ATTR_VISITOR_DECLS
+  #include "clang/AST/AttrVisitor.inc"
+  #undef ATTR_VISITOR_DECLS*/
+
+#define ABSTRACT_DECL(DECL)
+#define DECL(CLASS, BASE)                                                      \
+  bool Traverse##CLASS##Decl(CLASS##Decl *D) {                                 \
+    return Visitor.Traverse##CLASS##Decl(D);                                   \
+  }                                                                            \
+  bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) {                               \
+    return Visitor.WalkUpFrom##CLASS##Decl(D);                                 \
+  }                                                                            \
+  bool Visit##CLASS##Decl(CLASS##Decl *D) {                                    \
+    return Visitor.Visit##CLASS##Decl(D);                                      \
+  }
+#include "clang/AST/DeclNodes.inc"
+
+#define ABSTRACT_STMT(STMT)
+#define STMT(CLASS, PARENT)                                                    \
+  bool Traverse##CLASS(CLASS *S) { return Visitor.Traverse##CLASS(S); }        \
+  bool WalkUpFrom##CLASS(CLASS *S) { return Visitor.WalkUpFrom##CLASS(S); }    \
+  bool Visit##CLASS(CLASS *S) { return Visitor.Visit##CLASS(S); }
+#include "clang/AST/StmtNodes.inc"
+
+  // Declare Traverse*() and friends for all concrete Typeclasses.
+#define ABSTRACT_TYPE(CLASS, BASE)
+#define TYPE(CLASS, BASE)                                                      \
+  bool Traverse##CLASS##Type(CLASS##Type *T) {                                 \
+    return Visitor.Traverse##CLASS##Type(T);                                   \
+  }                                                                            \
+  bool WalkUpFrom##CLASS##Type(CLASS##Type *T) {                               \
+    return Visitor.WalkUpFrom##CLASS##Type(T);                                 \
+  }                                                                            \
+  bool Visit##CLASS##Type(CLASS##Type *T) {                                    \
+    return Visitor.Visit##CLASS##Type(T);                                      \
+  }
+#include "clang/AST/TypeNodes.inc"
+
+#define ABSTRACT_TYPELOC(CLASS, BASE)
+#define TYPELOC(CLASS, BASE)                                                   \
+  bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL) {                           \
+    return Visitor.Traverse##CLASS##TypeLoc(TL);                               \
+  }                                                                            \
+  bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) {                         \
+    return Visitor.WalkUpFrom##CLASS##TypeLoc(TL);                             \
+  }                                                                            \
+  bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) {                              \
+    return Visitor.Visit##CLASS##TypeLoc(TL);                                  \
+  }
+#include "clang/AST/TypeLocNodes.def"
+};
+} // namespace
+
+// Declared out of line to serve as a vtable anchor.
+DynamicRecursiveASTVisitor::~DynamicRecursiveASTVisitor() = default;
+
+bool DynamicRecursiveASTVisitor::TraverseAST(ASTContext &AST) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseAST(AST);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseAttr(Attr *At) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseAttr(At);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseConstructorInitializer(
+    CXXCtorInitializer *Init) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConstructorInitializer(
+      Init);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseDecl(Decl *D) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseDecl(D);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseStmt(Stmt *S,
+                                              DataRecursionQueue *Queue) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseStmt(S, Queue);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseTemplateArgument(
+    const TemplateArgument &Arg) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTemplateArgument(Arg);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseTemplateArguments(
+    ArrayRef<TemplateArgument> Args) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTemplateArguments(Args);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseTemplateName(TemplateName Template) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTemplateName(Template);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseType(QualType T) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseType(T);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseTypeLoc(TypeLoc TL) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTypeLoc(TL);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseTypeConstraint(
+    const TypeConstraint *C) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTypeConstraint(C);
+}
+bool DynamicRecursiveASTVisitor::TraverseConceptRequirement(
+    concepts::Requirement *R) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConceptRequirement(R);
+}
+bool DynamicRecursiveASTVisitor::TraverseConceptTypeRequirement(
+    concepts::TypeRequirement *R) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConceptTypeRequirement(
+      R);
+}
+bool DynamicRecursiveASTVisitor::TraverseConceptExprRequirement(
+    concepts::ExprRequirement *R) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConceptExprRequirement(
+      R);
+}
+bool DynamicRecursiveASTVisitor::TraverseConceptNestedRequirement(
+    concepts::NestedRequirement *R) {
+  return Impl(*this)
+      .RecursiveASTVisitor<Impl>::TraverseConceptNestedRequirement(R);
+}
+
+/*
+#define DYNAMIC_ATTR_VISITOR_IMPL
+#include "clang/AST/AttrVisitor.inc"
+#undef DYNAMIC_ATTR_VISITOR_IMPL
+*/
+
+// Declare Traverse*() for and friends all concrete Decl classes.
+#define ABSTRACT_DECL(DECL)
+#define DECL(CLASS, BASE)                                                      \
+  bool DynamicRecursiveASTVisitor::Traverse##CLASS##Decl(CLASS##Decl *D) {     \
+    return Impl(*this).RecursiveASTVisitor<Impl>::Traverse##CLASS##Decl(D);    \
+  }                                                                            \
+  bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS##Decl(CLASS##Decl *D) {   \
+    return Impl(*this).RecursiveASTVisitor<Impl>::WalkUpFrom##CLASS##Decl(D);  \
+  }
+#include "clang/AST/DeclNodes.inc"
+
+// Declare Traverse*() and friends for all concrete Stmt classes.
+#define ABSTRACT_STMT(STMT)
+#define STMT(CLASS, PARENT)                                                    \
+  bool DynamicRecursiveASTVisitor::Traverse##CLASS(CLASS *S) {                 \
+    return Impl(*this).RecursiveASTVisitor<Impl>::Traverse##CLASS(S);          \
+  }                                                                            \
+  bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS(CLASS *S) {               \
+    return Impl(*this).RecursiveASTVisitor<Impl>::WalkUpFrom##CLASS(S);        \
+  }
+#include "clang/AST/StmtNodes.inc"
+
+// Declare Traverse*() and friends for all concrete Typeclasses.
+#define ABSTRACT_TYPE(CLASS, BASE)
+#define TYPE(CLASS, BASE)                                                      \
+  bool DynamicRecursiveASTVisitor::Traverse##CLASS##Type(CLASS##Type *T) {     \
+    return Impl(*this).RecursiveASTVisitor<Impl>::Traverse##CLASS##Type(T);    \
+  }                                                                            \
+  bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS##Type(CLASS##Type *T) {   \
+    return Impl(*this).RecursiveASTVisitor<Impl>::WalkUpFrom##CLASS##Type(T);  \
+  }
+#include "clang/AST/TypeNodes.inc"
+
+#define ABSTRACT_TYPELOC(CLASS, BASE)
+#define TYPELOC(CLASS, BASE)                                                   \
+  bool DynamicRecursiveASTVisitor::Traverse##CLASS##TypeLoc(                   \
+      CLASS##TypeLoc TL) {                                                     \
+    return Impl(*this).RecursiveASTVisitor<Impl>::Traverse##CLASS##TypeLoc(    \
+        TL);                                                                   \
+  }                                                                            \
+  bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS##TypeLoc(                 \
+      CLASS##TypeLoc TL) {                                                     \
+    return Impl(*this).RecursiveASTVisitor<Impl>::WalkUpFrom##CLASS##TypeLoc(  \
+        TL);                                                                   \
+  }
+#include "clang/AST/TypeLocNodes.def"
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 631fd4e354927f..bc859293d52dba 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -19,11 +19,11 @@
 #include "clang/AST/ComparisonCategories.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/EvaluatedExprVisitor.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/RecordLayout.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/TypeOrdering.h"
@@ -2511,10 +2511,7 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) {
   assert(FD->isImmediateEscalating() && !FD->isConsteval() &&
          "expected an immediate function");
   assert(FD->hasBody() && "expected the function to have a body");
-  struct ImmediateEscalatingExpressionsVisitor
-      : public RecursiveASTVisitor<ImmediateEscalatingExpressionsVisitor> {
-
-    using Base = RecursiveASTVisitor<ImmediateEscalatingExpressionsVisitor>;
+  struct ImmediateEscalatingExpressionsVisitor : DynamicRecursiveASTVisitor {
     Sema &SemaRef;
 
     const FunctionDecl *ImmediateFn;
@@ -2524,10 +2521,10 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) {
 
     ImmediateEscalatingExpressionsVisitor(Sema &SemaRef, FunctionDecl *FD)
         : SemaRef(SemaRef), ImmediateFn(FD),
-          ImmediateFnIsConstructor(isa<CXXConstructorDecl>(FD)) {}
-
-    bool shouldVisitImplicitCode() const { return true; }
-    bool shouldVisitLambdaBody() const { return false; }
+          ImmediateFnIsConstructor(isa<CXXConstructorDecl>(FD)) {
+      ShouldVisitImplicitCode = true;
+      ShouldVisitLambdaBody = false;
+    }
 
     void Diag(const Expr *E, const FunctionDecl *Fn, bool IsCall) {
       SourceLocation Loc = E->getBeginLoc();
@@ -2547,7 +2544,7 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) {
           << (CurrentInit && !CurrentInit->isWritten())
           << InitializedField << Range;
     }
-    bool TraverseCallExpr(CallExpr *E) {
+    bool TraverseCallExpr(CallExpr *E) override {
       if (const auto *DR =
               dyn_cast<DeclRefExpr>(E->getCallee()->IgnoreImplicit());
           DR && DR->isImmediateEscalating()) {
@@ -2556,13 +2553,13 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) {
       }
 
       for (Expr *A : E->arguments())
-        if (!getDerived().TraverseStmt(A))
+        if (!TraverseStmt(A))
           return false;
 
       return true;
     }
 
-    bool VisitDeclRefExpr(DeclRefExpr *E) {
+    bool VisitDeclRefExpr(DeclRefExpr *E) override {
       if (const auto *ReferencedFn = dyn_cast<FunctionDecl>(E->getDecl());
           ReferencedFn && E->isImmediateEscalating()) {
         Diag(E, ReferencedFn, /*IsCall=*/false);
@@ -2572,7 +2569,7 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) {
       return true;
     }
 
-    bool VisitCXXConstructExpr(CXXConstructExpr *E) {
+    bool VisitCXXConstructExpr(CXXConstructExpr *E) override {
       CXXConstructorDecl *D = E->getConstructor();
       if (E->isImmediateEscalating()) {
         Diag(E, D, /*IsCall=*/true);
@@ -2581,18 +2578,18 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) {
       return true;
     }
 
-    bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
+    bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override {
       llvm::SaveAndRestore RAII(CurrentInit, Init);
-      return Base::TraverseConstructorInitializer(Init);
+      return DynamicRecursiveASTVisitor::TraverseConstructorInitializer(Init);
     }
 
-    bool TraverseCXXConstructorDecl(CXXConstructorDecl *Ctr) {
+    bool TraverseCXXConstructorDecl(CXXConstructorDecl *Ctr) override {
       llvm::SaveAndRestore RAII(CurrentConstructor, Ctr);
-      return Base::TraverseCXXConstructorDecl(Ctr);
+      return DynamicRecursiveASTVisitor::TraverseCXXConstructorDecl(Ctr);
     }
 
-    bool TraverseType(QualType T) { return true; }
-    bool VisitBlockExpr(BlockExpr *T) { return true; }
+    bool TraverseType(QualType T) override { return true; }
+    bool VisitBlockExpr(BlockExpr *T) override { return true; }
 
   } Visitor(*this, FD);
   Visitor.TraverseDecl(FD);
@@ -18876,18 +18873,18 @@ void Sema::CheckDelegatingCtorCycles() {
 
 namespace {
   /// AST visitor that finds references to the 'this' expression.
-  class FindCXXThisExpr : public RecursiveASTVisitor<FindCXXThisExpr> {
-    Sema &S;
+class FindCXXThisExpr : public DynamicRecursiveASTVisitor {
+  Sema &S;
 
-  public:
-    explicit FindCXXThisExpr(Sema &S) : S(S) { }
+public:
+  explicit FindCXXThisExpr(Sema &S) : S(S) {}
 
-    bool VisitCXXThisExpr(CXXThisExpr *E) {
-      S.Diag(E->getLocation(), diag::err_this_static_member_func)
+  bool VisitCXXThisExpr(CXXThisExpr *E) override {
+    S.Diag(E->getLocation(), diag::err_this_static_member_func)
         << E->isImplicit();
-      return false;
-    }
-  };
+    return false;
+  }
+};
 }
 
 bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index fb4154757775bc..7c353df69ae179 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -19,6 +19,7 @@
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/EvaluatedExprVisitor.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
@@ -26,7 +27,6 @@
 #include "clang/AST/ExprOpenMP.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/ParentMapContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Builtins.h"
@@ -5443,32 +5443,33 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
   return false;
 }
 
-struct ImmediateCallVisitor : public RecursiveASTVisitor<ImmediateCallVisitor> {
+struct ImmediateCallVisitor : DynamicRecursiveASTVisitor {
   const ASTContext &Context;
-  ImmediateCallVisitor(const ASTContext &Ctx) : Context(Ctx) {}
+  ImmediateCallVisitor(const ASTContext &Ctx) : Context(Ctx) {
+    ShouldVisitImplicitCode = true;
+  }
 
   bool HasImmediateCalls = false;
-  bool shouldVisitImplicitCode() const { return true; }
 
-  bool VisitCallExpr(CallExpr *E) {
+  bool VisitCallExpr(CallExpr *E) override {
     if (const FunctionDecl *FD = E->getDirectCallee())
       HasImmediateCalls |= FD->isImmediateFunction();
-    return RecursiveASTVisitor<ImmediateCallVisitor>::VisitStmt(E);
+    return DynamicRecursiveASTVisitor::VisitStmt(E);
   }
 
-  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
+  bool VisitCXXConstructExpr(CXXConstructExpr *E) override {
     if (const FunctionDecl *FD = E->getConstructor())
       HasImmediateCalls |= FD->isImmediateFunction();
-    return RecursiveASTVisitor<ImmediateCallVisitor>::VisitStmt(E);
+    return DynamicRecursiveASTVisitor::VisitStmt(E);
   }
 
   // SourceLocExpr are not immediate invocations
   // but CXXDefaultInitExpr/CXXDefaultArgExpr containing a SourceLocExpr
   // need to be rebuilt so that they refer to the correct SourceLocation and
   // DeclContext.
-  bool VisitSourceLocExpr(SourceLocExpr *E) {
+  bool VisitSourceLocExpr(SourceLocExpr *E) override {
     HasImmediateCalls = true;
-    return RecursiveASTVisitor<ImmediateCallVisitor>::VisitStmt(E);
+    return DynamicRecursiveASTVisitor::VisitStmt(E);
   }
 
   // A nested lambda might have parameters with immediate invocations
@@ -5477,15 +5478,15 @@ struct ImmediateCallVisitor : public RecursiveASTVisitor<ImmediateCallVisitor> {
   // subexpression).
   // FIXME: We should consider visiting and transforming captures
   // with init expressions.
-  bool VisitLambdaExpr(LambdaExpr *E) {
+  bool VisitLambdaExpr(LambdaExpr *E) override {
     return VisitCXXMethodDecl(E->getCallOperator());
   }
 
-  bool VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+  bool VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) override {
     return TraverseStmt(E->getExpr());
   }
 
-  bool VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
+  bool VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) override {
     return TraverseStmt(E->getExpr());
   }
 };
@@ -17604,10 +17605,10 @@ HandleImmediateInvocations(Sema &SemaRef,
         RemoveNestedImmediateInvocation(SemaRef, Rec, It);
   } else if (Rec.ImmediateInvocationCandidates.size() == 1 &&
              Rec.ReferenceToConsteval.size()) {
-    struct SimpleRemove : RecursiveASTVisitor<SimpleRemove> {
+    struct SimpleRemove : DynamicRecursiveASTVisitor {
       llvm::SmallPtrSetImpl<DeclRefExpr *> &DRSet;
       SimpleRemove(llvm::SmallPtrSetImpl<DeclRefExpr *> &S) : DRSet(S) {}
-      bool VisitDeclRefExpr(DeclRefExpr *E) {
+      bool VisitDeclRefExpr(DeclRefExpr *E) override {
         DRSet.erase(E);
         return DRSet.size();
       }
@@ -19898,17 +19899,15 @@ namespace {
   // TreeTransforms rebuilding the type in a new context. Rather than
   // duplicating the TreeTransform logic, we should consider reusing it here.
   // Currently that causes problems when rebuilding LambdaExprs.
-  class MarkReferencedDecls : public RecursiveASTVisitor<MarkReferencedDecls> {
-    Sema &S;
-    SourceLocation Loc;
-
-  public:
-    typedef RecursiveASTVisitor<MarkReferencedDecls> Inherited;
+class MarkReferencedDecls : public DynamicRecursiveASTVisitor {
+  Sema &S;
+  SourceLocation Loc;
 
-    MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) { }
+public:
+  MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) {}
 
-    bool TraverseTemplateArgument(const TemplateArgument &Arg);
-  };
+  bool TraverseTemplateArgument(const TemplateArgument &Arg) override;
+};
 }
 
 bool MarkReferencedDecls::TraverseTemplateArgument(
@@ -19925,7 +19924,7 @@ bool MarkReferencedDecls::TraverseTemplateArgument(
     }
   }
 
-  return Inherited::TraverseTemplateArgument(Arg);
+  return DynamicRecursiveASTVisitor::TraverseTemplateArgument(Arg);
 }
 
 void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) {
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 4487c618862c5e..5e4508075d6187 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -18,10 +18,10 @@
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprConcepts.h"
 #include "clang/AST/ExprObjC.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/AlignedAllocation.h"
@@ -8716,13 +8716,13 @@ static ExprResult attemptRecovery(Sema &SemaRef,
 }
 
 namespace {
-class FindTypoExprs : public RecursiveASTVisitor<FindTypoExprs> {
+class FindTypoExprs : public DynamicRecursiveASTVisitor {
   llvm::SmallSetVector<TypoExpr *, 2> &TypoExprs;
 
 public:
   explicit FindTypoExprs(llvm::SmallSetVector<TypoExpr *, 2> &TypoExprs)
       : TypoExprs(TypoExprs) {}
-  bool VisitTypoExpr(TypoExpr *TE) {
+  bool VisitTypoExpr(TypoExpr *TE) override {
     TypoExprs.insert(TE);
     return true;
   }
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 57465d4a77ac29..7349a92eecf171 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -16,11 +16,11 @@
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/EvaluatedExprVisitor.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/IgnoreExpr.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
 #include "clang/AST/TypeLoc.h"
@@ -3662,15 +3662,15 @@ namespace {
 /// others. Pretend that all local typedefs are always referenced, to not warn
 /// on this. This isn't necessary if f has internal linkage, or the typedef
 /// is private.
-class LocalTypedefNameReferencer
-    : public RecursiveASTVisitor<LocalTypedefNameReferencer> {
+class LocalTypedefNameReferencer : public DynamicRecursiveASTVisitor {
 public:
   LocalTypedefNameReferencer(Sema &S) : S(S) {}
-  bool VisitRecordType(const RecordType *RT);
+  bool VisitRecordType(RecordType *RT) override;
+
 private:
   Sema &S;
 };
-bool LocalTypedefNameReferencer::VisitRecordType(const RecordType *RT) {
+bool LocalTypedefNameReferencer::VisitRecordType(RecordType *RT) {
   auto *R = dyn_cast<CXXRecordDecl>(RT->getDecl());
   if (!R || !R->isLocalClass() || !R->isLocalClass()->isExternallyVisible() ||
       R->isDependentType())
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 3e3ed77de710e5..0c8bffc6650b1f 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -14,9 +14,9 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclFriend.h"
 #include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/TypeVisitor.h"
 #include "clang/Basic/Builtins.h"
@@ -2691,27 +2691,26 @@ struct ConvertConstructorToDeductionGuideTransform {
 SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList(
     ArrayRef<NamedDecl *> TemplateParams,
     ArrayRef<TemplateArgument> DeducedArgs) {
-  struct TemplateParamsReferencedFinder
-      : public RecursiveASTVisitor<TemplateParamsReferencedFinder> {
+  struct TemplateParamsReferencedFinder : DynamicRecursiveASTVisitor {
     llvm::DenseSet<NamedDecl *> TemplateParams;
     llvm::DenseSet<const NamedDecl *> ReferencedTemplateParams;
 
     TemplateParamsReferencedFinder(ArrayRef<NamedDecl *> TemplateParams)
         : TemplateParams(TemplateParams.begin(), TemplateParams.end()) {}
 
-    bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+    bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) override {
       MarkAppeared(TTP->getDecl());
       return true;
     }
-    bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+    bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
       MarkAppeared(DRE->getFoundDecl());
       return true;
     }
 
-    bool TraverseTemplateName(TemplateName Template) {
+    bool TraverseTemplateName(TemplateName Template) override {
       if (auto *TD = Template.getAsTemplateDecl())
         MarkAppeared(TD);
-      return RecursiveASTVisitor::TraverseTemplateName(Template);
+      return DynamicRecursiveASTVisitor::TraverseTemplateName(Template);
     }
 
     void MarkAppeared(NamedDecl *ND) {
@@ -3806,9 +3805,7 @@ namespace {
 
 /// A class which looks for a use of a certain level of template
 /// parameter.
-struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> {
-  typedef RecursiveASTVisitor<DependencyChecker> super;
-
+struct DependencyChecker : DynamicRecursiveASTVisitor {
   unsigned Depth;
 
   // Whether we're looking for a use of a template parameter that makes the
@@ -3846,7 +3843,7 @@ struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> {
     return false;
   }
 
-  bool TraverseStmt(Stmt *S, DataRecursionQueue *Q = nullptr) {
+  bool TraverseStmt(Stmt *S, DataRecursionQueue *Q = nullptr) override {
     // Prune out non-type-dependent expressions if requested. This can
     // sometimes result in us failing to find a template parameter reference
     // (if a value-dependent expression creates a dependent type), but this
@@ -3854,51 +3851,51 @@ struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> {
     if (auto *E = dyn_cast_or_null<Expr>(S))
       if (IgnoreNonTypeDependent && !E->isTypeDependent())
         return true;
-    return super::TraverseStmt(S, Q);
+    return DynamicRecursiveASTVisitor::TraverseStmt(S, Q);
   }
 
-  bool TraverseTypeLoc(TypeLoc TL) {
+  bool TraverseTypeLoc(TypeLoc TL) override {
     if (IgnoreNonTypeDependent && !TL.isNull() &&
         !TL.getType()->isDependentType())
       return true;
-    return super::TraverseTypeLoc(TL);
+    return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL);
   }
 
-  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) override {
     return !Matches(TL.getTypePtr()->getDepth(), TL.getNameLoc());
   }
 
-  bool VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
+  bool VisitTemplateTypeParmType(TemplateTypeParmType *T) override {
     // For a best-effort search, keep looking until we find a location.
     return IgnoreNonTypeDependent || !Matches(T->getDepth());
   }
 
-  bool TraverseTemplateName(TemplateName N) {
+  bool TraverseTemplateName(TemplateName N) override {
     if (TemplateTemplateParmDecl *PD =
           dyn_cast_or_null<TemplateTemplateParmDecl>(N.getAsTemplateDecl()))
       if (Matches(PD->getDepth()))
         return false;
-    return super::TraverseTemplateName(N);
+    return DynamicRecursiveASTVisitor::TraverseTemplateName(N);
   }
 
-  bool VisitDeclRefExpr(DeclRefExpr *E) {
+  bool VisitDeclRefExpr(DeclRefExpr *E) override {
     if (NonTypeTemplateParmDecl *PD =
           dyn_cast<NonTypeTemplateParmDecl>(E->getDecl()))
       if (Matches(PD->getDepth(), E->getExprLoc()))
         return false;
-    return super::VisitDeclRefExpr(E);
+    return DynamicRecursiveASTVisitor::VisitDeclRefExpr(E);
   }
 
-  bool VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
+  bool VisitSubstTemplateTypeParmType(SubstTemplateTypeParmType *T) override {
     return TraverseType(T->getReplacementType());
   }
 
-  bool
-  VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
+  bool VisitSubstTemplateTypeParmPackType(
+      SubstTemplateTypeParmPackType *T) override {
     return TraverseTemplateArgument(T->getArgumentPack());
   }
 
-  bool TraverseInjectedClassNameType(const InjectedClassNameType *T) {
+  bool TraverseInjectedClassNameType(InjectedClassNameType *T) override {
     return TraverseType(T->getInjectedSpecializationType());
   }
 };
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index ca7630adfbb7b5..23789027583bd8 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -3822,7 +3822,7 @@ void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
   OS << "  return 0;\n";
 }
 
-// Emits code used by RecursiveASTVisitor to visit attributes
+// Emits code used by (Dynamic)RecursiveASTVisitor to visit attributes
 void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) {
   emitSourceFileHeader("Used by RecursiveASTVisitor to visit attributes.", OS,
                        Records);
@@ -3832,7 +3832,7 @@ void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) {
   // Write method declarations for Traverse* methods.
   // We emit this here because we only generate methods for attributes that
   // are declared as ASTNodes.
-  OS << "#ifdef ATTR_VISITOR_DECLS_ONLY\n\n";
+  OS << "#ifdef ATTR_VISITOR_DECLS\n\n";
   for (const auto *Attr : Attrs) {
     const Record &R = *Attr;
     if (!R.getValueAsBit("ASTNode"))
@@ -3844,9 +3844,10 @@ void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) {
        << "    return true; \n"
        << "  }\n";
   }
-  OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n";
+  OS << "\n#endif // ATTR_VISITOR_DECLS\n\n";
 
   // Write individual Traverse* methods for each attribute class.
+  OS << "#ifdef ATTR_VISITOR_IMPL\n\n";
   for (const auto *Attr : Attrs) {
     const Record &R = *Attr;
     if (!R.getValueAsBit("ASTNode"))
@@ -3892,7 +3893,40 @@ void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) {
   OS << "  }\n";  // end switch
   OS << "  llvm_unreachable(\"bad attribute kind\");\n";
   OS << "}\n";  // end function
-  OS << "#endif  // ATTR_VISITOR_DECLS_ONLY\n";
+  OS << "#endif  // ATTR_VISITOR_IMPL\n";
+
+  // Write virtual function declarations / trivial definitions.
+  OS << "#ifdef DYNAMIC_ATTR_VISITOR_DECLS\n\n";
+  for (const auto *Attr : Attrs) {
+    const Record &R = *Attr;
+    if (!R.getValueAsBit("ASTNode"))
+      continue;
+    OS << "  virtual bool Traverse" << R.getName() << "Attr(" << R.getName()
+       << "Attr *A);\n";
+    OS << "  virtual bool Visit" << R.getName() << "Attr(" << R.getName()
+       << "Attr *A) {\n"
+       << "    return true; \n"
+       << "  }\n";
+  }
+  OS << "\n#endif // DYNAMIC_ATTR_VISITOR_DECLS\n\n";
+
+  // Write traversal functions that dispatch to the appropriate visitor.
+  OS << "#ifdef DYNAMIC_ATTR_VISITOR_IMPL\n\n";
+  for (const auto *Attr : Attrs) {
+    const Record &R = *Attr;
+    if (!R.getValueAsBit("ASTNode"))
+      continue;
+    OS << "bool Impl::Traverse" << R.getName() << "Attr(" << R.getName()
+       << "Attr *A) {\n"
+       << "  return Visitor.Traverse" << R.getName() << "Attr(A);\n"
+       << "}\n";
+    OS << "bool DynamicRecursiveASTVisitor::Traverse" << R.getName() << "Attr("
+       << R.getName() << "Attr *A) {\n"
+       << "  return Impl(*this).RecursiveASTVisitor<Impl>::Traverse"
+       << R.getName() << "Attr(A);\n"
+       << "}\n";
+  }
+  OS << "\n#endif // DYNAMIC_ATTR_VISITOR_IMPL\n\n";
 }
 
 void EmitClangAttrTemplateInstantiateHelper(const std::vector<Record *> &Attrs,

>From 5db2b4cafa8eb2d991ba0f337a47a0806f2dbc0f Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Thu, 6 Jun 2024 17:16:48 +0200
Subject: [PATCH 02/25] [Clang] CollectUnexpandedParameterPacksVisitor

---
 .../clang/AST/DynamicRecursiveASTVisitor.h    |  35 ++
 clang/lib/AST/DynamicRecursiveASTVisitor.cpp  |  61 +++
 clang/lib/Sema/SemaTemplateVariadic.cpp       | 407 +++++++++---------
 3 files changed, 298 insertions(+), 205 deletions(-)

diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
index 58797d9e19fe43..bf9d91576f7b18 100644
--- a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -65,6 +65,12 @@ class DynamicRecursiveASTVisitor {
   /// \returns false if the visitation was terminated early, true otherwise.
   virtual bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
 
+  /// Recursively visit a base specifier. This can be overridden by a
+  /// subclass.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base);
+
   /// Recursively visit a declaration, by dispatching to
   /// Traverse*Decl() based on the argument's dynamic type.
   ///
@@ -72,6 +78,29 @@ class DynamicRecursiveASTVisitor {
   /// otherwise (including when the argument is NULL).
   virtual bool TraverseDecl(Decl *D);
 
+  /// Recursively visit a name with its location information.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo);
+
+  /// Recursively visit a lambda capture. \c Init is the expression that
+  /// will be used to initialize the capture.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
+                                     Expr *Init);
+
+  /// Recursively visit a C++ nested-name-specifier.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
+
+  /// Recursively visit a C++ nested-name-specifier with location
+  /// information.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
+
   /// Recursively visit a statement or expression, by
   /// dispatching to Traverse*() based on the argument's dynamic type.
   ///
@@ -86,6 +115,12 @@ class DynamicRecursiveASTVisitor {
   // FIXME: migrate callers to TemplateArgumentLoc instead.
   virtual bool TraverseTemplateArgument(const TemplateArgument &Arg);
 
+  /// Recursively visit a template argument location and dispatch to the
+  /// appropriate method for the argument type.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc);
+
   /// Recursively visit a set of template arguments.
   ///
   /// \returns false if the visitation was terminated early, true otherwise.
diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
index b9994f31a0730e..24c2a9dcfa0812 100644
--- a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
+++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
@@ -55,6 +55,10 @@ struct Impl : RecursiveASTVisitor<Impl> {
     return Visitor.TraverseTemplateArgument(Arg);
   }
 
+  bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
+    return Visitor.TraverseTemplateArgumentLoc(ArgLoc);
+  }
+
   bool TraverseTemplateName(TemplateName Template) {
     return Visitor.TraverseTemplateName(Template);
   }
@@ -75,6 +79,27 @@ struct Impl : RecursiveASTVisitor<Impl> {
     return Visitor.TraverseConceptNestedRequirement(R);
   }
 
+  bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) {
+    return Visitor.TraverseCXXBaseSpecifier(Base);
+  }
+
+  bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo) {
+    return Visitor.TraverseDeclarationNameInfo(NameInfo);
+  }
+
+  bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
+                             Expr *Init) {
+    return Visitor.TraverseLambdaCapture(LE, C, Init);
+  }
+
+  bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
+    return Visitor.TraverseNestedNameSpecifier(NNS);
+  }
+
+  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+    return Visitor.TraverseNestedNameSpecifierLoc(NNS);
+  }
+
   /// Visit a node.
   bool VisitAttr(Attr *A) { return Visitor.VisitAttr(A); }
   bool VisitDecl(Decl *D) { return Visitor.VisitDecl(D); }
@@ -162,6 +187,13 @@ bool DynamicRecursiveASTVisitor::TraverseDecl(Decl *D) {
   return Impl(*this).RecursiveASTVisitor<Impl>::TraverseDecl(D);
 }
 
+bool DynamicRecursiveASTVisitor::TraverseLambdaCapture(LambdaExpr *LE,
+                                                       const LambdaCapture *C,
+                                                       Expr *Init) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseLambdaCapture(LE, C,
+                                                                      Init);
+}
+
 bool DynamicRecursiveASTVisitor::TraverseStmt(Stmt *S,
                                               DataRecursionQueue *Queue) {
   return Impl(*this).RecursiveASTVisitor<Impl>::TraverseStmt(S, Queue);
@@ -177,6 +209,12 @@ bool DynamicRecursiveASTVisitor::TraverseTemplateArguments(
   return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTemplateArguments(Args);
 }
 
+bool DynamicRecursiveASTVisitor::TraverseTemplateArgumentLoc(
+    const TemplateArgumentLoc &ArgLoc) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTemplateArgumentLoc(
+      ArgLoc);
+}
+
 bool DynamicRecursiveASTVisitor::TraverseTemplateName(TemplateName Template) {
   return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTemplateName(Template);
 }
@@ -213,6 +251,29 @@ bool DynamicRecursiveASTVisitor::TraverseConceptNestedRequirement(
       .RecursiveASTVisitor<Impl>::TraverseConceptNestedRequirement(R);
 }
 
+bool DynamicRecursiveASTVisitor::TraverseCXXBaseSpecifier(
+    const CXXBaseSpecifier &Base) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseCXXBaseSpecifier(Base);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseDeclarationNameInfo(
+    DeclarationNameInfo NameInfo) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseDeclarationNameInfo(
+      NameInfo);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseNestedNameSpecifier(
+    NestedNameSpecifier *NNS) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseNestedNameSpecifier(
+      NNS);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(
+    NestedNameSpecifierLoc NNS) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseNestedNameSpecifierLoc(
+      NNS);
+}
+
 /*
 #define DYNAMIC_ATTR_VISITOR_IMPL
 #include "clang/AST/AttrVisitor.inc"
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 7a44b978aacdb7..f1ed39d816bf5b 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -8,14 +8,14 @@
 //  This file implements semantic analysis for C++0x variadic templates.
 //===----------------------------------------------------------------------===/
 
-#include "clang/Sema/Sema.h"
 #include "TypeLocBuilder.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/Expr.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/Sema.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/Template.h"
 #include <optional>
@@ -28,259 +28,256 @@ using namespace clang;
 
 namespace {
   /// A class that collects unexpanded parameter packs.
-  class CollectUnexpandedParameterPacksVisitor :
-    public RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
-  {
-    typedef RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
-      inherited;
-
-    SmallVectorImpl<UnexpandedParameterPack> &Unexpanded;
-
-    bool InLambda = false;
-    unsigned DepthLimit = (unsigned)-1;
-
-    void addUnexpanded(NamedDecl *ND, SourceLocation Loc = SourceLocation()) {
-      if (auto *VD = dyn_cast<VarDecl>(ND)) {
-        // For now, the only problematic case is a generic lambda's templated
-        // call operator, so we don't need to look for all the other ways we
-        // could have reached a dependent parameter pack.
-        auto *FD = dyn_cast<FunctionDecl>(VD->getDeclContext());
-        auto *FTD = FD ? FD->getDescribedFunctionTemplate() : nullptr;
-        if (FTD && FTD->getTemplateParameters()->getDepth() >= DepthLimit)
-          return;
-      } else if (getDepthAndIndex(ND).first >= DepthLimit)
+class CollectUnexpandedParameterPacksVisitor
+    : public DynamicRecursiveASTVisitor {
+  SmallVectorImpl<UnexpandedParameterPack> &Unexpanded;
+
+  bool InLambda = false;
+  unsigned DepthLimit = (unsigned)-1;
+
+  void addUnexpanded(NamedDecl *ND, SourceLocation Loc = SourceLocation()) {
+    if (auto *VD = dyn_cast<VarDecl>(ND)) {
+      // For now, the only problematic case is a generic lambda's templated
+      // call operator, so we don't need to look for all the other ways we
+      // could have reached a dependent parameter pack.
+      auto *FD = dyn_cast<FunctionDecl>(VD->getDeclContext());
+      auto *FTD = FD ? FD->getDescribedFunctionTemplate() : nullptr;
+      if (FTD && FTD->getTemplateParameters()->getDepth() >= DepthLimit)
         return;
+    } else if (getDepthAndIndex(ND).first >= DepthLimit)
+      return;
 
-      Unexpanded.push_back({ND, Loc});
-    }
-    void addUnexpanded(const TemplateTypeParmType *T,
-                       SourceLocation Loc = SourceLocation()) {
-      if (T->getDepth() < DepthLimit)
-        Unexpanded.push_back({T, Loc});
-    }
+    Unexpanded.push_back({ND, Loc});
+  }
+  void addUnexpanded(const TemplateTypeParmType *T,
+                     SourceLocation Loc = SourceLocation()) {
+    if (T->getDepth() < DepthLimit)
+      Unexpanded.push_back({T, Loc});
+  }
 
-  public:
-    explicit CollectUnexpandedParameterPacksVisitor(
-        SmallVectorImpl<UnexpandedParameterPack> &Unexpanded)
-        : Unexpanded(Unexpanded) {}
+public:
+  explicit CollectUnexpandedParameterPacksVisitor(
+      SmallVectorImpl<UnexpandedParameterPack> &Unexpanded)
+      : Unexpanded(Unexpanded) {
+    ShouldWalkTypesOfTypeLocs = false;
+    ShouldVisitImplicitCode = true;
+  }
 
-    bool shouldWalkTypesOfTypeLocs() const { return false; }
+  //------------------------------------------------------------------------
+  // Recording occurrences of (unexpanded) parameter packs.
+  //------------------------------------------------------------------------
 
-    // We need this so we can find e.g. attributes on lambdas.
-    bool shouldVisitImplicitCode() const { return true; }
+  /// Record occurrences of template type parameter packs.
+  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) override {
+    if (TL.getTypePtr()->isParameterPack())
+      addUnexpanded(TL.getTypePtr(), TL.getNameLoc());
+    return true;
+  }
 
-    //------------------------------------------------------------------------
-    // Recording occurrences of (unexpanded) parameter packs.
-    //------------------------------------------------------------------------
+  /// Record occurrences of template type parameter packs
+  /// when we don't have proper source-location information for
+  /// them.
+  ///
+  /// Ideally, this routine would never be used.
+  bool VisitTemplateTypeParmType(TemplateTypeParmType *T) override {
+    if (T->isParameterPack())
+      addUnexpanded(T);
 
-    /// Record occurrences of template type parameter packs.
-    bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
-      if (TL.getTypePtr()->isParameterPack())
-        addUnexpanded(TL.getTypePtr(), TL.getNameLoc());
-      return true;
-    }
+    return true;
+  }
 
-    /// Record occurrences of template type parameter packs
-    /// when we don't have proper source-location information for
-    /// them.
-    ///
-    /// Ideally, this routine would never be used.
-    bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
-      if (T->isParameterPack())
-        addUnexpanded(T);
+  /// Record occurrences of function and non-type template
+  /// parameter packs in an expression.
+  bool VisitDeclRefExpr(DeclRefExpr *E) override {
+    if (E->getDecl()->isParameterPack())
+      addUnexpanded(E->getDecl(), E->getLocation());
 
-      return true;
+    return true;
+  }
+
+  /// Record occurrences of template template parameter packs.
+  bool TraverseTemplateName(TemplateName Template) override {
+    if (auto *TTP = dyn_cast_or_null<TemplateTemplateParmDecl>(
+            Template.getAsTemplateDecl())) {
+      if (TTP->isParameterPack())
+        addUnexpanded(TTP);
     }
 
-    /// Record occurrences of function and non-type template
-    /// parameter packs in an expression.
-    bool VisitDeclRefExpr(DeclRefExpr *E) {
-      if (E->getDecl()->isParameterPack())
-        addUnexpanded(E->getDecl(), E->getLocation());
+    return DynamicRecursiveASTVisitor::TraverseTemplateName(Template);
+  }
 
+  /// Suppress traversal into Objective-C container literal
+  /// elements that are pack expansions.
+  bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) override {
+    if (!E->containsUnexpandedParameterPack())
       return true;
-    }
 
-    /// Record occurrences of template template parameter packs.
-    bool TraverseTemplateName(TemplateName Template) {
-      if (auto *TTP = dyn_cast_or_null<TemplateTemplateParmDecl>(
-              Template.getAsTemplateDecl())) {
-        if (TTP->isParameterPack())
-          addUnexpanded(TTP);
-      }
+    for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) {
+      ObjCDictionaryElement Element = E->getKeyValueElement(I);
+      if (Element.isPackExpansion())
+        continue;
 
-      return inherited::TraverseTemplateName(Template);
+      TraverseStmt(Element.Key);
+      TraverseStmt(Element.Value);
     }
+    return true;
+  }
+  //------------------------------------------------------------------------
+  // Pruning the search for unexpanded parameter packs.
+  //------------------------------------------------------------------------
 
-    /// Suppress traversal into Objective-C container literal
-    /// elements that are pack expansions.
-    bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
-      if (!E->containsUnexpandedParameterPack())
-        return true;
+  /// Suppress traversal into statements and expressions that
+  /// do not contain unexpanded parameter packs.
+  bool TraverseStmt(Stmt *S, DataRecursionQueue *Q = nullptr) override {
+    Expr *E = dyn_cast_or_null<Expr>(S);
+    if ((E && E->containsUnexpandedParameterPack()) || InLambda)
+      return DynamicRecursiveASTVisitor::TraverseStmt(S, Q);
 
-      for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) {
-        ObjCDictionaryElement Element = E->getKeyValueElement(I);
-        if (Element.isPackExpansion())
-          continue;
+    return true;
+  }
 
-        TraverseStmt(Element.Key);
-        TraverseStmt(Element.Value);
-      }
-      return true;
-    }
-    //------------------------------------------------------------------------
-    // Pruning the search for unexpanded parameter packs.
-    //------------------------------------------------------------------------
+  /// Suppress traversal into types that do not contain
+  /// unexpanded parameter packs.
+  bool TraverseType(QualType T) override {
+    if ((!T.isNull() && T->containsUnexpandedParameterPack()) || InLambda)
+      return DynamicRecursiveASTVisitor::TraverseType(T);
 
-    /// Suppress traversal into statements and expressions that
-    /// do not contain unexpanded parameter packs.
-    bool TraverseStmt(Stmt *S) {
-      Expr *E = dyn_cast_or_null<Expr>(S);
-      if ((E && E->containsUnexpandedParameterPack()) || InLambda)
-        return inherited::TraverseStmt(S);
+    return true;
+  }
 
-      return true;
-    }
+  /// Suppress traversal into types with location information
+  /// that do not contain unexpanded parameter packs.
+  bool TraverseTypeLoc(TypeLoc TL) override {
+    if ((!TL.getType().isNull() &&
+         TL.getType()->containsUnexpandedParameterPack()) ||
+        InLambda)
+      return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL);
 
-    /// Suppress traversal into types that do not contain
-    /// unexpanded parameter packs.
-    bool TraverseType(QualType T) {
-      if ((!T.isNull() && T->containsUnexpandedParameterPack()) || InLambda)
-        return inherited::TraverseType(T);
+    return true;
+  }
 
+  /// Suppress traversal of parameter packs.
+  bool TraverseDecl(Decl *D) override {
+    // A function parameter pack is a pack expansion, so cannot contain
+    // an unexpanded parameter pack. Likewise for a template parameter
+    // pack that contains any references to other packs.
+    if (D && D->isParameterPack())
       return true;
-    }
 
-    /// Suppress traversal into types with location information
-    /// that do not contain unexpanded parameter packs.
-    bool TraverseTypeLoc(TypeLoc TL) {
-      if ((!TL.getType().isNull() &&
-           TL.getType()->containsUnexpandedParameterPack()) ||
-          InLambda)
-        return inherited::TraverseTypeLoc(TL);
+    return DynamicRecursiveASTVisitor::TraverseDecl(D);
+  }
 
+  /// Suppress traversal of pack-expanded attributes.
+  bool TraverseAttr(Attr *A) override {
+    if (A->isPackExpansion())
       return true;
-    }
 
-    /// Suppress traversal of parameter packs.
-    bool TraverseDecl(Decl *D) {
-      // A function parameter pack is a pack expansion, so cannot contain
-      // an unexpanded parameter pack. Likewise for a template parameter
-      // pack that contains any references to other packs.
-      if (D && D->isParameterPack())
-        return true;
-
-      return inherited::TraverseDecl(D);
-    }
-
-    /// Suppress traversal of pack-expanded attributes.
-    bool TraverseAttr(Attr *A) {
-      if (A->isPackExpansion())
-        return true;
+    return DynamicRecursiveASTVisitor::TraverseAttr(A);
+  }
 
-      return inherited::TraverseAttr(A);
-    }
+  /// Suppress traversal of pack expansion expressions and types.
+  ///@{
+  bool TraversePackExpansionType(PackExpansionType *T) override { return true; }
+  bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) override {
+    return true;
+  }
+  bool TraversePackExpansionExpr(PackExpansionExpr *E) override { return true; }
+  bool TraverseCXXFoldExpr(CXXFoldExpr *E) override { return true; }
+  bool TraversePackIndexingExpr(PackIndexingExpr *E) override {
+    return DynamicRecursiveASTVisitor::TraverseStmt(E->getIndexExpr());
+  }
+  bool TraversePackIndexingType(PackIndexingType *E) override {
+    return DynamicRecursiveASTVisitor::TraverseStmt(E->getIndexExpr());
+  }
+  bool TraversePackIndexingTypeLoc(PackIndexingTypeLoc TL) override {
+    return DynamicRecursiveASTVisitor::TraverseStmt(TL.getIndexExpr());
+  }
 
-    /// Suppress traversal of pack expansion expressions and types.
-    ///@{
-    bool TraversePackExpansionType(PackExpansionType *T) { return true; }
-    bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) { return true; }
-    bool TraversePackExpansionExpr(PackExpansionExpr *E) { return true; }
-    bool TraverseCXXFoldExpr(CXXFoldExpr *E) { return true; }
-    bool TraversePackIndexingExpr(PackIndexingExpr *E) {
-      return inherited::TraverseStmt(E->getIndexExpr());
-    }
-    bool TraversePackIndexingType(PackIndexingType *E) {
-      return inherited::TraverseStmt(E->getIndexExpr());
-    }
-    bool TraversePackIndexingTypeLoc(PackIndexingTypeLoc TL) {
-      return inherited::TraverseStmt(TL.getIndexExpr());
-    }
+  ///@}
 
-    ///@}
+  /// Suppress traversal of using-declaration pack expansion.
+  bool TraverseUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) override {
+    if (D->isPackExpansion())
+      return true;
 
-    /// Suppress traversal of using-declaration pack expansion.
-    bool TraverseUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
-      if (D->isPackExpansion())
-        return true;
+    return DynamicRecursiveASTVisitor::TraverseUnresolvedUsingValueDecl(D);
+  }
 
-      return inherited::TraverseUnresolvedUsingValueDecl(D);
-    }
+  /// Suppress traversal of using-declaration pack expansion.
+  bool
+  TraverseUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) override {
+    if (D->isPackExpansion())
+      return true;
 
-    /// Suppress traversal of using-declaration pack expansion.
-    bool TraverseUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
-      if (D->isPackExpansion())
-        return true;
+    return DynamicRecursiveASTVisitor::TraverseUnresolvedUsingTypenameDecl(D);
+  }
 
-      return inherited::TraverseUnresolvedUsingTypenameDecl(D);
-    }
+  /// Suppress traversal of template argument pack expansions.
+  bool TraverseTemplateArgument(const TemplateArgument &Arg) override {
+    if (Arg.isPackExpansion())
+      return true;
 
-    /// Suppress traversal of template argument pack expansions.
-    bool TraverseTemplateArgument(const TemplateArgument &Arg) {
-      if (Arg.isPackExpansion())
-        return true;
+    return DynamicRecursiveASTVisitor::TraverseTemplateArgument(Arg);
+  }
 
-      return inherited::TraverseTemplateArgument(Arg);
-    }
+  /// Suppress traversal of template argument pack expansions.
+  bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) override {
+    if (ArgLoc.getArgument().isPackExpansion())
+      return true;
 
-    /// Suppress traversal of template argument pack expansions.
-    bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
-      if (ArgLoc.getArgument().isPackExpansion())
-        return true;
+    return DynamicRecursiveASTVisitor::TraverseTemplateArgumentLoc(ArgLoc);
+  }
 
-      return inherited::TraverseTemplateArgumentLoc(ArgLoc);
-    }
+  /// Suppress traversal of base specifier pack expansions.
+  bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) override {
+    if (Base.isPackExpansion())
+      return true;
 
-    /// Suppress traversal of base specifier pack expansions.
-    bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) {
-      if (Base.isPackExpansion())
-        return true;
+    return DynamicRecursiveASTVisitor::TraverseCXXBaseSpecifier(Base);
+  }
 
-      return inherited::TraverseCXXBaseSpecifier(Base);
-    }
+  /// Suppress traversal of mem-initializer pack expansions.
+  bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override {
+    if (Init->isPackExpansion())
+      return true;
 
-    /// Suppress traversal of mem-initializer pack expansions.
-    bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
-      if (Init->isPackExpansion())
-        return true;
+    return DynamicRecursiveASTVisitor::TraverseConstructorInitializer(Init);
+  }
 
-      return inherited::TraverseConstructorInitializer(Init);
-    }
+  /// Note whether we're traversing a lambda containing an unexpanded
+  /// parameter pack. In this case, the unexpanded pack can occur anywhere,
+  /// including all the places where we normally wouldn't look. Within a
+  /// lambda, we don't propagate the 'contains unexpanded parameter pack' bit
+  /// outside an expression.
+  bool TraverseLambdaExpr(LambdaExpr *Lambda) override {
+    // The ContainsUnexpandedParameterPack bit on a lambda is always correct,
+    // even if it's contained within another lambda.
+    if (!Lambda->containsUnexpandedParameterPack())
+      return true;
 
-    /// Note whether we're traversing a lambda containing an unexpanded
-    /// parameter pack. In this case, the unexpanded pack can occur anywhere,
-    /// including all the places where we normally wouldn't look. Within a
-    /// lambda, we don't propagate the 'contains unexpanded parameter pack' bit
-    /// outside an expression.
-    bool TraverseLambdaExpr(LambdaExpr *Lambda) {
-      // The ContainsUnexpandedParameterPack bit on a lambda is always correct,
-      // even if it's contained within another lambda.
-      if (!Lambda->containsUnexpandedParameterPack())
-        return true;
+    bool WasInLambda = InLambda;
+    unsigned OldDepthLimit = DepthLimit;
 
-      bool WasInLambda = InLambda;
-      unsigned OldDepthLimit = DepthLimit;
+    InLambda = true;
+    if (auto *TPL = Lambda->getTemplateParameterList())
+      DepthLimit = TPL->getDepth();
 
-      InLambda = true;
-      if (auto *TPL = Lambda->getTemplateParameterList())
-        DepthLimit = TPL->getDepth();
+    DynamicRecursiveASTVisitor::TraverseLambdaExpr(Lambda);
 
-      inherited::TraverseLambdaExpr(Lambda);
+    InLambda = WasInLambda;
+    DepthLimit = OldDepthLimit;
+    return true;
+  }
 
-      InLambda = WasInLambda;
-      DepthLimit = OldDepthLimit;
+  /// Suppress traversal within pack expansions in lambda captures.
+  bool TraverseLambdaCapture(LambdaExpr *Lambda, const LambdaCapture *C,
+                             Expr *Init) override {
+    if (C->isPackExpansion())
       return true;
-    }
 
-    /// Suppress traversal within pack expansions in lambda captures.
-    bool TraverseLambdaCapture(LambdaExpr *Lambda, const LambdaCapture *C,
-                               Expr *Init) {
-      if (C->isPackExpansion())
-        return true;
-
-      return inherited::TraverseLambdaCapture(Lambda, C, Init);
-    }
-  };
+    return DynamicRecursiveASTVisitor::TraverseLambdaCapture(Lambda, C, Init);
+  }
+};
 }
 
 /// Determine whether it's possible for an unexpanded parameter pack to

>From ac15b6d005788cff0bbb5e393d43de916caead7f Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Thu, 6 Jun 2024 17:33:08 +0200
Subject: [PATCH 03/25] [Clang] CodeGen

---
 clang/lib/CodeGen/CGDebugInfo.cpp   | 21 ++++++++++-----------
 clang/lib/CodeGen/CodeGenModule.cpp | 21 ++++++++++-----------
 2 files changed, 20 insertions(+), 22 deletions(-)

diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 1713f7065e7a20..1451a28eeceec3 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -24,9 +24,9 @@
 #include "clang/AST/DeclFriend.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/RecordLayout.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/VTableBuilder.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/FileManager.h"
@@ -5364,10 +5364,9 @@ static bool ReferencesAnonymousEntity(ArrayRef<TemplateArgument> Args) {
     case TemplateArgument::Pack:
       return ReferencesAnonymousEntity(TA.getPackAsArray());
     case TemplateArgument::Type: {
-      struct ReferencesAnonymous
-          : public RecursiveASTVisitor<ReferencesAnonymous> {
+      struct ReferencesAnonymous : DynamicRecursiveASTVisitor {
         bool RefAnon = false;
-        bool VisitRecordType(RecordType *RT) {
+        bool VisitRecordType(RecordType *RT) override {
           if (ReferencesAnonymousEntity(RT)) {
             RefAnon = true;
             return false;
@@ -5388,17 +5387,17 @@ static bool ReferencesAnonymousEntity(ArrayRef<TemplateArgument> Args) {
   });
 }
 namespace {
-struct ReconstitutableType : public RecursiveASTVisitor<ReconstitutableType> {
+struct ReconstitutableType : DynamicRecursiveASTVisitor {
   bool Reconstitutable = true;
-  bool VisitVectorType(VectorType *FT) {
+  bool VisitVectorType(VectorType *FT) override {
     Reconstitutable = false;
     return false;
   }
-  bool VisitAtomicType(AtomicType *FT) {
+  bool VisitAtomicType(AtomicType *FT) override {
     Reconstitutable = false;
     return false;
   }
-  bool VisitType(Type *T) {
+  bool VisitType(Type *T) override {
     // _BitInt(N) isn't reconstitutable because the bit width isn't encoded in
     // the DWARF, only the byte width.
     if (T->isBitIntType()) {
@@ -5407,7 +5406,7 @@ struct ReconstitutableType : public RecursiveASTVisitor<ReconstitutableType> {
     }
     return true;
   }
-  bool TraverseEnumType(EnumType *ET) {
+  bool TraverseEnumType(EnumType *ET) override {
     // Unnamed enums can't be reconstituted due to a lack of column info we
     // produce in the DWARF, so we can't get Clang's full name back.
     if (const auto *ED = dyn_cast<EnumDecl>(ET->getDecl())) {
@@ -5422,13 +5421,13 @@ struct ReconstitutableType : public RecursiveASTVisitor<ReconstitutableType> {
     }
     return true;
   }
-  bool VisitFunctionProtoType(FunctionProtoType *FT) {
+  bool VisitFunctionProtoType(FunctionProtoType *FT) override {
     // noexcept is not encoded in DWARF, so the reversi
     Reconstitutable &= !isNoexceptExceptionSpec(FT->getExceptionSpecType());
     Reconstitutable &= !FT->getNoReturnAttr();
     return Reconstitutable;
   }
-  bool VisitRecordType(RecordType *RT) {
+  bool VisitRecordType(RecordType *RT) override {
     if (ReferencesAnonymousEntity(RT)) {
       Reconstitutable = false;
       return false;
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index c2314c3a57d330..fd229b67ea724a 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -34,8 +34,8 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/Mangle.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/CharInfo.h"
@@ -3890,13 +3890,12 @@ namespace {
   };
 
   // Make sure we're not referencing non-imported vars or functions.
-  struct DLLImportFunctionVisitor
-      : public RecursiveASTVisitor<DLLImportFunctionVisitor> {
+  struct DLLImportFunctionVisitor : DynamicRecursiveASTVisitor {
     bool SafeToInline = true;
 
-    bool shouldVisitImplicitCode() const { return true; }
+    DLLImportFunctionVisitor() { ShouldVisitImplicitCode = true; }
 
-    bool VisitVarDecl(VarDecl *VD) {
+    bool VisitVarDecl(VarDecl *VD) override {
       if (VD->getTLSKind()) {
         // A thread-local variable cannot be imported.
         SafeToInline = false;
@@ -3910,13 +3909,13 @@ namespace {
       return SafeToInline;
     }
 
-    bool VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+    bool VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) override {
       if (const auto *D = E->getTemporary()->getDestructor())
         SafeToInline = D->hasAttr<DLLImportAttr>();
       return SafeToInline;
     }
 
-    bool VisitDeclRefExpr(DeclRefExpr *E) {
+    bool VisitDeclRefExpr(DeclRefExpr *E) override {
       ValueDecl *VD = E->getDecl();
       if (isa<FunctionDecl>(VD))
         SafeToInline = VD->hasAttr<DLLImportAttr>();
@@ -3925,12 +3924,12 @@ namespace {
       return SafeToInline;
     }
 
-    bool VisitCXXConstructExpr(CXXConstructExpr *E) {
+    bool VisitCXXConstructExpr(CXXConstructExpr *E) override {
       SafeToInline = E->getConstructor()->hasAttr<DLLImportAttr>();
       return SafeToInline;
     }
 
-    bool VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
+    bool VisitCXXMemberCallExpr(CXXMemberCallExpr *E) override {
       CXXMethodDecl *M = E->getMethodDecl();
       if (!M) {
         // Call through a pointer to member function. This is safe to inline.
@@ -3941,12 +3940,12 @@ namespace {
       return SafeToInline;
     }
 
-    bool VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+    bool VisitCXXDeleteExpr(CXXDeleteExpr *E) override {
       SafeToInline = E->getOperatorDelete()->hasAttr<DLLImportAttr>();
       return SafeToInline;
     }
 
-    bool VisitCXXNewExpr(CXXNewExpr *E) {
+    bool VisitCXXNewExpr(CXXNewExpr *E) override {
       SafeToInline = E->getOperatorNew()->hasAttr<DLLImportAttr>();
       return SafeToInline;
     }

>From 5b65237e559c0c0369dd37c2ddc1768d67205608 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Thu, 6 Jun 2024 18:25:19 +0200
Subject: [PATCH 04/25] [Clang] Separate Traverse() and friends

---
 .../clang/AST/DynamicRecursiveASTVisitor.h    | 10 ++++++++--
 clang/lib/AST/DynamicRecursiveASTVisitor.cpp  | 20 +++++++++++++++----
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
index bf9d91576f7b18..01567237ba7cb4 100644
--- a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -184,7 +184,10 @@ class DynamicRecursiveASTVisitor {
   // Declare Traverse*() and friends for all concrete Stmt classes.
 #define ABSTRACT_STMT(STMT)
 #define STMT(CLASS, PARENT)                                                    \
-  virtual bool Traverse##CLASS(CLASS *S);                                      \
+  virtual bool Traverse##CLASS(CLASS *S);
+#include "clang/AST/StmtNodes.inc"
+
+#define STMT(CLASS, PARENT)                                                    \
   virtual bool WalkUpFrom##CLASS(CLASS *S);                                    \
   virtual bool Visit##CLASS(CLASS *S) { return true; }
 #include "clang/AST/StmtNodes.inc"
@@ -199,7 +202,10 @@ class DynamicRecursiveASTVisitor {
 
 #define ABSTRACT_TYPELOC(CLASS, BASE)
 #define TYPELOC(CLASS, BASE)                                                   \
-  virtual bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL);                    \
+  virtual bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL);
+#include "clang/AST/TypeLocNodes.def"
+
+#define TYPELOC(CLASS, BASE)                                                   \
   virtual bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL);                  \
   virtual bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; }
 #include "clang/AST/TypeLocNodes.def"
diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
index 24c2a9dcfa0812..52bfea86d4cc30 100644
--- a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
+++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
@@ -132,7 +132,10 @@ struct Impl : RecursiveASTVisitor<Impl> {
 
 #define ABSTRACT_STMT(STMT)
 #define STMT(CLASS, PARENT)                                                    \
-  bool Traverse##CLASS(CLASS *S) { return Visitor.Traverse##CLASS(S); }        \
+  bool Traverse##CLASS(CLASS *S) { return Visitor.Traverse##CLASS(S); }
+#include "clang/AST/StmtNodes.inc"
+
+#define STMT(CLASS, PARENT)                                                    \
   bool WalkUpFrom##CLASS(CLASS *S) { return Visitor.WalkUpFrom##CLASS(S); }    \
   bool Visit##CLASS(CLASS *S) { return Visitor.Visit##CLASS(S); }
 #include "clang/AST/StmtNodes.inc"
@@ -155,7 +158,10 @@ struct Impl : RecursiveASTVisitor<Impl> {
 #define TYPELOC(CLASS, BASE)                                                   \
   bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL) {                           \
     return Visitor.Traverse##CLASS##TypeLoc(TL);                               \
-  }                                                                            \
+  }
+#include "clang/AST/TypeLocNodes.def"
+
+#define TYPELOC(CLASS, BASE)                                                   \
   bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) {                         \
     return Visitor.WalkUpFrom##CLASS##TypeLoc(TL);                             \
   }                                                                            \
@@ -296,7 +302,10 @@ bool DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(
 #define STMT(CLASS, PARENT)                                                    \
   bool DynamicRecursiveASTVisitor::Traverse##CLASS(CLASS *S) {                 \
     return Impl(*this).RecursiveASTVisitor<Impl>::Traverse##CLASS(S);          \
-  }                                                                            \
+  }
+#include "clang/AST/StmtNodes.inc"
+
+#define STMT(CLASS, PARENT)                                                    \
   bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS(CLASS *S) {               \
     return Impl(*this).RecursiveASTVisitor<Impl>::WalkUpFrom##CLASS(S);        \
   }
@@ -319,7 +328,10 @@ bool DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(
       CLASS##TypeLoc TL) {                                                     \
     return Impl(*this).RecursiveASTVisitor<Impl>::Traverse##CLASS##TypeLoc(    \
         TL);                                                                   \
-  }                                                                            \
+  }
+#include "clang/AST/TypeLocNodes.def"
+
+#define TYPELOC(CLASS, BASE)                                                   \
   bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS##TypeLoc(                 \
       CLASS##TypeLoc TL) {                                                     \
     return Impl(*this).RecursiveASTVisitor<Impl>::WalkUpFrom##CLASS##TypeLoc(  \

>From 79ff93d59ef56c293a622e6a48afd2dc185c1d40 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Thu, 6 Jun 2024 19:49:17 +0200
Subject: [PATCH 05/25] [Clang] Migrate most of ARCMigrate

---
 clang/lib/ARCMigrate/ObjCMT.cpp               | 113 +++++++++---------
 clang/lib/ARCMigrate/TransAPIUses.cpp         |   4 +-
 clang/lib/ARCMigrate/TransARCAssign.cpp       |   4 +-
 clang/lib/ARCMigrate/TransAutoreleasePool.cpp |  13 +-
 .../lib/ARCMigrate/TransBlockObjCVariable.cpp |  18 ++-
 .../TransEmptyStatementsAndDealloc.cpp        |   7 +-
 clang/lib/ARCMigrate/TransGCAttrs.cpp         |  16 ++-
 clang/lib/ARCMigrate/TransGCCalls.cpp         |   8 +-
 clang/lib/ARCMigrate/TransProtectedScope.cpp  |   8 +-
 .../ARCMigrate/TransZeroOutPropsInDealloc.cpp |  21 ++--
 clang/lib/ARCMigrate/Transforms.cpp           |  48 ++++----
 clang/lib/ARCMigrate/Transforms.h             |   1 +
 12 files changed, 127 insertions(+), 134 deletions(-)

diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp
index 4357c8e3f09a55..4164e452059307 100644
--- a/clang/lib/ARCMigrate/ObjCMT.cpp
+++ b/clang/lib/ARCMigrate/ObjCMT.cpp
@@ -308,67 +308,68 @@ namespace {
     return true;
   }
 
-class ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> {
-  ObjCMigrateASTConsumer &Consumer;
-  ParentMap &PMap;
-
-public:
-  ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap)
-    : Consumer(consumer), PMap(PMap) { }
-
-  bool shouldVisitTemplateInstantiations() const { return false; }
-  bool shouldWalkTypesOfTypeLocs() const { return false; }
-
-  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
-    if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Literals) {
-      edit::Commit commit(*Consumer.Editor);
-      edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap);
-      Consumer.Editor->commit(commit);
+  class ObjCMigrator : public DynamicRecursiveASTVisitor {
+    ObjCMigrateASTConsumer &Consumer;
+    ParentMap &PMap;
+
+  public:
+    ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap)
+        : Consumer(consumer), PMap(PMap) {
+      ShouldVisitTemplateInstantiations = false;
+      ShouldWalkTypesOfTypeLocs = false;
     }
 
-    if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Subscripting) {
-      edit::Commit commit(*Consumer.Editor);
-      edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit);
-      Consumer.Editor->commit(commit);
-    }
+    bool VisitObjCMessageExpr(ObjCMessageExpr *E) override {
+      if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Literals) {
+        edit::Commit commit(*Consumer.Editor);
+        edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap);
+        Consumer.Editor->commit(commit);
+      }
 
-    if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_PropertyDotSyntax) {
-      edit::Commit commit(*Consumer.Editor);
-      rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj,
-                                 commit, &PMap);
-      Consumer.Editor->commit(commit);
-    }
+      if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Subscripting) {
+        edit::Commit commit(*Consumer.Editor);
+        edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit);
+        Consumer.Editor->commit(commit);
+      }
 
-    return true;
-  }
+      if (Consumer.ASTMigrateActions &
+          FrontendOptions::ObjCMT_PropertyDotSyntax) {
+        edit::Commit commit(*Consumer.Editor);
+        rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj, commit,
+                                   &PMap);
+        Consumer.Editor->commit(commit);
+      }
 
-  bool TraverseObjCMessageExpr(ObjCMessageExpr *E) {
-    // Do depth first; we want to rewrite the subexpressions first so that if
-    // we have to move expressions we will move them already rewritten.
-    for (Stmt *SubStmt : E->children())
-      if (!TraverseStmt(SubStmt))
-        return false;
+      return true;
+    }
 
-    return WalkUpFromObjCMessageExpr(E);
-  }
-};
+    bool TraverseObjCMessageExpr(ObjCMessageExpr *E) override {
+      // Do depth first; we want to rewrite the subexpressions first so that if
+      // we have to move expressions we will move them already rewritten.
+      for (Stmt *SubStmt : E->children())
+        if (!TraverseStmt(SubStmt))
+          return false;
 
-class BodyMigrator : public RecursiveASTVisitor<BodyMigrator> {
-  ObjCMigrateASTConsumer &Consumer;
-  std::unique_ptr<ParentMap> PMap;
+      return WalkUpFromObjCMessageExpr(E);
+    }
+  };
 
-public:
-  BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }
+  class BodyMigrator : public DynamicRecursiveASTVisitor {
+    ObjCMigrateASTConsumer &Consumer;
+    std::unique_ptr<ParentMap> PMap;
 
-  bool shouldVisitTemplateInstantiations() const { return false; }
-  bool shouldWalkTypesOfTypeLocs() const { return false; }
+  public:
+    BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) {
+      ShouldVisitTemplateInstantiations = false;
+      ShouldWalkTypesOfTypeLocs = false;
+    }
 
-  bool TraverseStmt(Stmt *S) {
-    PMap.reset(new ParentMap(S));
-    ObjCMigrator(Consumer, *PMap).TraverseStmt(S);
-    return true;
-  }
-};
+    bool TraverseStmt(Stmt *S, DataRecursionQueue * = nullptr) override {
+      PMap.reset(new ParentMap(S));
+      ObjCMigrator(Consumer, *PMap).TraverseStmt(S);
+      return true;
+    }
+  };
 } // end anonymous namespace
 
 void ObjCMigrateASTConsumer::migrateDecl(Decl *D) {
@@ -1671,12 +1672,14 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
 }
 
 namespace {
-class SuperInitChecker : public RecursiveASTVisitor<SuperInitChecker> {
+class SuperInitChecker : public DynamicRecursiveASTVisitor {
 public:
-  bool shouldVisitTemplateInstantiations() const { return false; }
-  bool shouldWalkTypesOfTypeLocs() const { return false; }
+  SuperInitChecker() {
+    ShouldVisitTemplateInstantiations = false;
+    ShouldWalkTypesOfTypeLocs = false;
+  }
 
-  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+  bool VisitObjCMessageExpr(ObjCMessageExpr *E) override {
     if (E->getReceiverKind() == ObjCMessageExpr::SuperInstance) {
       if (E->getMethodFamily() == OMF_init)
         return false;
diff --git a/clang/lib/ARCMigrate/TransAPIUses.cpp b/clang/lib/ARCMigrate/TransAPIUses.cpp
index 8f5d4f4bde06ca..4525aa8718d890 100644
--- a/clang/lib/ARCMigrate/TransAPIUses.cpp
+++ b/clang/lib/ARCMigrate/TransAPIUses.cpp
@@ -27,7 +27,7 @@ using namespace trans;
 
 namespace {
 
-class APIChecker : public RecursiveASTVisitor<APIChecker> {
+class APIChecker : public DynamicRecursiveASTVisitor {
   MigrationPass &Pass;
 
   Selector getReturnValueSel, setReturnValueSel;
@@ -51,7 +51,7 @@ class APIChecker : public RecursiveASTVisitor<APIChecker> {
     zoneSel = sels.getNullarySelector(&ids.get("zone"));
   }
 
-  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+  bool VisitObjCMessageExpr(ObjCMessageExpr *E) override {
     // NSInvocation.
     if (E->isInstanceMessage() &&
         E->getReceiverInterface() &&
diff --git a/clang/lib/ARCMigrate/TransARCAssign.cpp b/clang/lib/ARCMigrate/TransARCAssign.cpp
index d1d5b9e014b17a..672d9b7865d805 100644
--- a/clang/lib/ARCMigrate/TransARCAssign.cpp
+++ b/clang/lib/ARCMigrate/TransARCAssign.cpp
@@ -31,14 +31,14 @@ using namespace trans;
 
 namespace {
 
-class ARCAssignChecker : public RecursiveASTVisitor<ARCAssignChecker> {
+class ARCAssignChecker : public DynamicRecursiveASTVisitor {
   MigrationPass &Pass;
   llvm::DenseSet<VarDecl *> ModifiedVars;
 
 public:
   ARCAssignChecker(MigrationPass &pass) : Pass(pass) { }
 
-  bool VisitBinaryOperator(BinaryOperator *Exp) {
+  bool VisitBinaryOperator(BinaryOperator *Exp) override {
     if (Exp->getType()->isDependentType())
       return true;
 
diff --git a/clang/lib/ARCMigrate/TransAutoreleasePool.cpp b/clang/lib/ARCMigrate/TransAutoreleasePool.cpp
index 6d501228e712b2..03dba2b20f95e9 100644
--- a/clang/lib/ARCMigrate/TransAutoreleasePool.cpp
+++ b/clang/lib/ARCMigrate/TransAutoreleasePool.cpp
@@ -39,7 +39,7 @@ using namespace trans;
 
 namespace {
 
-class ReleaseCollector : public RecursiveASTVisitor<ReleaseCollector> {
+class ReleaseCollector : public DynamicRecursiveASTVisitor {
   Decl *Dcl;
   SmallVectorImpl<ObjCMessageExpr *> &Releases;
 
@@ -47,7 +47,7 @@ class ReleaseCollector : public RecursiveASTVisitor<ReleaseCollector> {
   ReleaseCollector(Decl *D, SmallVectorImpl<ObjCMessageExpr *> &releases)
     : Dcl(D), Releases(releases) { }
 
-  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+  bool VisitObjCMessageExpr(ObjCMessageExpr *E) override {
     if (!E->isInstanceMessage())
       return true;
     if (E->getMethodFamily() != OMF_release)
@@ -60,7 +60,6 @@ class ReleaseCollector : public RecursiveASTVisitor<ReleaseCollector> {
     return true;
   }
 };
-
 }
 
 namespace {
@@ -245,7 +244,7 @@ class AutoreleasePoolRewriter
     }
   };
 
-  class NameReferenceChecker : public RecursiveASTVisitor<NameReferenceChecker>{
+  class NameReferenceChecker : public DynamicRecursiveASTVisitor {
     ASTContext &Ctx;
     SourceRange ScopeRange;
     SourceLocation &referenceLoc, &declarationLoc;
@@ -260,15 +259,15 @@ class AutoreleasePoolRewriter
                                (*scope.End)->getBeginLoc());
     }
 
-    bool VisitDeclRefExpr(DeclRefExpr *E) {
+    bool VisitDeclRefExpr(DeclRefExpr *E) override {
       return checkRef(E->getLocation(), E->getDecl()->getLocation());
     }
 
-    bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+    bool VisitTypedefTypeLoc(TypedefTypeLoc TL) override {
       return checkRef(TL.getBeginLoc(), TL.getTypedefNameDecl()->getLocation());
     }
 
-    bool VisitTagTypeLoc(TagTypeLoc TL) {
+    bool VisitTagTypeLoc(TagTypeLoc TL) override {
       return checkRef(TL.getBeginLoc(), TL.getDecl()->getLocation());
     }
 
diff --git a/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp b/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
index 1e4db33135b6a1..3d4e34952a1798 100644
--- a/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
+++ b/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
@@ -36,18 +36,16 @@ using namespace trans;
 
 namespace {
 
-class RootBlockObjCVarRewriter :
-                          public RecursiveASTVisitor<RootBlockObjCVarRewriter> {
+class RootBlockObjCVarRewriter : public DynamicRecursiveASTVisitor {
   llvm::DenseSet<VarDecl *> &VarsToChange;
 
-  class BlockVarChecker : public RecursiveASTVisitor<BlockVarChecker> {
+  class BlockVarChecker : public DynamicRecursiveASTVisitor {
     VarDecl *Var;
 
-    typedef RecursiveASTVisitor<BlockVarChecker> base;
   public:
     BlockVarChecker(VarDecl *var) : Var(var) { }
 
-    bool TraverseImplicitCastExpr(ImplicitCastExpr *castE) {
+    bool TraverseImplicitCastExpr(ImplicitCastExpr *castE) override {
       if (DeclRefExpr *
             ref = dyn_cast<DeclRefExpr>(castE->getSubExpr())) {
         if (ref->getDecl() == Var) {
@@ -59,10 +57,10 @@ class RootBlockObjCVarRewriter :
         }
       }
 
-      return base::TraverseImplicitCastExpr(castE);
+      return DynamicRecursiveASTVisitor::TraverseImplicitCastExpr(castE);
     }
 
-    bool VisitDeclRefExpr(DeclRefExpr *E) {
+    bool VisitDeclRefExpr(DeclRefExpr *E) override {
       if (E->getDecl() == Var)
         return false; // The reference of the variable, and not just its value,
                       //  is needed.
@@ -74,7 +72,7 @@ class RootBlockObjCVarRewriter :
   RootBlockObjCVarRewriter(llvm::DenseSet<VarDecl *> &VarsToChange)
     : VarsToChange(VarsToChange) { }
 
-  bool VisitBlockDecl(BlockDecl *block) {
+  bool VisitBlockDecl(BlockDecl *block) override {
     SmallVector<VarDecl *, 4> BlockVars;
 
     for (const auto &I : block->captures()) {
@@ -108,14 +106,14 @@ class RootBlockObjCVarRewriter :
   }
 };
 
-class BlockObjCVarRewriter : public RecursiveASTVisitor<BlockObjCVarRewriter> {
+class BlockObjCVarRewriter : public DynamicRecursiveASTVisitor {
   llvm::DenseSet<VarDecl *> &VarsToChange;
 
 public:
   BlockObjCVarRewriter(llvm::DenseSet<VarDecl *> &VarsToChange)
     : VarsToChange(VarsToChange) { }
 
-  bool TraverseBlockDecl(BlockDecl *block) {
+  bool TraverseBlockDecl(BlockDecl *block) override {
     RootBlockObjCVarRewriter(VarsToChange).TraverseDecl(block);
     return true;
   }
diff --git a/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp b/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
index e9c21b8106d7dd..51c07a1d4fc4ab 100644
--- a/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
+++ b/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
@@ -143,14 +143,13 @@ class EmptyChecker : public StmtVisitor<EmptyChecker, bool> {
   }
 };
 
-class EmptyStatementsRemover :
-                            public RecursiveASTVisitor<EmptyStatementsRemover> {
+class EmptyStatementsRemover : public DynamicRecursiveASTVisitor {
   MigrationPass &Pass;
 
 public:
   EmptyStatementsRemover(MigrationPass &pass) : Pass(pass) { }
 
-  bool TraverseStmtExpr(StmtExpr *E) {
+  bool TraverseStmtExpr(StmtExpr *E) override {
     CompoundStmt *S = E->getSubStmt();
     for (CompoundStmt::body_iterator
            I = S->body_begin(), E = S->body_end(); I != E; ++I) {
@@ -161,7 +160,7 @@ class EmptyStatementsRemover :
     return true;
   }
 
-  bool VisitCompoundStmt(CompoundStmt *S) {
+  bool VisitCompoundStmt(CompoundStmt *S) override {
     for (auto *I : S->body())
       check(I);
     return true;
diff --git a/clang/lib/ARCMigrate/TransGCAttrs.cpp b/clang/lib/ARCMigrate/TransGCAttrs.cpp
index 85e3fe77660b5c..f4cc0d839e495e 100644
--- a/clang/lib/ARCMigrate/TransGCAttrs.cpp
+++ b/clang/lib/ARCMigrate/TransGCAttrs.cpp
@@ -23,26 +23,24 @@ using namespace trans;
 namespace {
 
 /// Collects all the places where GC attributes __strong/__weak occur.
-class GCAttrsCollector : public RecursiveASTVisitor<GCAttrsCollector> {
+class GCAttrsCollector : public DynamicRecursiveASTVisitor {
   MigrationContext &MigrateCtx;
   bool FullyMigratable;
   std::vector<ObjCPropertyDecl *> &AllProps;
 
-  typedef RecursiveASTVisitor<GCAttrsCollector> base;
 public:
   GCAttrsCollector(MigrationContext &ctx,
                    std::vector<ObjCPropertyDecl *> &AllProps)
-    : MigrateCtx(ctx), FullyMigratable(false),
-      AllProps(AllProps) { }
-
-  bool shouldWalkTypesOfTypeLocs() const { return false; }
+      : MigrateCtx(ctx), FullyMigratable(false), AllProps(AllProps) {
+    ShouldWalkTypesOfTypeLocs = false;
+  }
 
-  bool VisitAttributedTypeLoc(AttributedTypeLoc TL) {
+  bool VisitAttributedTypeLoc(AttributedTypeLoc TL) override {
     handleAttr(TL);
     return true;
   }
 
-  bool TraverseDecl(Decl *D) {
+  bool TraverseDecl(Decl *D) override {
     if (!D || D->isImplicit())
       return true;
 
@@ -54,7 +52,7 @@ class GCAttrsCollector : public RecursiveASTVisitor<GCAttrsCollector> {
     } else if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
       lookForAttribute(DD, DD->getTypeSourceInfo());
     }
-    return base::TraverseDecl(D);
+    return DynamicRecursiveASTVisitor::TraverseDecl(D);
   }
 
   void lookForAttribute(Decl *D, TypeSourceInfo *TInfo) {
diff --git a/clang/lib/ARCMigrate/TransGCCalls.cpp b/clang/lib/ARCMigrate/TransGCCalls.cpp
index 43233e2d0b456a..1da686cd7ec8c2 100644
--- a/clang/lib/ARCMigrate/TransGCCalls.cpp
+++ b/clang/lib/ARCMigrate/TransGCCalls.cpp
@@ -17,8 +17,7 @@ using namespace trans;
 
 namespace {
 
-class GCCollectableCallsChecker :
-                         public RecursiveASTVisitor<GCCollectableCallsChecker> {
+class GCCollectableCallsChecker : public DynamicRecursiveASTVisitor {
   MigrationContext &MigrateCtx;
   IdentifierInfo *NSMakeCollectableII;
   IdentifierInfo *CFMakeCollectableII;
@@ -29,11 +28,10 @@ class GCCollectableCallsChecker :
     IdentifierTable &Ids = MigrateCtx.Pass.Ctx.Idents;
     NSMakeCollectableII = &Ids.get("NSMakeCollectable");
     CFMakeCollectableII = &Ids.get("CFMakeCollectable");
+    ShouldWalkTypesOfTypeLocs = false;
   }
 
-  bool shouldWalkTypesOfTypeLocs() const { return false; }
-
-  bool VisitCallExpr(CallExpr *E) {
+  bool VisitCallExpr(CallExpr *E) override {
     TransformActions &TA = MigrateCtx.Pass.TA;
 
     if (MigrateCtx.isGCOwnedNonObjC(E->getType())) {
diff --git a/clang/lib/ARCMigrate/TransProtectedScope.cpp b/clang/lib/ARCMigrate/TransProtectedScope.cpp
index 154e0b54800f99..b6d4b1b7c771ae 100644
--- a/clang/lib/ARCMigrate/TransProtectedScope.cpp
+++ b/clang/lib/ARCMigrate/TransProtectedScope.cpp
@@ -23,14 +23,14 @@ using namespace trans;
 
 namespace {
 
-class LocalRefsCollector : public RecursiveASTVisitor<LocalRefsCollector> {
+class LocalRefsCollector : public DynamicRecursiveASTVisitor {
   SmallVectorImpl<DeclRefExpr *> &Refs;
 
 public:
   LocalRefsCollector(SmallVectorImpl<DeclRefExpr *> &refs)
     : Refs(refs) { }
 
-  bool VisitDeclRefExpr(DeclRefExpr *E) {
+  bool VisitDeclRefExpr(DeclRefExpr *E) override {
     if (ValueDecl *D = E->getDecl())
       if (D->getDeclContext()->getRedeclContext()->isFunctionOrMethod())
         Refs.push_back(E);
@@ -52,7 +52,7 @@ struct CaseInfo {
     : SC(S), Range(Range), State(St_Unchecked) {}
 };
 
-class CaseCollector : public RecursiveASTVisitor<CaseCollector> {
+class CaseCollector : public DynamicRecursiveASTVisitor {
   ParentMap &PMap;
   SmallVectorImpl<CaseInfo> &Cases;
 
@@ -60,7 +60,7 @@ class CaseCollector : public RecursiveASTVisitor<CaseCollector> {
   CaseCollector(ParentMap &PMap, SmallVectorImpl<CaseInfo> &Cases)
     : PMap(PMap), Cases(Cases) { }
 
-  bool VisitSwitchStmt(SwitchStmt *S) {
+  bool VisitSwitchStmt(SwitchStmt *S) override {
     SwitchCase *Curr = S->getSwitchCaseList();
     if (!Curr)
       return true;
diff --git a/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp b/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
index 81e67628fb1f46..ea87b9288de13e 100644
--- a/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
+++ b/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
@@ -22,10 +22,7 @@ using namespace trans;
 
 namespace {
 
-class ZeroOutInDeallocRemover :
-                           public RecursiveASTVisitor<ZeroOutInDeallocRemover> {
-  typedef RecursiveASTVisitor<ZeroOutInDeallocRemover> base;
-
+class ZeroOutInDeallocRemover : public DynamicRecursiveASTVisitor {
   MigrationPass &Pass;
 
   llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*> SynthesizedProperties;
@@ -39,7 +36,7 @@ class ZeroOutInDeallocRemover :
         Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("finalize"));
   }
 
-  bool VisitObjCMessageExpr(ObjCMessageExpr *ME) {
+  bool VisitObjCMessageExpr(ObjCMessageExpr *ME) override {
     ASTContext &Ctx = Pass.Ctx;
     TransformActions &TA = Pass.TA;
 
@@ -78,7 +75,7 @@ class ZeroOutInDeallocRemover :
     return true;
   }
 
-  bool VisitPseudoObjectExpr(PseudoObjectExpr *POE) {
+  bool VisitPseudoObjectExpr(PseudoObjectExpr *POE) override {
     if (isZeroingPropIvar(POE) && isRemovable(POE)) {
       Transaction Trans(Pass.TA);
       Pass.TA.removeStmt(POE);
@@ -87,7 +84,7 @@ class ZeroOutInDeallocRemover :
     return true;
   }
 
-  bool VisitBinaryOperator(BinaryOperator *BOE) {
+  bool VisitBinaryOperator(BinaryOperator *BOE) override {
     if (isZeroingPropIvar(BOE) && isRemovable(BOE)) {
       Transaction Trans(Pass.TA);
       Pass.TA.removeStmt(BOE);
@@ -96,7 +93,7 @@ class ZeroOutInDeallocRemover :
     return true;
   }
 
-  bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
+  bool TraverseObjCMethodDecl(ObjCMethodDecl *D) override {
     if (D->getMethodFamily() != OMF_dealloc &&
         !(D->isInstanceMethod() && D->getSelector() == FinalizeSel))
       return true;
@@ -128,7 +125,7 @@ class ZeroOutInDeallocRemover :
     }
 
     // Now, remove all zeroing of ivars etc.
-    base::TraverseObjCMethodDecl(D);
+    DynamicRecursiveASTVisitor::TraverseObjCMethodDecl(D);
 
     // clear out for next method.
     SynthesizedProperties.clear();
@@ -137,9 +134,9 @@ class ZeroOutInDeallocRemover :
     return true;
   }
 
-  bool TraverseFunctionDecl(FunctionDecl *D) { return true; }
-  bool TraverseBlockDecl(BlockDecl *block) { return true; }
-  bool TraverseBlockExpr(BlockExpr *block) { return true; }
+  bool TraverseFunctionDecl(FunctionDecl *D) override { return true; }
+  bool TraverseBlockDecl(BlockDecl *block) override { return true; }
+  bool TraverseBlockExpr(BlockExpr *block) override { return true; }
 
 private:
   bool isRemovable(Expr *E) const {
diff --git a/clang/lib/ARCMigrate/Transforms.cpp b/clang/lib/ARCMigrate/Transforms.cpp
index fda0e1c932fc0e..4c35bcda2c15da 100644
--- a/clang/lib/ARCMigrate/Transforms.cpp
+++ b/clang/lib/ARCMigrate/Transforms.cpp
@@ -211,14 +211,17 @@ StringRef trans::getNilString(MigrationPass &Pass) {
 
 namespace {
 
-class ReferenceClear : public RecursiveASTVisitor<ReferenceClear> {
+class ReferenceClear : public DynamicRecursiveASTVisitor {
   ExprSet &Refs;
 public:
   ReferenceClear(ExprSet &refs) : Refs(refs) { }
-  bool VisitDeclRefExpr(DeclRefExpr *E) { Refs.erase(E); return true; }
+  bool VisitDeclRefExpr(DeclRefExpr *E) override {
+    Refs.erase(E);
+    return true;
+  }
 };
 
-class ReferenceCollector : public RecursiveASTVisitor<ReferenceCollector> {
+class ReferenceCollector : public DynamicRecursiveASTVisitor {
   ValueDecl *Dcl;
   ExprSet &Refs;
 
@@ -226,23 +229,22 @@ class ReferenceCollector : public RecursiveASTVisitor<ReferenceCollector> {
   ReferenceCollector(ValueDecl *D, ExprSet &refs)
     : Dcl(D), Refs(refs) { }
 
-  bool VisitDeclRefExpr(DeclRefExpr *E) {
+  bool VisitDeclRefExpr(DeclRefExpr *E) override {
     if (E->getDecl() == Dcl)
       Refs.insert(E);
     return true;
   }
 };
 
-class RemovablesCollector : public RecursiveASTVisitor<RemovablesCollector> {
+class RemovablesCollector : public DynamicRecursiveASTVisitor {
   ExprSet &Removables;
 
 public:
-  RemovablesCollector(ExprSet &removables)
-  : Removables(removables) { }
-
-  bool shouldWalkTypesOfTypeLocs() const { return false; }
+  RemovablesCollector(ExprSet &removables) : Removables(removables) {
+    ShouldWalkTypesOfTypeLocs = false;
+  }
 
-  bool TraverseStmtExpr(StmtExpr *E) {
+  bool TraverseStmtExpr(StmtExpr *E) override {
     CompoundStmt *S = E->getSubStmt();
     for (CompoundStmt::body_iterator
         I = S->body_begin(), E = S->body_end(); I != E; ++I) {
@@ -253,29 +255,29 @@ class RemovablesCollector : public RecursiveASTVisitor<RemovablesCollector> {
     return true;
   }
 
-  bool VisitCompoundStmt(CompoundStmt *S) {
+  bool VisitCompoundStmt(CompoundStmt *S) override {
     for (auto *I : S->body())
       mark(I);
     return true;
   }
 
-  bool VisitIfStmt(IfStmt *S) {
+  bool VisitIfStmt(IfStmt *S) override {
     mark(S->getThen());
     mark(S->getElse());
     return true;
   }
 
-  bool VisitWhileStmt(WhileStmt *S) {
+  bool VisitWhileStmt(WhileStmt *S) override {
     mark(S->getBody());
     return true;
   }
 
-  bool VisitDoStmt(DoStmt *S) {
+  bool VisitDoStmt(DoStmt *S) override {
     mark(S->getBody());
     return true;
   }
 
-  bool VisitForStmt(ForStmt *S) {
+  bool VisitForStmt(ForStmt *S) override {
     mark(S->getInit());
     mark(S->getInc());
     mark(S->getBody());
@@ -315,26 +317,25 @@ void trans::collectRemovables(Stmt *S, ExprSet &exprs) {
 
 namespace {
 
-class ASTTransform : public RecursiveASTVisitor<ASTTransform> {
+class ASTTransform : public DynamicRecursiveASTVisitor {
   MigrationContext &MigrateCtx;
-  typedef RecursiveASTVisitor<ASTTransform> base;
 
 public:
-  ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { }
-
-  bool shouldWalkTypesOfTypeLocs() const { return false; }
+  ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) {
+    ShouldWalkTypesOfTypeLocs = false;
+  }
 
-  bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
+  bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) override {
     ObjCImplementationContext ImplCtx(MigrateCtx, D);
     for (MigrationContext::traverser_iterator
            I = MigrateCtx.traversers_begin(),
            E = MigrateCtx.traversers_end(); I != E; ++I)
       (*I)->traverseObjCImplementation(ImplCtx);
 
-    return base::TraverseObjCImplementationDecl(D);
+    return DynamicRecursiveASTVisitor::TraverseObjCImplementationDecl(D);
   }
 
-  bool TraverseStmt(Stmt *rootS) {
+  bool TraverseStmt(Stmt *rootS, DataRecursionQueue * = nullptr) override {
     if (!rootS)
       return true;
 
@@ -347,7 +348,6 @@ class ASTTransform : public RecursiveASTVisitor<ASTTransform> {
     return true;
   }
 };
-
 }
 
 MigrationContext::~MigrationContext() {
diff --git a/clang/lib/ARCMigrate/Transforms.h b/clang/lib/ARCMigrate/Transforms.h
index 37e2d6b2a7e12f..07de28e3b3e3d7 100644
--- a/clang/lib/ARCMigrate/Transforms.h
+++ b/clang/lib/ARCMigrate/Transforms.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H
 #define LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H
 
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/ParentMap.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "llvm/ADT/DenseSet.h"

>From 8133eac3a56bd0bc839b4db33b3df7122886f34a Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 10 Jun 2024 20:09:28 +0200
Subject: [PATCH 06/25] Disable post-order traversal and overriding WalkUpFromX

---
 .../clang/AST/DynamicRecursiveASTVisitor.h    | 23 ++++++++++---------
 clang/lib/AST/DynamicRecursiveASTVisitor.cpp  | 20 +---------------
 2 files changed, 13 insertions(+), 30 deletions(-)

diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
index 01567237ba7cb4..00cf3da6656362 100644
--- a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -10,6 +10,10 @@ class ASTContext;
 
 /// Recursive AST visitor that supports extension via dynamic dispatch.
 ///
+/// This only supports some of the more common visitation operations; in
+/// particular, it does not support overriding WalkUpFromX or post-order
+/// traversal.
+///
 /// \see RecursiveASTVisitor
 class DynamicRecursiveASTVisitor {
 public:
@@ -29,9 +33,6 @@ class DynamicRecursiveASTVisitor {
   /// Whether this visitor should recurse into lambda body
   bool ShouldVisitLambdaBody = true;
 
-  /// Return whether this visitor should traverse post-order.
-  bool ShouldTraversePostOrder = false;
-
 protected:
   DynamicRecursiveASTVisitor() = default;
 
@@ -163,10 +164,10 @@ class DynamicRecursiveASTVisitor {
   virtual bool VisitTypeLoc(TypeLoc TL) { return true; }
 
   /// Walk up from a node.
-  virtual bool WalkUpFromDecl(Decl *D) { return VisitDecl(D); }
-  virtual bool WalkUpFromStmt(Stmt *S) { return VisitStmt(S); }
-  virtual bool WalkUpFromType(Type *T) { return VisitType(T); }
-  virtual bool WalkUpFromTypeLoc(TypeLoc TL) { return VisitTypeLoc(TL); }
+  bool WalkUpFromDecl(Decl *D) { return VisitDecl(D); }
+  bool WalkUpFromStmt(Stmt *S) { return VisitStmt(S); }
+  bool WalkUpFromType(Type *T) { return VisitType(T); }
+  bool WalkUpFromTypeLoc(TypeLoc TL) { return VisitTypeLoc(TL); }
 
   /*// Declare Traverse*() and friends for attributes.
 #define DYNAMIC_ATTR_VISITOR_DECLS
@@ -177,7 +178,7 @@ class DynamicRecursiveASTVisitor {
 #define ABSTRACT_DECL(DECL)
 #define DECL(CLASS, BASE)                                                      \
   virtual bool Traverse##CLASS##Decl(CLASS##Decl *D);                          \
-  virtual bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D);                        \
+  bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D);                                \
   virtual bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; }
 #include "clang/AST/DeclNodes.inc"
 
@@ -188,7 +189,7 @@ class DynamicRecursiveASTVisitor {
 #include "clang/AST/StmtNodes.inc"
 
 #define STMT(CLASS, PARENT)                                                    \
-  virtual bool WalkUpFrom##CLASS(CLASS *S);                                    \
+  bool WalkUpFrom##CLASS(CLASS *S);                                            \
   virtual bool Visit##CLASS(CLASS *S) { return true; }
 #include "clang/AST/StmtNodes.inc"
 
@@ -196,7 +197,7 @@ class DynamicRecursiveASTVisitor {
 #define ABSTRACT_TYPE(CLASS, BASE)
 #define TYPE(CLASS, BASE)                                                      \
   virtual bool Traverse##CLASS##Type(CLASS##Type *T);                          \
-  virtual bool WalkUpFrom##CLASS##Type(CLASS##Type *T);                        \
+  bool WalkUpFrom##CLASS##Type(CLASS##Type *T);                                \
   virtual bool Visit##CLASS##Type(CLASS##Type *T) { return true; }
 #include "clang/AST/TypeNodes.inc"
 
@@ -206,7 +207,7 @@ class DynamicRecursiveASTVisitor {
 #include "clang/AST/TypeLocNodes.def"
 
 #define TYPELOC(CLASS, BASE)                                                   \
-  virtual bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL);                  \
+  bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL);                          \
   virtual bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; }
 #include "clang/AST/TypeLocNodes.def"
 };
diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
index 52bfea86d4cc30..c4bb1b4b0debd9 100644
--- a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
+++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
@@ -34,9 +34,7 @@ struct Impl : RecursiveASTVisitor<Impl> {
 
   bool shouldVisitLambdaBody() const { return Visitor.ShouldVisitLambdaBody; }
 
-  bool shouldTraversePostOrder() const {
-    return Visitor.ShouldTraversePostOrder;
-  }
+  bool shouldTraversePostOrder() const { return false; }
 
   bool TraverseAST(ASTContext &AST) { return Visitor.TraverseAST(AST); }
   bool TraverseAttr(Attr *At) { return Visitor.TraverseAttr(At); }
@@ -107,12 +105,6 @@ struct Impl : RecursiveASTVisitor<Impl> {
   bool VisitType(Type *T) { return Visitor.VisitType(T); }
   bool VisitTypeLoc(TypeLoc TL) { return Visitor.VisitTypeLoc(TL); }
 
-  /// Walk up from a node.
-  bool WalkUpFromDecl(Decl *D) { return Visitor.WalkUpFromDecl(D); }
-  bool WalkUpFromStmt(Stmt *S) { return Visitor.WalkUpFromStmt(S); }
-  bool WalkUpFromType(Type *T) { return Visitor.WalkUpFromType(T); }
-  bool WalkUpFromTypeLoc(TypeLoc TL) { return Visitor.WalkUpFromTypeLoc(TL); }
-
   /*#define ATTR_VISITOR_DECLS
   #include "clang/AST/AttrVisitor.inc"
   #undef ATTR_VISITOR_DECLS*/
@@ -122,9 +114,6 @@ struct Impl : RecursiveASTVisitor<Impl> {
   bool Traverse##CLASS##Decl(CLASS##Decl *D) {                                 \
     return Visitor.Traverse##CLASS##Decl(D);                                   \
   }                                                                            \
-  bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) {                               \
-    return Visitor.WalkUpFrom##CLASS##Decl(D);                                 \
-  }                                                                            \
   bool Visit##CLASS##Decl(CLASS##Decl *D) {                                    \
     return Visitor.Visit##CLASS##Decl(D);                                      \
   }
@@ -136,7 +125,6 @@ struct Impl : RecursiveASTVisitor<Impl> {
 #include "clang/AST/StmtNodes.inc"
 
 #define STMT(CLASS, PARENT)                                                    \
-  bool WalkUpFrom##CLASS(CLASS *S) { return Visitor.WalkUpFrom##CLASS(S); }    \
   bool Visit##CLASS(CLASS *S) { return Visitor.Visit##CLASS(S); }
 #include "clang/AST/StmtNodes.inc"
 
@@ -146,9 +134,6 @@ struct Impl : RecursiveASTVisitor<Impl> {
   bool Traverse##CLASS##Type(CLASS##Type *T) {                                 \
     return Visitor.Traverse##CLASS##Type(T);                                   \
   }                                                                            \
-  bool WalkUpFrom##CLASS##Type(CLASS##Type *T) {                               \
-    return Visitor.WalkUpFrom##CLASS##Type(T);                                 \
-  }                                                                            \
   bool Visit##CLASS##Type(CLASS##Type *T) {                                    \
     return Visitor.Visit##CLASS##Type(T);                                      \
   }
@@ -162,9 +147,6 @@ struct Impl : RecursiveASTVisitor<Impl> {
 #include "clang/AST/TypeLocNodes.def"
 
 #define TYPELOC(CLASS, BASE)                                                   \
-  bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) {                         \
-    return Visitor.WalkUpFrom##CLASS##TypeLoc(TL);                             \
-  }                                                                            \
   bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) {                              \
     return Visitor.Visit##CLASS##TypeLoc(TL);                                  \
   }

>From 9a48ed0852e225e430c3a72e84088726ecd8e0c8 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 1 Jul 2024 16:44:06 +0200
Subject: [PATCH 07/25] Enable overriding Visit for abstract nodes

---
 clang/include/clang/AST/DynamicRecursiveASTVisitor.h | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
index 00cf3da6656362..c2903b76268598 100644
--- a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -176,8 +176,11 @@ class DynamicRecursiveASTVisitor {
 
   // Declare Traverse*() for and friends all concrete Decl classes.
 #define ABSTRACT_DECL(DECL)
+#define DECL(CLASS, BASE) \
+  virtual bool Traverse##CLASS##Decl(CLASS##Decl *D);
+#include "clang/AST/DeclNodes.inc"
+
 #define DECL(CLASS, BASE)                                                      \
-  virtual bool Traverse##CLASS##Decl(CLASS##Decl *D);                          \
   bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D);                                \
   virtual bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; }
 #include "clang/AST/DeclNodes.inc"
@@ -196,7 +199,10 @@ class DynamicRecursiveASTVisitor {
   // Declare Traverse*() and friends for all concrete Type classes.
 #define ABSTRACT_TYPE(CLASS, BASE)
 #define TYPE(CLASS, BASE)                                                      \
-  virtual bool Traverse##CLASS##Type(CLASS##Type *T);                          \
+  virtual bool Traverse##CLASS##Type(CLASS##Type *T);
+#include "clang/AST/TypeNodes.inc"
+
+#define TYPE(CLASS, BASE)                                                      \
   bool WalkUpFrom##CLASS##Type(CLASS##Type *T);                                \
   virtual bool Visit##CLASS##Type(CLASS##Type *T) { return true; }
 #include "clang/AST/TypeNodes.inc"

>From 8e5616ce722eadae4a0b47f4ad50c56b5d4632db Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 1 Jul 2024 17:30:47 +0200
Subject: [PATCH 08/25] Migrate more visitors in Sema

---
 clang/include/clang/Analysis/CallGraph.h | 15 ++++-----
 clang/lib/AST/ASTImporterLookupTable.cpp |  2 ++
 clang/lib/AST/StmtOpenACC.cpp            |  8 ++---
 clang/lib/Analysis/CallGraph.cpp         |  3 ++
 clang/lib/Sema/AnalysisBasedWarnings.cpp | 34 +++++++++----------
 clang/lib/Sema/SemaAvailability.cpp      | 42 +++++++++++++-----------
 clang/lib/Sema/SemaCodeComplete.cpp      | 16 ++++-----
 clang/lib/Sema/SemaDeclAttr.cpp          |  9 +++--
 clang/lib/Sema/SemaDeclObjC.cpp          |  9 +++--
 clang/lib/Sema/SemaHLSL.cpp              |  9 +++--
 clang/lib/Sema/SemaTemplateDeduction.cpp | 14 ++++----
 11 files changed, 79 insertions(+), 82 deletions(-)

diff --git a/clang/include/clang/Analysis/CallGraph.h b/clang/include/clang/Analysis/CallGraph.h
index 78f8d115550178..891c4c750011d2 100644
--- a/clang/include/clang/Analysis/CallGraph.h
+++ b/clang/include/clang/Analysis/CallGraph.h
@@ -18,7 +18,8 @@
 #define LLVM_CLANG_ANALYSIS_CALLGRAPH_H
 
 #include "clang/AST/Decl.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/GraphTraits.h"
 #include "llvm/ADT/STLExtras.h"
@@ -39,7 +40,7 @@ class Stmt;
 /// The call graph extends itself with the given declarations by implementing
 /// the recursive AST visitor, which constructs the graph by visiting the given
 /// declarations.
-class CallGraph : public RecursiveASTVisitor<CallGraph> {
+class CallGraph : public DynamicRecursiveASTVisitor {
   friend class CallGraphNode;
 
   using FunctionMapTy =
@@ -109,7 +110,7 @@ class CallGraph : public RecursiveASTVisitor<CallGraph> {
 
   /// Part of recursive declaration visitation. We recursively visit all the
   /// declarations to collect the root functions.
-  bool VisitFunctionDecl(FunctionDecl *FD) {
+  bool VisitFunctionDecl(FunctionDecl *FD) override {
     // We skip function template definitions, as their semantics is
     // only determined when they are instantiated.
     if (includeInGraph(FD) && FD->isThisDeclarationADefinition()) {
@@ -124,7 +125,7 @@ class CallGraph : public RecursiveASTVisitor<CallGraph> {
   }
 
   /// Part of recursive declaration visitation.
-  bool VisitObjCMethodDecl(ObjCMethodDecl *MD) {
+  bool VisitObjCMethodDecl(ObjCMethodDecl *MD) override {
     if (includeInGraph(MD)) {
       addNodesForBlocks(MD);
       addNodeForDecl(MD, true);
@@ -133,11 +134,7 @@ class CallGraph : public RecursiveASTVisitor<CallGraph> {
   }
 
   // We are only collecting the declarations, so do not step into the bodies.
-  bool TraverseStmt(Stmt *S) { return true; }
-
-  bool shouldWalkTypesOfTypeLocs() const { return false; }
-  bool shouldVisitTemplateInstantiations() const { return true; }
-  bool shouldVisitImplicitCode() const { return true; }
+  bool TraverseStmt(Stmt *S, DataRecursionQueue*) override { return true; }
 
 private:
   /// Add the given declaration to the call graph.
diff --git a/clang/lib/AST/ASTImporterLookupTable.cpp b/clang/lib/AST/ASTImporterLookupTable.cpp
index 07d39dcee2583a..307c03404e0121 100644
--- a/clang/lib/AST/ASTImporterLookupTable.cpp
+++ b/clang/lib/AST/ASTImporterLookupTable.cpp
@@ -20,6 +20,8 @@ namespace clang {
 
 namespace {
 
+// FIXME: This breaks if we try to use a dynamic visitor,
+// and I have no idea why.
 struct Builder : RecursiveASTVisitor<Builder> {
   ASTImporterLookupTable <
   Builder(ASTImporterLookupTable &LT) : LT(LT) {}
diff --git a/clang/lib/AST/StmtOpenACC.cpp b/clang/lib/AST/StmtOpenACC.cpp
index 2d864a28857966..fbf0ef540eb685 100644
--- a/clang/lib/AST/StmtOpenACC.cpp
+++ b/clang/lib/AST/StmtOpenACC.cpp
@@ -12,7 +12,7 @@
 
 #include "clang/AST/StmtOpenACC.h"
 #include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/StmtCXX.h"
 using namespace clang;
 
@@ -44,17 +44,17 @@ OpenACCComputeConstruct *OpenACCComputeConstruct::Create(
 }
 
 void OpenACCComputeConstruct::findAndSetChildLoops() {
-  struct LoopConstructFinder : RecursiveASTVisitor<LoopConstructFinder> {
+  struct LoopConstructFinder : DynamicRecursiveASTVisitor {
     OpenACCComputeConstruct *Construct = nullptr;
 
     LoopConstructFinder(OpenACCComputeConstruct *Construct)
         : Construct(Construct) {}
 
-    bool TraverseOpenACCComputeConstruct(OpenACCComputeConstruct *C) {
+    bool TraverseOpenACCComputeConstruct(OpenACCComputeConstruct *C) override {
       // Stop searching if we find a compute construct.
       return true;
     }
-    bool TraverseOpenACCLoopConstruct(OpenACCLoopConstruct *C) {
+    bool TraverseOpenACCLoopConstruct(OpenACCLoopConstruct *C) override {
       // Stop searching if we find a loop construct, after taking ownership of
       // it.
       C->setParentComputeConstruct(Construct);
diff --git a/clang/lib/Analysis/CallGraph.cpp b/clang/lib/Analysis/CallGraph.cpp
index f892980ed31386..958dbfec426344 100644
--- a/clang/lib/Analysis/CallGraph.cpp
+++ b/clang/lib/Analysis/CallGraph.cpp
@@ -148,6 +148,9 @@ void CallGraph::addNodesForBlocks(DeclContext *D) {
 
 CallGraph::CallGraph() {
   Root = getOrInsertNode(nullptr);
+  ShouldWalkTypesOfTypeLocs = false;
+  ShouldVisitTemplateInstantiations = true;
+  ShouldVisitImplicitCode = true;
 }
 
 CallGraph::~CallGraph() = default;
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 0f604c61fa3af9..b2b563759ea88d 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -22,7 +22,7 @@
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/ParentMap.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
 #include "clang/AST/StmtVisitor.h"
@@ -1067,11 +1067,12 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
 }
 
 namespace {
-  class FallthroughMapper : public RecursiveASTVisitor<FallthroughMapper> {
+  class FallthroughMapper : public DynamicRecursiveASTVisitor {
   public:
     FallthroughMapper(Sema &S)
       : FoundSwitchStatements(false),
         S(S) {
+      ShouldWalkTypesOfTypeLocs = false;
     }
 
     bool foundSwitchStatements() const { return FoundSwitchStatements; }
@@ -1186,26 +1187,23 @@ namespace {
       return !!UnannotatedCnt;
     }
 
-    // RecursiveASTVisitor setup.
-    bool shouldWalkTypesOfTypeLocs() const { return false; }
-
-    bool VisitAttributedStmt(AttributedStmt *S) {
+    bool VisitAttributedStmt(AttributedStmt *S) override {
       if (asFallThroughAttr(S))
         FallthroughStmts.insert(S);
       return true;
     }
 
-    bool VisitSwitchStmt(SwitchStmt *S) {
+    bool VisitSwitchStmt(SwitchStmt *S) override {
       FoundSwitchStatements = true;
       return true;
     }
 
     // We don't want to traverse local type declarations. We analyze their
     // methods separately.
-    bool TraverseDecl(Decl *D) { return true; }
+    bool TraverseDecl(Decl *D) override { return true; }
 
     // We analyze lambda bodies separately. Skip them here.
-    bool TraverseLambdaExpr(LambdaExpr *LE) {
+    bool TraverseLambdaExpr(LambdaExpr *LE) override {
       // Traverse the captures, but not the body.
       for (const auto C : zip(LE->captures(), LE->capture_inits()))
         TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));
@@ -2463,15 +2461,18 @@ static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) {
 
 // An AST Visitor that calls a callback function on each callable DEFINITION
 // that is NOT in a dependent context:
-class CallableVisitor : public RecursiveASTVisitor<CallableVisitor> {
+class CallableVisitor : public DynamicRecursiveASTVisitor {
 private:
   llvm::function_ref<void(const Decl *)> Callback;
 
 public:
   CallableVisitor(llvm::function_ref<void(const Decl *)> Callback)
-      : Callback(Callback) {}
+      : Callback(Callback) {
+    ShouldVisitTemplateInstantiations = true;
+    ShouldVisitImplicitCode = false;
+  }
 
-  bool VisitFunctionDecl(FunctionDecl *Node) {
+  bool VisitFunctionDecl(FunctionDecl *Node) override {
     if (cast<DeclContext>(Node)->isDependentContext())
       return true; // Not to analyze dependent decl
     // `FunctionDecl->hasBody()` returns true if the function has a body
@@ -2482,14 +2483,14 @@ class CallableVisitor : public RecursiveASTVisitor<CallableVisitor> {
     return true;
   }
 
-  bool VisitBlockDecl(BlockDecl *Node) {
+  bool VisitBlockDecl(BlockDecl *Node) override {
     if (cast<DeclContext>(Node)->isDependentContext())
       return true; // Not to analyze dependent decl
     Callback(Node);
     return true;
   }
 
-  bool VisitObjCMethodDecl(ObjCMethodDecl *Node) {
+  bool VisitObjCMethodDecl(ObjCMethodDecl *Node) override {
     if (cast<DeclContext>(Node)->isDependentContext())
       return true; // Not to analyze dependent decl
     if (Node->hasBody())
@@ -2497,12 +2498,9 @@ class CallableVisitor : public RecursiveASTVisitor<CallableVisitor> {
     return true;
   }
 
-  bool VisitLambdaExpr(LambdaExpr *Node) {
+  bool VisitLambdaExpr(LambdaExpr *Node) override {
     return VisitFunctionDecl(Node->getCallOperator());
   }
-
-  bool shouldVisitTemplateInstantiations() const { return true; }
-  bool shouldVisitImplicitCode() const { return false; }
 };
 
 void clang::sema::AnalysisBasedWarnings::IssueWarnings(
diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp
index fed1c68d4d33a9..a365466c24d19e 100644
--- a/clang/lib/Sema/SemaAvailability.cpp
+++ b/clang/lib/Sema/SemaAvailability.cpp
@@ -12,8 +12,9 @@
 
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/StmtObjC.h"
 #include "clang/AST/DeclTemplate.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/DiagnosticSema.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/LangOptions.h"
@@ -710,11 +711,11 @@ bool isBodyLikeChildStmt(const Stmt *S, const Stmt *Parent) {
   }
 }
 
-class StmtUSEFinder : public RecursiveASTVisitor<StmtUSEFinder> {
+class StmtUSEFinder : public DynamicRecursiveASTVisitor {
   const Stmt *Target;
 
 public:
-  bool VisitStmt(Stmt *S) { return S != Target; }
+  bool VisitStmt(Stmt *S) override { return S != Target; }
 
   /// Returns true if the given statement is present in the given declaration.
   static bool isContained(const Stmt *Target, const Decl *D) {
@@ -726,11 +727,11 @@ class StmtUSEFinder : public RecursiveASTVisitor<StmtUSEFinder> {
 
 /// Traverses the AST and finds the last statement that used a given
 /// declaration.
-class LastDeclUSEFinder : public RecursiveASTVisitor<LastDeclUSEFinder> {
+class LastDeclUSEFinder : public DynamicRecursiveASTVisitor {
   const Decl *D;
 
 public:
-  bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
     if (DRE->getDecl() == D)
       return false;
     return true;
@@ -754,10 +755,7 @@ class LastDeclUSEFinder : public RecursiveASTVisitor<LastDeclUSEFinder> {
 /// to a partially available declaration. Whenever we encounter an \c if of the
 /// form: \c if(@available(...)), we use the version from the condition to visit
 /// the then statement.
-class DiagnoseUnguardedAvailability
-    : public RecursiveASTVisitor<DiagnoseUnguardedAvailability> {
-  typedef RecursiveASTVisitor<DiagnoseUnguardedAvailability> Base;
-
+class DiagnoseUnguardedAvailability : public DynamicRecursiveASTVisitor {
   Sema &SemaRef;
   Decl *Ctx;
 
@@ -775,26 +773,30 @@ class DiagnoseUnguardedAvailability
         SemaRef.Context.getTargetInfo().getPlatformMinVersion());
   }
 
-  bool TraverseStmt(Stmt *S) {
+  bool TraverseStmt(Stmt *S, DataRecursionQueue* = nullptr) override {
     if (!S)
       return true;
     StmtStack.push_back(S);
-    bool Result = Base::TraverseStmt(S);
+    bool Result = DynamicRecursiveASTVisitor::TraverseStmt(S);
     StmtStack.pop_back();
     return Result;
   }
 
   void IssueDiagnostics(Stmt *S) { TraverseStmt(S); }
 
-  bool TraverseIfStmt(IfStmt *If);
+  bool TraverseIfStmt(IfStmt *If) override;
 
   // for 'case X:' statements, don't bother looking at the 'X'; it can't lead
   // to any useful diagnostics.
-  bool TraverseCaseStmt(CaseStmt *CS) { return TraverseStmt(CS->getSubStmt()); }
+  bool TraverseCaseStmt(CaseStmt *CS) override {
+    return TraverseStmt(CS->getSubStmt());
+  }
 
-  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *PRE) { return true; }
+  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *PRE) override {
+    return true;
+  }
 
-  bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) {
+  bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) override {
     if (ObjCMethodDecl *D = Msg->getMethodDecl()) {
       ObjCInterfaceDecl *ID = nullptr;
       QualType ReceiverTy = Msg->getClassReceiver();
@@ -807,25 +809,25 @@ class DiagnoseUnguardedAvailability
     return true;
   }
 
-  bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
     DiagnoseDeclAvailability(DRE->getDecl(),
                              SourceRange(DRE->getBeginLoc(), DRE->getEndLoc()));
     return true;
   }
 
-  bool VisitMemberExpr(MemberExpr *ME) {
+  bool VisitMemberExpr(MemberExpr *ME) override {
     DiagnoseDeclAvailability(ME->getMemberDecl(),
                              SourceRange(ME->getBeginLoc(), ME->getEndLoc()));
     return true;
   }
 
-  bool VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) {
+  bool VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) override {
     SemaRef.Diag(E->getBeginLoc(), diag::warn_at_available_unchecked_use)
         << (!SemaRef.getLangOpts().ObjC);
     return true;
   }
 
-  bool VisitTypeLoc(TypeLoc Ty);
+  bool VisitTypeLoc(TypeLoc Ty) override;
 };
 
 void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
@@ -990,7 +992,7 @@ bool DiagnoseUnguardedAvailability::TraverseIfStmt(IfStmt *If) {
       return TraverseStmt(If->getThen()) && TraverseStmt(If->getElse());
   } else {
     // This isn't an availability checking 'if', we can just continue.
-    return Base::TraverseIfStmt(If);
+    return DynamicRecursiveASTVisitor::TraverseIfStmt(If);
   }
 
   AvailabilityStack.push_back(CondVersion);
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index cd1c5f9391ccd4..1bbcf468ddf7c2 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -22,7 +22,7 @@
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/QualTypeNames.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/AttributeCommonInfo.h"
 #include "clang/Basic/CharInfo.h"
@@ -5426,7 +5426,7 @@ class ConceptInfo {
 
   // This visitor infers members of T based on traversing expressions/types
   // that involve T. It is invoked with code known to be valid for T.
-  class ValidVisitor : public RecursiveASTVisitor<ValidVisitor> {
+  class ValidVisitor : public DynamicRecursiveASTVisitor {
     ConceptInfo *Outer;
     const TemplateTypeParmType *T;
 
@@ -5444,7 +5444,7 @@ class ConceptInfo {
     }
 
     // In T.foo or T->foo, `foo` is a member function/variable.
-    bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
+    bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) override {
       const Type *Base = E->getBaseType().getTypePtr();
       bool IsArrow = E->isArrow();
       if (Base->isPointerType() && IsArrow) {
@@ -5457,14 +5457,14 @@ class ConceptInfo {
     }
 
     // In T::foo, `foo` is a static member function/variable.
-    bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
+    bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) override {
       if (E->getQualifier() && isApprox(E->getQualifier()->getAsType(), T))
         addValue(E, E->getDeclName(), Member::Colons);
       return true;
     }
 
     // In T::typename foo, `foo` is a type.
-    bool VisitDependentNameType(DependentNameType *DNT) {
+    bool VisitDependentNameType(DependentNameType *DNT) override {
       const auto *Q = DNT->getQualifier();
       if (Q && isApprox(Q->getAsType(), T))
         addType(DNT->getIdentifier());
@@ -5473,7 +5473,7 @@ class ConceptInfo {
 
     // In T::foo::bar, `foo` must be a type.
     // VisitNNS() doesn't exist, and TraverseNNS isn't always called :-(
-    bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSL) {
+    bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSL) override {
       if (NNSL) {
         NestedNameSpecifier *NNS = NNSL.getNestedNameSpecifier();
         const auto *Q = NNS->getPrefix();
@@ -5481,14 +5481,14 @@ class ConceptInfo {
           addType(NNS->getAsIdentifier());
       }
       // FIXME: also handle T::foo<X>::bar
-      return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNSL);
+      return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNSL);
     }
 
     // FIXME also handle T::foo<X>
 
     // Track the innermost caller/callee relationship so we can tell if a
     // nested expr is being called as a function.
-    bool VisitCallExpr(CallExpr *CE) {
+    bool VisitCallExpr(CallExpr *CE) override {
       Caller = CE;
       Callee = CE->getCallee();
       return true;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index b8842e9003e101..636b1b045ba76e 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -20,7 +20,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/Mangle.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/Cuda.h"
@@ -730,8 +730,7 @@ static void handleExcludeFromExplicitInstantiationAttr(Sema &S, Decl *D,
 namespace {
 /// Determines if a given Expr references any of the given function's
 /// ParmVarDecls, or the function's implicit `this` parameter (if applicable).
-class ArgumentDependenceChecker
-    : public RecursiveASTVisitor<ArgumentDependenceChecker> {
+class ArgumentDependenceChecker : public DynamicRecursiveASTVisitor {
 #ifndef NDEBUG
   const CXXRecordDecl *ClassType;
 #endif
@@ -755,14 +754,14 @@ class ArgumentDependenceChecker
     return Result;
   }
 
-  bool VisitCXXThisExpr(CXXThisExpr *E) {
+  bool VisitCXXThisExpr(CXXThisExpr *E) override {
     assert(E->getType()->getPointeeCXXRecordDecl() == ClassType &&
            "`this` doesn't refer to the enclosing class?");
     Result = true;
     return false;
   }
 
-  bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
     if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
       if (Parms.count(PVD)) {
         Result = true;
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 807453400abdd0..4d0be8ff41daca 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -17,7 +17,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprObjC.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Sema/DeclSpec.h"
@@ -5320,8 +5320,7 @@ SemaObjC::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,
 namespace {
 /// Used by SemaObjC::DiagnoseUnusedBackingIvarInAccessor to check if a property
 /// accessor references the backing ivar.
-class UnusedBackingIvarChecker
-    : public RecursiveASTVisitor<UnusedBackingIvarChecker> {
+class UnusedBackingIvarChecker : public DynamicRecursiveASTVisitor {
 public:
   Sema &S;
   const ObjCMethodDecl *Method;
@@ -5336,7 +5335,7 @@ class UnusedBackingIvarChecker
     assert(IvarD);
   }
 
-  bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+  bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) override {
     if (E->getDecl() == IvarD) {
       AccessedIvar = true;
       return false;
@@ -5344,7 +5343,7 @@ class UnusedBackingIvarChecker
     return true;
   }
 
-  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+  bool VisitObjCMessageExpr(ObjCMessageExpr *E) override {
     if (E->getReceiverKind() == ObjCMessageExpr::Instance &&
         S.ObjC().isSelfExpr(E->getInstanceReceiver(), Method)) {
       InvokedSelfMethod = true;
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index eebe17a5b4bf72..31cc2674a02c0f 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -11,7 +11,7 @@
 #include "clang/Sema/SemaHLSL.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/DiagnosticSema.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/TargetInfo.h"
@@ -530,8 +530,7 @@ namespace {
 /// and of all exported functions, and any functions that are referenced
 /// from this AST. In other words, any functions that are reachable from
 /// the entry points.
-class DiagnoseHLSLAvailability
-    : public RecursiveASTVisitor<DiagnoseHLSLAvailability> {
+class DiagnoseHLSLAvailability : public DynamicRecursiveASTVisitor {
 
   Sema &SemaRef;
 
@@ -634,14 +633,14 @@ class DiagnoseHLSLAvailability
   void RunOnTranslationUnit(const TranslationUnitDecl *TU);
   void RunOnFunction(const FunctionDecl *FD);
 
-  bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+  bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
     FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->getDecl());
     if (FD)
       HandleFunctionOrMethodRef(FD, DRE);
     return true;
   }
 
-  bool VisitMemberExpr(MemberExpr *ME) {
+  bool VisitMemberExpr(MemberExpr *ME) override {
     FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->getMemberDecl());
     if (FD)
       HandleFunctionOrMethodRef(FD, ME);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index a432918cbf5e20..5a1cca32e7f900 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -23,7 +23,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/NestedNameSpecifier.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
@@ -6459,8 +6459,7 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
 }
 
 namespace {
-struct MarkUsedTemplateParameterVisitor :
-    RecursiveASTVisitor<MarkUsedTemplateParameterVisitor> {
+struct MarkUsedTemplateParameterVisitor : DynamicRecursiveASTVisitor {
   llvm::SmallBitVector &Used;
   unsigned Depth;
 
@@ -6468,23 +6467,22 @@ struct MarkUsedTemplateParameterVisitor :
                                    unsigned Depth)
       : Used(Used), Depth(Depth) { }
 
-  bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
+  bool VisitTemplateTypeParmType(TemplateTypeParmType *T) override {
     if (T->getDepth() == Depth)
       Used[T->getIndex()] = true;
     return true;
   }
 
-  bool TraverseTemplateName(TemplateName Template) {
+  bool TraverseTemplateName(TemplateName Template) override {
     if (auto *TTP = llvm::dyn_cast_or_null<TemplateTemplateParmDecl>(
             Template.getAsTemplateDecl()))
       if (TTP->getDepth() == Depth)
         Used[TTP->getIndex()] = true;
-    RecursiveASTVisitor<MarkUsedTemplateParameterVisitor>::
-        TraverseTemplateName(Template);
+    DynamicRecursiveASTVisitor::TraverseTemplateName(Template);
     return true;
   }
 
-  bool VisitDeclRefExpr(DeclRefExpr *E) {
+  bool VisitDeclRefExpr(DeclRefExpr *E) override {
     if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(E->getDecl()))
       if (NTTP->getDepth() == Depth)
         Used[NTTP->getIndex()] = true;

>From 9f17945ff8030d78986545e9edeb861aa82709d7 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 1 Jul 2024 21:01:24 +0200
Subject: [PATCH 09/25] Migrate more visitors in the AST library

---
 .../clang/AST/DynamicRecursiveASTVisitor.h    | 12 ++++++++
 .../clang/Analysis/FlowSensitive/ASTOps.h     | 28 +++++++++----------
 clang/lib/AST/DynamicRecursiveASTVisitor.cpp  |  8 ++++++
 clang/lib/Analysis/FlowSensitive/ASTOps.cpp   | 15 +++++-----
 .../FlowSensitive/DataflowEnvironment.cpp     | 10 +++----
 5 files changed, 46 insertions(+), 27 deletions(-)

diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
index c2903b76268598..cb7fe93a5b76b5 100644
--- a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -14,6 +14,12 @@ class ASTContext;
 /// particular, it does not support overriding WalkUpFromX or post-order
 /// traversal.
 ///
+/// Features that are currently not supported:
+///
+///   - Visiting attributes
+///   - Post-order traversal
+///   - Overriding WalkUpFromX
+///
 /// \see RecursiveASTVisitor
 class DynamicRecursiveASTVisitor {
 public:
@@ -149,6 +155,12 @@ class DynamicRecursiveASTVisitor {
   /// otherwise (including when the argument is a Null type location).
   virtual bool TraverseTypeLoc(TypeLoc TL);
 
+  /// Recursively visit an Objective-C protocol reference with location
+  /// information.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc);
+
   /// Traverse a concept (requirement).
   virtual bool TraverseTypeConstraint(const TypeConstraint *C);
   virtual bool TraverseConceptRequirement(concepts::Requirement *R);
diff --git a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h
index 925b99af9141a3..2a359e8c69d366 100644
--- a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h
+++ b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h
@@ -15,7 +15,7 @@
 
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
 #include "llvm/ADT/DenseSet.h"
@@ -88,14 +88,14 @@ class RecordInitListHelper {
 /// the function to analyze. Don't call `TraverseDecl()` on the function itself;
 /// this won't work as `TraverseDecl()` contains code to avoid traversing nested
 /// functions.
-template <class Derived>
-class AnalysisASTVisitor : public RecursiveASTVisitor<Derived> {
+class AnalysisASTVisitor : public DynamicRecursiveASTVisitor {
 public:
-  bool shouldVisitImplicitCode() { return true; }
-
-  bool shouldVisitLambdaBody() const { return false; }
+  AnalysisASTVisitor() {
+    ShouldVisitImplicitCode = true;
+    ShouldVisitLambdaBody = false;
+  }
 
-  bool TraverseDecl(Decl *D) {
+  bool TraverseDecl(Decl *D) override {
     // Don't traverse nested record or function declarations.
     // - We won't be analyzing code contained in these anyway
     // - We don't model fields that are used only in these nested declaration,
@@ -104,26 +104,26 @@ class AnalysisASTVisitor : public RecursiveASTVisitor<Derived> {
     if (isa_and_nonnull<RecordDecl>(D) || isa_and_nonnull<FunctionDecl>(D))
       return true;
 
-    return RecursiveASTVisitor<Derived>::TraverseDecl(D);
+    return DynamicRecursiveASTVisitor::TraverseDecl(D);
   }
 
   // Don't traverse expressions in unevaluated contexts, as we don't model
   // fields that are only used in these.
   // Note: The operand of the `noexcept` operator is an unevaluated operand, but
   // nevertheless it appears in the Clang CFG, so we don't exclude it here.
-  bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) { return true; }
-  bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc) { return true; }
-  bool TraverseCXXTypeidExpr(CXXTypeidExpr *) { return true; }
-  bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *) {
+  bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) override { return true; }
+  bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc) override { return true; }
+  bool TraverseCXXTypeidExpr(CXXTypeidExpr *) override { return true; }
+  bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *) override {
     return true;
   }
 
-  bool TraverseBindingDecl(BindingDecl *BD) {
+  bool TraverseBindingDecl(BindingDecl *BD) override {
     // `RecursiveASTVisitor` doesn't traverse holding variables for
     // `BindingDecl`s by itself, so we need to tell it to.
     if (VarDecl *HoldingVar = BD->getHoldingVar())
       TraverseDecl(HoldingVar);
-    return RecursiveASTVisitor<Derived>::TraverseBindingDecl(BD);
+    return DynamicRecursiveASTVisitor::TraverseBindingDecl(BD);
   }
 };
 
diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
index c4bb1b4b0debd9..b4ac4517f72096 100644
--- a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
+++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
@@ -61,6 +61,10 @@ struct Impl : RecursiveASTVisitor<Impl> {
     return Visitor.TraverseTemplateName(Template);
   }
 
+  bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc) {
+    return Visitor.TraverseObjCProtocolLoc(ProtocolLoc);
+  }
+
   bool TraverseTypeConstraint(const TypeConstraint *C) {
     return Visitor.TraverseTypeConstraint(C);
   }
@@ -219,6 +223,10 @@ bool DynamicRecursiveASTVisitor::TraverseTypeConstraint(
     const TypeConstraint *C) {
   return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTypeConstraint(C);
 }
+bool DynamicRecursiveASTVisitor::TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseObjCProtocolLoc(ProtocolLoc);
+}
+
 bool DynamicRecursiveASTVisitor::TraverseConceptRequirement(
     concepts::Requirement *R) {
   return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConceptRequirement(R);
diff --git a/clang/lib/Analysis/FlowSensitive/ASTOps.cpp b/clang/lib/Analysis/FlowSensitive/ASTOps.cpp
index 27d42a7b508562..1b0a4287c851f3 100644
--- a/clang/lib/Analysis/FlowSensitive/ASTOps.cpp
+++ b/clang/lib/Analysis/FlowSensitive/ASTOps.cpp
@@ -191,8 +191,7 @@ static MemberExpr *getMemberForAccessor(const CXXMemberCallExpr &C) {
   return nullptr;
 }
 
-class ReferencedDeclsVisitor
-    : public AnalysisASTVisitor<ReferencedDeclsVisitor> {
+class ReferencedDeclsVisitor : public AnalysisASTVisitor {
 public:
   ReferencedDeclsVisitor(ReferencedDecls &Referenced)
       : Referenced(Referenced) {}
@@ -218,19 +217,19 @@ class ReferencedDeclsVisitor
     }
   }
 
-  bool VisitDecl(Decl *D) {
+  bool VisitDecl(Decl *D) override {
     insertIfGlobal(*D, Referenced.Globals);
     insertIfFunction(*D, Referenced.Functions);
     return true;
   }
 
-  bool VisitDeclRefExpr(DeclRefExpr *E) {
+  bool VisitDeclRefExpr(DeclRefExpr *E) override {
     insertIfGlobal(*E->getDecl(), Referenced.Globals);
     insertIfFunction(*E->getDecl(), Referenced.Functions);
     return true;
   }
 
-  bool VisitCXXMemberCallExpr(CXXMemberCallExpr *C) {
+  bool VisitCXXMemberCallExpr(CXXMemberCallExpr *C) override {
     // If this is a method that returns a member variable but does nothing else,
     // model the field of the return value.
     if (MemberExpr *E = getMemberForAccessor(*C))
@@ -239,7 +238,7 @@ class ReferencedDeclsVisitor
     return true;
   }
 
-  bool VisitMemberExpr(MemberExpr *E) {
+  bool VisitMemberExpr(MemberExpr *E) override {
     // FIXME: should we be using `E->getFoundDecl()`?
     const ValueDecl *VD = E->getMemberDecl();
     insertIfGlobal(*VD, Referenced.Globals);
@@ -249,14 +248,14 @@ class ReferencedDeclsVisitor
     return true;
   }
 
-  bool VisitInitListExpr(InitListExpr *InitList) {
+  bool VisitInitListExpr(InitListExpr *InitList) override {
     if (InitList->getType()->isRecordType())
       for (const auto *FD : getFieldsForInitListExpr(InitList))
         Referenced.Fields.insert(FD);
     return true;
   }
 
-  bool VisitCXXParenListInitExpr(CXXParenListInitExpr *ParenInitList) {
+  bool VisitCXXParenListInitExpr(CXXParenListInitExpr *ParenInitList) override {
     if (ParenInitList->getType()->isRecordType())
       for (const auto *FD : getFieldsForInitListExpr(ParenInitList))
         Referenced.Fields.insert(FD);
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 7c88917faf9c65..0de4cff346ecb5 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -297,7 +297,7 @@ namespace {
 // Visitor that builds a map from record prvalues to result objects.
 // For each result object that it encounters, it propagates the storage location
 // of the result object to all record prvalues that can initialize it.
-class ResultObjectVisitor : public AnalysisASTVisitor<ResultObjectVisitor> {
+class ResultObjectVisitor : public AnalysisASTVisitor {
 public:
   // `ResultObjectMap` will be filled with a map from record prvalues to result
   // object. If this visitor will traverse a function that returns a record by
@@ -338,7 +338,7 @@ class ResultObjectVisitor : public AnalysisASTVisitor<ResultObjectVisitor> {
     }
   }
 
-  bool VisitVarDecl(VarDecl *VD) {
+  bool VisitVarDecl(VarDecl *VD) override {
     if (VD->getType()->isRecordType() && VD->hasInit())
       PropagateResultObject(
           VD->getInit(),
@@ -346,7 +346,7 @@ class ResultObjectVisitor : public AnalysisASTVisitor<ResultObjectVisitor> {
     return true;
   }
 
-  bool VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE) {
+  bool VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE) override {
     if (MTE->getType()->isRecordType())
       PropagateResultObject(
           MTE->getSubExpr(),
@@ -354,7 +354,7 @@ class ResultObjectVisitor : public AnalysisASTVisitor<ResultObjectVisitor> {
     return true;
   }
 
-  bool VisitReturnStmt(ReturnStmt *Return) {
+  bool VisitReturnStmt(ReturnStmt *Return) override {
     Expr *RetValue = Return->getRetValue();
     if (RetValue != nullptr && RetValue->getType()->isRecordType() &&
         RetValue->isPRValue())
@@ -362,7 +362,7 @@ class ResultObjectVisitor : public AnalysisASTVisitor<ResultObjectVisitor> {
     return true;
   }
 
-  bool VisitExpr(Expr *E) {
+  bool VisitExpr(Expr *E) override {
     // Clang's AST can have record-type prvalues without a result object -- for
     // example as full-expressions contained in a compound statement or as
     // arguments of call expressions. We notice this if we get here and a

>From 4bea1314df80bc8191a9226c4e5d8d774022cca8 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 1 Jul 2024 21:29:40 +0200
Subject: [PATCH 10/25] Migrate static analyser visitors

---
 .../clang/AST/DynamicRecursiveASTVisitor.h    | 13 +++++++
 clang/lib/AST/DynamicRecursiveASTVisitor.cpp  |  4 +++
 clang/lib/Analysis/CalledOnceCheck.cpp        |  8 ++---
 clang/lib/Analysis/ReachableCode.cpp          | 14 ++++----
 .../Checkers/CastToStructChecker.cpp          |  8 ++---
 .../Checkers/DeadStoresChecker.cpp            | 16 ++++-----
 .../Checkers/DynamicTypePropagation.cpp       |  6 ++--
 .../Checkers/IdenticalExprChecker.cpp         | 17 +++++----
 .../Checkers/LocalizationChecker.cpp          | 28 +++++++--------
 .../Checkers/ObjCMissingSuperCallChecker.cpp  |  6 ++--
 .../Checkers/PaddingChecker.cpp               | 15 ++++----
 .../WebKit/NoUncountedMembersChecker.cpp      | 11 +++---
 .../WebKit/RefCntblBaseVirtualDtorChecker.cpp | 11 +++---
 .../WebKit/UncountedCallArgsChecker.cpp       | 16 ++++-----
 .../WebKit/UncountedLambdaCapturesChecker.cpp | 11 +++---
 .../WebKit/UncountedLocalVarsChecker.cpp      | 35 +++++++++----------
 .../StaticAnalyzer/Core/BugSuppression.cpp    |  8 ++---
 .../Frontend/AnalysisConsumer.cpp             | 20 +++++------
 18 files changed, 129 insertions(+), 118 deletions(-)

diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
index cb7fe93a5b76b5..a0c7aa2736a7b7 100644
--- a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -19,6 +19,7 @@ class ASTContext;
 ///   - Visiting attributes
 ///   - Post-order traversal
 ///   - Overriding WalkUpFromX
+///   - Overriding dataTraverseStmtPre/Post()
 ///
 /// \see RecursiveASTVisitor
 class DynamicRecursiveASTVisitor {
@@ -181,6 +182,18 @@ class DynamicRecursiveASTVisitor {
   bool WalkUpFromType(Type *T) { return VisitType(T); }
   bool WalkUpFromTypeLoc(TypeLoc TL) { return VisitTypeLoc(TL); }
 
+  /*/// Invoked before visiting a statement or expression via data recursion.
+  ///
+  /// \returns false to skip visiting the node, true otherwise.
+  virtual bool dataTraverseStmtPre(Stmt *S) { return true; }
+
+  /// Invoked after visiting a statement or expression via data recursion.
+  /// This is not invoked if the previously invoked \c dataTraverseStmtPre
+  /// returned false.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool dataTraverseStmtPost(Stmt *S) { return true; }*/
+
   /*// Declare Traverse*() and friends for attributes.
 #define DYNAMIC_ATTR_VISITOR_DECLS
 #include "clang/AST/AttrVisitor.inc"
diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
index b4ac4517f72096..86986e94b9a3cd 100644
--- a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
+++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
@@ -102,6 +102,10 @@ struct Impl : RecursiveASTVisitor<Impl> {
     return Visitor.TraverseNestedNameSpecifierLoc(NNS);
   }
 
+
+  /*bool dataTraverseStmtPre(Stmt *S) { return Visitor.dataTraverseStmtPre(S); }
+  bool dataTraverseStmtPost(Stmt *S) { return Visitor.dataTraverseStmtPost(S); }*/
+
   /// Visit a node.
   bool VisitAttr(Attr *A) { return Visitor.VisitAttr(A); }
   bool VisitDecl(Decl *D) { return Visitor.VisitDecl(D); }
diff --git a/clang/lib/Analysis/CalledOnceCheck.cpp b/clang/lib/Analysis/CalledOnceCheck.cpp
index 30cbd257b65e8f..73dc6bbe154b2b 100644
--- a/clang/lib/Analysis/CalledOnceCheck.cpp
+++ b/clang/lib/Analysis/CalledOnceCheck.cpp
@@ -15,7 +15,7 @@
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/ParentMap.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/StmtObjC.h"
 #include "clang/AST/StmtVisitor.h"
@@ -426,7 +426,7 @@ const Expr *getCondition(const Stmt *S) {
 /// of the AST will end up in the results.
 /// Results might have duplicate names, if this is a problem, convert to
 /// string sets afterwards.
-class NamesCollector : public RecursiveASTVisitor<NamesCollector> {
+class NamesCollector : public DynamicRecursiveASTVisitor {
 public:
   static constexpr unsigned EXPECTED_NUMBER_OF_NAMES = 5;
   using NameCollection =
@@ -438,12 +438,12 @@ class NamesCollector : public RecursiveASTVisitor<NamesCollector> {
     return Impl.Result;
   }
 
-  bool VisitDeclRefExpr(const DeclRefExpr *E) {
+  bool VisitDeclRefExpr(DeclRefExpr *E) override {
     Result.push_back(E->getDecl()->getName());
     return true;
   }
 
-  bool VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *E) {
+  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) override {
     llvm::StringRef Name;
 
     if (E->isImplicitProperty()) {
diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp
index acbe1470b38991..905192c7edd226 100644
--- a/clang/lib/Analysis/ReachableCode.cpp
+++ b/clang/lib/Analysis/ReachableCode.cpp
@@ -17,7 +17,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/ParentMap.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
 #include "clang/Analysis/CFG.h"
@@ -476,17 +476,19 @@ static bool isInCoroutineStmt(const Stmt *DeadStmt, const CFGBlock *Block) {
     }
   if (!CoroStmt)
     return false;
-  struct Checker : RecursiveASTVisitor<Checker> {
+  struct Checker : DynamicRecursiveASTVisitor {
     const Stmt *DeadStmt;
     bool CoroutineSubStmt = false;
-    Checker(const Stmt *S) : DeadStmt(S) {}
-    bool VisitStmt(const Stmt *S) {
+    Checker(const Stmt *S) : DeadStmt(S) {
+      // Statements captured in the CFG can be implicit.
+      ShouldVisitImplicitCode = true;
+    }
+
+    bool VisitStmt(Stmt *S) override {
       if (S == DeadStmt)
         CoroutineSubStmt = true;
       return true;
     }
-    // Statements captured in the CFG can be implicit.
-    bool shouldVisitImplicitCode() const { return true; }
   };
   Checker checker(DeadStmt);
   checker.TraverseStmt(const_cast<Stmt *>(CoroStmt));
diff --git a/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
index e674ec43bcd9df..aa0bd78c1472f5 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
@@ -13,7 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -23,7 +23,7 @@ using namespace clang;
 using namespace ento;
 
 namespace {
-class CastToStructVisitor : public RecursiveASTVisitor<CastToStructVisitor> {
+class CastToStructVisitor : public DynamicRecursiveASTVisitor {
   BugReporter &BR;
   const CheckerBase *Checker;
   AnalysisDeclContext *AC;
@@ -32,11 +32,11 @@ class CastToStructVisitor : public RecursiveASTVisitor<CastToStructVisitor> {
   explicit CastToStructVisitor(BugReporter &B, const CheckerBase *Checker,
                                AnalysisDeclContext *A)
       : BR(B), Checker(Checker), AC(A) {}
-  bool VisitCastExpr(const CastExpr *CE);
+  bool VisitCastExpr(CastExpr *CE) override;
 };
 }
 
-bool CastToStructVisitor::VisitCastExpr(const CastExpr *CE) {
+bool CastToStructVisitor::VisitCastExpr(CastExpr *CE) {
   const Expr *E = CE->getSubExpr();
   ASTContext &Ctx = AC->getASTContext();
   QualType OrigTy = Ctx.getCanonicalType(E->getType());
diff --git a/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
index 86f446fc411ca2..f7dba536b524f3 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
@@ -14,7 +14,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/ParentMap.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Analysis/Analyses/LiveVariables.h"
 #include "clang/Lex/Lexer.h"
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
@@ -32,27 +32,27 @@ using namespace ento;
 namespace {
 
 /// A simple visitor to record what VarDecls occur in EH-handling code.
-class EHCodeVisitor : public RecursiveASTVisitor<EHCodeVisitor> {
+class EHCodeVisitor : public DynamicRecursiveASTVisitor {
 public:
   bool inEH;
   llvm::DenseSet<const VarDecl *> &S;
 
-  bool TraverseObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+  bool TraverseObjCAtFinallyStmt(ObjCAtFinallyStmt *S) override {
     SaveAndRestore inFinally(inEH, true);
-    return ::RecursiveASTVisitor<EHCodeVisitor>::TraverseObjCAtFinallyStmt(S);
+    return DynamicRecursiveASTVisitor::TraverseObjCAtFinallyStmt(S);
   }
 
-  bool TraverseObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+  bool TraverseObjCAtCatchStmt(ObjCAtCatchStmt *S) override {
     SaveAndRestore inCatch(inEH, true);
-    return ::RecursiveASTVisitor<EHCodeVisitor>::TraverseObjCAtCatchStmt(S);
+    return DynamicRecursiveASTVisitor::TraverseObjCAtCatchStmt(S);
   }
 
-  bool TraverseCXXCatchStmt(CXXCatchStmt *S) {
+  bool TraverseCXXCatchStmt(CXXCatchStmt *S) override {
     SaveAndRestore inCatch(inEH, true);
     return TraverseStmt(S->getHandlerBlock());
   }
 
-  bool VisitDeclRefExpr(DeclRefExpr *DR) {
+  bool VisitDeclRefExpr(DeclRefExpr *DR) override {
     if (inEH)
       if (const VarDecl *D = dyn_cast<VarDecl>(DR->getDecl()))
         S.insert(D);
diff --git a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
index 034774a252b118..cdda319924563a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
@@ -21,7 +21,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/ParentMap.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -711,10 +711,10 @@ static bool isObjCTypeParamDependent(QualType Type) {
   // an Objective-C type can only be dependent on a type parameter when the type
   // parameter structurally present in the type itself.
   class IsObjCTypeParamDependentTypeVisitor
-      : public RecursiveASTVisitor<IsObjCTypeParamDependentTypeVisitor> {
+      : public DynamicRecursiveASTVisitor  {
   public:
     IsObjCTypeParamDependentTypeVisitor() = default;
-    bool VisitObjCTypeParamType(const ObjCTypeParamType *Type) {
+    bool VisitObjCTypeParamType(ObjCTypeParamType *Type) override {
       if (isa<ObjCTypeParamDecl>(Type->getDecl())) {
         Result = true;
         return false;
diff --git a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
index 7ac34ef8164e4c..fa20766b639dcf 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
@@ -16,7 +16,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -32,8 +32,7 @@ static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1,
 //===----------------------------------------------------------------------===//
 
 namespace {
-class FindIdenticalExprVisitor
-    : public RecursiveASTVisitor<FindIdenticalExprVisitor> {
+class FindIdenticalExprVisitor : public DynamicRecursiveASTVisitor {
   BugReporter &BR;
   const CheckerBase *Checker;
   AnalysisDeclContext *AC;
@@ -45,9 +44,9 @@ class FindIdenticalExprVisitor
   // FindIdenticalExprVisitor only visits nodes
   // that are binary operators, if statements or
   // conditional operators.
-  bool VisitBinaryOperator(const BinaryOperator *B);
-  bool VisitIfStmt(const IfStmt *I);
-  bool VisitConditionalOperator(const ConditionalOperator *C);
+  bool VisitBinaryOperator(BinaryOperator *B) override;
+  bool VisitIfStmt(IfStmt *I) override;
+  bool VisitConditionalOperator(ConditionalOperator *C) override;
 
 private:
   void reportIdenticalExpr(const BinaryOperator *B, bool CheckBitwise,
@@ -103,7 +102,7 @@ void FindIdenticalExprVisitor::checkBitwiseOrLogicalOp(const BinaryOperator *B,
   }
 }
 
-bool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) {
+bool FindIdenticalExprVisitor::VisitIfStmt(IfStmt *I) {
   const Stmt *Stmt1 = I->getThen();
   const Stmt *Stmt2 = I->getElse();
 
@@ -178,7 +177,7 @@ bool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) {
   return true;
 }
 
-bool FindIdenticalExprVisitor::VisitBinaryOperator(const BinaryOperator *B) {
+bool FindIdenticalExprVisitor::VisitBinaryOperator(BinaryOperator *B) {
   BinaryOperator::Opcode Op = B->getOpcode();
 
   if (BinaryOperator::isBitwiseOp(Op))
@@ -268,7 +267,7 @@ void FindIdenticalExprVisitor::checkComparisonOp(const BinaryOperator *B) {
 }
 
 bool FindIdenticalExprVisitor::VisitConditionalOperator(
-    const ConditionalOperator *C) {
+    ConditionalOperator *C) {
 
   // Check if expressions in conditional expression are identical
   // from a symbolic point of view.
diff --git a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
index f524c4c067c8c3..342ff7fd6d817a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
@@ -17,7 +17,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclObjC.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Lex/Lexer.h"
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
@@ -1191,7 +1191,7 @@ namespace {
 class PluralMisuseChecker : public Checker<check::ASTCodeBody> {
 
   // A helper class, which walks the AST
-  class MethodCrawler : public RecursiveASTVisitor<MethodCrawler> {
+  class MethodCrawler : public DynamicRecursiveASTVisitor {
     BugReporter &BR;
     const CheckerBase *Checker;
     AnalysisDeclContext *AC;
@@ -1209,13 +1209,13 @@ class PluralMisuseChecker : public Checker<check::ASTCodeBody> {
                            AnalysisDeclContext *InAC)
         : BR(InBR), Checker(Checker), AC(InAC) {}
 
-    bool VisitIfStmt(const IfStmt *I);
+    bool VisitIfStmt(IfStmt *I) override;
     bool EndVisitIfStmt(IfStmt *I);
-    bool TraverseIfStmt(IfStmt *x);
-    bool VisitConditionalOperator(const ConditionalOperator *C);
-    bool TraverseConditionalOperator(ConditionalOperator *C);
-    bool VisitCallExpr(const CallExpr *CE);
-    bool VisitObjCMessageExpr(const ObjCMessageExpr *ME);
+    bool TraverseIfStmt(IfStmt *x) override;
+    bool VisitConditionalOperator(ConditionalOperator *C) override;
+    bool TraverseConditionalOperator(ConditionalOperator *C) override;
+    bool VisitCallExpr(CallExpr *CE) override;
+    bool VisitObjCMessageExpr(ObjCMessageExpr *ME) override;
 
   private:
     void reportPluralMisuseError(const Stmt *S) const;
@@ -1274,7 +1274,7 @@ bool PluralMisuseChecker::MethodCrawler::isCheckingPlurality(
 // has been shown to almost always be a function that returns a localized
 // string. Raise a diagnostic when this is in a statement that matches
 // the condition.
-bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(const CallExpr *CE) {
+bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(CallExpr *CE) {
   if (InMatchingStatement) {
     if (const FunctionDecl *FD = CE->getDirectCallee()) {
       std::string NormalizedName =
@@ -1296,7 +1296,7 @@ bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(const CallExpr *CE) {
 // diagnostic when this is in a statement that matches
 // the condition.
 bool PluralMisuseChecker::MethodCrawler::VisitObjCMessageExpr(
-    const ObjCMessageExpr *ME) {
+    ObjCMessageExpr *ME) {
   const ObjCInterfaceDecl *OD = ME->getReceiverInterface();
   if (!OD)
     return true;
@@ -1314,7 +1314,7 @@ bool PluralMisuseChecker::MethodCrawler::VisitObjCMessageExpr(
 
 /// Override TraverseIfStmt so we know when we are done traversing an IfStmt
 bool PluralMisuseChecker::MethodCrawler::TraverseIfStmt(IfStmt *I) {
-  RecursiveASTVisitor<MethodCrawler>::TraverseIfStmt(I);
+  DynamicRecursiveASTVisitor::TraverseIfStmt(I);
   return EndVisitIfStmt(I);
 }
 
@@ -1333,7 +1333,7 @@ bool PluralMisuseChecker::MethodCrawler::EndVisitIfStmt(IfStmt *I) {
   return true;
 }
 
-bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(const IfStmt *I) {
+bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(IfStmt *I) {
   const Expr *Condition = I->getCond();
   if (!Condition)
     return true;
@@ -1352,7 +1352,7 @@ bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(const IfStmt *I) {
 // Preliminary support for conditional operators.
 bool PluralMisuseChecker::MethodCrawler::TraverseConditionalOperator(
     ConditionalOperator *C) {
-  RecursiveASTVisitor<MethodCrawler>::TraverseConditionalOperator(C);
+  DynamicRecursiveASTVisitor::TraverseConditionalOperator(C);
   MatchingStatements.pop_back();
   if (!MatchingStatements.empty()) {
     if (MatchingStatements.back() != nullptr)
@@ -1366,7 +1366,7 @@ bool PluralMisuseChecker::MethodCrawler::TraverseConditionalOperator(
 }
 
 bool PluralMisuseChecker::MethodCrawler::VisitConditionalOperator(
-    const ConditionalOperator *C) {
+    ConditionalOperator *C) {
   const Expr *Condition = C->getCond()->IgnoreParenImpCasts();
   if (isCheckingPlurality(Condition)) {
     MatchingStatements.push_back(C);
diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
index 03dab4f7ada7ae..dea1b1aea016bf 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
@@ -17,7 +17,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprObjC.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
@@ -38,11 +38,11 @@ struct SelectorDescriptor {
 // FindSuperCallVisitor - Identify specific calls to the superclass.
 //===----------------------------------------------------------------------===//
 
-class FindSuperCallVisitor : public RecursiveASTVisitor<FindSuperCallVisitor> {
+class FindSuperCallVisitor : public DynamicRecursiveASTVisitor {
 public:
   explicit FindSuperCallVisitor(Selector S) : DoesCallSuper(false), Sel(S) {}
 
-  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+  bool VisitObjCMessageExpr(ObjCMessageExpr *E) override {
     if (E->getSelector() == Sel)
       if (E->getReceiverKind() == ObjCMessageExpr::SuperInstance)
         DoesCallSuper = true;
diff --git a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
index 4f35d9442ad988..4354f36b397977 100644
--- a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
@@ -15,7 +15,7 @@
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/RecordLayout.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Driver/DriverDiagnostic.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -45,16 +45,17 @@ class PaddingChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {
     // The calls to checkAST* from AnalysisConsumer don't
     // visit template instantiations or lambda classes. We
     // want to visit those, so we make our own RecursiveASTVisitor.
-    struct LocalVisitor : public RecursiveASTVisitor<LocalVisitor> {
+    struct LocalVisitor : DynamicRecursiveASTVisitor {
       const PaddingChecker *Checker;
-      bool shouldVisitTemplateInstantiations() const { return true; }
-      bool shouldVisitImplicitCode() const { return true; }
-      explicit LocalVisitor(const PaddingChecker *Checker) : Checker(Checker) {}
-      bool VisitRecordDecl(const RecordDecl *RD) {
+      explicit LocalVisitor(const PaddingChecker *Checker) : Checker(Checker) {
+        ShouldVisitTemplateInstantiations = true;
+        ShouldVisitImplicitCode = true;
+      }
+      bool VisitRecordDecl(RecordDecl *RD) override {
         Checker->visitRecord(RD);
         return true;
       }
-      bool VisitVarDecl(const VarDecl *VD) {
+      bool VisitVarDecl(VarDecl *VD) override {
         Checker->visitVariable(VD);
         return true;
       }
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/NoUncountedMembersChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/NoUncountedMembersChecker.cpp
index 69a0eb3086ab72..2c30c7825b51e3 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/NoUncountedMembersChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/NoUncountedMembersChecker.cpp
@@ -12,7 +12,7 @@
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -45,17 +45,16 @@ class NoUncountedMemberChecker
     // The calls to checkAST* from AnalysisConsumer don't
     // visit template instantiations or lambda classes. We
     // want to visit those, so we make our own RecursiveASTVisitor.
-    struct LocalVisitor : public RecursiveASTVisitor<LocalVisitor> {
+    struct LocalVisitor : DynamicRecursiveASTVisitor {
       const NoUncountedMemberChecker *Checker;
       explicit LocalVisitor(const NoUncountedMemberChecker *Checker)
           : Checker(Checker) {
         assert(Checker);
+        ShouldVisitTemplateInstantiations = true;
+        ShouldVisitImplicitCode = true;
       }
 
-      bool shouldVisitTemplateInstantiations() const { return true; }
-      bool shouldVisitImplicitCode() const { return false; }
-
-      bool VisitRecordDecl(const RecordDecl *RD) {
+      bool VisitRecordDecl(RecordDecl *RD) override {
         Checker->visitRecordDecl(RD);
         return true;
       }
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp
index 9df108e28ecdbb..c5e1af6e3ce082 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp
@@ -10,7 +10,7 @@
 #include "DiagOutputUtils.h"
 #include "PtrTypesSemantics.h"
 #include "clang/AST/CXXInheritance.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
@@ -140,17 +140,16 @@ class RefCntblBaseVirtualDtorChecker
     // The calls to checkAST* from AnalysisConsumer don't
     // visit template instantiations or lambda classes. We
     // want to visit those, so we make our own RecursiveASTVisitor.
-    struct LocalVisitor : public RecursiveASTVisitor<LocalVisitor> {
+    struct LocalVisitor : DynamicRecursiveASTVisitor {
       const RefCntblBaseVirtualDtorChecker *Checker;
       explicit LocalVisitor(const RefCntblBaseVirtualDtorChecker *Checker)
           : Checker(Checker) {
         assert(Checker);
+        ShouldVisitTemplateInstantiations = true;
+        ShouldVisitImplicitCode = false;
       }
 
-      bool shouldVisitTemplateInstantiations() const { return true; }
-      bool shouldVisitImplicitCode() const { return false; }
-
-      bool VisitCXXRecordDecl(const CXXRecordDecl *RD) {
+      bool VisitCXXRecordDecl(CXXRecordDecl *RD) override {
         if (!RD->hasDefinition())
           return true;
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
index 704c082a4d1d63..a71027d0acb936 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
@@ -12,7 +12,7 @@
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
@@ -43,24 +43,22 @@ class UncountedCallArgsChecker
     // The calls to checkAST* from AnalysisConsumer don't
     // visit template instantiations or lambda classes. We
     // want to visit those, so we make our own RecursiveASTVisitor.
-    struct LocalVisitor : public RecursiveASTVisitor<LocalVisitor> {
+    struct LocalVisitor : DynamicRecursiveASTVisitor {
       const UncountedCallArgsChecker *Checker;
       explicit LocalVisitor(const UncountedCallArgsChecker *Checker)
           : Checker(Checker) {
         assert(Checker);
+        ShouldVisitTemplateInstantiations = true;
+        ShouldVisitImplicitCode = false;
       }
 
-      bool shouldVisitTemplateInstantiations() const { return true; }
-      bool shouldVisitImplicitCode() const { return false; }
-
-      bool TraverseClassTemplateDecl(ClassTemplateDecl *Decl) {
+      bool TraverseClassTemplateDecl(ClassTemplateDecl *Decl) override {
         if (isRefType(safeGetName(Decl)))
           return true;
-        return RecursiveASTVisitor<LocalVisitor>::TraverseClassTemplateDecl(
-            Decl);
+        return DynamicRecursiveASTVisitor::TraverseClassTemplateDecl(Decl);
       }
 
-      bool VisitCallExpr(const CallExpr *CE) {
+      bool VisitCallExpr(CallExpr *CE) override {
         Checker->visitCallExpr(CE);
         return true;
       }
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
index a226a01ec0a579..917c7670c3790e 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
@@ -9,7 +9,7 @@
 #include "DiagOutputUtils.h"
 #include "PtrTypesSemantics.h"
 #include "clang/AST/CXXInheritance.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -35,17 +35,16 @@ class UncountedLambdaCapturesChecker
     // The calls to checkAST* from AnalysisConsumer don't
     // visit template instantiations or lambda classes. We
     // want to visit those, so we make our own RecursiveASTVisitor.
-    struct LocalVisitor : public RecursiveASTVisitor<LocalVisitor> {
+    struct LocalVisitor : DynamicRecursiveASTVisitor {
       const UncountedLambdaCapturesChecker *Checker;
       explicit LocalVisitor(const UncountedLambdaCapturesChecker *Checker)
           : Checker(Checker) {
         assert(Checker);
+        ShouldVisitTemplateInstantiations = true;
+        ShouldVisitImplicitCode = false;
       }
 
-      bool shouldVisitTemplateInstantiations() const { return true; }
-      bool shouldVisitImplicitCode() const { return false; }
-
-      bool VisitLambdaExpr(LambdaExpr *L) {
+      bool VisitLambdaExpr(LambdaExpr *L) override {
         Checker->visitLambdaExpr(L);
         return true;
       }
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp
index 274da0baf2ce5c..e24c67c4d788ea 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp
@@ -13,7 +13,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ParentMapContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
@@ -119,29 +119,26 @@ class UncountedLocalVarsChecker
     // The calls to checkAST* from AnalysisConsumer don't
     // visit template instantiations or lambda classes. We
     // want to visit those, so we make our own RecursiveASTVisitor.
-    struct LocalVisitor : public RecursiveASTVisitor<LocalVisitor> {
+    struct LocalVisitor : DynamicRecursiveASTVisitor {
       const UncountedLocalVarsChecker *Checker;
 
       TrivialFunctionAnalysis TFA;
 
-      using Base = RecursiveASTVisitor<LocalVisitor>;
-
       explicit LocalVisitor(const UncountedLocalVarsChecker *Checker)
           : Checker(Checker) {
         assert(Checker);
+        ShouldVisitTemplateInstantiations = true;
+        ShouldVisitImplicitCode = false;
       }
 
-      bool shouldVisitTemplateInstantiations() const { return true; }
-      bool shouldVisitImplicitCode() const { return false; }
-
-      bool VisitVarDecl(VarDecl *V) {
+      bool VisitVarDecl(VarDecl *V) override {
         auto *Init = V->getInit();
         if (Init && V->isLocalVarDecl())
           Checker->visitVarDecl(V, Init);
         return true;
       }
 
-      bool VisitBinaryOperator(const BinaryOperator *BO) {
+      bool VisitBinaryOperator(BinaryOperator *BO) override {
         if (BO->isAssignmentOp()) {
           if (auto *VarRef = dyn_cast<DeclRefExpr>(BO->getLHS())) {
             if (auto *V = dyn_cast<VarDecl>(VarRef->getDecl()))
@@ -151,33 +148,33 @@ class UncountedLocalVarsChecker
         return true;
       }
 
-      bool TraverseIfStmt(IfStmt *IS) {
+      bool TraverseIfStmt(IfStmt *IS) override {
         if (!TFA.isTrivial(IS))
-          return Base::TraverseIfStmt(IS);
+          return DynamicRecursiveASTVisitor::TraverseIfStmt(IS);
         return true;
       }
 
-      bool TraverseForStmt(ForStmt *FS) {
+      bool TraverseForStmt(ForStmt *FS) override {
         if (!TFA.isTrivial(FS))
-          return Base::TraverseForStmt(FS);
+          return DynamicRecursiveASTVisitor::TraverseForStmt(FS);
         return true;
       }
 
-      bool TraverseCXXForRangeStmt(CXXForRangeStmt *FRS) {
+      bool TraverseCXXForRangeStmt(CXXForRangeStmt *FRS) override {
         if (!TFA.isTrivial(FRS))
-          return Base::TraverseCXXForRangeStmt(FRS);
+          return DynamicRecursiveASTVisitor::TraverseCXXForRangeStmt(FRS);
         return true;
       }
 
-      bool TraverseWhileStmt(WhileStmt *WS) {
+      bool TraverseWhileStmt(WhileStmt *WS) override {
         if (!TFA.isTrivial(WS))
-          return Base::TraverseWhileStmt(WS);
+          return DynamicRecursiveASTVisitor::TraverseWhileStmt(WS);
         return true;
       }
 
-      bool TraverseCompoundStmt(CompoundStmt *CS) {
+      bool TraverseCompoundStmt(CompoundStmt *CS) override {
         if (!TFA.isTrivial(CS))
-          return Base::TraverseCompoundStmt(CS);
+          return DynamicRecursiveASTVisitor::TraverseCompoundStmt(CS);
         return true;
       }
     };
diff --git a/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp b/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp
index 84004b8e5c1cdb..05c99c4a844e9e 100644
--- a/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/StaticAnalyzer/Core/BugReporter/BugSuppression.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
 
 using namespace clang;
@@ -76,13 +76,13 @@ inline bool fullyContains(SourceRange Larger, SourceRange Smaller,
          isLessOrEqual(Smaller.getEnd(), Larger.getEnd(), SM);
 }
 
-class CacheInitializer : public RecursiveASTVisitor<CacheInitializer> {
+class CacheInitializer : public DynamicRecursiveASTVisitor {
 public:
   static void initialize(const Decl *D, Ranges &ToInit) {
     CacheInitializer(ToInit).TraverseDecl(const_cast<Decl *>(D));
   }
 
-  bool VisitDecl(Decl *D) {
+  bool VisitDecl(Decl *D) override {
     // Bug location could be somewhere in the init value of
     // a freshly declared variable.  Even though it looks like the
     // user applied attribute to a statement, it will apply to a
@@ -90,7 +90,7 @@ class CacheInitializer : public RecursiveASTVisitor<CacheInitializer> {
     return VisitAttributedNode(D);
   }
 
-  bool VisitAttributedStmt(AttributedStmt *AS) {
+  bool VisitAttributedStmt(AttributedStmt *AS) override {
     // When we apply attributes to statements, it actually creates
     // a wrapper statement that only contains attributes and the wrapped
     // statement.
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 03bc40804d7328..91c9b085f68292 100644
--- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -15,7 +15,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Analysis/Analyses/LiveVariables.h"
 #include "clang/Analysis/CFG.h"
 #include "clang/Analysis/CallGraph.h"
@@ -68,7 +68,7 @@ STATISTIC(MaxCFGSize, "The maximum number of basic blocks in a function.");
 namespace {
 
 class AnalysisConsumer : public AnalysisASTConsumer,
-                         public RecursiveASTVisitor<AnalysisConsumer> {
+                         public DynamicRecursiveASTVisitor {
   enum {
     AM_None = 0,
     AM_Syntax = 0x1,
@@ -147,6 +147,9 @@ class AnalysisConsumer : public AnalysisASTConsumer,
 
     if (Opts.ShouldDisplayMacroExpansions)
       MacroExpansions.registerForPreprocessor(PP);
+
+    // Visitor options.
+    ShouldWalkTypesOfTypeLocs = false;
   }
 
   ~AnalysisConsumer() override {
@@ -261,11 +264,8 @@ class AnalysisConsumer : public AnalysisASTConsumer,
                               ExprEngine::InliningModes IMode,
                               SetOfConstDecls *VisitedCallees);
 
-  /// Visitors for the RecursiveASTVisitor.
-  bool shouldWalkTypesOfTypeLocs() const { return false; }
-
   /// Handle callbacks for arbitrary Decls.
-  bool VisitDecl(Decl *D) {
+  bool VisitDecl(Decl *D) override {
     AnalysisMode Mode = getModeForDecl(D, RecVisitorMode);
     if (Mode & AM_Syntax) {
       if (SyntaxCheckTimer)
@@ -277,7 +277,7 @@ class AnalysisConsumer : public AnalysisASTConsumer,
     return true;
   }
 
-  bool VisitVarDecl(VarDecl *VD) {
+  bool VisitVarDecl(VarDecl *VD) override {
     if (!Opts.IsNaiveCTUEnabled)
       return true;
 
@@ -306,7 +306,7 @@ class AnalysisConsumer : public AnalysisASTConsumer,
     return true;
   }
 
-  bool VisitFunctionDecl(FunctionDecl *FD) {
+  bool VisitFunctionDecl(FunctionDecl *FD) override {
     IdentifierInfo *II = FD->getIdentifier();
     if (II && II->getName().starts_with("__inline"))
       return true;
@@ -321,7 +321,7 @@ class AnalysisConsumer : public AnalysisASTConsumer,
     return true;
   }
 
-  bool VisitObjCMethodDecl(ObjCMethodDecl *MD) {
+  bool VisitObjCMethodDecl(ObjCMethodDecl *MD) override {
     if (MD->isThisDeclarationADefinition()) {
       assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
       HandleCode(MD, RecVisitorMode);
@@ -329,7 +329,7 @@ class AnalysisConsumer : public AnalysisASTConsumer,
     return true;
   }
 
-  bool VisitBlockDecl(BlockDecl *BD) {
+  bool VisitBlockDecl(BlockDecl *BD) override {
     if (BD->hasBody()) {
       assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
       // Since we skip function template definitions, we should skip blocks

>From 3c16260454b27d98fa6e81e56b9b05100231424f Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Tue, 2 Jul 2024 23:55:50 +0200
Subject: [PATCH 11/25] Actually override Visit for abstract nodes

---
 clang/lib/AST/DynamicRecursiveASTVisitor.cpp | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
index 86986e94b9a3cd..fb846792f1e6e6 100644
--- a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
+++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
@@ -117,16 +117,21 @@ struct Impl : RecursiveASTVisitor<Impl> {
   #include "clang/AST/AttrVisitor.inc"
   #undef ATTR_VISITOR_DECLS*/
 
+  // Declarations.
 #define ABSTRACT_DECL(DECL)
 #define DECL(CLASS, BASE)                                                      \
   bool Traverse##CLASS##Decl(CLASS##Decl *D) {                                 \
     return Visitor.Traverse##CLASS##Decl(D);                                   \
-  }                                                                            \
+  }
+#include "clang/AST/DeclNodes.inc"
+
+#define DECL(CLASS, BASE)                                                      \
   bool Visit##CLASS##Decl(CLASS##Decl *D) {                                    \
     return Visitor.Visit##CLASS##Decl(D);                                      \
   }
 #include "clang/AST/DeclNodes.inc"
 
+  // Statements.
 #define ABSTRACT_STMT(STMT)
 #define STMT(CLASS, PARENT)                                                    \
   bool Traverse##CLASS(CLASS *S) { return Visitor.Traverse##CLASS(S); }
@@ -136,17 +141,21 @@ struct Impl : RecursiveASTVisitor<Impl> {
   bool Visit##CLASS(CLASS *S) { return Visitor.Visit##CLASS(S); }
 #include "clang/AST/StmtNodes.inc"
 
-  // Declare Traverse*() and friends for all concrete Typeclasses.
+  // Types.
 #define ABSTRACT_TYPE(CLASS, BASE)
 #define TYPE(CLASS, BASE)                                                      \
   bool Traverse##CLASS##Type(CLASS##Type *T) {                                 \
     return Visitor.Traverse##CLASS##Type(T);                                   \
-  }                                                                            \
+  }
+#include "clang/AST/TypeNodes.inc"
+
+#define TYPE(CLASS, BASE)                                                      \
   bool Visit##CLASS##Type(CLASS##Type *T) {                                    \
     return Visitor.Visit##CLASS##Type(T);                                      \
   }
 #include "clang/AST/TypeNodes.inc"
 
+  // TypeLocs.
 #define ABSTRACT_TYPELOC(CLASS, BASE)
 #define TYPELOC(CLASS, BASE)                                                   \
   bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL) {                           \

>From e542efa7636105f4ee6784a208cc50ad87f9d680 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 3 Jul 2024 00:22:00 +0200
Subject: [PATCH 12/25] Migrate even more visitors

---
 clang/include/clang/InstallAPI/Visitor.h      | 20 ++++----
 .../Refactoring/RecursiveSymbolVisitor.h      | 31 +++++-------
 clang/lib/AST/ASTImporterLookupTable.cpp      | 22 ++++----
 clang/lib/Analysis/UnsafeBufferUsage.cpp      | 50 ++++++++-----------
 .../ObjectFilePCHContainerOperations.cpp      | 14 +++---
 clang/lib/Frontend/ASTConsumers.cpp           | 26 +++++-----
 clang/lib/Index/IndexTypeSourceInfo.cpp       | 41 ++++++++-------
 clang/lib/InstallAPI/Visitor.cpp              | 10 ++--
 clang/lib/Tooling/ASTDiff/ASTDiff.cpp         | 19 +++----
 .../Tooling/Refactoring/Rename/USRFinder.cpp  | 12 ++---
 .../Refactoring/Rename/USRFindingAction.cpp   | 11 ++--
 .../Refactoring/Rename/USRLocFinder.cpp       | 23 ++++-----
 12 files changed, 132 insertions(+), 147 deletions(-)

diff --git a/clang/include/clang/InstallAPI/Visitor.h b/clang/include/clang/InstallAPI/Visitor.h
index 3680ee566ca875..ab8b5588b62c92 100644
--- a/clang/include/clang/InstallAPI/Visitor.h
+++ b/clang/include/clang/InstallAPI/Visitor.h
@@ -14,7 +14,7 @@
 #define LLVM_CLANG_INSTALLAPI_VISITOR_H
 
 #include "clang/AST/Mangle.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Frontend/FrontendActions.h"
 #include "clang/InstallAPI/Context.h"
@@ -26,35 +26,37 @@ namespace installapi {
 
 /// ASTVisitor for collecting declarations that represent global symbols.
 class InstallAPIVisitor final : public ASTConsumer,
-                                public RecursiveASTVisitor<InstallAPIVisitor> {
+                                public DynamicRecursiveASTVisitor {
 public:
   InstallAPIVisitor(ASTContext &ASTCtx, InstallAPIContext &Ctx,
                     SourceManager &SrcMgr, Preprocessor &PP)
       : Ctx(Ctx), SrcMgr(SrcMgr), PP(PP),
         MC(ItaniumMangleContext::create(ASTCtx, ASTCtx.getDiagnostics())),
-        Layout(ASTCtx.getTargetInfo().getDataLayoutString()) {}
+        Layout(ASTCtx.getTargetInfo().getDataLayoutString()) {
+    ShouldVisitTemplateInstantiations = true;
+  }
+
   void HandleTranslationUnit(ASTContext &ASTCtx) override;
-  bool shouldVisitTemplateInstantiations() const { return true; }
 
   /// Collect global variables.
-  bool VisitVarDecl(const VarDecl *D);
+  bool VisitVarDecl(VarDecl *D) override;
 
   /// Collect global functions.
-  bool VisitFunctionDecl(const FunctionDecl *D);
+  bool VisitFunctionDecl(FunctionDecl *D) override;
 
   /// Collect Objective-C Interface declarations.
   /// Every Objective-C class has an interface declaration that lists all the
   /// ivars, properties, and methods of the class.
-  bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D);
+  bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) override;
 
   /// Collect Objective-C Category/Extension declarations.
   ///
   /// The class that is being extended might come from a different library and
   /// is therefore itself not collected.
-  bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D);
+  bool VisitObjCCategoryDecl(ObjCCategoryDecl *D) override;
 
   /// Collect global c++ declarations.
-  bool VisitCXXRecordDecl(const CXXRecordDecl *D);
+  bool VisitCXXRecordDecl(CXXRecordDecl *D) override;
 
 private:
   std::string getMangledName(const NamedDecl *D) const;
diff --git a/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
index 015dbba26f6887..aeea0c1b2df7f0 100644
--- a/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
+++ b/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
@@ -24,27 +24,23 @@ namespace tooling {
 
 /// Traverses the AST and visits the occurrence of each named symbol in the
 /// given nodes.
-template <typename T>
-class RecursiveSymbolVisitor
-    : public RecursiveASTVisitor<RecursiveSymbolVisitor<T>> {
-  using BaseType = RecursiveASTVisitor<RecursiveSymbolVisitor<T>>;
-
+class RecursiveSymbolVisitor : public DynamicRecursiveASTVisitor {
 public:
   RecursiveSymbolVisitor(const SourceManager &SM, const LangOptions &LangOpts)
       : SM(SM), LangOpts(LangOpts) {}
 
-  bool visitSymbolOccurrence(const NamedDecl *ND,
+  virtual bool visitSymbolOccurrence(const NamedDecl *ND,
                              ArrayRef<SourceRange> NameRanges) {
     return true;
   }
 
   // Declaration visitors:
 
-  bool VisitNamedDecl(const NamedDecl *D) {
+  bool VisitNamedDecl(NamedDecl *D) override {
     return isa<CXXConversionDecl>(D) ? true : visit(D, D->getLocation());
   }
 
-  bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) {
+  bool VisitCXXConstructorDecl(CXXConstructorDecl *CD) override {
     for (const auto *Initializer : CD->inits()) {
       // Ignore implicit initializers.
       if (!Initializer->isWritten())
@@ -61,15 +57,15 @@ class RecursiveSymbolVisitor
 
   // Expression visitors:
 
-  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
+  bool VisitDeclRefExpr(DeclRefExpr *Expr) override {
     return visit(Expr->getFoundDecl(), Expr->getLocation());
   }
 
-  bool VisitMemberExpr(const MemberExpr *Expr) {
+  bool VisitMemberExpr(MemberExpr *Expr) override {
     return visit(Expr->getFoundDecl().getDecl(), Expr->getMemberLoc());
   }
 
-  bool VisitOffsetOfExpr(const OffsetOfExpr *S) {
+  bool VisitOffsetOfExpr(OffsetOfExpr *S) override {
     for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
       const OffsetOfNode &Component = S->getComponent(I);
       if (Component.getKind() == OffsetOfNode::Field) {
@@ -83,7 +79,7 @@ class RecursiveSymbolVisitor
 
   // Other visitors:
 
-  bool VisitTypeLoc(const TypeLoc Loc) {
+  bool VisitTypeLoc(TypeLoc Loc) override {
     const SourceLocation TypeBeginLoc = Loc.getBeginLoc();
     const SourceLocation TypeEndLoc =
         Lexer::getLocForEndOfToken(TypeBeginLoc, 0, SM, LangOpts);
@@ -105,13 +101,13 @@ class RecursiveSymbolVisitor
     return true;
   }
 
-  bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+  bool VisitTypedefTypeLoc(TypedefTypeLoc TL) override {
     const SourceLocation TypeEndLoc =
         Lexer::getLocForEndOfToken(TL.getBeginLoc(), 0, SM, LangOpts);
     return visit(TL.getTypedefNameDecl(), TL.getBeginLoc(), TypeEndLoc);
   }
 
-  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) override {
     // The base visitor will visit NNSL prefixes, so we should only look at
     // the current NNS.
     if (NNS) {
@@ -119,10 +115,10 @@ class RecursiveSymbolVisitor
       if (!visit(ND, NNS.getLocalBeginLoc(), NNS.getLocalEndLoc()))
         return false;
     }
-    return BaseType::TraverseNestedNameSpecifierLoc(NNS);
+    return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNS);
   }
 
-  bool VisitDesignatedInitExpr(const DesignatedInitExpr *E) {
+  bool VisitDesignatedInitExpr(DesignatedInitExpr *E) override {
     for (const DesignatedInitExpr::Designator &D : E->designators()) {
       if (D.isFieldDesignator()) {
         if (const FieldDecl *Decl = D.getFieldDecl()) {
@@ -140,8 +136,7 @@ class RecursiveSymbolVisitor
 
   bool visit(const NamedDecl *ND, SourceLocation BeginLoc,
              SourceLocation EndLoc) {
-    return static_cast<T *>(this)->visitSymbolOccurrence(
-        ND, SourceRange(BeginLoc, EndLoc));
+    return visitSymbolOccurrence(ND, SourceRange(BeginLoc, EndLoc));
   }
   bool visit(const NamedDecl *ND, SourceLocation Loc) {
     return visit(ND, Loc, Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts));
diff --git a/clang/lib/AST/ASTImporterLookupTable.cpp b/clang/lib/AST/ASTImporterLookupTable.cpp
index 307c03404e0121..b7c112540c1c60 100644
--- a/clang/lib/AST/ASTImporterLookupTable.cpp
+++ b/clang/lib/AST/ASTImporterLookupTable.cpp
@@ -13,20 +13,22 @@
 
 #include "clang/AST/ASTImporterLookupTable.h"
 #include "clang/AST/Decl.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "llvm/Support/FormatVariadic.h"
 
 namespace clang {
 
 namespace {
 
-// FIXME: This breaks if we try to use a dynamic visitor,
-// and I have no idea why.
-struct Builder : RecursiveASTVisitor<Builder> {
+struct Builder : DynamicRecursiveASTVisitor {
   ASTImporterLookupTable <
-  Builder(ASTImporterLookupTable &LT) : LT(LT) {}
+  Builder(ASTImporterLookupTable &LT) : LT(LT) {
+    ShouldVisitTemplateInstantiations = true;
+    ShouldVisitImplicitCode = true;
+  }
 
-  bool VisitTypedefNameDecl(TypedefNameDecl *D) {
+  bool VisitTypedefNameDecl(TypedefNameDecl *D) override {
     QualType Ty = D->getUnderlyingType();
     Ty = Ty.getCanonicalType();
     if (const auto *RTy = dyn_cast<RecordType>(Ty)) {
@@ -39,7 +41,7 @@ struct Builder : RecursiveASTVisitor<Builder> {
     return true;
   }
 
-  bool VisitNamedDecl(NamedDecl *D) {
+  bool VisitNamedDecl(NamedDecl *D) override {
     LT.add(D);
     return true;
   }
@@ -48,7 +50,7 @@ struct Builder : RecursiveASTVisitor<Builder> {
   // visitation. However, there are cases when the befriended class is not a
   // child, thus it must be fetched explicitly from the FriendDecl, and only
   // then can we add it to the lookup table.
-  bool VisitFriendDecl(FriendDecl *D) {
+  bool VisitFriendDecl(FriendDecl *D) override {
     if (D->getFriendType()) {
       QualType Ty = D->getFriendType()->getType();
       if (isa<ElaboratedType>(Ty))
@@ -78,10 +80,6 @@ struct Builder : RecursiveASTVisitor<Builder> {
     }
     return true;
   }
-
-  // Override default settings of base.
-  bool shouldVisitTemplateInstantiations() const { return true; }
-  bool shouldVisitImplicitCode() const { return true; }
 };
 
 } // anonymous namespace
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index 866222380974b6..a412d951bb0fbb 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -10,7 +10,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -81,11 +81,8 @@ static std::string getDREAncestorString(const DeclRefExpr *DRE,
 namespace clang::ast_matchers {
 // A `RecursiveASTVisitor` that traverses all descendants of a given node "n"
 // except for those belonging to a different callable of "n".
-class MatchDescendantVisitor
-    : public RecursiveASTVisitor<MatchDescendantVisitor> {
+class MatchDescendantVisitor : public DynamicRecursiveASTVisitor {
 public:
-  typedef RecursiveASTVisitor<MatchDescendantVisitor> VisitorBase;
-
   // Creates an AST visitor that matches `Matcher` on all
   // descendants of a given node "n" except for the ones
   // belonging to a different callable of "n".
@@ -95,7 +92,10 @@ class MatchDescendantVisitor
                          internal::ASTMatchFinder::BindKind Bind,
                          const bool ignoreUnevaluatedContext)
       : Matcher(Matcher), Finder(Finder), Builder(Builder), Bind(Bind),
-        Matches(false), ignoreUnevaluatedContext(ignoreUnevaluatedContext) {}
+        Matches(false), ignoreUnevaluatedContext(ignoreUnevaluatedContext) {
+    ShouldVisitTemplateInstantiations = true;
+    ShouldVisitImplicitCode = false; // TODO: let's ignore implicit code for now
+  }
 
   // Returns true if a match is found in a subtree of `DynNode`, which belongs
   // to the same callable of `DynNode`.
@@ -116,7 +116,7 @@ class MatchDescendantVisitor
   // For the matchers so far used in safe buffers, we only need to match
   // `Stmt`s.  To override more as needed.
 
-  bool TraverseDecl(Decl *Node) {
+  bool TraverseDecl(Decl *Node) override {
     if (!Node)
       return true;
     if (!match(*Node))
@@ -125,63 +125,57 @@ class MatchDescendantVisitor
     if (isa<FunctionDecl, BlockDecl, ObjCMethodDecl>(Node))
       return true;
     // Traverse descendants
-    return VisitorBase::TraverseDecl(Node);
+    return DynamicRecursiveASTVisitor::TraverseDecl(Node);
   }
 
-  bool TraverseGenericSelectionExpr(GenericSelectionExpr *Node) {
+  bool TraverseGenericSelectionExpr(GenericSelectionExpr *Node) override {
     // These are unevaluated, except the result expression.
     if (ignoreUnevaluatedContext)
       return TraverseStmt(Node->getResultExpr());
-    return VisitorBase::TraverseGenericSelectionExpr(Node);
+    return DynamicRecursiveASTVisitor::TraverseGenericSelectionExpr(Node);
   }
 
-  bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) {
+  bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) override {
     // Unevaluated context.
     if (ignoreUnevaluatedContext)
       return true;
-    return VisitorBase::TraverseUnaryExprOrTypeTraitExpr(Node);
+    return DynamicRecursiveASTVisitor::TraverseUnaryExprOrTypeTraitExpr(Node);
   }
 
-  bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) {
+  bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) override {
     // Unevaluated context.
     if (ignoreUnevaluatedContext)
       return true;
-    return VisitorBase::TraverseTypeOfExprTypeLoc(Node);
+    return DynamicRecursiveASTVisitor::TraverseTypeOfExprTypeLoc(Node);
   }
 
-  bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) {
+  bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) override {
     // Unevaluated context.
     if (ignoreUnevaluatedContext)
       return true;
-    return VisitorBase::TraverseDecltypeTypeLoc(Node);
+    return DynamicRecursiveASTVisitor::TraverseDecltypeTypeLoc(Node);
   }
 
-  bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) {
+  bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) override {
     // Unevaluated context.
     if (ignoreUnevaluatedContext)
       return true;
-    return VisitorBase::TraverseCXXNoexceptExpr(Node);
+    return DynamicRecursiveASTVisitor::TraverseCXXNoexceptExpr(Node);
   }
 
-  bool TraverseCXXTypeidExpr(CXXTypeidExpr *Node) {
+  bool TraverseCXXTypeidExpr(CXXTypeidExpr *Node) override {
     // Unevaluated context.
     if (ignoreUnevaluatedContext)
       return true;
-    return VisitorBase::TraverseCXXTypeidExpr(Node);
+    return DynamicRecursiveASTVisitor::TraverseCXXTypeidExpr(Node);
   }
 
-  bool TraverseStmt(Stmt *Node, DataRecursionQueue *Queue = nullptr) {
+  bool TraverseStmt(Stmt *Node, DataRecursionQueue *Queue = nullptr) override {
     if (!Node)
       return true;
     if (!match(*Node))
       return false;
-    return VisitorBase::TraverseStmt(Node);
-  }
-
-  bool shouldVisitTemplateInstantiations() const { return true; }
-  bool shouldVisitImplicitCode() const {
-    // TODO: let's ignore implicit code for now
-    return false;
+    return DynamicRecursiveASTVisitor::TraverseStmt(Node);
   }
 
 private:
diff --git a/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
index ee543e40b46099..c598c33a458ec6 100644
--- a/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
+++ b/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
@@ -12,7 +12,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/Expr.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/TargetInfo.h"
@@ -58,7 +58,7 @@ class PCHContainerGenerator : public ASTConsumer {
   std::shared_ptr<PCHBuffer> Buffer;
 
   /// Visit every type and emit debug info for it.
-  struct DebugTypeVisitor : public RecursiveASTVisitor<DebugTypeVisitor> {
+  struct DebugTypeVisitor : DynamicRecursiveASTVisitor {
     clang::CodeGen::CGDebugInfo &DI;
     ASTContext &Ctx;
     DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx)
@@ -69,13 +69,13 @@ class PCHContainerGenerator : public ASTConsumer {
       return !Ty->isDependentType() && !Ty->isUndeducedType();
     }
 
-    bool VisitImportDecl(ImportDecl *D) {
+    bool VisitImportDecl(ImportDecl *D) override {
       if (!D->getImportedOwningModule())
         DI.EmitImportDecl(*D);
       return true;
     }
 
-    bool VisitTypeDecl(TypeDecl *D) {
+    bool VisitTypeDecl(TypeDecl *D) override {
       // TagDecls may be deferred until after all decls have been merged and we
       // know the complete type. Pure forward declarations will be skipped, but
       // they don't need to be emitted into the module anyway.
@@ -89,14 +89,14 @@ class PCHContainerGenerator : public ASTConsumer {
       return true;
     }
 
-    bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
+    bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) override {
       QualType QualTy(D->getTypeForDecl(), 0);
       if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr()))
         DI.getOrCreateStandaloneType(QualTy, D->getLocation());
       return true;
     }
 
-    bool VisitFunctionDecl(FunctionDecl *D) {
+    bool VisitFunctionDecl(FunctionDecl *D) override {
       // Skip deduction guides.
       if (isa<CXXDeductionGuideDecl>(D))
         return true;
@@ -117,7 +117,7 @@ class PCHContainerGenerator : public ASTConsumer {
       return true;
     }
 
-    bool VisitObjCMethodDecl(ObjCMethodDecl *D) {
+    bool VisitObjCMethodDecl(ObjCMethodDecl *D) override {
       if (!D->getClassInterface())
         return true;
 
diff --git a/clang/lib/Frontend/ASTConsumers.cpp b/clang/lib/Frontend/ASTConsumers.cpp
index 7b58eaa04df95a..5ecd17ad36ada8 100644
--- a/clang/lib/Frontend/ASTConsumers.cpp
+++ b/clang/lib/Frontend/ASTConsumers.cpp
@@ -16,7 +16,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/RecordLayout.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/SourceManager.h"
 #include "llvm/Support/Path.h"
@@ -29,9 +29,7 @@ using namespace clang;
 
 namespace {
   class ASTPrinter : public ASTConsumer,
-                     public RecursiveASTVisitor<ASTPrinter> {
-    typedef RecursiveASTVisitor<ASTPrinter> base;
-
+                     public DynamicRecursiveASTVisitor {
   public:
     enum Kind { DumpFull, Dump, Print, None };
     ASTPrinter(std::unique_ptr<raw_ostream> Out, Kind K,
@@ -39,7 +37,9 @@ namespace {
                bool DumpLookups = false, bool DumpDeclTypes = false)
         : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)),
           OutputKind(K), OutputFormat(Format), FilterString(FilterString),
-          DumpLookups(DumpLookups), DumpDeclTypes(DumpDeclTypes) {}
+          DumpLookups(DumpLookups), DumpDeclTypes(DumpDeclTypes) {
+      ShouldWalkTypesOfTypeLocs = false;
+    }
 
     void HandleTranslationUnit(ASTContext &Context) override {
       TranslationUnitDecl *D = Context.getTranslationUnitDecl();
@@ -50,9 +50,7 @@ namespace {
       TraverseDecl(D);
     }
 
-    bool shouldWalkTypesOfTypeLocs() const { return false; }
-
-    bool TraverseDecl(Decl *D) {
+    bool TraverseDecl(Decl *D) override {
       if (D && filterMatches(D)) {
         bool ShowColors = Out.has_colors();
         if (ShowColors)
@@ -69,7 +67,7 @@ namespace {
         // Don't traverse child nodes to avoid output duplication.
         return true;
       }
-      return base::TraverseDecl(D);
+      return DynamicRecursiveASTVisitor::TraverseDecl(D);
     }
 
   private:
@@ -134,18 +132,18 @@ namespace {
   };
 
   class ASTDeclNodeLister : public ASTConsumer,
-                     public RecursiveASTVisitor<ASTDeclNodeLister> {
+                     public DynamicRecursiveASTVisitor {
   public:
     ASTDeclNodeLister(raw_ostream *Out = nullptr)
-        : Out(Out ? *Out : llvm::outs()) {}
+        : Out(Out ? *Out : llvm::outs()) {
+      ShouldWalkTypesOfTypeLocs = false;
+    }
 
     void HandleTranslationUnit(ASTContext &Context) override {
       TraverseDecl(Context.getTranslationUnitDecl());
     }
 
-    bool shouldWalkTypesOfTypeLocs() const { return false; }
-
-    bool VisitNamedDecl(NamedDecl *D) {
+    bool VisitNamedDecl(NamedDecl *D) override {
       D->printQualifiedName(Out);
       Out << '\n';
       return true;
diff --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp
index b986ccde574525..4f09d0d7a16e8e 100644
--- a/clang/lib/Index/IndexTypeSourceInfo.cpp
+++ b/clang/lib/Index/IndexTypeSourceInfo.cpp
@@ -8,8 +8,9 @@
 
 #include "IndexingContext.h"
 #include "clang/AST/ASTConcept.h"
+#include "clang/AST/DeclObjC.h"
 #include "clang/AST/PrettyPrinter.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/TypeLoc.h"
 #include "llvm/ADT/ScopeExit.h"
 
@@ -18,15 +19,13 @@ using namespace index;
 
 namespace {
 
-class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
+class TypeIndexer : public DynamicRecursiveASTVisitor {
   IndexingContext &IndexCtx;
   const NamedDecl *Parent;
   const DeclContext *ParentDC;
   bool IsBase;
   SmallVector<SymbolRelation, 3> Relations;
 
-  typedef RecursiveASTVisitor<TypeIndexer> base;
-
 public:
   TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
               const DeclContext *DC, bool isBase, bool isIBType)
@@ -39,9 +38,9 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
       assert(Parent);
       Relations.emplace_back((unsigned)SymbolRole::RelationIBTypeOf, Parent);
     }
-  }
 
-  bool shouldWalkTypesOfTypeLocs() const { return false; }
+    ShouldWalkTypesOfTypeLocs = false;
+  }
 
 #define TRY_TO(CALL_EXPR)                                                      \
   do {                                                                         \
@@ -49,14 +48,14 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
       return false;                                                            \
   } while (0)
 
-  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TTPL) {
+  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TTPL) override {
     SourceLocation Loc = TTPL.getNameLoc();
     TemplateTypeParmDecl *TTPD = TTPL.getDecl();
     return IndexCtx.handleReference(TTPD, Loc, Parent, ParentDC,
                                     SymbolRoleSet());
   }
 
-  bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+  bool VisitTypedefTypeLoc(TypedefTypeLoc TL) override {
     SourceLocation Loc = TL.getNameLoc();
     TypedefNameDecl *ND = TL.getTypedefNameDecl();
     if (ND->isTransparentTag()) {
@@ -80,7 +79,7 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
     return true;
   }
 
-  bool VisitAutoTypeLoc(AutoTypeLoc TL) {
+  bool VisitAutoTypeLoc(AutoTypeLoc TL) override {
     if (auto *C = TL.getNamedConcept())
       return IndexCtx.handleReference(C, TL.getConceptNameLoc(), Parent,
                                       ParentDC);
@@ -94,7 +93,7 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
     return true;
   }
 
-  bool TraverseParmVarDecl(ParmVarDecl *D) {
+  bool TraverseParmVarDecl(ParmVarDecl *D) override {
     // Avoid visiting default arguments from the definition that were already
     // visited in the declaration.
     // FIXME: A free function definition can have default arguments.
@@ -107,15 +106,15 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
       }
     }
 
-    return base::TraverseParmVarDecl(D);
+    return DynamicRecursiveASTVisitor::TraverseParmVarDecl(D);
   }
 
-  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) override {
     IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
     return true;
   }
 
-  bool VisitTagTypeLoc(TagTypeLoc TL) {
+  bool VisitTagTypeLoc(TagTypeLoc TL) override {
     TagDecl *D = TL.getDecl();
     if (!IndexCtx.shouldIndexFunctionLocalSymbols() &&
         D->getParentFunctionOrMethod())
@@ -131,12 +130,12 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
                                     Relations);
   }
 
-  bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+  bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) override {
     return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
                                     Parent, ParentDC, SymbolRoleSet(), Relations);
   }
 
-  bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
+  bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) override {
     for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
       IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
                                Parent, ParentDC, SymbolRoleSet(), Relations);
@@ -161,7 +160,7 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
     }
   }
 
-  bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
+  bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) override {
     auto *T = TL.getTypePtr();
     if (!T)
       return true;
@@ -171,7 +170,7 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
     return true;
   }
 
-  bool TraverseTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
+  bool TraverseTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) override {
     if (!WalkUpFromTemplateSpecializationTypeLoc(TL))
       return false;
     if (!TraverseTemplateName(TL.getTypePtr()->getTemplateName()))
@@ -191,7 +190,7 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
     return true;
   }
 
-  bool VisitDeducedTemplateSpecializationTypeLoc(DeducedTemplateSpecializationTypeLoc TL) {
+  bool VisitDeducedTemplateSpecializationTypeLoc(DeducedTemplateSpecializationTypeLoc TL) override {
     auto *T = TL.getTypePtr();
     if (!T)
       return true;
@@ -201,12 +200,12 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
     return true;
   }
 
-  bool VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
+  bool VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) override {
     return IndexCtx.handleReference(TL.getDecl(), TL.getNameLoc(), Parent,
                                     ParentDC, SymbolRoleSet(), Relations);
   }
 
-  bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
+  bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) override {
     const DependentNameType *DNT = TL.getTypePtr();
     const NestedNameSpecifier *NNS = DNT->getQualifier();
     const Type *T = NNS->getAsType();
@@ -234,7 +233,7 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
                                     ParentDC, SymbolRoleSet(), Relations);
   }
 
-  bool TraverseStmt(Stmt *S) {
+  bool TraverseStmt(Stmt *S, DataRecursionQueue* = nullptr) override {
     IndexCtx.indexBody(S, Parent, ParentDC);
     return true;
   }
diff --git a/clang/lib/InstallAPI/Visitor.cpp b/clang/lib/InstallAPI/Visitor.cpp
index a73ea0b0d124c2..6b1951c54fe17c 100644
--- a/clang/lib/InstallAPI/Visitor.cpp
+++ b/clang/lib/InstallAPI/Visitor.cpp
@@ -163,7 +163,7 @@ void InstallAPIVisitor::recordObjCInstanceVariables(
   }
 }
 
-bool InstallAPIVisitor::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
+bool InstallAPIVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
   // Skip forward declaration for classes (@class)
   if (!D->isThisDeclarationADefinition())
     return true;
@@ -195,7 +195,7 @@ bool InstallAPIVisitor::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
   return true;
 }
 
-bool InstallAPIVisitor::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
+bool InstallAPIVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
   StringRef CategoryName = D->getName();
   // Skip over declarations that access could not be collected for.
   auto Access = getAccessForDecl(D);
@@ -213,7 +213,7 @@ bool InstallAPIVisitor::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
   return true;
 }
 
-bool InstallAPIVisitor::VisitVarDecl(const VarDecl *D) {
+bool InstallAPIVisitor::VisitVarDecl(VarDecl *D) {
   // Skip function parameters.
   if (isa<ParmVarDecl>(D))
     return true;
@@ -248,7 +248,7 @@ bool InstallAPIVisitor::VisitVarDecl(const VarDecl *D) {
   return true;
 }
 
-bool InstallAPIVisitor::VisitFunctionDecl(const FunctionDecl *D) {
+bool InstallAPIVisitor::VisitFunctionDecl(FunctionDecl *D) {
   if (const CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(D)) {
     // Skip member function in class templates.
     if (M->getParent()->getDescribedClassTemplate() != nullptr)
@@ -554,7 +554,7 @@ void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D,
   }
 }
 
-bool InstallAPIVisitor::VisitCXXRecordDecl(const CXXRecordDecl *D) {
+bool InstallAPIVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) {
   if (!D->isCompleteDefinition())
     return true;
 
diff --git a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
index 5f7153cd53ac21..ee5c69ef55e598 100644
--- a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
+++ b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
@@ -11,8 +11,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Tooling/ASTDiff/ASTDiff.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/ParentMapContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Lex/Lexer.h"
 #include "llvm/ADT/PriorityQueue.h"
@@ -186,7 +187,7 @@ static bool isNodeExcluded(const SourceManager &SrcMgr, T *N) {
 
 namespace {
 // Sets Height, Parent and Children for each node.
-struct PreorderVisitor : public RecursiveASTVisitor<PreorderVisitor> {
+struct PreorderVisitor : DynamicRecursiveASTVisitor {
   int Id = 0, Depth = 0;
   NodeId Parent;
   SyntaxTree::Impl &Tree;
@@ -228,30 +229,30 @@ struct PreorderVisitor : public RecursiveASTVisitor<PreorderVisitor> {
     for (NodeId Child : N.Children)
       N.Height = std::max(N.Height, 1 + Tree.getNode(Child).Height);
   }
-  bool TraverseDecl(Decl *D) {
+  bool TraverseDecl(Decl *D) override {
     if (isNodeExcluded(Tree.AST.getSourceManager(), D))
       return true;
     auto SavedState = PreTraverse(D);
-    RecursiveASTVisitor<PreorderVisitor>::TraverseDecl(D);
+    DynamicRecursiveASTVisitor::TraverseDecl(D);
     PostTraverse(SavedState);
     return true;
   }
-  bool TraverseStmt(Stmt *S) {
+  bool TraverseStmt(Stmt *S, DataRecursionQueue* = nullptr) override {
     if (auto *E = dyn_cast_or_null<Expr>(S))
       S = E->IgnoreImplicit();
     if (isNodeExcluded(Tree.AST.getSourceManager(), S))
       return true;
     auto SavedState = PreTraverse(S);
-    RecursiveASTVisitor<PreorderVisitor>::TraverseStmt(S);
+    DynamicRecursiveASTVisitor::TraverseStmt(S);
     PostTraverse(SavedState);
     return true;
   }
-  bool TraverseType(QualType T) { return true; }
-  bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
+  bool TraverseType(QualType T) override { return true; }
+  bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override {
     if (isNodeExcluded(Tree.AST.getSourceManager(), Init))
       return true;
     auto SavedState = PreTraverse(Init);
-    RecursiveASTVisitor<PreorderVisitor>::TraverseConstructorInitializer(Init);
+    DynamicRecursiveASTVisitor::TraverseConstructorInitializer(Init);
     PostTraverse(SavedState);
     return true;
   }
diff --git a/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp b/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp
index ac8ad344623cc3..a726990d8ff5f2 100644
--- a/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp
+++ b/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp
@@ -14,7 +14,7 @@
 #include "clang/Tooling/Refactoring/Rename/USRFinder.h"
 #include "clang/AST/AST.h"
 #include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Index/USRGeneration.h"
 #include "clang/Lex/Lexer.h"
@@ -29,8 +29,7 @@ namespace tooling {
 namespace {
 
 /// Recursively visits each AST node to find the symbol underneath the cursor.
-class NamedDeclOccurrenceFindingVisitor
-    : public RecursiveSymbolVisitor<NamedDeclOccurrenceFindingVisitor> {
+class NamedDeclOccurrenceFindingVisitor : public RecursiveSymbolVisitor {
 public:
   // Finds the NamedDecl at a point in the source.
   // \param Point the location in the source to search for the NamedDecl.
@@ -41,7 +40,7 @@ class NamedDeclOccurrenceFindingVisitor
         Point(Point), Context(Context) {}
 
   bool visitSymbolOccurrence(const NamedDecl *ND,
-                             ArrayRef<SourceRange> NameRanges) {
+                             ArrayRef<SourceRange> NameRanges) override {
     if (!ND)
       return true;
     for (const auto &Range : NameRanges) {
@@ -98,14 +97,13 @@ namespace {
 
 /// Recursively visits each NamedDecl node to find the declaration with a
 /// specific name.
-class NamedDeclFindingVisitor
-    : public RecursiveASTVisitor<NamedDeclFindingVisitor> {
+class NamedDeclFindingVisitor : public DynamicRecursiveASTVisitor {
 public:
   explicit NamedDeclFindingVisitor(StringRef Name) : Name(Name) {}
 
   // We don't have to traverse the uses to find some declaration with a
   // specific name, so just visit the named declarations.
-  bool VisitNamedDecl(const NamedDecl *ND) {
+  bool VisitNamedDecl(NamedDecl *ND) override {
     if (!ND)
       return true;
     // Fully qualified name is used to find the declaration.
diff --git a/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp b/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
index 7708fea53d014c..d7a1f761fc3030 100644
--- a/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ b/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -17,7 +17,7 @@
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendAction.h"
@@ -60,10 +60,12 @@ namespace {
 // AdditionalUSRFinder. AdditionalUSRFinder adds USRs of ctor and dtor if given
 // Decl refers to class and adds USRs of all overridden methods if Decl refers
 // to virtual method.
-class AdditionalUSRFinder : public RecursiveASTVisitor<AdditionalUSRFinder> {
+class AdditionalUSRFinder : public DynamicRecursiveASTVisitor {
 public:
   AdditionalUSRFinder(const Decl *FoundDecl, ASTContext &Context)
-      : FoundDecl(FoundDecl), Context(Context) {}
+      : FoundDecl(FoundDecl), Context(Context) {
+    ShouldVisitTemplateInstantiations = true;
+  }
 
   std::vector<std::string> Find() {
     // Fill OverriddenMethods and PartialSpecs storages.
@@ -102,9 +104,8 @@ class AdditionalUSRFinder : public RecursiveASTVisitor<AdditionalUSRFinder> {
     return std::vector<std::string>(USRSet.begin(), USRSet.end());
   }
 
-  bool shouldVisitTemplateInstantiations() const { return true; }
 
-  bool VisitCXXMethodDecl(const CXXMethodDecl *MethodDecl) {
+  bool VisitCXXMethodDecl(CXXMethodDecl *MethodDecl) override {
     if (MethodDecl->isVirtual())
       OverriddenMethods.push_back(MethodDecl);
     if (MethodDecl->getInstantiatedFromMemberFunction())
diff --git a/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp b/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
index c18f9290471fe4..8b60134017724f 100644
--- a/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
+++ b/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
@@ -16,7 +16,7 @@
 #include "clang/Tooling/Refactoring/Rename/USRLocFinder.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ParentMapContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
@@ -52,8 +52,7 @@ bool IsValidEditLoc(const clang::SourceManager& SM, clang::SourceLocation Loc) {
 
 // This visitor recursively searches for all instances of a USR in a
 // translation unit and stores them for later usage.
-class USRLocFindingASTVisitor
-    : public RecursiveSymbolVisitor<USRLocFindingASTVisitor> {
+class USRLocFindingASTVisitor : public RecursiveSymbolVisitor {
 public:
   explicit USRLocFindingASTVisitor(const std::vector<std::string> &USRs,
                                    StringRef PrevName,
@@ -64,7 +63,7 @@ class USRLocFindingASTVisitor
   }
 
   bool visitSymbolOccurrence(const NamedDecl *ND,
-                             ArrayRef<SourceRange> NameRanges) {
+                             ArrayRef<SourceRange> NameRanges) override {
     if (USRSet.find(getUSRForDecl(ND)) != USRSet.end()) {
       assert(NameRanges.size() == 1 &&
              "Multiple name pieces are not supported yet!");
@@ -153,7 +152,7 @@ NestedNameSpecifier *GetNestedNameForType(TypeLoc TL) {
 //
 // This class will traverse the AST and find every AST node whose USR is in the
 // given USRs' set.
-class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
+class RenameLocFinder : public DynamicRecursiveASTVisitor {
 public:
   RenameLocFinder(llvm::ArrayRef<std::string> USRs, ASTContext &Context)
       : USRSet(USRs.begin(), USRs.end()), Context(Context) {}
@@ -179,7 +178,7 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
     bool IgnorePrefixQualifers;
   };
 
-  bool VisitNamedDecl(const NamedDecl *Decl) {
+  bool VisitNamedDecl(NamedDecl *Decl) override {
     // UsingDecl has been handled in other place.
     if (llvm::isa<UsingDecl>(Decl))
       return true;
@@ -212,7 +211,7 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
     return true;
   }
 
-  bool VisitMemberExpr(const MemberExpr *Expr) {
+  bool VisitMemberExpr(MemberExpr *Expr) override {
     const NamedDecl *Decl = Expr->getFoundDecl();
     auto StartLoc = Expr->getMemberLoc();
     auto EndLoc = Expr->getMemberLoc();
@@ -226,7 +225,7 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
     return true;
   }
 
-  bool VisitDesignatedInitExpr(const DesignatedInitExpr *E) {
+  bool VisitDesignatedInitExpr(DesignatedInitExpr *E) override {
     for (const DesignatedInitExpr::Designator &D : E->designators()) {
       if (D.isFieldDesignator()) {
         if (const FieldDecl *Decl = D.getFieldDecl()) {
@@ -245,7 +244,7 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
     return true;
   }
 
-  bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) {
+  bool VisitCXXConstructorDecl(CXXConstructorDecl *CD) override {
     // Fix the constructor initializer when renaming class members.
     for (const auto *Initializer : CD->inits()) {
       // Ignore implicit initializers.
@@ -266,7 +265,7 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
     return true;
   }
 
-  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
+  bool VisitDeclRefExpr(DeclRefExpr *Expr) override {
     const NamedDecl *Decl = Expr->getFoundDecl();
     // Get the underlying declaration of the shadow declaration introduced by a
     // using declaration.
@@ -340,7 +339,7 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
     return true;
   }
 
-  bool VisitUsingDecl(const UsingDecl *Using) {
+  bool VisitUsingDecl(UsingDecl *Using) override {
     for (const auto *UsingShadow : Using->shadows()) {
       if (isInUSRSet(UsingShadow->getTargetDecl())) {
         UsingDecls.push_back(Using);
@@ -369,7 +368,7 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
     return true;
   }
 
-  bool VisitTypeLoc(TypeLoc Loc) {
+  bool VisitTypeLoc(TypeLoc Loc) override {
     auto Parents = Context.getParents(Loc);
     TypeLoc ParentTypeLoc;
     if (!Parents.empty()) {

>From 73fba5085c13e2fe2d154ab552be7482265da311 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 15 Jul 2024 18:46:26 +0200
Subject: [PATCH 13/25] Enable overriding dataTraverseStmtPre/Post

---
 clang/include/clang/AST/DynamicRecursiveASTVisitor.h | 4 ++--
 clang/lib/AST/DynamicRecursiveASTVisitor.cpp         | 5 ++---
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
index a0c7aa2736a7b7..208be2e924025b 100644
--- a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -182,7 +182,7 @@ class DynamicRecursiveASTVisitor {
   bool WalkUpFromType(Type *T) { return VisitType(T); }
   bool WalkUpFromTypeLoc(TypeLoc TL) { return VisitTypeLoc(TL); }
 
-  /*/// Invoked before visiting a statement or expression via data recursion.
+  /// Invoked before visiting a statement or expression via data recursion.
   ///
   /// \returns false to skip visiting the node, true otherwise.
   virtual bool dataTraverseStmtPre(Stmt *S) { return true; }
@@ -192,7 +192,7 @@ class DynamicRecursiveASTVisitor {
   /// returned false.
   ///
   /// \returns false if the visitation was terminated early, true otherwise.
-  virtual bool dataTraverseStmtPost(Stmt *S) { return true; }*/
+  virtual bool dataTraverseStmtPost(Stmt *S) { return true; }
 
   /*// Declare Traverse*() and friends for attributes.
 #define DYNAMIC_ATTR_VISITOR_DECLS
diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
index fb846792f1e6e6..f919067da7e759 100644
--- a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
+++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
@@ -102,9 +102,8 @@ struct Impl : RecursiveASTVisitor<Impl> {
     return Visitor.TraverseNestedNameSpecifierLoc(NNS);
   }
 
-
-  /*bool dataTraverseStmtPre(Stmt *S) { return Visitor.dataTraverseStmtPre(S); }
-  bool dataTraverseStmtPost(Stmt *S) { return Visitor.dataTraverseStmtPost(S); }*/
+  bool dataTraverseStmtPre(Stmt *S) { return Visitor.dataTraverseStmtPre(S); }
+  bool dataTraverseStmtPost(Stmt *S) { return Visitor.dataTraverseStmtPost(S); }
 
   /// Visit a node.
   bool VisitAttr(Attr *A) { return Visitor.VisitAttr(A); }

>From 6f622712b477f76f926cb7846f19dac524aa18e8 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Tue, 23 Jul 2024 16:20:07 +0200
Subject: [PATCH 14/25] Migrate more visitors

---
 .../clang/AST/DynamicRecursiveASTVisitor.h    |  21 ++-
 clang/lib/AST/DynamicRecursiveASTVisitor.cpp  |  27 +++
 clang/lib/ASTMatchers/ASTMatchFinder.cpp      | 156 +++++++++---------
 clang/lib/CodeGen/CodeGenPGO.cpp              |  52 +++---
 .../InterfaceStubFunctionsConsumer.cpp        |   6 +-
 5 files changed, 143 insertions(+), 119 deletions(-)

diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
index 208be2e924025b..e75433f7a8b704 100644
--- a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -19,7 +19,7 @@ class ASTContext;
 ///   - Visiting attributes
 ///   - Post-order traversal
 ///   - Overriding WalkUpFromX
-///   - Overriding dataTraverseStmtPre/Post()
+///   - Overriding getStmtChildren()
 ///
 /// \see RecursiveASTVisitor
 class DynamicRecursiveASTVisitor {
@@ -194,15 +194,24 @@ class DynamicRecursiveASTVisitor {
   /// \returns false if the visitation was terminated early, true otherwise.
   virtual bool dataTraverseStmtPost(Stmt *S) { return true; }
 
+  virtual bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue = nullptr);
+
   /*// Declare Traverse*() and friends for attributes.
 #define DYNAMIC_ATTR_VISITOR_DECLS
 #include "clang/AST/AttrVisitor.inc"
 #undef DYNAMIC_ATTR_VISITOR_DECLS*/
 
+  // Not virtual for now because no-one overrides them.
+#define DEF_TRAVERSE_TMPL_INST(kind)                                           \
+  virtual bool TraverseTemplateInstantiations(kind##TemplateDecl *D);
+  DEF_TRAVERSE_TMPL_INST(Class)
+  DEF_TRAVERSE_TMPL_INST(Var)
+  DEF_TRAVERSE_TMPL_INST(Function)
+#undef DEF_TRAVERSE_TMPL_INST
+
   // Declare Traverse*() for and friends all concrete Decl classes.
 #define ABSTRACT_DECL(DECL)
-#define DECL(CLASS, BASE) \
-  virtual bool Traverse##CLASS##Decl(CLASS##Decl *D);
+#define DECL(CLASS, BASE) virtual bool Traverse##CLASS##Decl(CLASS##Decl *D);
 #include "clang/AST/DeclNodes.inc"
 
 #define DECL(CLASS, BASE)                                                      \
@@ -212,8 +221,7 @@ class DynamicRecursiveASTVisitor {
 
   // Declare Traverse*() and friends for all concrete Stmt classes.
 #define ABSTRACT_STMT(STMT)
-#define STMT(CLASS, PARENT)                                                    \
-  virtual bool Traverse##CLASS(CLASS *S);
+#define STMT(CLASS, PARENT) virtual bool Traverse##CLASS(CLASS *S);
 #include "clang/AST/StmtNodes.inc"
 
 #define STMT(CLASS, PARENT)                                                    \
@@ -223,8 +231,7 @@ class DynamicRecursiveASTVisitor {
 
   // Declare Traverse*() and friends for all concrete Type classes.
 #define ABSTRACT_TYPE(CLASS, BASE)
-#define TYPE(CLASS, BASE)                                                      \
-  virtual bool Traverse##CLASS##Type(CLASS##Type *T);
+#define TYPE(CLASS, BASE) virtual bool Traverse##CLASS##Type(CLASS##Type *T);
 #include "clang/AST/TypeNodes.inc"
 
 #define TYPE(CLASS, BASE)                                                      \
diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
index f919067da7e759..e7f896f4bc56f5 100644
--- a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
+++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
@@ -104,6 +104,9 @@ struct Impl : RecursiveASTVisitor<Impl> {
 
   bool dataTraverseStmtPre(Stmt *S) { return Visitor.dataTraverseStmtPre(S); }
   bool dataTraverseStmtPost(Stmt *S) { return Visitor.dataTraverseStmtPost(S); }
+  bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) {
+    return Visitor.dataTraverseNode(S, Queue);
+  }
 
   /// Visit a node.
   bool VisitAttr(Attr *A) { return Visitor.VisitAttr(A); }
@@ -116,6 +119,15 @@ struct Impl : RecursiveASTVisitor<Impl> {
   #include "clang/AST/AttrVisitor.inc"
   #undef ATTR_VISITOR_DECLS*/
 
+#define DEF_TRAVERSE_TMPL_INST(kind)                                           \
+  bool TraverseTemplateInstantiations(kind##TemplateDecl *D) {                 \
+    return Visitor.TraverseTemplateInstantiations(D);                          \
+  }
+  DEF_TRAVERSE_TMPL_INST(Class)
+  DEF_TRAVERSE_TMPL_INST(Var)
+  DEF_TRAVERSE_TMPL_INST(Function)
+#undef DEF_TRAVERSE_TMPL_INST
+
   // Declarations.
 #define ABSTRACT_DECL(DECL)
 #define DECL(CLASS, BASE)                                                      \
@@ -282,12 +294,27 @@ bool DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(
       NNS);
 }
 
+bool DynamicRecursiveASTVisitor::dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::dataTraverseNode(S, Queue);
+}
+
 /*
 #define DYNAMIC_ATTR_VISITOR_IMPL
 #include "clang/AST/AttrVisitor.inc"
 #undef DYNAMIC_ATTR_VISITOR_IMPL
 */
 
+#define DEF_TRAVERSE_TMPL_INST(kind)                                           \
+  bool DynamicRecursiveASTVisitor::TraverseTemplateInstantiations(             \
+      kind##TemplateDecl *D) {                                                 \
+    return Impl(*this)                                                         \
+        .RecursiveASTVisitor<Impl>::TraverseTemplateInstantiations(D);         \
+  }
+DEF_TRAVERSE_TMPL_INST(Class)
+DEF_TRAVERSE_TMPL_INST(Var)
+DEF_TRAVERSE_TMPL_INST(Function)
+#undef DEF_TRAVERSE_TMPL_INST
+
 // Declare Traverse*() for and friends all concrete Decl classes.
 #define ABSTRACT_DECL(DECL)
 #define DECL(CLASS, BASE)                                                      \
diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index 0bac2ed63a927e..e9c8779972f475 100644
--- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -19,7 +19,7 @@
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/StringMap.h"
@@ -87,11 +87,8 @@ struct MemoizedMatchResult {
 
 // A RecursiveASTVisitor that traverses all children or all descendants of
 // a node.
-class MatchChildASTVisitor
-    : public RecursiveASTVisitor<MatchChildASTVisitor> {
+class MatchChildASTVisitor : public DynamicRecursiveASTVisitor {
 public:
-  typedef RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase;
-
   // Creates an AST visitor that matches 'matcher' on all children or
   // descendants of a traversed node. max_depth is the maximum depth
   // to traverse: use 1 for matching the children and INT_MAX for
@@ -101,8 +98,10 @@ class MatchChildASTVisitor
                        bool IgnoreImplicitChildren,
                        ASTMatchFinder::BindKind Bind)
       : Matcher(Matcher), Finder(Finder), Builder(Builder), CurrentDepth(0),
-        MaxDepth(MaxDepth), IgnoreImplicitChildren(IgnoreImplicitChildren),
-        Bind(Bind), Matches(false) {}
+        MaxDepth(MaxDepth), Bind(Bind), Matches(false) {
+    ShouldVisitTemplateInstantiations = true;
+    ShouldVisitImplicitCode = !IgnoreImplicitChildren;
+  }
 
   // Returns true if a match is found in the subtree rooted at the
   // given AST node. This is done via a set of mutually recursive
@@ -111,7 +110,7 @@ class MatchChildASTVisitor
   //
   //   - Traverse(node) calls BaseTraverse(node) when it needs
   //     to visit the descendants of node.
-  //   - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node))
+  //   - BaseTraverse(node) then calls (via the DynamicRecursiveASTVisitor)
   //     Traverse*(c) for each child c of 'node'.
   //   - Traverse*(c) in turn calls Traverse(c), completing the
   //     recursion.
@@ -151,7 +150,7 @@ class MatchChildASTVisitor
   // The following are overriding methods from the base visitor class.
   // They are public only to allow CRTP to work. They are *not *part
   // of the public API of this class.
-  bool TraverseDecl(Decl *DeclNode) {
+  bool TraverseDecl(Decl *DeclNode) override {
 
     if (DeclNode && DeclNode->isImplicit() &&
         Finder->isTraversalIgnoringImplicitNodes())
@@ -175,7 +174,7 @@ class MatchChildASTVisitor
     return StmtToTraverse;
   }
 
-  bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr) {
+  bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr) override {
     // If we need to keep track of the depth, we can't perform data recursion.
     if (CurrentDepth == 0 || (CurrentDepth <= MaxDepth && MaxDepth < INT_MAX))
       Queue = nullptr;
@@ -185,16 +184,16 @@ class MatchChildASTVisitor
     if (!StmtToTraverse)
       return true;
 
-    if (IgnoreImplicitChildren && isa<CXXDefaultArgExpr>(StmtNode))
+    if (!ShouldVisitImplicitCode && isa<CXXDefaultArgExpr>(StmtNode))
       return true;
 
     if (!match(*StmtToTraverse))
       return false;
-    return VisitorBase::TraverseStmt(StmtToTraverse, Queue);
+    return DynamicRecursiveASTVisitor::TraverseStmt(StmtToTraverse, Queue);
   }
   // We assume that the QualType and the contained type are on the same
   // hierarchy level. Thus, we try to match either of them.
-  bool TraverseType(QualType TypeNode) {
+  bool TraverseType(QualType TypeNode) override {
     if (TypeNode.isNull())
       return true;
     ScopedIncrement ScopedDepth(&CurrentDepth);
@@ -206,7 +205,7 @@ class MatchChildASTVisitor
   }
   // We assume that the TypeLoc, contained QualType and contained Type all are
   // on the same hierarchy level. Thus, we try to match all of them.
-  bool TraverseTypeLoc(TypeLoc TypeLocNode) {
+  bool TraverseTypeLoc(TypeLoc TypeLocNode) override {
     if (TypeLocNode.isNull())
       return true;
     ScopedIncrement ScopedDepth(&CurrentDepth);
@@ -219,11 +218,11 @@ class MatchChildASTVisitor
     // The TypeLoc is matched inside traverse.
     return traverse(TypeLocNode);
   }
-  bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
+  bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) override {
     ScopedIncrement ScopedDepth(&CurrentDepth);
     return (NNS == nullptr) || traverse(*NNS);
   }
-  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) override {
     if (!NNS)
       return true;
     ScopedIncrement ScopedDepth(&CurrentDepth);
@@ -231,19 +230,19 @@ class MatchChildASTVisitor
       return false;
     return traverse(NNS);
   }
-  bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) {
+  bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) override {
     if (!CtorInit)
       return true;
     ScopedIncrement ScopedDepth(&CurrentDepth);
     return traverse(*CtorInit);
   }
-  bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL) {
+  bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc& TAL) override {
     ScopedIncrement ScopedDepth(&CurrentDepth);
     return traverse(TAL);
   }
-  bool TraverseCXXForRangeStmt(CXXForRangeStmt *Node) {
+  bool TraverseCXXForRangeStmt(CXXForRangeStmt *Node) override {
     if (!Finder->isTraversalIgnoringImplicitNodes())
-      return VisitorBase::TraverseCXXForRangeStmt(Node);
+      return DynamicRecursiveASTVisitor::TraverseCXXForRangeStmt(Node);
     if (!Node)
       return true;
     ScopedIncrement ScopedDepth(&CurrentDepth);
@@ -253,22 +252,22 @@ class MatchChildASTVisitor
     if (!match(*Node->getLoopVariable()))
       return false;
     if (match(*Node->getRangeInit()))
-      if (!VisitorBase::TraverseStmt(Node->getRangeInit()))
+      if (!DynamicRecursiveASTVisitor::TraverseStmt(Node->getRangeInit()))
         return false;
     if (!match(*Node->getBody()))
       return false;
-    return VisitorBase::TraverseStmt(Node->getBody());
+    return DynamicRecursiveASTVisitor::TraverseStmt(Node->getBody());
   }
-  bool TraverseCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *Node) {
+  bool TraverseCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *Node) override {
     if (!Finder->isTraversalIgnoringImplicitNodes())
-      return VisitorBase::TraverseCXXRewrittenBinaryOperator(Node);
+      return DynamicRecursiveASTVisitor::TraverseCXXRewrittenBinaryOperator(Node);
     if (!Node)
       return true;
     ScopedIncrement ScopedDepth(&CurrentDepth);
 
     return match(*Node->getLHS()) && match(*Node->getRHS());
   }
-  bool TraverseAttr(Attr *A) {
+  bool TraverseAttr(Attr *A) override {
     if (A == nullptr ||
         (A->isImplicit() &&
          Finder->getASTContext().getParentMapContext().getTraversalKind() ==
@@ -277,9 +276,9 @@ class MatchChildASTVisitor
     ScopedIncrement ScopedDepth(&CurrentDepth);
     return traverse(*A);
   }
-  bool TraverseLambdaExpr(LambdaExpr *Node) {
+  bool TraverseLambdaExpr(LambdaExpr *Node) override {
     if (!Finder->isTraversalIgnoringImplicitNodes())
-      return VisitorBase::TraverseLambdaExpr(Node);
+      return DynamicRecursiveASTVisitor::TraverseLambdaExpr(Node);
     if (!Node)
       return true;
     ScopedIncrement ScopedDepth(&CurrentDepth);
@@ -309,12 +308,9 @@ class MatchChildASTVisitor
     if (!match(*Node->getBody()))
       return false;
 
-    return VisitorBase::TraverseStmt(Node->getBody());
+    return DynamicRecursiveASTVisitor::TraverseStmt(Node->getBody());
   }
 
-  bool shouldVisitTemplateInstantiations() const { return true; }
-  bool shouldVisitImplicitCode() const { return !IgnoreImplicitChildren; }
-
 private:
   // Used for updating the depth during traversal.
   struct ScopedIncrement {
@@ -334,33 +330,33 @@ class MatchChildASTVisitor
   // Forwards the call to the corresponding Traverse*() method in the
   // base visitor class.
   bool baseTraverse(const Decl &DeclNode) {
-    return VisitorBase::TraverseDecl(const_cast<Decl*>(&DeclNode));
+    return DynamicRecursiveASTVisitor::TraverseDecl(const_cast<Decl*>(&DeclNode));
   }
   bool baseTraverse(const Stmt &StmtNode) {
-    return VisitorBase::TraverseStmt(const_cast<Stmt*>(&StmtNode));
+    return DynamicRecursiveASTVisitor::TraverseStmt(const_cast<Stmt*>(&StmtNode));
   }
   bool baseTraverse(QualType TypeNode) {
-    return VisitorBase::TraverseType(TypeNode);
+    return DynamicRecursiveASTVisitor::TraverseType(TypeNode);
   }
   bool baseTraverse(TypeLoc TypeLocNode) {
-    return VisitorBase::TraverseTypeLoc(TypeLocNode);
+    return DynamicRecursiveASTVisitor::TraverseTypeLoc(TypeLocNode);
   }
   bool baseTraverse(const NestedNameSpecifier &NNS) {
-    return VisitorBase::TraverseNestedNameSpecifier(
+    return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifier(
         const_cast<NestedNameSpecifier*>(&NNS));
   }
   bool baseTraverse(NestedNameSpecifierLoc NNS) {
-    return VisitorBase::TraverseNestedNameSpecifierLoc(NNS);
+    return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNS);
   }
   bool baseTraverse(const CXXCtorInitializer &CtorInit) {
-    return VisitorBase::TraverseConstructorInitializer(
+    return DynamicRecursiveASTVisitor::TraverseConstructorInitializer(
         const_cast<CXXCtorInitializer *>(&CtorInit));
   }
   bool baseTraverse(TemplateArgumentLoc TAL) {
-    return VisitorBase::TraverseTemplateArgumentLoc(TAL);
+    return DynamicRecursiveASTVisitor::TraverseTemplateArgumentLoc(TAL);
   }
   bool baseTraverse(const Attr &AttrNode) {
-    return VisitorBase::TraverseAttr(const_cast<Attr *>(&AttrNode));
+    return DynamicRecursiveASTVisitor::TraverseAttr(const_cast<Attr *>(&AttrNode));
   }
 
   // Sets 'Matched' to true if 'Matcher' matches 'Node' and:
@@ -410,19 +406,25 @@ class MatchChildASTVisitor
   BoundNodesTreeBuilder ResultBindings;
   int CurrentDepth;
   const int MaxDepth;
-  const bool IgnoreImplicitChildren;
   const ASTMatchFinder::BindKind Bind;
   bool Matches;
 };
 
 // Controls the outermost traversal of the AST and allows to match multiple
 // matchers.
-class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
+class MatchASTVisitor : public DynamicRecursiveASTVisitor,
                         public ASTMatchFinder {
 public:
   MatchASTVisitor(const MatchFinder::MatchersByType *Matchers,
                   const MatchFinder::MatchFinderOptions &Options)
-      : Matchers(Matchers), Options(Options), ActiveASTContext(nullptr) {}
+      : Matchers(Matchers), Options(Options), ActiveASTContext(nullptr) {
+    ShouldVisitTemplateInstantiations = true;
+    ShouldVisitImplicitCode = true;
+
+    // We visit the lambda body explicitly, so instruct the RAV
+    // to not visit it on our behalf too.
+    ShouldVisitLambdaBody = false;
+  }
 
   ~MatchASTVisitor() override {
     if (Options.CheckProfiling) {
@@ -454,10 +456,7 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
     ActiveASTContext = NewActiveASTContext;
   }
 
-  // The following Visit*() and Traverse*() functions "override"
-  // methods in RecursiveASTVisitor.
-
-  bool VisitTypedefNameDecl(TypedefNameDecl *DeclNode) {
+  bool VisitTypedefNameDecl(TypedefNameDecl *DeclNode) override {
     // When we see 'typedef A B', we add name 'B' to the set of names
     // A's canonical type maps to.  This is necessary for implementing
     // isDerivedFrom(x) properly, where x can be the name of the base
@@ -492,23 +491,23 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
     return true;
   }
 
-  bool VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
+  bool VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) override {
     const ObjCInterfaceDecl *InterfaceDecl = CAD->getClassInterface();
     CompatibleAliases[InterfaceDecl].insert(CAD);
     return true;
   }
 
-  bool TraverseDecl(Decl *DeclNode);
-  bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr);
-  bool TraverseType(QualType TypeNode);
-  bool TraverseTypeLoc(TypeLoc TypeNode);
-  bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
-  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
-  bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit);
-  bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL);
-  bool TraverseAttr(Attr *AttrNode);
+  bool TraverseDecl(Decl *DeclNode) override;
+  bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr) override;
+  bool TraverseType(QualType TypeNode) override;
+  bool TraverseTypeLoc(TypeLoc TypeNode) override;
+  bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) override;
+  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) override;
+  bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) override;
+  bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc& TAL) override;
+  bool TraverseAttr(Attr *AttrNode) override;
 
-  bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) {
+  bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) override {
     if (auto *RF = dyn_cast<CXXForRangeStmt>(S)) {
       {
         ASTNodeNotAsIsSourceScope RAII(this, true);
@@ -589,7 +588,7 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
       TraverseStmt(LE->getBody());
       return true;
     }
-    return RecursiveASTVisitor<MatchASTVisitor>::dataTraverseNode(S, Queue);
+    return DynamicRecursiveASTVisitor::dataTraverseNode(S, Queue);
   }
 
   // Matches children or descendants of 'Node' with 'BaseMatcher'.
@@ -733,13 +732,6 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
   // Implements ASTMatchFinder::getASTContext.
   ASTContext &getASTContext() const override { return *ActiveASTContext; }
 
-  bool shouldVisitTemplateInstantiations() const { return true; }
-  bool shouldVisitImplicitCode() const { return true; }
-
-  // We visit the lambda body explicitly, so instruct the RAV
-  // to not visit it on our behalf too.
-  bool shouldVisitLambdaBody() const { return false; }
-
   bool IsMatchingInASTNodeNotSpelledInSource() const override {
     return TraversingASTNodeNotSpelledInSource;
   }
@@ -754,21 +746,21 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
     return TraversingASTNodeNotAsIs;
   }
 
-  bool TraverseTemplateInstantiations(ClassTemplateDecl *D) {
+  bool TraverseTemplateInstantiations(ClassTemplateDecl *D) override {
     ASTNodeNotSpelledInSourceScope RAII(this, true);
-    return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
+    return DynamicRecursiveASTVisitor::TraverseTemplateInstantiations(
         D);
   }
 
-  bool TraverseTemplateInstantiations(VarTemplateDecl *D) {
+  bool TraverseTemplateInstantiations(VarTemplateDecl *D) override {
     ASTNodeNotSpelledInSourceScope RAII(this, true);
-    return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
+    return DynamicRecursiveASTVisitor::TraverseTemplateInstantiations(
         D);
   }
 
-  bool TraverseTemplateInstantiations(FunctionTemplateDecl *D) {
+  bool TraverseTemplateInstantiations(FunctionTemplateDecl *D) override {
     ASTNodeNotSpelledInSourceScope RAII(this, true);
-    return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
+    return DynamicRecursiveASTVisitor::TraverseTemplateInstantiations(
         D);
   }
 
@@ -1468,7 +1460,7 @@ bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
   ASTChildrenNotSpelledInSourceScope RAII2(this, ScopedChildren);
 
   match(*DeclNode);
-  return RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode);
+  return DynamicRecursiveASTVisitor::TraverseDecl(DeclNode);
 }
 
 bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
@@ -1480,12 +1472,12 @@ bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
 
   ASTNodeNotSpelledInSourceScope RAII(this, ScopedTraversal);
   match(*StmtNode);
-  return RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode, Queue);
+  return DynamicRecursiveASTVisitor::TraverseStmt(StmtNode, Queue);
 }
 
 bool MatchASTVisitor::TraverseType(QualType TypeNode) {
   match(TypeNode);
-  return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode);
+  return DynamicRecursiveASTVisitor::TraverseType(TypeNode);
 }
 
 bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) {
@@ -1496,12 +1488,12 @@ bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) {
   // each TypeLoc.
   match(TypeLocNode);
   match(TypeLocNode.getType());
-  return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(TypeLocNode);
+  return DynamicRecursiveASTVisitor::TraverseTypeLoc(TypeLocNode);
 }
 
 bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
   match(*NNS);
-  return RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifier(NNS);
+  return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifier(NNS);
 }
 
 bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
@@ -1516,7 +1508,7 @@ bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
   if (NNS.hasQualifier())
     match(*NNS.getNestedNameSpecifier());
   return
-      RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS);
+      DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNS);
 }
 
 bool MatchASTVisitor::TraverseConstructorInitializer(
@@ -1534,18 +1526,18 @@ bool MatchASTVisitor::TraverseConstructorInitializer(
 
   match(*CtorInit);
 
-  return RecursiveASTVisitor<MatchASTVisitor>::TraverseConstructorInitializer(
+  return DynamicRecursiveASTVisitor::TraverseConstructorInitializer(
       CtorInit);
 }
 
-bool MatchASTVisitor::TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc) {
+bool MatchASTVisitor::TraverseTemplateArgumentLoc(const TemplateArgumentLoc& Loc) {
   match(Loc);
-  return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateArgumentLoc(Loc);
+  return DynamicRecursiveASTVisitor::TraverseTemplateArgumentLoc(Loc);
 }
 
 bool MatchASTVisitor::TraverseAttr(Attr *AttrNode) {
   match(*AttrNode);
-  return RecursiveASTVisitor<MatchASTVisitor>::TraverseAttr(AttrNode);
+  return DynamicRecursiveASTVisitor::TraverseAttr(AttrNode);
 }
 
 class MatchASTConsumer : public ASTConsumer {
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index ea726b5708a4a1..91aea219e8b6ff 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -13,7 +13,7 @@
 #include "CodeGenPGO.h"
 #include "CodeGenFunction.h"
 #include "CoverageMappingGen.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/StmtVisitor.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/MDBuilder.h"
@@ -158,9 +158,7 @@ static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader,
 }
 
 /// A RecursiveASTVisitor that fills a map of statements to PGO counters.
-struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
-  using Base = RecursiveASTVisitor<MapRegionCounters>;
-
+struct MapRegionCounters : DynamicRecursiveASTVisitor {
   /// The next counter value to assign.
   unsigned NextCounter;
   /// The function hash.
@@ -186,16 +184,16 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
 
   // Blocks and lambdas are handled as separate functions, so we need not
   // traverse them in the parent context.
-  bool TraverseBlockExpr(BlockExpr *BE) { return true; }
-  bool TraverseLambdaExpr(LambdaExpr *LE) {
+  bool TraverseBlockExpr(BlockExpr *BE) override { return true; }
+  bool TraverseLambdaExpr(LambdaExpr *LE) override {
     // Traverse the captures, but not the body.
     for (auto C : zip(LE->captures(), LE->capture_inits()))
       TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));
     return true;
   }
-  bool TraverseCapturedStmt(CapturedStmt *CS) { return true; }
+  bool TraverseCapturedStmt(CapturedStmt *CS) override { return true; }
 
-  bool VisitDecl(const Decl *D) {
+  bool VisitDecl(Decl *D) override {
     switch (D->getKind()) {
     default:
       break;
@@ -237,7 +235,7 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
   SmallVector<const BinaryOperator *, 16> LogOpStack;
 
   // Hook: dataTraverseStmtPre() is invoked prior to visiting an AST Stmt node.
-  bool dataTraverseStmtPre(Stmt *S) {
+  bool dataTraverseStmtPre(Stmt *S) override {
     /// If MC/DC is not enabled, MCDCMaxCond will be set to 0. Do nothing.
     if (MCDCMaxCond == 0)
       return true;
@@ -277,7 +275,7 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
   // Hook: dataTraverseStmtPost() is invoked by the AST visitor after visiting
   // an AST Stmt node.  MC/DC will use it to to signal when the top of a
   // logical operation (boolean expression) nest is encountered.
-  bool dataTraverseStmtPost(Stmt *S) {
+  bool dataTraverseStmtPost(Stmt *S) override {
     /// If MC/DC is not enabled, MCDCMaxCond will be set to 0. Do nothing.
     if (MCDCMaxCond == 0)
       return true;
@@ -330,7 +328,7 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
   /// semantics of the operator. This is only valid for ">= v7" of the profile
   /// version so that we facilitate backward compatibility. In addition, in
   /// order to use MC/DC, count the number of total LHS and RHS conditions.
-  bool VisitBinaryOperator(BinaryOperator *S) {
+  bool VisitBinaryOperator(BinaryOperator *S) override {
     if (S->isLogicalOp()) {
       if (CodeGenFunction::isInstrumentedCondition(S->getLHS()))
         NumCond++;
@@ -342,19 +340,19 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
         NumCond++;
       }
     }
-    return Base::VisitBinaryOperator(S);
+    return DynamicRecursiveASTVisitor::VisitBinaryOperator(S);
   }
 
-  bool VisitConditionalOperator(ConditionalOperator *S) {
+  bool VisitConditionalOperator(ConditionalOperator *S) override {
     if (llvm::EnableSingleByteCoverage && S->getTrueExpr())
       CounterMap[S->getTrueExpr()] = NextCounter++;
     if (llvm::EnableSingleByteCoverage && S->getFalseExpr())
       CounterMap[S->getFalseExpr()] = NextCounter++;
-    return Base::VisitConditionalOperator(S);
+    return DynamicRecursiveASTVisitor::VisitConditionalOperator(S);
   }
 
   /// Include \p S in the function hash.
-  bool VisitStmt(Stmt *S) {
+  bool VisitStmt(Stmt *S) override {
     auto Type = updateCounterMappings(S);
     if (Hash.getHashVersion() != PGO_HASH_V1)
       Type = getHashType(Hash.getHashVersion(), S);
@@ -363,10 +361,10 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
     return true;
   }
 
-  bool TraverseIfStmt(IfStmt *If) {
+  bool TraverseIfStmt(IfStmt *If) override {
     // If we used the V1 hash, use the default traversal.
     if (Hash.getHashVersion() == PGO_HASH_V1)
-      return Base::TraverseIfStmt(If);
+      return DynamicRecursiveASTVisitor::TraverseIfStmt(If);
 
     // When single byte coverage mode is enabled, add a counter to then and
     // else.
@@ -396,7 +394,7 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
     return true;
   }
 
-  bool TraverseWhileStmt(WhileStmt *While) {
+  bool TraverseWhileStmt(WhileStmt *While) override {
     // When single byte coverage mode is enabled, add a counter to condition and
     // body.
     bool NoSingleByteCoverage = !llvm::EnableSingleByteCoverage;
@@ -409,13 +407,13 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
         CounterMap[While->getBody()] = NextCounter++;
     }
 
-    Base::TraverseWhileStmt(While);
+    DynamicRecursiveASTVisitor::TraverseWhileStmt(While);
     if (Hash.getHashVersion() != PGO_HASH_V1)
       Hash.combine(PGOHash::EndOfScope);
     return true;
   }
 
-  bool TraverseDoStmt(DoStmt *Do) {
+  bool TraverseDoStmt(DoStmt *Do) override {
     // When single byte coverage mode is enabled, add a counter to condition and
     // body.
     bool NoSingleByteCoverage = !llvm::EnableSingleByteCoverage;
@@ -428,13 +426,13 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
         CounterMap[Do->getBody()] = NextCounter++;
     }
 
-    Base::TraverseDoStmt(Do);
+    DynamicRecursiveASTVisitor::TraverseDoStmt(Do);
     if (Hash.getHashVersion() != PGO_HASH_V1)
       Hash.combine(PGOHash::EndOfScope);
     return true;
   }
 
-  bool TraverseForStmt(ForStmt *For) {
+  bool TraverseForStmt(ForStmt *For) override {
     // When single byte coverage mode is enabled, add a counter to condition,
     // increment and body.
     bool NoSingleByteCoverage = !llvm::EnableSingleByteCoverage;
@@ -449,13 +447,13 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
         CounterMap[For->getBody()] = NextCounter++;
     }
 
-    Base::TraverseForStmt(For);
+    DynamicRecursiveASTVisitor::TraverseForStmt(For);
     if (Hash.getHashVersion() != PGO_HASH_V1)
       Hash.combine(PGOHash::EndOfScope);
     return true;
   }
 
-  bool TraverseCXXForRangeStmt(CXXForRangeStmt *ForRange) {
+  bool TraverseCXXForRangeStmt(CXXForRangeStmt *ForRange) override {
     // When single byte coverage mode is enabled, add a counter to body.
     bool NoSingleByteCoverage = !llvm::EnableSingleByteCoverage;
     for (Stmt *CS : ForRange->children()) {
@@ -465,7 +463,7 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
         CounterMap[ForRange->getBody()] = NextCounter++;
     }
 
-    Base::TraverseCXXForRangeStmt(ForRange);
+    DynamicRecursiveASTVisitor::TraverseCXXForRangeStmt(ForRange);
     if (Hash.getHashVersion() != PGO_HASH_V1)
       Hash.combine(PGOHash::EndOfScope);
     return true;
@@ -475,8 +473,8 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
 // stability, define a custom traversal which tracks the end of the statement
 // in the hash (provided we're not using the V1 hash).
 #define DEFINE_NESTABLE_TRAVERSAL(N)                                           \
-  bool Traverse##N(N *S) {                                                     \
-    Base::Traverse##N(S);                                                      \
+  bool Traverse##N(N *S) override {                                            \
+    DynamicRecursiveASTVisitor::Traverse##N(S);                                \
     if (Hash.getHashVersion() != PGO_HASH_V1)                                  \
       Hash.combine(PGOHash::EndOfScope);                                       \
     return true;                                                               \
diff --git a/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp b/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp
index d7cfd23bb0a7a6..616f0c9a8241f6 100644
--- a/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp
+++ b/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/Mangle.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendActions.h"
@@ -242,8 +242,8 @@ class InterfaceStubFunctionsConsumer : public ASTConsumer {
       : Instance(Instance), InFile(InFile), Format(Format) {}
 
   void HandleTranslationUnit(ASTContext &context) override {
-    struct Visitor : public RecursiveASTVisitor<Visitor> {
-      bool VisitNamedDecl(NamedDecl *ND) {
+    struct Visitor : DynamicRecursiveASTVisitor {
+      bool VisitNamedDecl(NamedDecl *ND) override {
         if (const auto *FD = dyn_cast<FunctionDecl>(ND))
           if (FD->isLateTemplateParsed()) {
             LateParsedDecls.insert(FD);

>From c756a6599a18cb12f882f5f04737884c28bf8afb Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Tue, 23 Jul 2024 17:50:51 +0200
Subject: [PATCH 15/25] Migrate more visitors, again

---
 clang/docs/RAVFrontendAction.rst              | 17 ++--
 .../CallSuperAttribute/CallSuperAttrInfo.cpp  | 12 +--
 .../PrintFunctionNames/PrintFunctionNames.cpp |  7 +-
 .../clang/AST/DynamicRecursiveASTVisitor.h    |  4 +
 clang/lib/AST/ParentMapContext.cpp            | 42 +++++-----
 clang/lib/Index/IndexBody.cpp                 | 81 +++++++++----------
 6 files changed, 82 insertions(+), 81 deletions(-)

diff --git a/clang/docs/RAVFrontendAction.rst b/clang/docs/RAVFrontendAction.rst
index 2e387b4b339d6c..1e7d88a19f201a 100644
--- a/clang/docs/RAVFrontendAction.rst
+++ b/clang/docs/RAVFrontendAction.rst
@@ -70,10 +70,9 @@ CXXRecordDecl's.
 
 ::
 
-      class FindNamedClassVisitor
-        : public RecursiveASTVisitor<FindNamedClassVisitor> {
+      class FindNamedClassVisitor : public DynamicRecursiveASTVisitor {
       public:
-        bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
+        bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) override {
           // For debugging, dumping the AST nodes will show which nodes are already
           // being visited.
           Declaration->dump();
@@ -91,7 +90,7 @@ can check for a specific qualified name:
 
 ::
 
-      bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
+      bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) override {
         if (Declaration->getQualifiedNameAsString() == "n::m::C")
           Declaration->dump();
         return true;
@@ -122,7 +121,7 @@ locations:
 
 ::
 
-      bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
+      bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) override {
         if (Declaration->getQualifiedNameAsString() == "n::m::C") {
           // getFullLoc uses the ASTContext's SourceManager to resolve the source
           // location and break it up into its line and column parts.
@@ -143,20 +142,20 @@ Now we can combine all of the above into a small example program:
 ::
 
       #include "clang/AST/ASTConsumer.h"
-      #include "clang/AST/RecursiveASTVisitor.h"
+      #include "clang/AST/DynamicRecursiveASTVisitor.h"
+      #include "clang/AST/DeclCXX.h"
       #include "clang/Frontend/CompilerInstance.h"
       #include "clang/Frontend/FrontendAction.h"
       #include "clang/Tooling/Tooling.h"
 
       using namespace clang;
 
-      class FindNamedClassVisitor
-        : public RecursiveASTVisitor<FindNamedClassVisitor> {
+      class FindNamedClassVisitor : public DynamicRecursiveASTVisitor {
       public:
         explicit FindNamedClassVisitor(ASTContext *Context)
           : Context(Context) {}
 
-        bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
+        bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) override {
           if (Declaration->getQualifiedNameAsString() == "n::m::C") {
             FullSourceLoc FullLocation = Context->getFullLoc(Declaration->getBeginLoc());
             if (FullLocation.isValid())
diff --git a/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp b/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp
index 12d4c311586e6f..451506b13ab313 100644
--- a/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp
+++ b/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp
@@ -25,7 +25,7 @@
 
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Attr.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Frontend/FrontendPluginRegistry.h"
 #include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/Sema.h"
@@ -41,13 +41,14 @@ bool isMarkedAsCallSuper(const CXXMethodDecl *D) {
   return MarkedMethods.contains(D);
 }
 
-class MethodUsageVisitor : public RecursiveASTVisitor<MethodUsageVisitor> {
+class MethodUsageVisitor : public DynamicRecursiveASTVisitor {
 public:
   bool IsOverriddenUsed = false;
   explicit MethodUsageVisitor(
       llvm::SmallPtrSet<const CXXMethodDecl *, 16> &MustCalledMethods)
       : MustCalledMethods(MustCalledMethods) {}
-  bool VisitCallExpr(CallExpr *CallExpr) {
+
+  bool VisitCallExpr(CallExpr *CallExpr) override {
     const CXXMethodDecl *Callee = nullptr;
     for (const auto &MustCalled : MustCalledMethods) {
       if (CallExpr->getCalleeDecl() == MustCalled) {
@@ -67,7 +68,7 @@ class MethodUsageVisitor : public RecursiveASTVisitor<MethodUsageVisitor> {
   llvm::SmallPtrSet<const CXXMethodDecl *, 16> &MustCalledMethods;
 };
 
-class CallSuperVisitor : public RecursiveASTVisitor<CallSuperVisitor> {
+class CallSuperVisitor : public DynamicRecursiveASTVisitor {
 public:
   CallSuperVisitor(DiagnosticsEngine &Diags) : Diags(Diags) {
     WarningSuperNotCalled = Diags.getCustomDiagID(
@@ -77,7 +78,8 @@ class CallSuperVisitor : public RecursiveASTVisitor<CallSuperVisitor> {
     NotePreviousCallSuperDeclaration = Diags.getCustomDiagID(
         DiagnosticsEngine::Note, "function marked 'call_super' here");
   }
-  bool VisitCXXMethodDecl(CXXMethodDecl *MethodDecl) {
+
+  bool VisitCXXMethodDecl(CXXMethodDecl *MethodDecl) override {
     if (MethodDecl->isThisDeclarationADefinition() && MethodDecl->hasBody()) {
       // First find out which overridden methods are marked as 'call_super'
       llvm::SmallPtrSet<const CXXMethodDecl *, 16> OverriddenMarkedMethods;
diff --git a/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp b/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp
index b2b785b87c25cf..5100901f74d992 100644
--- a/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp
+++ b/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp
@@ -14,7 +14,7 @@
 #include "clang/Frontend/FrontendPluginRegistry.h"
 #include "clang/AST/AST.h"
 #include "clang/AST/ASTConsumer.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Sema/Sema.h"
 #include "llvm/Support/raw_ostream.h"
@@ -52,11 +52,12 @@ class PrintFunctionsConsumer : public ASTConsumer {
     // The advantage of doing this in HandleTranslationUnit() is that all
     // codegen (when using -add-plugin) is completely finished and this can't
     // affect the compiler output.
-    struct Visitor : public RecursiveASTVisitor<Visitor> {
+    struct Visitor : DynamicRecursiveASTVisitor {
       const std::set<std::string> &ParsedTemplates;
       Visitor(const std::set<std::string> &ParsedTemplates)
           : ParsedTemplates(ParsedTemplates) {}
-      bool VisitFunctionDecl(FunctionDecl *FD) {
+
+      bool VisitFunctionDecl(FunctionDecl *FD) override {
         if (FD->isLateTemplateParsed() &&
             ParsedTemplates.count(FD->getNameAsString()))
           LateParsedDecls.insert(FD);
diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
index e75433f7a8b704..8b89518863540d 100644
--- a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -24,6 +24,7 @@ class ASTContext;
 /// \see RecursiveASTVisitor
 class DynamicRecursiveASTVisitor {
 public:
+  // FIXME: I think we can just get rid of the Queue entirely.
   using DataRecursionQueue =
       SmallVectorImpl<llvm::PointerIntPair<Stmt *, 1, bool>>;
 
@@ -114,6 +115,8 @@ class DynamicRecursiveASTVisitor {
   ///
   /// \returns false if the visitation was terminated early, true
   /// otherwise (including when the argument is nullptr).
+  ///
+  // FIXME: I think we can just get rid of the Queue entirely.
   virtual bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr);
 
   /// Recursively visit a template argument and dispatch to the
@@ -194,6 +197,7 @@ class DynamicRecursiveASTVisitor {
   /// \returns false if the visitation was terminated early, true otherwise.
   virtual bool dataTraverseStmtPost(Stmt *S) { return true; }
 
+  // FIXME: I think we can just get rid of the Queue entirely.
   virtual bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue = nullptr);
 
   /*// Declare Traverse*() and friends for attributes.
diff --git a/clang/lib/AST/ParentMapContext.cpp b/clang/lib/AST/ParentMapContext.cpp
index 9723c0cfa83bbe..eb8a2119afd795 100644
--- a/clang/lib/AST/ParentMapContext.cpp
+++ b/clang/lib/AST/ParentMapContext.cpp
@@ -12,9 +12,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/ParentMapContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/TemplateBase.h"
 
 using namespace clang;
@@ -352,19 +353,14 @@ template <> DynTypedNode createDynTypedNode(const ObjCProtocolLoc &Node) {
 /// traversal - there are other relationships (for example declaration context)
 /// in the AST that are better modeled by special matchers.
 class ParentMapContext::ParentMap::ASTVisitor
-    : public RecursiveASTVisitor<ASTVisitor> {
+    : public DynamicRecursiveASTVisitor {
 public:
-  ASTVisitor(ParentMap &Map) : Map(Map) {}
+  ASTVisitor(ParentMap &Map) : Map(Map) {
+    ShouldVisitTemplateInstantiations = true;
+    ShouldVisitImplicitCode = true;
+  }
 
 private:
-  friend class RecursiveASTVisitor<ASTVisitor>;
-
-  using VisitorBase = RecursiveASTVisitor<ASTVisitor>;
-
-  bool shouldVisitTemplateInstantiations() const { return true; }
-
-  bool shouldVisitImplicitCode() const { return true; }
-
   /// Record the parent of the node we're visiting.
   /// MapNode is the child, the parent is on top of ParentStack.
   /// Parents is the parent storage (either PointerParents or OtherParents).
@@ -427,42 +423,42 @@ class ParentMapContext::ParentMap::ASTVisitor
     return Result;
   }
 
-  bool TraverseDecl(Decl *DeclNode) {
+  bool TraverseDecl(Decl *DeclNode) override {
     return TraverseNode(
-        DeclNode, DeclNode, [&] { return VisitorBase::TraverseDecl(DeclNode); },
+        DeclNode, DeclNode, [&] { return DynamicRecursiveASTVisitor::TraverseDecl(DeclNode); },
         &Map.PointerParents);
   }
-  bool TraverseTypeLoc(TypeLoc TypeLocNode) {
+  bool TraverseTypeLoc(TypeLoc TypeLocNode) override {
     return TraverseNode(
         TypeLocNode, DynTypedNode::create(TypeLocNode),
-        [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); },
+        [&] { return DynamicRecursiveASTVisitor::TraverseTypeLoc(TypeLocNode); },
         &Map.OtherParents);
   }
-  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) {
+  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) override {
     return TraverseNode(
         NNSLocNode, DynTypedNode::create(NNSLocNode),
-        [&] { return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode); },
+        [&] { return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNSLocNode); },
         &Map.OtherParents);
   }
-  bool TraverseAttr(Attr *AttrNode) {
+  bool TraverseAttr(Attr *AttrNode) override {
     return TraverseNode(
-        AttrNode, AttrNode, [&] { return VisitorBase::TraverseAttr(AttrNode); },
+        AttrNode, AttrNode, [&] { return DynamicRecursiveASTVisitor::TraverseAttr(AttrNode); },
         &Map.PointerParents);
   }
-  bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLocNode) {
+  bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLocNode) override {
     return TraverseNode(
         ProtocolLocNode, DynTypedNode::create(ProtocolLocNode),
-        [&] { return VisitorBase::TraverseObjCProtocolLoc(ProtocolLocNode); },
+        [&] { return DynamicRecursiveASTVisitor::TraverseObjCProtocolLoc(ProtocolLocNode); },
         &Map.OtherParents);
   }
 
   // Using generic TraverseNode for Stmt would prevent data-recursion.
-  bool dataTraverseStmtPre(Stmt *StmtNode) {
+  bool dataTraverseStmtPre(Stmt *StmtNode) override {
     addParent(StmtNode, &Map.PointerParents);
     ParentStack.push_back(DynTypedNode::create(*StmtNode));
     return true;
   }
-  bool dataTraverseStmtPost(Stmt *StmtNode) {
+  bool dataTraverseStmtPost(Stmt *StmtNode) override {
     ParentStack.pop_back();
     return true;
   }
diff --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp
index c18daf7faa7497..40f9deffa96292 100644
--- a/clang/lib/Index/IndexBody.cpp
+++ b/clang/lib/Index/IndexBody.cpp
@@ -10,8 +10,10 @@
 #include "clang/AST/ASTConcept.h"
 #include "clang/AST/ASTLambda.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
 #include "clang/AST/ExprConcepts.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
 
 using namespace clang;
@@ -19,41 +21,39 @@ using namespace clang::index;
 
 namespace {
 
-class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
+class BodyIndexer : public DynamicRecursiveASTVisitor {
   IndexingContext &IndexCtx;
   const NamedDecl *Parent;
   const DeclContext *ParentDC;
   SmallVector<Stmt*, 16> StmtStack;
 
-  typedef RecursiveASTVisitor<BodyIndexer> base;
-
   Stmt *getParentStmt() const {
     return StmtStack.size() < 2 ? nullptr : StmtStack.end()[-2];
   }
 public:
   BodyIndexer(IndexingContext &indexCtx,
               const NamedDecl *Parent, const DeclContext *DC)
-    : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
-
-  bool shouldWalkTypesOfTypeLocs() const { return false; }
+    : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) {
+    ShouldWalkTypesOfTypeLocs = false;
+  }
 
-  bool dataTraverseStmtPre(Stmt *S) {
+  bool dataTraverseStmtPre(Stmt *S) override {
     StmtStack.push_back(S);
     return true;
   }
 
-  bool dataTraverseStmtPost(Stmt *S) {
+  bool dataTraverseStmtPost(Stmt *S) override {
     assert(StmtStack.back() == S);
     StmtStack.pop_back();
     return true;
   }
 
-  bool TraverseTypeLoc(TypeLoc TL) {
+  bool TraverseTypeLoc(TypeLoc TL) override {
     IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
     return true;
   }
 
-  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) override {
     IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
     return true;
   }
@@ -137,25 +137,25 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
       Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD);
   }
 
-  bool VisitDeclRefExpr(DeclRefExpr *E) {
+  bool VisitDeclRefExpr(DeclRefExpr *E) override {
     SmallVector<SymbolRelation, 4> Relations;
     SymbolRoleSet Roles = getRolesForRef(E, Relations);
     return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
                                     Parent, ParentDC, Roles, Relations, E);
   }
 
-  bool VisitGotoStmt(GotoStmt *S) {
+  bool VisitGotoStmt(GotoStmt *S) override {
     return IndexCtx.handleReference(S->getLabel(), S->getLabelLoc(), Parent,
                                     ParentDC);
   }
 
-  bool VisitLabelStmt(LabelStmt *S) {
+  bool VisitLabelStmt(LabelStmt *S) override {
     if (IndexCtx.shouldIndexFunctionLocalSymbols())
       return IndexCtx.handleDecl(S->getDecl());
     return true;
   }
 
-  bool VisitMemberExpr(MemberExpr *E) {
+  bool VisitMemberExpr(MemberExpr *E) override {
     SourceLocation Loc = E->getMemberLoc();
     if (Loc.isInvalid())
       Loc = E->getBeginLoc();
@@ -197,14 +197,14 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
                                     Relations, E);
   }
 
-  bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
+  bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) override {
     const DeclarationNameInfo &Info = E->getMemberNameInfo();
     return indexDependentReference(
         E, E->getBaseType().getTypePtrOrNull(), Info,
         [](const NamedDecl *D) { return D->isCXXInstanceMember(); });
   }
 
-  bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
+  bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) override {
     const DeclarationNameInfo &Info = E->getNameInfo();
     const NestedNameSpecifier *NNS = E->getQualifier();
     return indexDependentReference(
@@ -212,7 +212,7 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
         [](const NamedDecl *D) { return !D->isCXXInstanceMember(); });
   }
 
-  bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+  bool VisitDesignatedInitExpr(DesignatedInitExpr *E) override {
     for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
       if (D.isFieldDesignator()) {
         if (const FieldDecl *FD = D.getFieldDecl()) {
@@ -224,14 +224,14 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
     return true;
   }
 
-  bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+  bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) override {
     SmallVector<SymbolRelation, 4> Relations;
     SymbolRoleSet Roles = getRolesForRef(E, Relations);
     return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
                                     Parent, ParentDC, Roles, Relations, E);
   }
 
-  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+  bool VisitObjCMessageExpr(ObjCMessageExpr *E) override {
     auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
       if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
         return false;
@@ -303,7 +303,7 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
     return true;
   }
 
-  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) override {
     if (E->isExplicitProperty()) {
       SmallVector<SymbolRelation, 2> Relations;
       SymbolRoleSet Roles = getRolesForRef(E, Relations);
@@ -328,12 +328,12 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
     return true;
   }
 
-  bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
+  bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) override {
     return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
                                     Parent, ParentDC, SymbolRoleSet(), {}, E);
   }
 
-  bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
+  bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) override {
     return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
                                     Parent, ParentDC, SymbolRoleSet(), {}, E);
   }
@@ -347,28 +347,28 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
                                     Roles, Relations, E);
   }
 
-  bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
+  bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) override {
     if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
       return passObjCLiteralMethodCall(MD, E);
     }
     return true;
   }
 
-  bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
+  bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) override {
     if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
       return passObjCLiteralMethodCall(MD, E);
     }
     return true;
   }
 
-  bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
+  bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) override {
     if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
       return passObjCLiteralMethodCall(MD, E);
     }
     return true;
   }
 
-  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
+  bool VisitCXXConstructExpr(CXXConstructExpr *E) override {
     SymbolRoleSet Roles{};
     SmallVector<SymbolRelation, 2> Relations;
     addCallRole(Roles, Relations);
@@ -376,14 +376,13 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
                                     Parent, ParentDC, Roles, Relations, E);
   }
 
-  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
-                                   DataRecursionQueue *Q = nullptr) {
+  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E) override {
     if (E->getOperatorLoc().isInvalid())
       return true; // implicit.
-    return base::TraverseCXXOperatorCallExpr(E, Q);
+    return DynamicRecursiveASTVisitor::TraverseCXXOperatorCallExpr(E);
   }
 
-  bool VisitDeclStmt(DeclStmt *S) {
+  bool VisitDeclStmt(DeclStmt *S) override {
     if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
       IndexCtx.indexDeclGroupRef(S->getDeclGroup());
       return true;
@@ -402,11 +401,11 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
   }
 
   bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
-                             Expr *Init) {
+                             Expr *Init) override {
     if (C->capturesThis() || C->capturesVLAType())
       return true;
 
-    if (!base::TraverseStmt(Init))
+    if (!DynamicRecursiveASTVisitor::TraverseStmt(Init))
       return false;
 
     if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
@@ -420,10 +419,10 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
   // the things that we visit. Make sure to only visit the semantic form.
   // Also visit things that are in the syntactic form but not the semantic one,
   // for example the indices in DesignatedInitExprs.
-  bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
+  bool TraverseInitListExpr(InitListExpr *S) override {
     auto visitForm = [&](InitListExpr *Form) {
       for (Stmt *SubStmt : Form->children()) {
-        if (!TraverseStmt(SubStmt, Q))
+        if (!TraverseStmt(SubStmt))
           return false;
       }
       return true;
@@ -464,7 +463,7 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
     return true;
   }
 
-  bool VisitOffsetOfExpr(OffsetOfExpr *S) {
+  bool VisitOffsetOfExpr(OffsetOfExpr *S) override {
     for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
       const OffsetOfNode &Component = S->getComponent(I);
       if (Component.getKind() == OffsetOfNode::Field)
@@ -475,7 +474,7 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
     return true;
   }
 
-  bool VisitParmVarDecl(ParmVarDecl* D) {
+  bool VisitParmVarDecl(ParmVarDecl* D) override {
     // Index the parameters of lambda expression and requires expression.
     if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
       const auto *DC = D->getDeclContext();
@@ -485,7 +484,7 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
     return true;
   }
 
-  bool VisitOverloadExpr(OverloadExpr *E) {
+  bool VisitOverloadExpr(OverloadExpr *E) override {
     SmallVector<SymbolRelation, 4> Relations;
     SymbolRoleSet Roles = getRolesForRef(E, Relations);
     for (auto *D : E->decls())
@@ -494,16 +493,16 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
     return true;
   }
 
-  bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *R) {
+  bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *R) override {
     IndexCtx.handleReference(R->getNamedConcept(), R->getConceptNameLoc(),
                              Parent, ParentDC);
     return true;
   }
 
-  bool TraverseTypeConstraint(const TypeConstraint *C) {
+  bool TraverseTypeConstraint(const TypeConstraint *C) override {
     IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(),
                              Parent, ParentDC);
-    return RecursiveASTVisitor::TraverseTypeConstraint(C);
+    return DynamicRecursiveASTVisitor::TraverseTypeConstraint(C);
   }
 };
 

>From 98350fba73bc17242190ab7322ea3d29bcd40f4f Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 19 Aug 2024 17:46:53 +0200
Subject: [PATCH 16/25] [Tests] Refactor most tests to use the dynamic visitor

---
 .../clang/AST/DynamicRecursiveASTVisitor.h    |   2 +
 clang/lib/AST/DynamicRecursiveASTVisitor.cpp  |  16 +-
 clang/unittests/AST/EvaluateAsRValueTest.cpp  |  10 +-
 .../unittests/Analysis/CloneDetectionTest.cpp |   7 +-
 .../unittests/Frontend/FrontendActionTest.cpp |   6 +-
 clang/unittests/Tooling/ASTSelectionTest.cpp  |   4 +-
 clang/unittests/Tooling/CRTPTestVisitor.h     |  42 +++++
 clang/unittests/Tooling/CastExprTest.cpp      |   6 +-
 .../unittests/Tooling/CommentHandlerTest.cpp  |   8 +-
 clang/unittests/Tooling/ExecutionTest.cpp     |  10 +-
 ...exicallyOrderedRecursiveASTVisitorTest.cpp |   5 +-
 clang/unittests/Tooling/LookupTest.cpp        |  10 +-
 clang/unittests/Tooling/QualTypeNamesTest.cpp |   4 +-
 .../RecursiveASTVisitorTestDeclVisitor.cpp    |  18 +--
 ...ecursiveASTVisitorTestPostOrderVisitor.cpp |  12 +-
 .../RecursiveASTVisitorTestTypeLocVisitor.cpp |   4 +-
 .../Tooling/RecursiveASTVisitorTests/Attr.cpp |   4 +-
 .../BitfieldInitializer.cpp                   |   5 +-
 .../CXXBoolLiteralExpr.cpp                    |   5 +-
 .../CXXMemberCall.cpp                         |   5 +-
 .../CXXMethodDecl.cpp                         |  18 +--
 .../CXXOperatorCallExprTraverser.cpp          |   8 +-
 .../CallbacksCommon.h                         |   4 +-
 .../RecursiveASTVisitorTests/Class.cpp        |   5 +-
 .../RecursiveASTVisitorTests/Concept.cpp      | 114 ++++++-------
 .../ConstructExpr.cpp                         |  20 +--
 .../RecursiveASTVisitorTests/DeclRefExpr.cpp  |  17 +-
 .../DeductionGuide.cpp                        |  17 +-
 .../RecursiveASTVisitorTests/ImplicitCtor.cpp |   7 +-
 .../ImplicitCtorInitializer.cpp               |  18 +--
 .../InitListExprPostOrder.cpp                 |   4 +-
 .../InitListExprPostOrderNoQueue.cpp          |   6 +-
 .../InitListExprPreOrder.cpp                  |  15 +-
 .../InitListExprPreOrderNoQueue.cpp           |   7 +-
 .../IntegerLiteral.cpp                        |   5 +-
 .../LambdaDefaultCapture.cpp                  |   5 +-
 .../RecursiveASTVisitorTests/LambdaExpr.cpp   |  19 +--
 .../LambdaTemplateParams.cpp                  |  13 +-
 .../MemberPointerTypeLoc.cpp                  |   7 +-
 .../NestedNameSpecifiers.cpp                  |   7 +-
 .../RecursiveASTVisitorTests/ParenExpr.cpp    |   4 +-
 .../TemplateArgumentLocTraverser.cpp          |   8 +-
 .../TraversalScope.cpp                        |   6 +-
 clang/unittests/Tooling/RefactoringTest.cpp   |  21 ++-
 clang/unittests/Tooling/SourceCodeTest.cpp    |  55 ++++---
 clang/unittests/Tooling/TestVisitor.h         | 150 ++++++++++--------
 46 files changed, 393 insertions(+), 350 deletions(-)
 create mode 100644 clang/unittests/Tooling/CRTPTestVisitor.h

diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
index 8b89518863540d..75d7597c2b7497 100644
--- a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -171,6 +171,8 @@ class DynamicRecursiveASTVisitor {
   virtual bool TraverseConceptTypeRequirement(concepts::TypeRequirement *R);
   virtual bool TraverseConceptExprRequirement(concepts::ExprRequirement *R);
   virtual bool TraverseConceptNestedRequirement(concepts::NestedRequirement *R);
+  virtual bool TraverseConceptReference(ConceptReference *CR);
+  virtual bool VisitConceptReference(ConceptReference *CR) { return true; }
 
   /// Visit a node.
   virtual bool VisitAttr(Attr *A) { return true; }
diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
index e7f896f4bc56f5..fe9b80df3e5477 100644
--- a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
+++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 //
 // This file implements an AST visitor that does not require any template
-// instantiation to allow users to override this behaviour.
+// instantiation to allow users to override its behaviour.
 //
 //===----------------------------------------------------------------------===//
 #include "clang/AST/DynamicRecursiveASTVisitor.h"
@@ -81,6 +81,10 @@ struct Impl : RecursiveASTVisitor<Impl> {
     return Visitor.TraverseConceptNestedRequirement(R);
   }
 
+  bool TraverseConceptReference(ConceptReference *CR) {
+    return Visitor.TraverseConceptReference(CR);
+  }
+
   bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) {
     return Visitor.TraverseCXXBaseSpecifier(Base);
   }
@@ -102,6 +106,10 @@ struct Impl : RecursiveASTVisitor<Impl> {
     return Visitor.TraverseNestedNameSpecifierLoc(NNS);
   }
 
+  bool VisitConceptReference(ConceptReference *CR) {
+    return Visitor.VisitConceptReference(CR);
+  }
+
   bool dataTraverseStmtPre(Stmt *S) { return Visitor.dataTraverseStmtPre(S); }
   bool dataTraverseStmtPost(Stmt *S) { return Visitor.dataTraverseStmtPost(S); }
   bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) {
@@ -271,6 +279,12 @@ bool DynamicRecursiveASTVisitor::TraverseConceptNestedRequirement(
       .RecursiveASTVisitor<Impl>::TraverseConceptNestedRequirement(R);
 }
 
+bool DynamicRecursiveASTVisitor::TraverseConceptReference(
+    ConceptReference *CR) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConceptReference(CR);
+}
+
+
 bool DynamicRecursiveASTVisitor::TraverseCXXBaseSpecifier(
     const CXXBaseSpecifier &Base) {
   return Impl(*this).RecursiveASTVisitor<Impl>::TraverseCXXBaseSpecifier(Base);
diff --git a/clang/unittests/AST/EvaluateAsRValueTest.cpp b/clang/unittests/AST/EvaluateAsRValueTest.cpp
index f6261b827671bc..2645d3c8e05c6b 100644
--- a/clang/unittests/AST/EvaluateAsRValueTest.cpp
+++ b/clang/unittests/AST/EvaluateAsRValueTest.cpp
@@ -13,7 +13,7 @@
 
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Tooling/Tooling.h"
 #include "gtest/gtest.h"
 #include <map>
@@ -28,7 +28,7 @@ typedef std::map<std::string, bool> VarInfoMap;
 
 /// \brief Records information on variable initializers to a map.
 class EvaluateConstantInitializersVisitor
-    : public clang::RecursiveASTVisitor<EvaluateConstantInitializersVisitor> {
+    : public clang::DynamicRecursiveASTVisitor {
  public:
   explicit EvaluateConstantInitializersVisitor(VarInfoMap &VarInfo)
       : VarInfo(VarInfo) {}
@@ -38,7 +38,7 @@ class EvaluateConstantInitializersVisitor
   ///
   /// For each VarDecl with an initializer this also records in VarInfo
   /// whether the initializer could be evaluated as a constant.
-  bool VisitVarDecl(const clang::VarDecl *VD) {
+  bool VisitVarDecl(clang::VarDecl *VD) override {
     if (const clang::Expr *Init = VD->getInit()) {
       clang::Expr::EvalResult Result;
       bool WasEvaluated = Init->EvaluateAsRValue(Result, VD->getASTContext());
@@ -109,9 +109,9 @@ TEST(EvaluateAsRValue, FailsGracefullyForUnknownTypes) {
 }
 
 class CheckLValueToRValueConversionVisitor
-    : public clang::RecursiveASTVisitor<CheckLValueToRValueConversionVisitor> {
+    : public clang::DynamicRecursiveASTVisitor {
 public:
-  bool VisitDeclRefExpr(const clang::DeclRefExpr *E) {
+  bool VisitDeclRefExpr(clang::DeclRefExpr *E) override {
     clang::Expr::EvalResult Result;
     E->EvaluateAsRValue(Result, E->getDecl()->getASTContext(), true);
 
diff --git a/clang/unittests/Analysis/CloneDetectionTest.cpp b/clang/unittests/Analysis/CloneDetectionTest.cpp
index 738f6efd2018d7..1b34ee5d6dde1f 100644
--- a/clang/unittests/Analysis/CloneDetectionTest.cpp
+++ b/clang/unittests/Analysis/CloneDetectionTest.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Analysis/CloneDetection.h"
 #include "clang/Tooling/Tooling.h"
 #include "gtest/gtest.h"
@@ -15,15 +15,14 @@ namespace clang {
 namespace analysis {
 namespace {
 
-class CloneDetectionVisitor
-    : public RecursiveASTVisitor<CloneDetectionVisitor> {
+class CloneDetectionVisitor : public DynamicRecursiveASTVisitor {
 
   CloneDetector &Detector;
 
 public:
   explicit CloneDetectionVisitor(CloneDetector &D) : Detector(D) {}
 
-  bool VisitFunctionDecl(FunctionDecl *D) {
+  bool VisitFunctionDecl(FunctionDecl *D) override {
     Detector.analyzeCodeBody(D);
     return true;
   }
diff --git a/clang/unittests/Frontend/FrontendActionTest.cpp b/clang/unittests/Frontend/FrontendActionTest.cpp
index 818e8cef27e51b..6ce9ba6f6a0888 100644
--- a/clang/unittests/Frontend/FrontendActionTest.cpp
+++ b/clang/unittests/Frontend/FrontendActionTest.cpp
@@ -9,7 +9,7 @@
 #include "clang/Frontend/FrontendAction.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/LangStandard.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/CompilerInvocation.h"
@@ -53,7 +53,7 @@ class TestASTFrontendAction : public ASTFrontendAction {
   }
 
 private:
-  class Visitor : public ASTConsumer, public RecursiveASTVisitor<Visitor> {
+  class Visitor : public ASTConsumer, public DynamicRecursiveASTVisitor {
   public:
     Visitor(CompilerInstance &CI, bool ActOnEndOfTranslationUnit,
             std::vector<std::string> &decl_names) :
@@ -67,7 +67,7 @@ class TestASTFrontendAction : public ASTFrontendAction {
       TraverseDecl(context.getTranslationUnitDecl());
     }
 
-    virtual bool VisitNamedDecl(NamedDecl *Decl) {
+    bool VisitNamedDecl(NamedDecl *Decl) override {
       decl_names_.push_back(Decl->getQualifiedNameAsString());
       return true;
     }
diff --git a/clang/unittests/Tooling/ASTSelectionTest.cpp b/clang/unittests/Tooling/ASTSelectionTest.cpp
index 38b7df8fd564f9..eefbc8cca9029b 100644
--- a/clang/unittests/Tooling/ASTSelectionTest.cpp
+++ b/clang/unittests/Tooling/ASTSelectionTest.cpp
@@ -26,7 +26,7 @@ struct FileLocation {
 
 using FileRange = std::pair<FileLocation, FileLocation>;
 
-class SelectionFinderVisitor : public TestVisitor<SelectionFinderVisitor> {
+class SelectionFinderVisitor : public TestVisitor {
   FileLocation Location;
   std::optional<FileRange> SelectionRange;
   llvm::function_ref<void(SourceRange SelectionRange,
@@ -42,7 +42,7 @@ class SelectionFinderVisitor : public TestVisitor<SelectionFinderVisitor> {
       : Location(Location), SelectionRange(SelectionRange), Consumer(Consumer) {
   }
 
-  bool VisitTranslationUnitDecl(const TranslationUnitDecl *TU) {
+  bool VisitTranslationUnitDecl(TranslationUnitDecl *TU) override {
     const ASTContext &Context = TU->getASTContext();
     const SourceManager &SM = Context.getSourceManager();
 
diff --git a/clang/unittests/Tooling/CRTPTestVisitor.h b/clang/unittests/Tooling/CRTPTestVisitor.h
new file mode 100644
index 00000000000000..67ae36b2e3ddd9
--- /dev/null
+++ b/clang/unittests/Tooling/CRTPTestVisitor.h
@@ -0,0 +1,42 @@
+//===--- TestVisitor.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines a CRTP-based RecursiveASTVisitor helper for tests.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_TOOLING_CRTPTESTVISITOR_H
+#define LLVM_CLANG_UNITTESTS_TOOLING_CRTPTESTVISITOR_H
+
+#include "TestVisitor.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+
+// CRTP versions of the visitors in TestVisitor.h.
+namespace clang {
+template <typename T>
+class CRTPTestVisitor : public RecursiveASTVisitor<T>,
+                        public detail::TestVisitorHelper {
+public:
+  bool shouldVisitTemplateInstantiations() const { return true; }
+  bool shouldVisitImplicitCode() const { return true; }
+
+  void InvokeTraverseDecl(TranslationUnitDecl *D) override {
+    RecursiveASTVisitor<T>::TraverseDecl(D);
+  }
+};
+
+template <typename T>
+class CRTPExpectedLocationVisitor
+    : public CRTPTestVisitor<T>,
+      public detail::ExpectedLocationVisitorHelper {
+  ASTContext *getASTContext() override { return this->Context; }
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_UNITTESTS_TOOLING_CRTPTESTVISITOR_H
diff --git a/clang/unittests/Tooling/CastExprTest.cpp b/clang/unittests/Tooling/CastExprTest.cpp
index eab23a5a98e5d5..e5a8d994bf011b 100644
--- a/clang/unittests/Tooling/CastExprTest.cpp
+++ b/clang/unittests/Tooling/CastExprTest.cpp
@@ -12,17 +12,17 @@ using namespace clang;
 
 namespace {
 
-struct CastExprVisitor : TestVisitor<CastExprVisitor> {
+struct CastExprVisitor : TestVisitor {
   std::function<void(ExplicitCastExpr *)> OnExplicitCast;
   std::function<void(CastExpr *)> OnCast;
 
-  bool VisitExplicitCastExpr(ExplicitCastExpr *Expr) {
+  bool VisitExplicitCastExpr(ExplicitCastExpr *Expr) override {
     if (OnExplicitCast)
       OnExplicitCast(Expr);
     return true;
   }
 
-  bool VisitCastExpr(CastExpr *Expr) {
+  bool VisitCastExpr(CastExpr *Expr) override {
     if (OnCast)
       OnCast(Expr);
     return true;
diff --git a/clang/unittests/Tooling/CommentHandlerTest.cpp b/clang/unittests/Tooling/CommentHandlerTest.cpp
index 7eb11ccd6ee2d1..d7184b08076d80 100644
--- a/clang/unittests/Tooling/CommentHandlerTest.cpp
+++ b/clang/unittests/Tooling/CommentHandlerTest.cpp
@@ -22,12 +22,10 @@ struct Comment {
 class CommentVerifier;
 typedef std::vector<Comment> CommentList;
 
-class CommentHandlerVisitor : public TestVisitor<CommentHandlerVisitor>,
+class CommentHandlerVisitor : public TestVisitor,
                               public CommentHandler {
-  typedef TestVisitor<CommentHandlerVisitor> base;
-
 public:
-  CommentHandlerVisitor() : base(), PP(nullptr), Verified(false) {}
+  CommentHandlerVisitor() : PP(nullptr), Verified(false) {}
 
   ~CommentHandlerVisitor() override {
     EXPECT_TRUE(Verified) << "CommentVerifier not accessed";
@@ -64,7 +62,7 @@ class CommentHandlerVisitor : public TestVisitor<CommentHandlerVisitor>,
   CommentList Comments;
   bool Verified;
 
-  class CommentHandlerAction : public base::TestAction {
+  class CommentHandlerAction : public TestAction {
   public:
     CommentHandlerAction(CommentHandlerVisitor *Visitor)
         : TestAction(Visitor) { }
diff --git a/clang/unittests/Tooling/ExecutionTest.cpp b/clang/unittests/Tooling/ExecutionTest.cpp
index 91ab8594f6823d..1bfe6293f3f27b 100644
--- a/clang/unittests/Tooling/ExecutionTest.cpp
+++ b/clang/unittests/Tooling/ExecutionTest.cpp
@@ -9,7 +9,7 @@
 #include "clang/Tooling/Execution.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/DeclCXX.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/Frontend/FrontendAction.h"
 #include "clang/Frontend/FrontendActions.h"
@@ -32,10 +32,8 @@ namespace {
 // each function declaration.
 class ASTConsumerWithResult
     : public ASTConsumer,
-      public RecursiveASTVisitor<ASTConsumerWithResult> {
+      public DynamicRecursiveASTVisitor {
 public:
-  using ASTVisitor = RecursiveASTVisitor<ASTConsumerWithResult>;
-
   explicit ASTConsumerWithResult(ExecutionContext *Context) : Context(Context) {
     assert(Context != nullptr);
   }
@@ -44,12 +42,12 @@ class ASTConsumerWithResult
     TraverseDecl(Context.getTranslationUnitDecl());
   }
 
-  bool TraverseFunctionDecl(clang::FunctionDecl *Decl) {
+  bool TraverseFunctionDecl(clang::FunctionDecl *Decl) override {
     Context->reportResult(Decl->getNameAsString(),
                           Context->getRevision() + ":" + Context->getCorpus() +
                               ":" + Context->getCurrentCompilationUnit() +
                               "/1");
-    return ASTVisitor::TraverseFunctionDecl(Decl);
+    return DynamicRecursiveASTVisitor::TraverseFunctionDecl(Decl);
   }
 
 private:
diff --git a/clang/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp b/clang/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp
index 5d16595aec8014..b167eb4b811755 100644
--- a/clang/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp
+++ b/clang/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp
@@ -44,13 +44,14 @@ class LexicallyOrderedDeclVisitor
   llvm::SmallVector<Decl *, 8> TraversalStack;
 };
 
-class DummyMatchVisitor : public ExpectedLocationVisitor<DummyMatchVisitor> {
+class DummyMatchVisitor : public ExpectedLocationVisitor {
   bool EmitDeclIndices, EmitStmtIndices;
 
 public:
   DummyMatchVisitor(bool EmitDeclIndices = false, bool EmitStmtIndices = false)
       : EmitDeclIndices(EmitDeclIndices), EmitStmtIndices(EmitStmtIndices) {}
-  bool VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
+
+  bool VisitTranslationUnitDecl(TranslationUnitDecl *TU) override {
     const ASTContext &Context = TU->getASTContext();
     const SourceManager &SM = Context.getSourceManager();
     LexicallyOrderedDeclVisitor SubVisitor(*this, SM, EmitDeclIndices,
diff --git a/clang/unittests/Tooling/LookupTest.cpp b/clang/unittests/Tooling/LookupTest.cpp
index 2cf5ebb2a4cbd0..acd1714a26e071 100644
--- a/clang/unittests/Tooling/LookupTest.cpp
+++ b/clang/unittests/Tooling/LookupTest.cpp
@@ -13,31 +13,31 @@
 using namespace clang;
 
 namespace {
-struct GetDeclsVisitor : TestVisitor<GetDeclsVisitor> {
+struct GetDeclsVisitor : TestVisitor {
   std::function<void(CallExpr *)> OnCall;
   std::function<void(RecordTypeLoc)> OnRecordTypeLoc;
   std::function<void(UsingTypeLoc)> OnUsingTypeLoc;
   SmallVector<Decl *, 4> DeclStack;
 
-  bool VisitCallExpr(CallExpr *Expr) {
+  bool VisitCallExpr(CallExpr *Expr) override {
     if (OnCall)
       OnCall(Expr);
     return true;
   }
 
-  bool VisitRecordTypeLoc(RecordTypeLoc Loc) {
+  bool VisitRecordTypeLoc(RecordTypeLoc Loc) override {
     if (OnRecordTypeLoc)
       OnRecordTypeLoc(Loc);
     return true;
   }
 
-  bool VisitUsingTypeLoc(UsingTypeLoc Loc) {
+  bool VisitUsingTypeLoc(UsingTypeLoc Loc) override {
     if (OnUsingTypeLoc)
       OnUsingTypeLoc(Loc);
     return true;
   }
 
-  bool TraverseDecl(Decl *D) {
+  bool TraverseDecl(Decl *D) override {
     DeclStack.push_back(D);
     bool Ret = TestVisitor::TraverseDecl(D);
     DeclStack.pop_back();
diff --git a/clang/unittests/Tooling/QualTypeNamesTest.cpp b/clang/unittests/Tooling/QualTypeNamesTest.cpp
index 686d189cf69eb2..5ded64d4fcc8c5 100644
--- a/clang/unittests/Tooling/QualTypeNamesTest.cpp
+++ b/clang/unittests/Tooling/QualTypeNamesTest.cpp
@@ -11,12 +11,12 @@
 using namespace clang;
 
 namespace {
-struct TypeNameVisitor : TestVisitor<TypeNameVisitor> {
+struct TypeNameVisitor : TestVisitor {
   llvm::StringMap<std::string> ExpectedQualTypeNames;
   bool WithGlobalNsPrefix = false;
 
   // ValueDecls are the least-derived decl with both a qualtype and a name.
-  bool VisitValueDecl(const ValueDecl *VD) {
+  bool VisitValueDecl(ValueDecl *VD) override {
     std::string ExpectedName =
         ExpectedQualTypeNames.lookup(VD->getNameAsString());
     if (ExpectedName != "") {
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp
index e207f03971ad2f..ccd3048b820efd 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp
@@ -12,9 +12,9 @@ using namespace clang;
 
 namespace {
 
-class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> {
+class VarDeclVisitor : public ExpectedLocationVisitor {
 public:
- bool VisitVarDecl(VarDecl *Variable) {
+ bool VisitVarDecl(VarDecl *Variable) override {
    Match(Variable->getNameAsString(), Variable->getBeginLoc());
    return true;
  }
@@ -29,12 +29,13 @@ TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) {
     VarDeclVisitor::Lang_CXX11));
 }
 
-class ParmVarDeclVisitorForImplicitCode :
-  public ExpectedLocationVisitor<ParmVarDeclVisitorForImplicitCode> {
+class ParmVarDeclVisitorForImplicitCode : public ExpectedLocationVisitor {
 public:
-  bool shouldVisitImplicitCode() const { return true; }
+  ParmVarDeclVisitorForImplicitCode() {
+    ShouldVisitImplicitCode = true;
+  }
 
-  bool VisitParmVarDecl(ParmVarDecl *ParamVar) {
+  bool VisitParmVarDecl(ParmVarDecl *ParamVar) override {
     Match(ParamVar->getNameAsString(), ParamVar->getBeginLoc());
     return true;
   }
@@ -58,10 +59,9 @@ TEST(RecursiveASTVisitor, VisitsParmVarDeclForImplicitCode) {
     "void bar(Y a) {Y b = a;}"));
 }
 
-class NamedDeclVisitor
-  : public ExpectedLocationVisitor<NamedDeclVisitor> {
+class NamedDeclVisitor : public ExpectedLocationVisitor {
 public:
-  bool VisitNamedDecl(NamedDecl *Decl) {
+  bool VisitNamedDecl(NamedDecl *Decl) override {
     std::string NameWithTemplateArgs;
     llvm::raw_string_ostream OS(NameWithTemplateArgs);
     Decl->getNameForDiagnostic(OS,
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp
index 8ac0604c09110a..e2942bf8a11a51 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp
@@ -11,14 +11,18 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "TestVisitor.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+#include <CRTPTestVisitor.h>
 
 using namespace clang;
 
 namespace {
-
-class RecordingVisitor : public TestVisitor<RecordingVisitor> {
-
+class RecordingVisitor : public CRTPTestVisitor<RecordingVisitor> {
   bool VisitPostOrder;
 
 public:
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp
index a21186265db6a9..eec628ca396417 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp
@@ -12,9 +12,9 @@ using namespace clang;
 
 namespace {
 
-class TypeLocVisitor : public ExpectedLocationVisitor<TypeLocVisitor> {
+class TypeLocVisitor : public ExpectedLocationVisitor {
 public:
-  bool VisitTypeLoc(TypeLoc TypeLocation) {
+  bool VisitTypeLoc(TypeLoc TypeLocation) override {
     Match(TypeLocation.getType().getAsString(), TypeLocation.getBeginLoc());
     return true;
   }
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp
index 022ef8b8322868..bbec767ae60896 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "TestVisitor.h"
+#include "CRTPTestVisitor.h"
 
 using namespace clang;
 
@@ -14,7 +14,7 @@ namespace {
 
 // Check to ensure that attributes and expressions within them are being
 // visited.
-class AttrVisitor : public ExpectedLocationVisitor<AttrVisitor> {
+class AttrVisitor : public CRTPExpectedLocationVisitor<AttrVisitor> {
 public:
   bool VisitMemberExpr(MemberExpr *ME) {
     Match(ME->getMemberDecl()->getNameAsString(), ME->getBeginLoc());
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/BitfieldInitializer.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/BitfieldInitializer.cpp
index c11e726fe85528..c1217179768ac2 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/BitfieldInitializer.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/BitfieldInitializer.cpp
@@ -14,10 +14,9 @@ using namespace clang;
 namespace {
 
 // Check to ensure that bitfield initializers are visited.
-class BitfieldInitializerVisitor
-    : public ExpectedLocationVisitor<BitfieldInitializerVisitor> {
+class BitfieldInitializerVisitor : public ExpectedLocationVisitor {
 public:
-  bool VisitIntegerLiteral(IntegerLiteral *IL) {
+  bool VisitIntegerLiteral(IntegerLiteral *IL) override {
     Match(std::to_string(IL->getValue().getSExtValue()), IL->getLocation());
     return true;
   }
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp
index 1fb192dcda0863..4b0c4c31f2dd2e 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp
@@ -12,10 +12,9 @@ using namespace clang;
 
 namespace {
 
-class CXXBoolLiteralExprVisitor 
-  : public ExpectedLocationVisitor<CXXBoolLiteralExprVisitor> {
+class CXXBoolLiteralExprVisitor : public ExpectedLocationVisitor {
 public:
-  bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) {
+  bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) override {
     if (BE->getValue())
       Match("true", BE->getLocation());
     else
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp
index c7b31e06e0e8e9..fe95e8987a73a1 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp
@@ -12,10 +12,9 @@ using namespace clang;
 
 namespace {
 
-class CXXMemberCallVisitor
-  : public ExpectedLocationVisitor<CXXMemberCallVisitor> {
+class CXXMemberCallVisitor : public ExpectedLocationVisitor {
 public:
-  bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) {
+  bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) override {
     Match(Call->getMethodDecl()->getQualifiedNameAsString(),
           Call->getBeginLoc());
     return true;
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp
index 90fa84bd448124..1eeb3df81a3168 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp
@@ -13,25 +13,21 @@ using namespace clang;
 
 namespace {
 
-class CXXMethodDeclVisitor
-    : public ExpectedLocationVisitor<CXXMethodDeclVisitor> {
+class CXXMethodDeclVisitor : public ExpectedLocationVisitor {
 public:
-  CXXMethodDeclVisitor(bool VisitImplicitCode)
-      : VisitImplicitCode(VisitImplicitCode) {}
-
-  bool shouldVisitImplicitCode() const { return VisitImplicitCode; }
+  CXXMethodDeclVisitor(bool VisitImplicitCode) {
+    ShouldVisitImplicitCode = VisitImplicitCode;
+  }
 
-  bool VisitDeclRefExpr(DeclRefExpr *D) {
+  bool VisitDeclRefExpr(DeclRefExpr *D) override {
     Match("declref", D->getLocation());
     return true;
   }
-  bool VisitParmVarDecl(ParmVarDecl *P) {
+
+  bool VisitParmVarDecl(ParmVarDecl *P) override {
     Match("parm", P->getLocation());
     return true;
   }
-
-private:
-  bool VisitImplicitCode;
 };
 
 TEST(RecursiveASTVisitor, CXXMethodDeclNoDefaultBodyVisited) {
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp
index 376874eb351de1..46686199c05d4e 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp
@@ -12,15 +12,13 @@ using namespace clang;
 
 namespace {
 
-class CXXOperatorCallExprTraverser
-  : public ExpectedLocationVisitor<CXXOperatorCallExprTraverser> {
+class CXXOperatorCallExprTraverser : public ExpectedLocationVisitor {
 public:
   // Use Traverse, not Visit, to check that data recursion optimization isn't
   // bypassing the call of this function.
-  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {
+  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) override {
     Match(getOperatorSpelling(CE->getOperator()), CE->getExprLoc());
-    return ExpectedLocationVisitor<CXXOperatorCallExprTraverser>::
-        TraverseCXXOperatorCallExpr(CE);
+    return ExpectedLocationVisitor::TraverseCXXOperatorCallExpr(CE);
   }
 };
 
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCommon.h b/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCommon.h
index 92e30c2d46e5fa..355ecfb452e7e8 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCommon.h
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCommon.h
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "TestVisitor.h"
+#include "CRTPTestVisitor.h"
 
 using namespace clang;
 
@@ -21,7 +21,7 @@ enum class ShouldTraversePostOrder : bool {
 /// sequence of calls to user-defined callbacks like Traverse*(), WalkUp*(),
 /// Visit*().
 template <typename Derived>
-class RecordingVisitorBase : public TestVisitor<Derived> {
+class RecordingVisitorBase : public CRTPTestVisitor<Derived> {
   ShouldTraversePostOrder ShouldTraversePostOrderValue;
 
 public:
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp
index 3ea5abd46a1eca..90953c66f6edf3 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp
@@ -14,10 +14,11 @@ namespace {
 
 // Checks for lambda classes that are not marked as implicitly-generated.
 // (There should be none.)
-class ClassVisitor : public ExpectedLocationVisitor<ClassVisitor> {
+class ClassVisitor : public ExpectedLocationVisitor {
 public:
   ClassVisitor() : SawNonImplicitLambdaClass(false) {}
-  bool VisitCXXRecordDecl(CXXRecordDecl* record) {
+
+  bool VisitCXXRecordDecl(CXXRecordDecl* record) override {
     if (record->isLambda() && !record->isImplicit())
       SawNonImplicitLambdaClass = true;
     return true;
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp
index 6a8d91672f1d93..3c8781d28e54d3 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp
@@ -16,78 +16,84 @@ using namespace clang;
 
 namespace {
 
-struct ConceptVisitor : ExpectedLocationVisitor<ConceptVisitor> {
-  bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
+struct ConceptVisitor : ExpectedLocationVisitor {
+  ConceptVisitor(bool VisitImplicitCode = false) {
+    ShouldVisitImplicitCode = VisitImplicitCode;
+  }
+
+  bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) override {
     ++ConceptSpecializationExprsVisited;
     return true;
   }
-  bool TraverseTypeConstraint(const TypeConstraint *C) {
+  bool TraverseTypeConstraint(const TypeConstraint *C) override {
     ++TypeConstraintsTraversed;
     return ExpectedLocationVisitor::TraverseTypeConstraint(C);
   }
-  bool TraverseConceptRequirement(concepts::Requirement *R) {
+  bool TraverseConceptRequirement(concepts::Requirement *R) override {
     ++ConceptRequirementsTraversed;
     return ExpectedLocationVisitor::TraverseConceptRequirement(R);
   }
-  bool TraverseConceptReference(ConceptReference *CR) {
+  bool TraverseConceptReference(ConceptReference *CR) override {
     ++ConceptReferencesTraversed;
     return ExpectedLocationVisitor::TraverseConceptReference(CR);
   }
-  bool VisitConceptReference(ConceptReference *CR) {
+  bool VisitConceptReference(ConceptReference *CR) override {
     ++ConceptReferencesVisited;
     return true;
   }
 
-  bool shouldVisitImplicitCode() { return ShouldVisitImplicitCode; }
-
   int ConceptSpecializationExprsVisited = 0;
   int TypeConstraintsTraversed = 0;
   int ConceptRequirementsTraversed = 0;
   int ConceptReferencesTraversed = 0;
   int ConceptReferencesVisited = 0;
-  bool ShouldVisitImplicitCode = false;
 };
 
 TEST(RecursiveASTVisitor, Concepts) {
-  ConceptVisitor Visitor;
-  Visitor.ShouldVisitImplicitCode = true;
-  EXPECT_TRUE(Visitor.runOver("template <typename T> concept Fooable = true;\n"
-                              "template <Fooable T> void bar(T);",
-                              ConceptVisitor::Lang_CXX2a));
-  // Check that we traverse the "Fooable T" template parameter's
-  // TypeConstraint's ImmediatelyDeclaredConstraint, which is a
-  // ConceptSpecializationExpr.
-  EXPECT_EQ(1, Visitor.ConceptSpecializationExprsVisited);
-  // Also check we traversed the TypeConstraint that produced the expr.
-  EXPECT_EQ(1, Visitor.TypeConstraintsTraversed);
-  EXPECT_EQ(1, Visitor.ConceptReferencesTraversed);
-  EXPECT_EQ(1, Visitor.ConceptReferencesVisited);
+  {
+    ConceptVisitor Visitor{true};
+    EXPECT_TRUE(Visitor.runOver("template <typename T> concept Fooable = true;\n"
+                                "template <Fooable T> void bar(T);",
+                                ConceptVisitor::Lang_CXX2a));
+    // Check that we traverse the "Fooable T" template parameter's
+    // TypeConstraint's ImmediatelyDeclaredConstraint, which is a
+    // ConceptSpecializationExpr.
+    EXPECT_EQ(1, Visitor.ConceptSpecializationExprsVisited);
+    // Also check we traversed the TypeConstraint that produced the expr.
+    EXPECT_EQ(1, Visitor.TypeConstraintsTraversed);
+    EXPECT_EQ(1, Visitor.ConceptReferencesTraversed);
+    EXPECT_EQ(1, Visitor.ConceptReferencesVisited);
+  }
 
-  Visitor = {}; // Don't visit implicit code now.
-  EXPECT_TRUE(Visitor.runOver("template <typename T> concept Fooable = true;\n"
-                              "template <Fooable T> void bar(T);",
-                              ConceptVisitor::Lang_CXX2a));
-  // Check that we only visit the TypeConstraint, but not the implicitly
-  // generated immediately declared expression.
-  EXPECT_EQ(0, Visitor.ConceptSpecializationExprsVisited);
-  EXPECT_EQ(1, Visitor.TypeConstraintsTraversed);
-  EXPECT_EQ(1, Visitor.ConceptReferencesTraversed);
-  EXPECT_EQ(1, Visitor.ConceptReferencesVisited);
+  {
+    ConceptVisitor Visitor; // Don't visit implicit code now.
+    EXPECT_TRUE(Visitor.runOver("template <typename T> concept Fooable = true;\n"
+                                "template <Fooable T> void bar(T);",
+                                ConceptVisitor::Lang_CXX2a));
+    // Check that we only visit the TypeConstraint, but not the implicitly
+    // generated immediately declared expression.
+    EXPECT_EQ(0, Visitor.ConceptSpecializationExprsVisited);
+    EXPECT_EQ(1, Visitor.TypeConstraintsTraversed);
+    EXPECT_EQ(1, Visitor.ConceptReferencesTraversed);
+    EXPECT_EQ(1, Visitor.ConceptReferencesVisited);
+  }
 
-  Visitor = {};
-  EXPECT_TRUE(Visitor.runOver("template <class T> concept A = true;\n"
-                              "template <class T> struct vector {};\n"
-                              "template <class T> concept B = requires(T x) {\n"
-                              "  typename vector<T*>;\n"
-                              "  {x} -> A;\n"
-                              "  requires true;\n"
-                              "};",
-                              ConceptVisitor::Lang_CXX2a));
-  EXPECT_EQ(3, Visitor.ConceptRequirementsTraversed);
-  EXPECT_EQ(1, Visitor.ConceptReferencesTraversed);
-  EXPECT_EQ(1, Visitor.ConceptReferencesVisited);
+  {
+    ConceptVisitor Visitor;
+    EXPECT_TRUE(Visitor.runOver("template <class T> concept A = true;\n"
+                                "template <class T> struct vector {};\n"
+                                "template <class T> concept B = requires(T x) {\n"
+                                "  typename vector<T*>;\n"
+                                "  {x} -> A;\n"
+                                "  requires true;\n"
+                                "};",
+                                ConceptVisitor::Lang_CXX2a));
+    EXPECT_EQ(3, Visitor.ConceptRequirementsTraversed);
+    EXPECT_EQ(1, Visitor.ConceptReferencesTraversed);
+    EXPECT_EQ(1, Visitor.ConceptReferencesVisited);
+  }
 
-  Visitor = {};
+  ConceptVisitor Visitor;
   llvm::StringRef Code =
       R"cpp(
 template<typename T> concept True = false;
@@ -107,34 +113,36 @@ struct Foo<F>  {};
   EXPECT_EQ(2, Visitor.ConceptReferencesVisited);
 }
 
-struct VisitDeclOnlyOnce : ExpectedLocationVisitor<VisitDeclOnlyOnce> {
-  bool VisitConceptDecl(ConceptDecl *D) {
+struct VisitDeclOnlyOnce : ExpectedLocationVisitor {
+  VisitDeclOnlyOnce() {
+    ShouldWalkTypesOfTypeLocs = false;
+  }
+
+  bool VisitConceptDecl(ConceptDecl *D) override {
     ++ConceptDeclsVisited;
     return true;
   }
 
-  bool VisitAutoType(AutoType *) {
+  bool VisitAutoType(AutoType *) override {
     ++AutoTypeVisited;
     return true;
   }
-  bool VisitAutoTypeLoc(AutoTypeLoc) {
+  bool VisitAutoTypeLoc(AutoTypeLoc) override {
     ++AutoTypeLocVisited;
     return true;
   }
-  bool VisitConceptReference(ConceptReference *) {
+  bool VisitConceptReference(ConceptReference *) override {
     ++ConceptReferencesVisited;
     return true;
   }
 
-  bool TraverseVarDecl(VarDecl *V) {
+  bool TraverseVarDecl(VarDecl *V) override {
     // The base traversal visits only the `TypeLoc`.
     // However, in the test we also validate the underlying `QualType`.
     TraverseType(V->getType());
     return ExpectedLocationVisitor::TraverseVarDecl(V);
   }
 
-  bool shouldWalkTypesOfTypeLocs() { return false; }
-
   int ConceptDeclsVisited = 0;
   int AutoTypeVisited = 0;
   int AutoTypeLocVisited = 0;
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp
index b4f4f54dc7e2f9..6e295be5a2956f 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp
@@ -18,18 +18,13 @@ namespace {
 /// The name recorded for the match is the name of the class whose constructor
 /// is invoked by the CXXConstructExpr, not the name of the class whose
 /// constructor the CXXConstructExpr is contained in.
-class ConstructExprVisitor
-    : public ExpectedLocationVisitor<ConstructExprVisitor> {
+class ConstructExprVisitor : public ExpectedLocationVisitor  {
 public:
-  ConstructExprVisitor() : ShouldVisitImplicitCode(false) {}
-
-  bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
-
-  void setShouldVisitImplicitCode(bool NewValue) {
-    ShouldVisitImplicitCode = NewValue;
+  ConstructExprVisitor() {
+    ShouldVisitImplicitCode = false;
   }
 
-  bool VisitCXXConstructExpr(CXXConstructExpr* Expr) {
+  bool VisitCXXConstructExpr(CXXConstructExpr* Expr) override {
     if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) {
       if (const CXXRecordDecl* Class = Ctor->getParent()) {
         Match(Class->getName(), Expr->getLocation());
@@ -37,14 +32,11 @@ class ConstructExprVisitor
     }
     return true;
   }
-
- private:
-  bool ShouldVisitImplicitCode;
 };
 
 TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) {
   ConstructExprVisitor Visitor;
-  Visitor.setShouldVisitImplicitCode(true);
+  Visitor.ShouldVisitImplicitCode = true;
   Visitor.ExpectMatch("WithCtor", 2, 8);
   // Simple has a constructor that implicitly initializes 'w'.  Test
   // that a visitor that visits implicit code visits that initialization.
@@ -60,7 +52,7 @@ TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) {
 // visits are omitted when the visitor does not include implicit code.
 TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) {
   ConstructExprVisitor Visitor;
-  Visitor.setShouldVisitImplicitCode(false);
+  Visitor.ShouldVisitImplicitCode = false;
   Visitor.DisallowMatch("WithCtor", 2, 8);
   // Simple has a constructor that implicitly initializes 'w'.  Test
   // that a visitor that skips implicit code skips that initialization.
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp
index adc972e1c3d913..653e9c8bdf8ec6 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp
@@ -12,23 +12,16 @@ using namespace clang;
 
 namespace {
 
-class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> {
+class DeclRefExprVisitor : public ExpectedLocationVisitor {
 public:
-  DeclRefExprVisitor() : ShouldVisitImplicitCode(false) {}
-
-  bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
-
-  void setShouldVisitImplicitCode(bool NewValue) {
-    ShouldVisitImplicitCode = NewValue;
+  DeclRefExprVisitor() {
+    ShouldVisitImplicitCode = false;
   }
 
-  bool VisitDeclRefExpr(DeclRefExpr *Reference) {
+  bool VisitDeclRefExpr(DeclRefExpr *Reference) override {
     Match(Reference->getNameInfo().getAsString(), Reference->getLocation());
     return true;
   }
-
-private:
-  bool ShouldVisitImplicitCode;
 };
 
 TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
@@ -73,7 +66,7 @@ TEST(RecursiveASTVisitor, VisitsUseOfImplicitLambdaCapture) {
 
 TEST(RecursiveASTVisitor, VisitsImplicitLambdaCaptureInit) {
   DeclRefExprVisitor Visitor;
-  Visitor.setShouldVisitImplicitCode(true);
+  Visitor.ShouldVisitImplicitCode = true;
   // We're expecting "i" to be visited twice: once for the initialization expr
   // for the captured variable "i" outside of the lambda body, and again for
   // the use of "i" inside the lambda.
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp
index df878bfc113e57..7d03b283947993 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp
@@ -13,23 +13,20 @@ using namespace clang;
 
 namespace {
 
-class DeductionGuideVisitor
-    : public ExpectedLocationVisitor<DeductionGuideVisitor> {
+class DeductionGuideVisitor : public ExpectedLocationVisitor {
 public:
-  DeductionGuideVisitor(bool ShouldVisitImplicitCode)
-      : ShouldVisitImplicitCode(ShouldVisitImplicitCode) {}
-  bool VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
+  DeductionGuideVisitor(bool VisitImplicitCode) {
+    ShouldVisitImplicitCode = VisitImplicitCode;
+    ShouldVisitTemplateInstantiations = false;
+  }
+
+  bool VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) override {
     std::string Storage;
     llvm::raw_string_ostream Stream(Storage);
     D->print(Stream);
     Match(Storage, D->getLocation());
     return true;
   }
-
-  bool shouldVisitTemplateInstantiations() const { return false; }
-
-  bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
-  bool ShouldVisitImplicitCode;
 };
 
 TEST(RecursiveASTVisitor, DeductionGuideNonImplicitMode) {
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp
index 27999e5ef8efcb..f67cff2586aa15 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp
@@ -13,12 +13,9 @@ using namespace clang;
 namespace {
 
 // A visitor that visits implicit declarations and matches constructors.
-class ImplicitCtorVisitor
-    : public ExpectedLocationVisitor<ImplicitCtorVisitor> {
+class ImplicitCtorVisitor : public ExpectedLocationVisitor {
 public:
-  bool shouldVisitImplicitCode() const { return true; }
-
-  bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) {
+    bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) override {
     if (Ctor->isImplicit()) {  // Was not written in source code
       if (const CXXRecordDecl* Class = Ctor->getParent()) {
         Match(Class->getName(), Ctor->getLocation());
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtorInitializer.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtorInitializer.cpp
index c762e1cffc3686..ae952c33bfe78b 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtorInitializer.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtorInitializer.cpp
@@ -12,26 +12,20 @@ using namespace clang;
 
 namespace {
 
-class CXXCtorInitializerVisitor
-    : public ExpectedLocationVisitor<CXXCtorInitializerVisitor> {
+class CXXCtorInitializerVisitor : public ExpectedLocationVisitor {
 public:
-  CXXCtorInitializerVisitor(bool VisitImplicitCode)
-      : VisitImplicitCode(VisitImplicitCode) {}
-
-  bool shouldVisitImplicitCode() const { return VisitImplicitCode; }
+  CXXCtorInitializerVisitor(bool VisitImplicitCode) {
+    ShouldVisitImplicitCode = VisitImplicitCode;
+  }
 
-  bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
+  bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override {
     if (!Init->isWritten())
       VisitedImplicitInitializer = true;
     Match("initializer", Init->getSourceLocation());
-    return ExpectedLocationVisitor<
-        CXXCtorInitializerVisitor>::TraverseConstructorInitializer(Init);
+    return ExpectedLocationVisitor::TraverseConstructorInitializer(Init);
   }
 
   bool VisitedImplicitInitializer = false;
-
-private:
-  bool VisitImplicitCode;
 };
 
 // Check to ensure that CXXCtorInitializer is not visited when implicit code
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp
index 80d9c9873505b4..5836fc1b2e8de5 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp
@@ -6,14 +6,14 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "TestVisitor.h"
+#include "CRTPTestVisitor.h"
 
 using namespace clang;
 
 namespace {
 
 class InitListExprPostOrderVisitor
-    : public ExpectedLocationVisitor<InitListExprPostOrderVisitor> {
+    : public CRTPExpectedLocationVisitor<InitListExprPostOrderVisitor> {
 public:
   bool shouldTraversePostOrder() const { return true; }
 
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
index 8750f78349443e..20140d2dcbf9e4 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
@@ -6,19 +6,19 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "TestVisitor.h"
+#include "CRTPTestVisitor.h"
 
 using namespace clang;
 
 namespace {
 
 class InitListExprPostOrderNoQueueVisitor
-    : public ExpectedLocationVisitor<InitListExprPostOrderNoQueueVisitor> {
+    : public CRTPExpectedLocationVisitor<InitListExprPostOrderNoQueueVisitor> {
 public:
   bool shouldTraversePostOrder() const { return true; }
 
   bool TraverseInitListExpr(InitListExpr *ILE) {
-    return ExpectedLocationVisitor::TraverseInitListExpr(ILE);
+    return CRTPExpectedLocationVisitor::TraverseInitListExpr(ILE);
   }
 
   bool VisitInitListExpr(InitListExpr *ILE) {
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
index 3fa1529ea0eefe..933d25898390dd 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
@@ -14,21 +14,16 @@ namespace {
 
 // Check to ensure that InitListExpr is visited twice, once each for the
 // syntactic and semantic form.
-class InitListExprPreOrderVisitor
-    : public ExpectedLocationVisitor<InitListExprPreOrderVisitor> {
+class InitListExprPreOrderVisitor : public ExpectedLocationVisitor {
 public:
-  InitListExprPreOrderVisitor(bool VisitImplicitCode)
-      : VisitImplicitCode(VisitImplicitCode) {}
-
-  bool shouldVisitImplicitCode() const { return VisitImplicitCode; }
+  InitListExprPreOrderVisitor(bool VisitImplicitCode) {
+    ShouldVisitImplicitCode = VisitImplicitCode;
+  }
 
-  bool VisitInitListExpr(InitListExpr *ILE) {
+  bool VisitInitListExpr(InitListExpr *ILE) override {
     Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc());
     return true;
   }
-
-private:
-  bool VisitImplicitCode;
 };
 
 TEST(RecursiveASTVisitor, InitListExprIsPreOrderVisitedTwice) {
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
index 8db88e1e063975..0dcd11b8027f04 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
@@ -12,14 +12,13 @@ using namespace clang;
 
 namespace {
 
-class InitListExprPreOrderNoQueueVisitor
-    : public ExpectedLocationVisitor<InitListExprPreOrderNoQueueVisitor> {
+class InitListExprPreOrderNoQueueVisitor : public ExpectedLocationVisitor {
 public:
-  bool TraverseInitListExpr(InitListExpr *ILE) {
+  bool TraverseInitListExpr(InitListExpr *ILE) override {
     return ExpectedLocationVisitor::TraverseInitListExpr(ILE);
   }
 
-  bool VisitInitListExpr(InitListExpr *ILE) {
+  bool VisitInitListExpr(InitListExpr *ILE) override {
     Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc());
     return true;
   }
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp
index 3fc3cb1a99a744..83136fc11edb2c 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp
@@ -13,10 +13,9 @@ using namespace clang;
 namespace {
 
 // Check to ensure that implicit default argument expressions are visited.
-class IntegerLiteralVisitor
-    : public ExpectedLocationVisitor<IntegerLiteralVisitor> {
+class IntegerLiteralVisitor : public ExpectedLocationVisitor {
 public:
-  bool VisitIntegerLiteral(const IntegerLiteral *IL) {
+  bool VisitIntegerLiteral(IntegerLiteral *IL) override {
     Match("literal", IL->getLocation());
     return true;
   }
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp
index b1d6d593e733a9..4a9175ed2dda24 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp
@@ -13,10 +13,9 @@ using namespace clang;
 namespace {
 
 // Matches the (optional) capture-default of a lambda-introducer.
-class LambdaDefaultCaptureVisitor
-  : public ExpectedLocationVisitor<LambdaDefaultCaptureVisitor> {
+class LambdaDefaultCaptureVisitor : public ExpectedLocationVisitor {
 public:
-  bool VisitLambdaExpr(LambdaExpr *Lambda) {
+  bool VisitLambdaExpr(LambdaExpr *Lambda) override {
     if (Lambda->getCaptureDefault() != LCD_None) {
       Match("", Lambda->getCaptureDefaultLoc());
     }
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp
index 337dace5fd2274..af84c6ef9ad832 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp
@@ -14,9 +14,13 @@ using namespace clang;
 
 namespace {
 
-class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
+class LambdaExprVisitor : public ExpectedLocationVisitor {
 public:
-  bool VisitLambdaExpr(LambdaExpr *Lambda) {
+  LambdaExprVisitor() {
+    ShouldVisitImplicitCode = false;
+  }
+
+  bool VisitLambdaExpr(LambdaExpr *Lambda) override {
     PendingBodies.push(Lambda->getBody());
     PendingClasses.push(Lambda->getLambdaClass());
     Match("", Lambda->getIntroducerRange().getBegin());
@@ -24,12 +28,12 @@ class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
   }
   /// For each call to VisitLambdaExpr, we expect a subsequent call to visit
   /// the body (and maybe the lambda class, which is implicit).
-  bool VisitStmt(Stmt *S) {
+  bool VisitStmt(Stmt *S) override {
     if (!PendingBodies.empty() && S == PendingBodies.top())
       PendingBodies.pop();
     return true;
   }
-  bool VisitDecl(Decl *D) {
+  bool VisitDecl(Decl *D) override {
     if (!PendingClasses.empty() && D == PendingClasses.top())
       PendingClasses.pop();
     return true;
@@ -38,9 +42,6 @@ class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
   bool allBodiesHaveBeenTraversed() const { return PendingBodies.empty(); }
   bool allClassesHaveBeenTraversed() const { return PendingClasses.empty(); }
 
-  bool VisitImplicitCode = false;
-  bool shouldVisitImplicitCode() const { return VisitImplicitCode; }
-
 private:
   std::stack<Stmt *> PendingBodies;
   std::stack<Decl *> PendingClasses;
@@ -67,7 +68,7 @@ TEST(RecursiveASTVisitor, LambdaInLambda) {
 
 TEST(RecursiveASTVisitor, TopLevelLambda) {
   LambdaExprVisitor Visitor;
-  Visitor.VisitImplicitCode = true;
+  Visitor.ShouldVisitImplicitCode = true;
   Visitor.ExpectMatch("", 1, 10);
   Visitor.ExpectMatch("", 1, 14);
   EXPECT_TRUE(Visitor.runOver("auto x = []{ [] {}; };",
@@ -78,7 +79,7 @@ TEST(RecursiveASTVisitor, TopLevelLambda) {
 
 TEST(RecursiveASTVisitor, VisitsLambdaExprAndImplicitClass) {
   LambdaExprVisitor Visitor;
-  Visitor.VisitImplicitCode = true;
+  Visitor.ShouldVisitImplicitCode = true;
   Visitor.ExpectMatch("", 1, 12);
   EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
                               LambdaExprVisitor::Lang_CXX11));
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp
index c355e3f1083f96..77194b04de0369 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp
@@ -13,24 +13,25 @@ using namespace clang;
 namespace {
 
 // Matches (optional) explicit template parameters.
-class LambdaTemplateParametersVisitor
-  : public ExpectedLocationVisitor<LambdaTemplateParametersVisitor> {
+class LambdaTemplateParametersVisitor : public ExpectedLocationVisitor {
 public:
-  bool shouldVisitImplicitCode() const { return false; }
+  LambdaTemplateParametersVisitor() {
+    ShouldVisitImplicitCode = false;
+  }
 
-  bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+  bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) override {
     EXPECT_FALSE(D->isImplicit());
     Match(D->getName(), D->getBeginLoc());
     return true;
   }
 
-  bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+  bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) override {
     EXPECT_FALSE(D->isImplicit());
     Match(D->getName(), D->getBeginLoc());
     return true;
   }
 
-  bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+  bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) override {
     EXPECT_FALSE(D->isImplicit());
     Match(D->getName(), D->getBeginLoc());
     return true;
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/MemberPointerTypeLoc.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/MemberPointerTypeLoc.cpp
index d67bd0395a670e..587a00dd270511 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/MemberPointerTypeLoc.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/MemberPointerTypeLoc.cpp
@@ -13,16 +13,15 @@ using namespace clang;
 
 namespace {
 
-class MemberPointerTypeLocVisitor
-    : public ExpectedLocationVisitor<MemberPointerTypeLocVisitor> {
+class MemberPointerTypeLocVisitor : public ExpectedLocationVisitor {
 public:
-  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) override {
     if (!TL)
       return true;
     Match(TL.getDecl()->getName(), TL.getNameLoc());
     return true;
   }
-  bool VisitRecordTypeLoc(RecordTypeLoc RTL) {
+  bool VisitRecordTypeLoc(RecordTypeLoc RTL) override {
     if (!RTL)
       return true;
     Match(RTL.getDecl()->getName(), RTL.getNameLoc());
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp
index 868a3988c756d2..ddc663e2b6fd3f 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp
@@ -13,17 +13,16 @@ using namespace clang;
 namespace {
 
 // Check to ensure that nested name specifiers are visited.
-class NestedNameSpecifiersVisitor
-    : public ExpectedLocationVisitor<NestedNameSpecifiersVisitor> {
+class NestedNameSpecifiersVisitor : public ExpectedLocationVisitor {
 public:
-  bool VisitRecordTypeLoc(RecordTypeLoc RTL) {
+  bool VisitRecordTypeLoc(RecordTypeLoc RTL) override {
     if (!RTL)
       return true;
     Match(RTL.getDecl()->getName(), RTL.getNameLoc());
     return true;
   }
 
-  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) override {
     if (!NNS)
       return true;
     if (const NamespaceDecl *ND =
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp
index c316f98f40ce0f..89ccf20587ad06 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp
@@ -12,9 +12,9 @@ using namespace clang;
 
 namespace {
 
-class ParenExprVisitor : public ExpectedLocationVisitor<ParenExprVisitor> {
+class ParenExprVisitor : public ExpectedLocationVisitor {
 public:
-  bool VisitParenExpr(ParenExpr *Parens) {
+  bool VisitParenExpr(ParenExpr *Parens) override {
     Match("", Parens->getExprLoc());
     return true;
   }
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp
index f068e53ae9c288..3af2b13dc5daf3 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp
@@ -12,18 +12,16 @@ using namespace clang;
 
 namespace {
 
-class TemplateArgumentLocTraverser
-  : public ExpectedLocationVisitor<TemplateArgumentLocTraverser> {
+class TemplateArgumentLocTraverser : public ExpectedLocationVisitor {
 public:
-  bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
+  bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) override {
     std::string ArgStr;
     llvm::raw_string_ostream Stream(ArgStr);
     const TemplateArgument &Arg = ArgLoc.getArgument();
 
     Arg.print(Context->getPrintingPolicy(), Stream, /*IncludeType*/ true);
     Match(Stream.str(), ArgLoc.getLocation());
-    return ExpectedLocationVisitor<TemplateArgumentLocTraverser>::
-      TraverseTemplateArgumentLoc(ArgLoc);
+    return ExpectedLocationVisitor::TraverseTemplateArgumentLoc(ArgLoc);
   }
 };
 
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp
index 9e71f9554e5951..2feddf58cac7b2 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp
@@ -12,17 +12,17 @@ using namespace clang;
 
 namespace {
 
-class Visitor : public ExpectedLocationVisitor<Visitor, clang::TestVisitor> {
+class Visitor : public ExpectedLocationVisitor {
 public:
   Visitor(ASTContext *Context) { this->Context = Context; }
 
-  bool VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+  bool VisitTranslationUnitDecl(TranslationUnitDecl *D) override {
     auto &SM = D->getParentASTContext().getSourceManager();
     Match("TU", SM.getLocForStartOfFile(SM.getMainFileID()));
     return true;
   }
 
-  bool VisitNamedDecl(NamedDecl *D) {
+  bool VisitNamedDecl(NamedDecl *D) override {
     if (!D->isImplicit())
       Match(D->getName(), D->getLocation());
     return true;
diff --git a/clang/unittests/Tooling/RefactoringTest.cpp b/clang/unittests/Tooling/RefactoringTest.cpp
index 77d410f5d3b604..9df8c1b94c6a45 100644
--- a/clang/unittests/Tooling/RefactoringTest.cpp
+++ b/clang/unittests/Tooling/RefactoringTest.cpp
@@ -13,7 +13,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclGroup.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileManager.h"
@@ -648,8 +648,7 @@ TEST_F(FlushRewrittenFilesTest, StoresChangesOnDisk) {
 }
 
 namespace {
-template <typename T>
-class TestVisitor : public clang::RecursiveASTVisitor<T> {
+class TestVisitor : public DynamicRecursiveASTVisitor {
 public:
   bool runOver(StringRef Code) {
     return runToolOnCode(std::make_unique<TestAction>(this), Code);
@@ -699,9 +698,9 @@ void expectReplacementAt(const Replacement &Replace,
   EXPECT_EQ(Length, Replace.getLength());
 }
 
-class ClassDeclXVisitor : public TestVisitor<ClassDeclXVisitor> {
+class ClassDeclXVisitor : public TestVisitor {
 public:
-  bool VisitCXXRecordDecl(CXXRecordDecl *Record) {
+  bool VisitCXXRecordDecl(CXXRecordDecl *Record) override {
     if (Record->getName() == "X") {
       Replace = Replacement(*SM, Record, "");
     }
@@ -722,9 +721,9 @@ TEST(Replacement, ReplacesAtSpellingLocation) {
   expectReplacementAt(ClassDeclX.Replace, "input.cc", 17, 7);
 }
 
-class CallToFVisitor : public TestVisitor<CallToFVisitor> {
+class CallToFVisitor : public TestVisitor {
 public:
-  bool VisitCallExpr(CallExpr *Call) {
+  bool VisitCallExpr(CallExpr *Call) override {
     if (Call->getDirectCallee()->getName() == "F") {
       Replace = Replacement(*SM, Call, "");
     }
@@ -746,10 +745,9 @@ TEST(Replacement, TemplatedFunctionCall) {
   expectReplacementAt(CallToF.Replace, "input.cc", 43, 8);
 }
 
-class NestedNameSpecifierAVisitor
-    : public TestVisitor<NestedNameSpecifierAVisitor> {
+class NestedNameSpecifierAVisitor : public TestVisitor {
 public:
-  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLoc) {
+  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLoc) override {
     if (NNSLoc.getNestedNameSpecifier()) {
       if (const NamespaceDecl* NS = NNSLoc.getNestedNameSpecifier()->getAsNamespace()) {
         if (NS->getName() == "a") {
@@ -757,8 +755,7 @@ class NestedNameSpecifierAVisitor
         }
       }
     }
-    return TestVisitor<NestedNameSpecifierAVisitor>::TraverseNestedNameSpecifierLoc(
-        NNSLoc);
+    return TestVisitor::TraverseNestedNameSpecifierLoc(NNSLoc);
   }
   Replacement Replace;
 };
diff --git a/clang/unittests/Tooling/SourceCodeTest.cpp b/clang/unittests/Tooling/SourceCodeTest.cpp
index 3c24b6220a224a..549b77752f1c21 100644
--- a/clang/unittests/Tooling/SourceCodeTest.cpp
+++ b/clang/unittests/Tooling/SourceCodeTest.cpp
@@ -35,8 +35,8 @@ using tooling::validateEditRange;
 
 namespace {
 
-struct IntLitVisitor : TestVisitor<IntLitVisitor> {
-  bool VisitIntegerLiteral(IntegerLiteral *Expr) {
+struct IntLitVisitor : TestVisitor {
+  bool VisitIntegerLiteral(IntegerLiteral *Expr) override {
     OnIntLit(Expr, Context);
     return true;
   }
@@ -44,8 +44,8 @@ struct IntLitVisitor : TestVisitor<IntLitVisitor> {
   std::function<void(IntegerLiteral *, ASTContext *Context)> OnIntLit;
 };
 
-struct CallsVisitor : TestVisitor<CallsVisitor> {
-  bool VisitCallExpr(CallExpr *Expr) {
+struct CallsVisitor : TestVisitor {
+  bool VisitCallExpr(CallExpr *Expr) override {
     OnCall(Expr, Context);
     return true;
   }
@@ -53,8 +53,8 @@ struct CallsVisitor : TestVisitor<CallsVisitor> {
   std::function<void(CallExpr *, ASTContext *Context)> OnCall;
 };
 
-struct TypeLocVisitor : TestVisitor<TypeLocVisitor> {
-  bool VisitTypeLoc(TypeLoc TL) {
+struct TypeLocVisitor : TestVisitor {
+  bool VisitTypeLoc(TypeLoc TL) override {
     OnTypeLoc(TL, Context);
     return true;
   }
@@ -97,7 +97,7 @@ static ::testing::Matcher<CharSourceRange> AsRange(const SourceManager &SM,
 
 // Base class for visitors that expect a single match corresponding to a
 // specific annotated range.
-template <typename T> class AnnotatedCodeVisitor : public TestVisitor<T> {
+class AnnotatedCodeVisitor : public TestVisitor {
 protected:
   int MatchCount = 0;
   llvm::Annotations Code;
@@ -199,9 +199,8 @@ TEST(SourceCodeTest, getExtendedText) {
 }
 
 TEST(SourceCodeTest, maybeExtendRange_TokenRange) {
-  struct ExtendTokenRangeVisitor
-      : AnnotatedCodeVisitor<ExtendTokenRangeVisitor> {
-    bool VisitCallExpr(CallExpr *CE) {
+  struct ExtendTokenRangeVisitor : AnnotatedCodeVisitor {
+    bool VisitCallExpr(CallExpr *CE) override {
       ++MatchCount;
       EXPECT_THAT(getExtendedRange(*CE, tok::TokenKind::semi, *Context),
                   EqualsAnnotatedRange(Context, Code.range("r")));
@@ -218,8 +217,8 @@ TEST(SourceCodeTest, maybeExtendRange_TokenRange) {
 }
 
 TEST(SourceCodeTest, maybeExtendRange_CharRange) {
-  struct ExtendCharRangeVisitor : AnnotatedCodeVisitor<ExtendCharRangeVisitor> {
-    bool VisitCallExpr(CallExpr *CE) {
+  struct ExtendCharRangeVisitor : AnnotatedCodeVisitor {
+    bool VisitCallExpr(CallExpr *CE) override {
       ++MatchCount;
       CharSourceRange Call = Lexer::getAsCharRange(CE->getSourceRange(),
                                                    Context->getSourceManager(),
@@ -238,8 +237,8 @@ TEST(SourceCodeTest, maybeExtendRange_CharRange) {
 }
 
 TEST(SourceCodeTest, getAssociatedRange) {
-  struct VarDeclsVisitor : AnnotatedCodeVisitor<VarDeclsVisitor> {
-    bool VisitVarDecl(VarDecl *Decl) { return VisitDeclHelper(Decl); }
+  struct VarDeclsVisitor : AnnotatedCodeVisitor {
+    bool VisitVarDecl(VarDecl *Decl) override { return VisitDeclHelper(Decl); }
   };
   VarDeclsVisitor Visitor;
 
@@ -283,8 +282,10 @@ TEST(SourceCodeTest, getAssociatedRange) {
 }
 
 TEST(SourceCodeTest, getAssociatedRangeClasses) {
-  struct RecordDeclsVisitor : AnnotatedCodeVisitor<RecordDeclsVisitor> {
-    bool VisitRecordDecl(RecordDecl *Decl) { return VisitDeclHelper(Decl); }
+  struct RecordDeclsVisitor : AnnotatedCodeVisitor {
+    bool VisitRecordDecl(RecordDecl *Decl) override {
+      return VisitDeclHelper(Decl);
+    }
   };
   RecordDeclsVisitor Visitor;
 
@@ -297,8 +298,8 @@ TEST(SourceCodeTest, getAssociatedRangeClasses) {
 }
 
 TEST(SourceCodeTest, getAssociatedRangeClassTemplateSpecializations) {
-  struct CXXRecordDeclsVisitor : AnnotatedCodeVisitor<CXXRecordDeclsVisitor> {
-    bool VisitCXXRecordDecl(CXXRecordDecl *Decl) {
+  struct CXXRecordDeclsVisitor : AnnotatedCodeVisitor {
+    bool VisitCXXRecordDecl(CXXRecordDecl *Decl) override {
       return Decl->getTemplateSpecializationKind() !=
                  TSK_ExplicitSpecialization ||
              VisitDeclHelper(Decl);
@@ -315,8 +316,10 @@ TEST(SourceCodeTest, getAssociatedRangeClassTemplateSpecializations) {
 }
 
 TEST(SourceCodeTest, getAssociatedRangeFunctions) {
-  struct FunctionDeclsVisitor : AnnotatedCodeVisitor<FunctionDeclsVisitor> {
-    bool VisitFunctionDecl(FunctionDecl *Decl) { return VisitDeclHelper(Decl); }
+  struct FunctionDeclsVisitor : AnnotatedCodeVisitor {
+    bool VisitFunctionDecl(FunctionDecl *Decl) override {
+      return VisitDeclHelper(Decl);
+    }
   };
   FunctionDeclsVisitor Visitor;
 
@@ -328,8 +331,8 @@ TEST(SourceCodeTest, getAssociatedRangeFunctions) {
 }
 
 TEST(SourceCodeTest, getAssociatedRangeMemberTemplates) {
-  struct CXXMethodDeclsVisitor : AnnotatedCodeVisitor<CXXMethodDeclsVisitor> {
-    bool VisitCXXMethodDecl(CXXMethodDecl *Decl) {
+  struct CXXMethodDeclsVisitor : AnnotatedCodeVisitor {
+    bool VisitCXXMethodDecl(CXXMethodDecl *Decl) override {
       // Only consider the definition of the template.
       return !Decl->doesThisDeclarationHaveABody() || VisitDeclHelper(Decl);
     }
@@ -346,8 +349,8 @@ TEST(SourceCodeTest, getAssociatedRangeMemberTemplates) {
 }
 
 TEST(SourceCodeTest, getAssociatedRangeWithComments) {
-  struct VarDeclsVisitor : AnnotatedCodeVisitor<VarDeclsVisitor> {
-    bool VisitVarDecl(VarDecl *Decl) { return VisitDeclHelper(Decl); }
+  struct VarDeclsVisitor : AnnotatedCodeVisitor {
+    bool VisitVarDecl(VarDecl *Decl) override { return VisitDeclHelper(Decl); }
   };
 
   VarDeclsVisitor Visitor;
@@ -447,9 +450,9 @@ TEST(SourceCodeTest, getAssociatedRangeWithComments) {
 }
 
 TEST(SourceCodeTest, getAssociatedRangeInvalidForPartialExpansions) {
-  struct FailingVarDeclsVisitor : TestVisitor<FailingVarDeclsVisitor> {
+  struct FailingVarDeclsVisitor : TestVisitor {
     FailingVarDeclsVisitor() {}
-    bool VisitVarDecl(VarDecl *Decl) {
+    bool VisitVarDecl(VarDecl *Decl) override {
       EXPECT_TRUE(getAssociatedRange(*Decl, *Context).isInvalid());
       return true;
     }
diff --git a/clang/unittests/Tooling/TestVisitor.h b/clang/unittests/Tooling/TestVisitor.h
index 751ca74d1a881c..cf39fc143507ce 100644
--- a/clang/unittests/Tooling/TestVisitor.h
+++ b/clang/unittests/Tooling/TestVisitor.h
@@ -16,7 +16,7 @@
 
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendAction.h"
 #include "clang/Tooling/Tooling.h"
@@ -24,20 +24,11 @@
 #include <vector>
 
 namespace clang {
-
-/// \brief Base class for simple RecursiveASTVisitor based tests.
-///
-/// This is a drop-in replacement for RecursiveASTVisitor itself, with the
-/// additional capability of running it over a snippet of code.
-///
-/// Visits template instantiations and implicit code by default.
-template <typename T>
-class TestVisitor : public RecursiveASTVisitor<T> {
+namespace detail {
+// Use 'TestVisitor' or include 'CRTPTestVisitor.h' and use 'CRTPTestVisitor'
+// instead of using this directly.
+class TestVisitorHelper {
 public:
-  TestVisitor() { }
-
-  virtual ~TestVisitor() { }
-
   enum Language {
     Lang_C,
     Lang_CXX98,
@@ -54,57 +45,53 @@ class TestVisitor : public RecursiveASTVisitor<T> {
   bool runOver(StringRef Code, Language L = Lang_CXX) {
     std::vector<std::string> Args;
     switch (L) {
-      case Lang_C:
-        Args.push_back("-x");
-        Args.push_back("c");
-        break;
-      case Lang_CXX98: Args.push_back("-std=c++98"); break;
-      case Lang_CXX11: Args.push_back("-std=c++11"); break;
-      case Lang_CXX14: Args.push_back("-std=c++14"); break;
-      case Lang_CXX17: Args.push_back("-std=c++17"); break;
-      case Lang_CXX2a: Args.push_back("-std=c++2a"); break;
-      case Lang_OBJC:
-        Args.push_back("-ObjC");
-        Args.push_back("-fobjc-runtime=macosx-10.12.0");
-        break;
-      case Lang_OBJCXX11:
-        Args.push_back("-ObjC++");
-        Args.push_back("-std=c++11");
-        Args.push_back("-fblocks");
-        break;
+    case Lang_C:
+      Args.push_back("-x");
+      Args.push_back("c");
+      break;
+    case Lang_CXX98: Args.push_back("-std=c++98"); break;
+    case Lang_CXX11: Args.push_back("-std=c++11"); break;
+    case Lang_CXX14: Args.push_back("-std=c++14"); break;
+    case Lang_CXX17: Args.push_back("-std=c++17"); break;
+    case Lang_CXX2a: Args.push_back("-std=c++2a"); break;
+    case Lang_OBJC:
+      Args.push_back("-ObjC");
+      Args.push_back("-fobjc-runtime=macosx-10.12.0");
+      break;
+    case Lang_OBJCXX11:
+      Args.push_back("-ObjC++");
+      Args.push_back("-std=c++11");
+      Args.push_back("-fblocks");
+      break;
     }
     return tooling::runToolOnCodeWithArgs(CreateTestAction(), Code, Args);
   }
 
-  bool shouldVisitTemplateInstantiations() const {
-    return true;
-  }
-
-  bool shouldVisitImplicitCode() const {
-    return true;
-  }
-
 protected:
+  TestVisitorHelper() = default;
+  virtual ~TestVisitorHelper() = default;
+  virtual void InvokeTraverseDecl(TranslationUnitDecl* D) = 0;
+
   virtual std::unique_ptr<ASTFrontendAction> CreateTestAction() {
     return std::make_unique<TestAction>(this);
   }
 
   class FindConsumer : public ASTConsumer {
   public:
-    FindConsumer(TestVisitor *Visitor) : Visitor(Visitor) {}
+    FindConsumer(TestVisitorHelper *Visitor) : Visitor(Visitor) {}
 
     void HandleTranslationUnit(clang::ASTContext &Context) override {
       Visitor->Context = &Context;
-      Visitor->TraverseDecl(Context.getTranslationUnitDecl());
+      Visitor->InvokeTraverseDecl(Context.getTranslationUnitDecl());
     }
 
   private:
-    TestVisitor *Visitor;
+    TestVisitorHelper *Visitor;
   };
 
   class TestAction : public ASTFrontendAction {
   public:
-    TestAction(TestVisitor *Visitor) : Visitor(Visitor) {}
+    TestAction(TestVisitorHelper *Visitor) : Visitor(Visitor) {}
 
     std::unique_ptr<clang::ASTConsumer>
     CreateASTConsumer(CompilerInstance &, llvm::StringRef dummy) override {
@@ -113,20 +100,13 @@ class TestVisitor : public RecursiveASTVisitor<T> {
     }
 
   protected:
-    TestVisitor *Visitor;
+    TestVisitorHelper *Visitor;
   };
 
   ASTContext *Context;
 };
 
-/// \brief A RecursiveASTVisitor to check that certain matches are (or are
-/// not) observed during visitation.
-///
-/// This is a RecursiveASTVisitor for testing the RecursiveASTVisitor itself,
-/// and allows simple creation of test visitors running matches on only a small
-/// subset of the Visit* methods.
-template <typename T, template <typename> class Visitor = TestVisitor>
-class ExpectedLocationVisitor : public Visitor<T> {
+class ExpectedLocationVisitorHelper {
 public:
   /// \brief Expect 'Match' *not* to occur at the given 'Line' and 'Column'.
   ///
@@ -147,37 +127,42 @@ class ExpectedLocationVisitor : public Visitor<T> {
   }
 
   /// \brief Checks that all expected matches have been found.
-  ~ExpectedLocationVisitor() override {
-    for (typename std::vector<ExpectedMatch>::const_iterator
+  virtual ~ExpectedLocationVisitorHelper() {
+    // FIXME: Range-based for loop.
+    for (std::vector<ExpectedMatch>::const_iterator
              It = ExpectedMatches.begin(), End = ExpectedMatches.end();
          It != End; ++It) {
       It->ExpectFound();
-    }
+         }
   }
 
 protected:
+  virtual ASTContext* getASTContext() = 0;
+
   /// \brief Checks an actual match against expected and disallowed matches.
   ///
   /// Implementations are required to call this with appropriate values
   /// for 'Name' during visitation.
   void Match(StringRef Name, SourceLocation Location) {
-    const FullSourceLoc FullLocation = this->Context->getFullLoc(Location);
+    const FullSourceLoc FullLocation = getASTContext()->getFullLoc(Location);
 
-    for (typename std::vector<MatchCandidate>::const_iterator
+    // FIXME: Range-based for loop.
+    for (std::vector<MatchCandidate>::const_iterator
              It = DisallowedMatches.begin(), End = DisallowedMatches.end();
          It != End; ++It) {
       EXPECT_FALSE(It->Matches(Name, FullLocation))
           << "Matched disallowed " << *It;
-    }
+         }
 
-    for (typename std::vector<ExpectedMatch>::iterator
+    // FIXME: Range-based for loop.
+    for (std::vector<ExpectedMatch>::iterator
              It = ExpectedMatches.begin(), End = ExpectedMatches.end();
          It != End; ++It) {
-      It->UpdateFor(Name, FullLocation, this->Context->getSourceManager());
-    }
+      It->UpdateFor(Name, FullLocation, getASTContext()->getSourceManager());
+         }
   }
 
- private:
+private:
   struct MatchCandidate {
     std::string ExpectedName;
     unsigned LineNumber;
@@ -228,7 +213,7 @@ class ExpectedLocationVisitor : public Visitor<T> {
         llvm::raw_string_ostream Stream(PartialMatches);
         Stream << ", partial match: \"" << Name << "\" at ";
         Location.print(Stream, SM);
-      }
+                 }
     }
 
     void ExpectFound() const {
@@ -249,4 +234,41 @@ class ExpectedLocationVisitor : public Visitor<T> {
 };
 }
 
+/// \brief Base class for simple (Dynamic)RecursiveASTVisitor based tests.
+///
+/// This is a drop-in replacement for DynamicRecursiveASTVisitor itself, with
+/// the additional capability of running it over a snippet of code.
+///
+/// Visits template instantiations and implicit code by default.
+///
+/// For post-order traversal etc. use CTRPTestVisitor from
+/// CTRPTestVisitor.h instead.
+class TestVisitor : public DynamicRecursiveASTVisitor,
+                    public detail::TestVisitorHelper {
+public:
+  TestVisitor() {
+    ShouldVisitTemplateInstantiations = true;
+    ShouldVisitImplicitCode = true;
+  }
+
+  void InvokeTraverseDecl(TranslationUnitDecl* D) override {
+    TraverseDecl(D);
+  }
+};
+
+/// \brief A RecursiveASTVisitor to check that certain matches are (or are
+/// not) observed during visitation.
+///
+/// This is a RecursiveASTVisitor for testing the RecursiveASTVisitor itself,
+/// and allows simple creation of test visitors running matches on only a small
+/// subset of the Visit* methods.
+///
+/// For post-order traversal etc. use CTRPExpectedLocationVisitor from
+/// CTRPTestVisitor.h instead.
+class ExpectedLocationVisitor : public TestVisitor,
+                                public detail::ExpectedLocationVisitorHelper {
+  ASTContext *getASTContext() override { return Context; }
+};
+}
+
 #endif

>From 676a069b35f45cd8578c2db67cf9b46042ec627a Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 19 Aug 2024 18:03:14 +0200
Subject: [PATCH 17/25] So long, DataRecursionQueue

---
 .../clang/AST/DynamicRecursiveASTVisitor.h    | 12 ++--------
 clang/include/clang/Analysis/CallGraph.h      |  2 +-
 clang/lib/ARCMigrate/ObjCMT.cpp               |  2 +-
 clang/lib/ARCMigrate/Transforms.cpp           |  2 +-
 clang/lib/AST/DynamicRecursiveASTVisitor.cpp  | 23 +++++++++++--------
 clang/lib/ASTMatchers/ASTMatchFinder.cpp      | 20 +++++++---------
 clang/lib/Analysis/UnsafeBufferUsage.cpp      |  2 +-
 clang/lib/Index/IndexTypeSourceInfo.cpp       |  2 +-
 clang/lib/Sema/SemaAvailability.cpp           |  2 +-
 clang/lib/Sema/SemaTemplate.cpp               |  4 ++--
 clang/lib/Sema/SemaTemplateVariadic.cpp       |  4 ++--
 clang/lib/Tooling/ASTDiff/ASTDiff.cpp         |  2 +-
 12 files changed, 35 insertions(+), 42 deletions(-)

diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
index 75d7597c2b7497..14b60ee0dc3192 100644
--- a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -24,10 +24,6 @@ class ASTContext;
 /// \see RecursiveASTVisitor
 class DynamicRecursiveASTVisitor {
 public:
-  // FIXME: I think we can just get rid of the Queue entirely.
-  using DataRecursionQueue =
-      SmallVectorImpl<llvm::PointerIntPair<Stmt *, 1, bool>>;
-
   /// Whether this visitor should recurse into template instantiations.
   bool ShouldVisitTemplateInstantiations = false;
 
@@ -115,9 +111,7 @@ class DynamicRecursiveASTVisitor {
   ///
   /// \returns false if the visitation was terminated early, true
   /// otherwise (including when the argument is nullptr).
-  ///
-  // FIXME: I think we can just get rid of the Queue entirely.
-  virtual bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr);
+  virtual bool TraverseStmt(Stmt *S);
 
   /// Recursively visit a template argument and dispatch to the
   /// appropriate method for the argument type.
@@ -198,9 +192,7 @@ class DynamicRecursiveASTVisitor {
   ///
   /// \returns false if the visitation was terminated early, true otherwise.
   virtual bool dataTraverseStmtPost(Stmt *S) { return true; }
-
-  // FIXME: I think we can just get rid of the Queue entirely.
-  virtual bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue = nullptr);
+  virtual bool dataTraverseNode(Stmt *S);
 
   /*// Declare Traverse*() and friends for attributes.
 #define DYNAMIC_ATTR_VISITOR_DECLS
diff --git a/clang/include/clang/Analysis/CallGraph.h b/clang/include/clang/Analysis/CallGraph.h
index 891c4c750011d2..c11d163f8fe20d 100644
--- a/clang/include/clang/Analysis/CallGraph.h
+++ b/clang/include/clang/Analysis/CallGraph.h
@@ -134,7 +134,7 @@ class CallGraph : public DynamicRecursiveASTVisitor {
   }
 
   // We are only collecting the declarations, so do not step into the bodies.
-  bool TraverseStmt(Stmt *S, DataRecursionQueue*) override { return true; }
+  bool TraverseStmt(Stmt *S) override { return true; }
 
 private:
   /// Add the given declaration to the call graph.
diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp
index 4164e452059307..62402646009e12 100644
--- a/clang/lib/ARCMigrate/ObjCMT.cpp
+++ b/clang/lib/ARCMigrate/ObjCMT.cpp
@@ -364,7 +364,7 @@ namespace {
       ShouldWalkTypesOfTypeLocs = false;
     }
 
-    bool TraverseStmt(Stmt *S, DataRecursionQueue * = nullptr) override {
+    bool TraverseStmt(Stmt *S) override {
       PMap.reset(new ParentMap(S));
       ObjCMigrator(Consumer, *PMap).TraverseStmt(S);
       return true;
diff --git a/clang/lib/ARCMigrate/Transforms.cpp b/clang/lib/ARCMigrate/Transforms.cpp
index 4c35bcda2c15da..8b429bcdd1e7a8 100644
--- a/clang/lib/ARCMigrate/Transforms.cpp
+++ b/clang/lib/ARCMigrate/Transforms.cpp
@@ -335,7 +335,7 @@ class ASTTransform : public DynamicRecursiveASTVisitor {
     return DynamicRecursiveASTVisitor::TraverseObjCImplementationDecl(D);
   }
 
-  bool TraverseStmt(Stmt *rootS, DataRecursionQueue * = nullptr) override {
+  bool TraverseStmt(Stmt *rootS) override {
     if (!rootS)
       return true;
 
diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
index fe9b80df3e5477..7c39c6c58c02f4 100644
--- a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
+++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
@@ -41,8 +41,8 @@ struct Impl : RecursiveASTVisitor<Impl> {
   bool TraverseDecl(Decl *D) { return Visitor.TraverseDecl(D); }
   bool TraverseType(QualType T) { return Visitor.TraverseType(T); }
   bool TraverseTypeLoc(TypeLoc TL) { return Visitor.TraverseTypeLoc(TL); }
-  bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr) {
-    return Visitor.TraverseStmt(S, Queue);
+  bool TraverseStmt(Stmt *S) {
+    return Visitor.TraverseStmt(S);
   }
 
   bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
@@ -112,8 +112,14 @@ struct Impl : RecursiveASTVisitor<Impl> {
 
   bool dataTraverseStmtPre(Stmt *S) { return Visitor.dataTraverseStmtPre(S); }
   bool dataTraverseStmtPost(Stmt *S) { return Visitor.dataTraverseStmtPost(S); }
-  bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) {
-    return Visitor.dataTraverseNode(S, Queue);
+
+  // TraverseStmt() always passes in a queue, so we have no choice but to
+  // accept it as a parameter here.
+  bool dataTraverseNode(Stmt *S, DataRecursionQueue* = nullptr) {
+    // But since don't support postorder traversal, we don't need it, so
+    // simply discard it here. This way, derived classes don't need to worry
+    // about including it as a parameter that they never use.
+    return Visitor.dataTraverseNode(S);
   }
 
   /// Visit a node.
@@ -218,9 +224,8 @@ bool DynamicRecursiveASTVisitor::TraverseLambdaCapture(LambdaExpr *LE,
                                                                       Init);
 }
 
-bool DynamicRecursiveASTVisitor::TraverseStmt(Stmt *S,
-                                              DataRecursionQueue *Queue) {
-  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseStmt(S, Queue);
+bool DynamicRecursiveASTVisitor::TraverseStmt(Stmt *S) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseStmt(S);
 }
 
 bool DynamicRecursiveASTVisitor::TraverseTemplateArgument(
@@ -308,8 +313,8 @@ bool DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(
       NNS);
 }
 
-bool DynamicRecursiveASTVisitor::dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) {
-  return Impl(*this).RecursiveASTVisitor<Impl>::dataTraverseNode(S, Queue);
+bool DynamicRecursiveASTVisitor::dataTraverseNode(Stmt *S) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::dataTraverseNode(S, nullptr);
 }
 
 /*
diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index e9c8779972f475..2c2399b1951b89 100644
--- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -174,11 +174,7 @@ class MatchChildASTVisitor : public DynamicRecursiveASTVisitor {
     return StmtToTraverse;
   }
 
-  bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr) override {
-    // If we need to keep track of the depth, we can't perform data recursion.
-    if (CurrentDepth == 0 || (CurrentDepth <= MaxDepth && MaxDepth < INT_MAX))
-      Queue = nullptr;
-
+  bool TraverseStmt(Stmt *StmtNode) override {
     ScopedIncrement ScopedDepth(&CurrentDepth);
     Stmt *StmtToTraverse = getStmtToTraverse(StmtNode);
     if (!StmtToTraverse)
@@ -189,7 +185,7 @@ class MatchChildASTVisitor : public DynamicRecursiveASTVisitor {
 
     if (!match(*StmtToTraverse))
       return false;
-    return DynamicRecursiveASTVisitor::TraverseStmt(StmtToTraverse, Queue);
+    return DynamicRecursiveASTVisitor::TraverseStmt(StmtToTraverse);
   }
   // We assume that the QualType and the contained type are on the same
   // hierarchy level. Thus, we try to match either of them.
@@ -498,7 +494,7 @@ class MatchASTVisitor : public DynamicRecursiveASTVisitor,
   }
 
   bool TraverseDecl(Decl *DeclNode) override;
-  bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr) override;
+  bool TraverseStmt(Stmt *StmtNode) override;
   bool TraverseType(QualType TypeNode) override;
   bool TraverseTypeLoc(TypeLoc TypeNode) override;
   bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) override;
@@ -507,7 +503,7 @@ class MatchASTVisitor : public DynamicRecursiveASTVisitor,
   bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc& TAL) override;
   bool TraverseAttr(Attr *AttrNode) override;
 
-  bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) override {
+  bool dataTraverseNode(Stmt *S) override {
     if (auto *RF = dyn_cast<CXXForRangeStmt>(S)) {
       {
         ASTNodeNotAsIsSourceScope RAII(this, true);
@@ -578,7 +574,7 @@ class MatchASTVisitor : public DynamicRecursiveASTVisitor,
           TraverseType(E);
 
         if (Expr *NE = T->getNoexceptExpr())
-          TraverseStmt(NE, Queue);
+          TraverseStmt(NE);
 
         if (LE->hasExplicitResultType())
           TraverseTypeLoc(Proto.getReturnLoc());
@@ -588,7 +584,7 @@ class MatchASTVisitor : public DynamicRecursiveASTVisitor,
       TraverseStmt(LE->getBody());
       return true;
     }
-    return DynamicRecursiveASTVisitor::dataTraverseNode(S, Queue);
+    return DynamicRecursiveASTVisitor::dataTraverseNode(S);
   }
 
   // Matches children or descendants of 'Node' with 'BaseMatcher'.
@@ -1463,7 +1459,7 @@ bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
   return DynamicRecursiveASTVisitor::TraverseDecl(DeclNode);
 }
 
-bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
+bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode) {
   if (!StmtNode) {
     return true;
   }
@@ -1472,7 +1468,7 @@ bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
 
   ASTNodeNotSpelledInSourceScope RAII(this, ScopedTraversal);
   match(*StmtNode);
-  return DynamicRecursiveASTVisitor::TraverseStmt(StmtNode, Queue);
+  return DynamicRecursiveASTVisitor::TraverseStmt(StmtNode);
 }
 
 bool MatchASTVisitor::TraverseType(QualType TypeNode) {
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index e1f214c1c582a7..912bcb6f353f96 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -170,7 +170,7 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor {
     return DynamicRecursiveASTVisitor::TraverseCXXTypeidExpr(Node);
   }
 
-  bool TraverseStmt(Stmt *Node, DataRecursionQueue *Queue = nullptr) override {
+  bool TraverseStmt(Stmt *Node) override {
     if (!Node)
       return true;
     if (!match(*Node))
diff --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp
index 4f09d0d7a16e8e..cf7da0893cafb8 100644
--- a/clang/lib/Index/IndexTypeSourceInfo.cpp
+++ b/clang/lib/Index/IndexTypeSourceInfo.cpp
@@ -233,7 +233,7 @@ class TypeIndexer : public DynamicRecursiveASTVisitor {
                                     ParentDC, SymbolRoleSet(), Relations);
   }
 
-  bool TraverseStmt(Stmt *S, DataRecursionQueue* = nullptr) override {
+  bool TraverseStmt(Stmt *S) override {
     IndexCtx.indexBody(S, Parent, ParentDC);
     return true;
   }
diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp
index 80f42f6cf4990f..ed78199015165d 100644
--- a/clang/lib/Sema/SemaAvailability.cpp
+++ b/clang/lib/Sema/SemaAvailability.cpp
@@ -779,7 +779,7 @@ class DiagnoseUnguardedAvailability : public DynamicRecursiveASTVisitor {
         SemaRef.Context.getTargetInfo().getPlatformMinVersion());
   }
 
-  bool TraverseStmt(Stmt *S, DataRecursionQueue* = nullptr) override {
+  bool TraverseStmt(Stmt *S) override {
     if (!S)
       return true;
     StmtStack.push_back(S);
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 6526548685c390..ce62cb417e1db2 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -2584,7 +2584,7 @@ struct DependencyChecker : DynamicRecursiveASTVisitor {
     return false;
   }
 
-  bool TraverseStmt(Stmt *S, DataRecursionQueue *Q = nullptr) override {
+  bool TraverseStmt(Stmt *S) override {
     // Prune out non-type-dependent expressions if requested. This can
     // sometimes result in us failing to find a template parameter reference
     // (if a value-dependent expression creates a dependent type), but this
@@ -2592,7 +2592,7 @@ struct DependencyChecker : DynamicRecursiveASTVisitor {
     if (auto *E = dyn_cast_or_null<Expr>(S))
       if (IgnoreNonTypeDependent && !E->isTypeDependent())
         return true;
-    return DynamicRecursiveASTVisitor::TraverseStmt(S, Q);
+    return DynamicRecursiveASTVisitor::TraverseStmt(S);
   }
 
   bool TraverseTypeLoc(TypeLoc TL) override {
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index e88d41208bdee0..11462fb362721e 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -128,10 +128,10 @@ class CollectUnexpandedParameterPacksVisitor
 
   /// Suppress traversal into statements and expressions that
   /// do not contain unexpanded parameter packs.
-  bool TraverseStmt(Stmt *S, DataRecursionQueue *Q = nullptr) override {
+  bool TraverseStmt(Stmt *S) override {
     Expr *E = dyn_cast_or_null<Expr>(S);
     if ((E && E->containsUnexpandedParameterPack()) || InLambda)
-      return DynamicRecursiveASTVisitor::TraverseStmt(S, Q);
+      return DynamicRecursiveASTVisitor::TraverseStmt(S);
 
     return true;
   }
diff --git a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
index ee5c69ef55e598..0440e47ddb4ae4 100644
--- a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
+++ b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
@@ -237,7 +237,7 @@ struct PreorderVisitor : DynamicRecursiveASTVisitor {
     PostTraverse(SavedState);
     return true;
   }
-  bool TraverseStmt(Stmt *S, DataRecursionQueue* = nullptr) override {
+  bool TraverseStmt(Stmt *S) override {
     if (auto *E = dyn_cast_or_null<Expr>(S))
       S = E->IgnoreImplicit();
     if (isNodeExcluded(Tree.AST.getSourceManager(), S))

>From c60376418407188af2017652114baae90c586be5 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 19 Aug 2024 18:11:39 +0200
Subject: [PATCH 18/25] Make a bunch of visitors 'final' to see if that makes a
 difference

---
 clang/docs/RAVFrontendAction.rst                          | 2 +-
 clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp   | 4 ++--
 clang/examples/PrintFunctionNames/PrintFunctionNames.cpp  | 2 +-
 clang/include/clang/Analysis/CallGraph.h                  | 2 +-
 clang/lib/ARCMigrate/ObjCMT.cpp                           | 6 +++---
 clang/lib/ARCMigrate/TransAPIUses.cpp                     | 2 +-
 clang/lib/ARCMigrate/TransARCAssign.cpp                   | 2 +-
 clang/lib/ARCMigrate/TransAutoreleasePool.cpp             | 4 ++--
 clang/lib/ARCMigrate/TransBlockObjCVariable.cpp           | 6 +++---
 clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp   | 2 +-
 clang/lib/ARCMigrate/TransGCAttrs.cpp                     | 2 +-
 clang/lib/ARCMigrate/TransGCCalls.cpp                     | 2 +-
 clang/lib/ARCMigrate/TransProtectedScope.cpp              | 4 ++--
 clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp       | 2 +-
 clang/lib/ARCMigrate/Transforms.cpp                       | 8 ++++----
 clang/lib/AST/ASTImporterLookupTable.cpp                  | 2 +-
 clang/lib/AST/StmtOpenACC.cpp                             | 2 +-
 clang/lib/ASTMatchers/ASTMatchFinder.cpp                  | 6 +++---
 clang/lib/Analysis/CalledOnceCheck.cpp                    | 2 +-
 clang/lib/Analysis/ReachableCode.cpp                      | 2 +-
 clang/lib/Analysis/UnsafeBufferUsage.cpp                  | 2 +-
 clang/lib/CodeGen/CGDebugInfo.cpp                         | 4 ++--
 clang/lib/CodeGen/CodeGenModule.cpp                       | 2 +-
 clang/lib/CodeGen/CodeGenPGO.cpp                          | 2 +-
 clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp        | 2 +-
 clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp     | 2 +-
 clang/lib/Index/IndexBody.cpp                             | 2 +-
 clang/lib/Index/IndexTypeSourceInfo.cpp                   | 2 +-
 clang/lib/Sema/AnalysisBasedWarnings.cpp                  | 4 ++--
 clang/lib/Sema/SemaAvailability.cpp                       | 6 +++---
 clang/lib/Sema/SemaCodeComplete.cpp                       | 2 +-
 clang/lib/Sema/SemaDeclAttr.cpp                           | 2 +-
 clang/lib/Sema/SemaDeclCXX.cpp                            | 4 ++--
 clang/lib/Sema/SemaDeclObjC.cpp                           | 2 +-
 clang/lib/Sema/SemaExpr.cpp                               | 6 +++---
 clang/lib/Sema/SemaExprCXX.cpp                            | 2 +-
 clang/lib/Sema/SemaHLSL.cpp                               | 4 ++--
 clang/lib/Sema/SemaStmt.cpp                               | 2 +-
 clang/lib/Sema/SemaTemplate.cpp                           | 2 +-
 clang/lib/Sema/SemaTemplateDeduction.cpp                  | 2 +-
 clang/lib/Sema/SemaTemplateVariadic.cpp                   | 2 +-
 clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp | 2 +-
 clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp   | 2 +-
 .../StaticAnalyzer/Checkers/DynamicTypePropagation.cpp    | 2 +-
 .../lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp  | 2 +-
 clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp | 2 +-
 .../Checkers/ObjCMissingSuperCallChecker.cpp              | 2 +-
 clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp      | 2 +-
 .../Checkers/WebKit/NoUncountedMembersChecker.cpp         | 2 +-
 .../Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp    | 2 +-
 .../Checkers/WebKit/UncountedCallArgsChecker.cpp          | 2 +-
 .../Checkers/WebKit/UncountedLambdaCapturesChecker.cpp    | 2 +-
 .../Checkers/WebKit/UncountedLocalVarsChecker.cpp         | 2 +-
 clang/lib/StaticAnalyzer/Core/BugSuppression.cpp          | 2 +-
 clang/lib/Tooling/ASTDiff/ASTDiff.cpp                     | 2 +-
 clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp        | 2 +-
 clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp | 2 +-
 clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp     | 2 +-
 clang/unittests/Analysis/CloneDetectionTest.cpp           | 2 +-
 59 files changed, 79 insertions(+), 79 deletions(-)

diff --git a/clang/docs/RAVFrontendAction.rst b/clang/docs/RAVFrontendAction.rst
index 1e7d88a19f201a..28a99d1744b7b5 100644
--- a/clang/docs/RAVFrontendAction.rst
+++ b/clang/docs/RAVFrontendAction.rst
@@ -150,7 +150,7 @@ Now we can combine all of the above into a small example program:
 
       using namespace clang;
 
-      class FindNamedClassVisitor : public DynamicRecursiveASTVisitor {
+      class FindNamedClassVisitor final : public DynamicRecursiveASTVisitor {
       public:
         explicit FindNamedClassVisitor(ASTContext *Context)
           : Context(Context) {}
diff --git a/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp b/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp
index 451506b13ab313..036c54e593dab4 100644
--- a/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp
+++ b/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp
@@ -41,7 +41,7 @@ bool isMarkedAsCallSuper(const CXXMethodDecl *D) {
   return MarkedMethods.contains(D);
 }
 
-class MethodUsageVisitor : public DynamicRecursiveASTVisitor {
+class MethodUsageVisitor final : public DynamicRecursiveASTVisitor {
 public:
   bool IsOverriddenUsed = false;
   explicit MethodUsageVisitor(
@@ -68,7 +68,7 @@ class MethodUsageVisitor : public DynamicRecursiveASTVisitor {
   llvm::SmallPtrSet<const CXXMethodDecl *, 16> &MustCalledMethods;
 };
 
-class CallSuperVisitor : public DynamicRecursiveASTVisitor {
+class CallSuperVisitor final : public DynamicRecursiveASTVisitor {
 public:
   CallSuperVisitor(DiagnosticsEngine &Diags) : Diags(Diags) {
     WarningSuperNotCalled = Diags.getCustomDiagID(
diff --git a/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp b/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp
index 5100901f74d992..248e3e159b329a 100644
--- a/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp
+++ b/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp
@@ -52,7 +52,7 @@ class PrintFunctionsConsumer : public ASTConsumer {
     // The advantage of doing this in HandleTranslationUnit() is that all
     // codegen (when using -add-plugin) is completely finished and this can't
     // affect the compiler output.
-    struct Visitor : DynamicRecursiveASTVisitor {
+    struct Visitor final : DynamicRecursiveASTVisitor {
       const std::set<std::string> &ParsedTemplates;
       Visitor(const std::set<std::string> &ParsedTemplates)
           : ParsedTemplates(ParsedTemplates) {}
diff --git a/clang/include/clang/Analysis/CallGraph.h b/clang/include/clang/Analysis/CallGraph.h
index c11d163f8fe20d..4266ebfd2f7829 100644
--- a/clang/include/clang/Analysis/CallGraph.h
+++ b/clang/include/clang/Analysis/CallGraph.h
@@ -40,7 +40,7 @@ class Stmt;
 /// The call graph extends itself with the given declarations by implementing
 /// the recursive AST visitor, which constructs the graph by visiting the given
 /// declarations.
-class CallGraph : public DynamicRecursiveASTVisitor {
+class CallGraph final : public DynamicRecursiveASTVisitor {
   friend class CallGraphNode;
 
   using FunctionMapTy =
diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp
index 62402646009e12..f99dcaabd4adb3 100644
--- a/clang/lib/ARCMigrate/ObjCMT.cpp
+++ b/clang/lib/ARCMigrate/ObjCMT.cpp
@@ -308,7 +308,7 @@ namespace {
     return true;
   }
 
-  class ObjCMigrator : public DynamicRecursiveASTVisitor {
+  class ObjCMigrator final : public DynamicRecursiveASTVisitor {
     ObjCMigrateASTConsumer &Consumer;
     ParentMap &PMap;
 
@@ -354,7 +354,7 @@ namespace {
     }
   };
 
-  class BodyMigrator : public DynamicRecursiveASTVisitor {
+  class BodyMigrator final : public DynamicRecursiveASTVisitor {
     ObjCMigrateASTConsumer &Consumer;
     std::unique_ptr<ParentMap> PMap;
 
@@ -1672,7 +1672,7 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
 }
 
 namespace {
-class SuperInitChecker : public DynamicRecursiveASTVisitor {
+class SuperInitChecker final : public DynamicRecursiveASTVisitor {
 public:
   SuperInitChecker() {
     ShouldVisitTemplateInstantiations = false;
diff --git a/clang/lib/ARCMigrate/TransAPIUses.cpp b/clang/lib/ARCMigrate/TransAPIUses.cpp
index 4525aa8718d890..1ec65d730a81e0 100644
--- a/clang/lib/ARCMigrate/TransAPIUses.cpp
+++ b/clang/lib/ARCMigrate/TransAPIUses.cpp
@@ -27,7 +27,7 @@ using namespace trans;
 
 namespace {
 
-class APIChecker : public DynamicRecursiveASTVisitor {
+class APIChecker final : public DynamicRecursiveASTVisitor {
   MigrationPass &Pass;
 
   Selector getReturnValueSel, setReturnValueSel;
diff --git a/clang/lib/ARCMigrate/TransARCAssign.cpp b/clang/lib/ARCMigrate/TransARCAssign.cpp
index 672d9b7865d805..8d93b10414ce63 100644
--- a/clang/lib/ARCMigrate/TransARCAssign.cpp
+++ b/clang/lib/ARCMigrate/TransARCAssign.cpp
@@ -31,7 +31,7 @@ using namespace trans;
 
 namespace {
 
-class ARCAssignChecker : public DynamicRecursiveASTVisitor {
+class ARCAssignChecker final : public DynamicRecursiveASTVisitor {
   MigrationPass &Pass;
   llvm::DenseSet<VarDecl *> ModifiedVars;
 
diff --git a/clang/lib/ARCMigrate/TransAutoreleasePool.cpp b/clang/lib/ARCMigrate/TransAutoreleasePool.cpp
index 03dba2b20f95e9..6a00bb1cbc5ed1 100644
--- a/clang/lib/ARCMigrate/TransAutoreleasePool.cpp
+++ b/clang/lib/ARCMigrate/TransAutoreleasePool.cpp
@@ -39,7 +39,7 @@ using namespace trans;
 
 namespace {
 
-class ReleaseCollector : public DynamicRecursiveASTVisitor {
+class ReleaseCollector final : public DynamicRecursiveASTVisitor {
   Decl *Dcl;
   SmallVectorImpl<ObjCMessageExpr *> &Releases;
 
@@ -244,7 +244,7 @@ class AutoreleasePoolRewriter
     }
   };
 
-  class NameReferenceChecker : public DynamicRecursiveASTVisitor {
+  class NameReferenceChecker final : public DynamicRecursiveASTVisitor {
     ASTContext &Ctx;
     SourceRange ScopeRange;
     SourceLocation &referenceLoc, &declarationLoc;
diff --git a/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp b/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
index 3d4e34952a1798..2d3cec91b96aa6 100644
--- a/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
+++ b/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
@@ -36,10 +36,10 @@ using namespace trans;
 
 namespace {
 
-class RootBlockObjCVarRewriter : public DynamicRecursiveASTVisitor {
+class RootBlockObjCVarRewriter final : public DynamicRecursiveASTVisitor {
   llvm::DenseSet<VarDecl *> &VarsToChange;
 
-  class BlockVarChecker : public DynamicRecursiveASTVisitor {
+  class BlockVarChecker final : public DynamicRecursiveASTVisitor {
     VarDecl *Var;
 
   public:
@@ -106,7 +106,7 @@ class RootBlockObjCVarRewriter : public DynamicRecursiveASTVisitor {
   }
 };
 
-class BlockObjCVarRewriter : public DynamicRecursiveASTVisitor {
+class BlockObjCVarRewriter final : public DynamicRecursiveASTVisitor {
   llvm::DenseSet<VarDecl *> &VarsToChange;
 
 public:
diff --git a/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp b/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
index 51c07a1d4fc4ab..a63e1750b95da5 100644
--- a/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
+++ b/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
@@ -143,7 +143,7 @@ class EmptyChecker : public StmtVisitor<EmptyChecker, bool> {
   }
 };
 
-class EmptyStatementsRemover : public DynamicRecursiveASTVisitor {
+class EmptyStatementsRemover final : public DynamicRecursiveASTVisitor {
   MigrationPass &Pass;
 
 public:
diff --git a/clang/lib/ARCMigrate/TransGCAttrs.cpp b/clang/lib/ARCMigrate/TransGCAttrs.cpp
index f4cc0d839e495e..bcf874c0fd56d2 100644
--- a/clang/lib/ARCMigrate/TransGCAttrs.cpp
+++ b/clang/lib/ARCMigrate/TransGCAttrs.cpp
@@ -23,7 +23,7 @@ using namespace trans;
 namespace {
 
 /// Collects all the places where GC attributes __strong/__weak occur.
-class GCAttrsCollector : public DynamicRecursiveASTVisitor {
+class GCAttrsCollector final : public DynamicRecursiveASTVisitor {
   MigrationContext &MigrateCtx;
   bool FullyMigratable;
   std::vector<ObjCPropertyDecl *> &AllProps;
diff --git a/clang/lib/ARCMigrate/TransGCCalls.cpp b/clang/lib/ARCMigrate/TransGCCalls.cpp
index 1da686cd7ec8c2..de758f33fdcd69 100644
--- a/clang/lib/ARCMigrate/TransGCCalls.cpp
+++ b/clang/lib/ARCMigrate/TransGCCalls.cpp
@@ -17,7 +17,7 @@ using namespace trans;
 
 namespace {
 
-class GCCollectableCallsChecker : public DynamicRecursiveASTVisitor {
+class GCCollectableCallsChecker final : public DynamicRecursiveASTVisitor {
   MigrationContext &MigrateCtx;
   IdentifierInfo *NSMakeCollectableII;
   IdentifierInfo *CFMakeCollectableII;
diff --git a/clang/lib/ARCMigrate/TransProtectedScope.cpp b/clang/lib/ARCMigrate/TransProtectedScope.cpp
index b6d4b1b7c771ae..ef526f7edcaa94 100644
--- a/clang/lib/ARCMigrate/TransProtectedScope.cpp
+++ b/clang/lib/ARCMigrate/TransProtectedScope.cpp
@@ -23,7 +23,7 @@ using namespace trans;
 
 namespace {
 
-class LocalRefsCollector : public DynamicRecursiveASTVisitor {
+class LocalRefsCollector final : public DynamicRecursiveASTVisitor {
   SmallVectorImpl<DeclRefExpr *> &Refs;
 
 public:
@@ -52,7 +52,7 @@ struct CaseInfo {
     : SC(S), Range(Range), State(St_Unchecked) {}
 };
 
-class CaseCollector : public DynamicRecursiveASTVisitor {
+class CaseCollector final : public DynamicRecursiveASTVisitor {
   ParentMap &PMap;
   SmallVectorImpl<CaseInfo> &Cases;
 
diff --git a/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp b/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
index ea87b9288de13e..a606a52b826614 100644
--- a/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
+++ b/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
@@ -22,7 +22,7 @@ using namespace trans;
 
 namespace {
 
-class ZeroOutInDeallocRemover : public DynamicRecursiveASTVisitor {
+class ZeroOutInDeallocRemover final : public DynamicRecursiveASTVisitor {
   MigrationPass &Pass;
 
   llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*> SynthesizedProperties;
diff --git a/clang/lib/ARCMigrate/Transforms.cpp b/clang/lib/ARCMigrate/Transforms.cpp
index 8b429bcdd1e7a8..7363427580c83b 100644
--- a/clang/lib/ARCMigrate/Transforms.cpp
+++ b/clang/lib/ARCMigrate/Transforms.cpp
@@ -211,7 +211,7 @@ StringRef trans::getNilString(MigrationPass &Pass) {
 
 namespace {
 
-class ReferenceClear : public DynamicRecursiveASTVisitor {
+class ReferenceClear final : public DynamicRecursiveASTVisitor {
   ExprSet &Refs;
 public:
   ReferenceClear(ExprSet &refs) : Refs(refs) { }
@@ -221,7 +221,7 @@ class ReferenceClear : public DynamicRecursiveASTVisitor {
   }
 };
 
-class ReferenceCollector : public DynamicRecursiveASTVisitor {
+class ReferenceCollector final : public DynamicRecursiveASTVisitor {
   ValueDecl *Dcl;
   ExprSet &Refs;
 
@@ -236,7 +236,7 @@ class ReferenceCollector : public DynamicRecursiveASTVisitor {
   }
 };
 
-class RemovablesCollector : public DynamicRecursiveASTVisitor {
+class RemovablesCollector final : public DynamicRecursiveASTVisitor {
   ExprSet &Removables;
 
 public:
@@ -317,7 +317,7 @@ void trans::collectRemovables(Stmt *S, ExprSet &exprs) {
 
 namespace {
 
-class ASTTransform : public DynamicRecursiveASTVisitor {
+class ASTTransform final : public DynamicRecursiveASTVisitor {
   MigrationContext &MigrateCtx;
 
 public:
diff --git a/clang/lib/AST/ASTImporterLookupTable.cpp b/clang/lib/AST/ASTImporterLookupTable.cpp
index b7c112540c1c60..37807de07e7593 100644
--- a/clang/lib/AST/ASTImporterLookupTable.cpp
+++ b/clang/lib/AST/ASTImporterLookupTable.cpp
@@ -21,7 +21,7 @@ namespace clang {
 
 namespace {
 
-struct Builder : DynamicRecursiveASTVisitor {
+struct Builder final : DynamicRecursiveASTVisitor {
   ASTImporterLookupTable <
   Builder(ASTImporterLookupTable &LT) : LT(LT) {
     ShouldVisitTemplateInstantiations = true;
diff --git a/clang/lib/AST/StmtOpenACC.cpp b/clang/lib/AST/StmtOpenACC.cpp
index fbf0ef540eb685..366f4e8df0885a 100644
--- a/clang/lib/AST/StmtOpenACC.cpp
+++ b/clang/lib/AST/StmtOpenACC.cpp
@@ -44,7 +44,7 @@ OpenACCComputeConstruct *OpenACCComputeConstruct::Create(
 }
 
 void OpenACCComputeConstruct::findAndSetChildLoops() {
-  struct LoopConstructFinder : DynamicRecursiveASTVisitor {
+  struct LoopConstructFinder final : DynamicRecursiveASTVisitor {
     OpenACCComputeConstruct *Construct = nullptr;
 
     LoopConstructFinder(OpenACCComputeConstruct *Construct)
diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index 2c2399b1951b89..e0aecb1d1ccad4 100644
--- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -87,7 +87,7 @@ struct MemoizedMatchResult {
 
 // A RecursiveASTVisitor that traverses all children or all descendants of
 // a node.
-class MatchChildASTVisitor : public DynamicRecursiveASTVisitor {
+class MatchChildASTVisitor final : public DynamicRecursiveASTVisitor {
 public:
   // Creates an AST visitor that matches 'matcher' on all children or
   // descendants of a traversed node. max_depth is the maximum depth
@@ -408,8 +408,8 @@ class MatchChildASTVisitor : public DynamicRecursiveASTVisitor {
 
 // Controls the outermost traversal of the AST and allows to match multiple
 // matchers.
-class MatchASTVisitor : public DynamicRecursiveASTVisitor,
-                        public ASTMatchFinder {
+class MatchASTVisitor final : public DynamicRecursiveASTVisitor,
+                              public ASTMatchFinder {
 public:
   MatchASTVisitor(const MatchFinder::MatchersByType *Matchers,
                   const MatchFinder::MatchFinderOptions &Options)
diff --git a/clang/lib/Analysis/CalledOnceCheck.cpp b/clang/lib/Analysis/CalledOnceCheck.cpp
index 73dc6bbe154b2b..cada4add01d9a5 100644
--- a/clang/lib/Analysis/CalledOnceCheck.cpp
+++ b/clang/lib/Analysis/CalledOnceCheck.cpp
@@ -426,7 +426,7 @@ const Expr *getCondition(const Stmt *S) {
 /// of the AST will end up in the results.
 /// Results might have duplicate names, if this is a problem, convert to
 /// string sets afterwards.
-class NamesCollector : public DynamicRecursiveASTVisitor {
+class NamesCollector final : public DynamicRecursiveASTVisitor {
 public:
   static constexpr unsigned EXPECTED_NUMBER_OF_NAMES = 5;
   using NameCollection =
diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp
index 905192c7edd226..02948479faae35 100644
--- a/clang/lib/Analysis/ReachableCode.cpp
+++ b/clang/lib/Analysis/ReachableCode.cpp
@@ -476,7 +476,7 @@ static bool isInCoroutineStmt(const Stmt *DeadStmt, const CFGBlock *Block) {
     }
   if (!CoroStmt)
     return false;
-  struct Checker : DynamicRecursiveASTVisitor {
+  struct Checker final : DynamicRecursiveASTVisitor {
     const Stmt *DeadStmt;
     bool CoroutineSubStmt = false;
     Checker(const Stmt *S) : DeadStmt(S) {
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index 912bcb6f353f96..22b628d230b907 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -81,7 +81,7 @@ static std::string getDREAncestorString(const DeclRefExpr *DRE,
 namespace clang::ast_matchers {
 // A `RecursiveASTVisitor` that traverses all descendants of a given node "n"
 // except for those belonging to a different callable of "n".
-class MatchDescendantVisitor : public DynamicRecursiveASTVisitor {
+class MatchDescendantVisitor final : public DynamicRecursiveASTVisitor {
 public:
   // Creates an AST visitor that matches `Matcher` on all
   // descendants of a given node "n" except for the ones
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 23a9ba18844a4a..2aff23aa271583 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -5446,7 +5446,7 @@ static bool ReferencesAnonymousEntity(ArrayRef<TemplateArgument> Args) {
     case TemplateArgument::Pack:
       return ReferencesAnonymousEntity(TA.getPackAsArray());
     case TemplateArgument::Type: {
-      struct ReferencesAnonymous : DynamicRecursiveASTVisitor {
+      struct ReferencesAnonymous final : DynamicRecursiveASTVisitor {
         bool RefAnon = false;
         bool VisitRecordType(RecordType *RT) override {
           if (ReferencesAnonymousEntity(RT)) {
@@ -5469,7 +5469,7 @@ static bool ReferencesAnonymousEntity(ArrayRef<TemplateArgument> Args) {
   });
 }
 namespace {
-struct ReconstitutableType : DynamicRecursiveASTVisitor {
+struct ReconstitutableType final : DynamicRecursiveASTVisitor {
   bool Reconstitutable = true;
   bool VisitVectorType(VectorType *FT) override {
     Reconstitutable = false;
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index d8e851dee474d5..690f0fece72975 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3951,7 +3951,7 @@ namespace {
   };
 
   // Make sure we're not referencing non-imported vars or functions.
-  struct DLLImportFunctionVisitor : DynamicRecursiveASTVisitor {
+  struct DLLImportFunctionVisitor final : DynamicRecursiveASTVisitor {
     bool SafeToInline = true;
 
     DLLImportFunctionVisitor() { ShouldVisitImplicitCode = true; }
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 0bfa3eb93eab09..833c491d2c5934 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -156,7 +156,7 @@ static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader,
 }
 
 /// A RecursiveASTVisitor that fills a map of statements to PGO counters.
-struct MapRegionCounters : DynamicRecursiveASTVisitor {
+struct MapRegionCounters final : DynamicRecursiveASTVisitor {
   /// The next counter value to assign.
   unsigned NextCounter;
   /// The function hash.
diff --git a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
index bfddb885b392e4..c3bc1641e542c4 100644
--- a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
+++ b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
@@ -58,7 +58,7 @@ class PCHContainerGenerator : public ASTConsumer {
   std::shared_ptr<PCHBuffer> Buffer;
 
   /// Visit every type and emit debug info for it.
-  struct DebugTypeVisitor : DynamicRecursiveASTVisitor {
+  struct DebugTypeVisitor final : DynamicRecursiveASTVisitor {
     clang::CodeGen::CGDebugInfo &DI;
     ASTContext &Ctx;
     DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx)
diff --git a/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp b/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp
index 616f0c9a8241f6..2473ad50ab4872 100644
--- a/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp
+++ b/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp
@@ -242,7 +242,7 @@ class InterfaceStubFunctionsConsumer : public ASTConsumer {
       : Instance(Instance), InFile(InFile), Format(Format) {}
 
   void HandleTranslationUnit(ASTContext &context) override {
-    struct Visitor : DynamicRecursiveASTVisitor {
+    struct Visitor final : DynamicRecursiveASTVisitor {
       bool VisitNamedDecl(NamedDecl *ND) override {
         if (const auto *FD = dyn_cast<FunctionDecl>(ND))
           if (FD->isLateTemplateParsed()) {
diff --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp
index 40f9deffa96292..8628a2dcdac90a 100644
--- a/clang/lib/Index/IndexBody.cpp
+++ b/clang/lib/Index/IndexBody.cpp
@@ -21,7 +21,7 @@ using namespace clang::index;
 
 namespace {
 
-class BodyIndexer : public DynamicRecursiveASTVisitor {
+class BodyIndexer final : public DynamicRecursiveASTVisitor {
   IndexingContext &IndexCtx;
   const NamedDecl *Parent;
   const DeclContext *ParentDC;
diff --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp
index cf7da0893cafb8..9c44847688f9ee 100644
--- a/clang/lib/Index/IndexTypeSourceInfo.cpp
+++ b/clang/lib/Index/IndexTypeSourceInfo.cpp
@@ -19,7 +19,7 @@ using namespace index;
 
 namespace {
 
-class TypeIndexer : public DynamicRecursiveASTVisitor {
+class TypeIndexer final : public DynamicRecursiveASTVisitor {
   IndexingContext &IndexCtx;
   const NamedDecl *Parent;
   const DeclContext *ParentDC;
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 62ed9d2c44a9bd..c894b358bf7c26 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -1067,7 +1067,7 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
 }
 
 namespace {
-  class FallthroughMapper : public DynamicRecursiveASTVisitor {
+  class FallthroughMapper final : public DynamicRecursiveASTVisitor {
   public:
     FallthroughMapper(Sema &S)
       : FoundSwitchStatements(false),
@@ -2473,7 +2473,7 @@ static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) {
 
 // An AST Visitor that calls a callback function on each callable DEFINITION
 // that is NOT in a dependent context:
-class CallableVisitor : public DynamicRecursiveASTVisitor {
+class CallableVisitor final : public DynamicRecursiveASTVisitor {
 private:
   llvm::function_ref<void(const Decl *)> Callback;
 
diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp
index ed78199015165d..d78cb406043e38 100644
--- a/clang/lib/Sema/SemaAvailability.cpp
+++ b/clang/lib/Sema/SemaAvailability.cpp
@@ -717,7 +717,7 @@ bool isBodyLikeChildStmt(const Stmt *S, const Stmt *Parent) {
   }
 }
 
-class StmtUSEFinder : public DynamicRecursiveASTVisitor {
+class StmtUSEFinder final : public DynamicRecursiveASTVisitor {
   const Stmt *Target;
 
 public:
@@ -733,7 +733,7 @@ class StmtUSEFinder : public DynamicRecursiveASTVisitor {
 
 /// Traverses the AST and finds the last statement that used a given
 /// declaration.
-class LastDeclUSEFinder : public DynamicRecursiveASTVisitor {
+class LastDeclUSEFinder final : public DynamicRecursiveASTVisitor {
   const Decl *D;
 
 public:
@@ -761,7 +761,7 @@ class LastDeclUSEFinder : public DynamicRecursiveASTVisitor {
 /// to a partially available declaration. Whenever we encounter an \c if of the
 /// form: \c if(@available(...)), we use the version from the condition to visit
 /// the then statement.
-class DiagnoseUnguardedAvailability : public DynamicRecursiveASTVisitor {
+class DiagnoseUnguardedAvailability final : public DynamicRecursiveASTVisitor {
   Sema &SemaRef;
   Decl *Ctx;
 
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 03a8915a68e933..3a7819a924b8d6 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -5424,7 +5424,7 @@ class ConceptInfo {
 
   // This visitor infers members of T based on traversing expressions/types
   // that involve T. It is invoked with code known to be valid for T.
-  class ValidVisitor : public DynamicRecursiveASTVisitor {
+  class ValidVisitor final : public DynamicRecursiveASTVisitor {
     ConceptInfo *Outer;
     const TemplateTypeParmType *T;
 
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index f85425a4cfa47d..0b45f7a8197d71 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -723,7 +723,7 @@ static void handleExcludeFromExplicitInstantiationAttr(Sema &S, Decl *D,
 namespace {
 /// Determines if a given Expr references any of the given function's
 /// ParmVarDecls, or the function's implicit `this` parameter (if applicable).
-class ArgumentDependenceChecker : public DynamicRecursiveASTVisitor {
+class ArgumentDependenceChecker final : public DynamicRecursiveASTVisitor {
 #ifndef NDEBUG
   const CXXRecordDecl *ClassType;
 #endif
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index bb9a2ab12f2f87..53ac48a07358bd 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -2499,7 +2499,7 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) {
   assert(FD->isImmediateEscalating() && !FD->isConsteval() &&
          "expected an immediate function");
   assert(FD->hasBody() && "expected the function to have a body");
-  struct ImmediateEscalatingExpressionsVisitor : DynamicRecursiveASTVisitor {
+  struct ImmediateEscalatingExpressionsVisitor final : DynamicRecursiveASTVisitor {
     Sema &SemaRef;
 
     const FunctionDecl *ImmediateFn;
@@ -18742,7 +18742,7 @@ void Sema::CheckDelegatingCtorCycles() {
 
 namespace {
   /// AST visitor that finds references to the 'this' expression.
-class FindCXXThisExpr : public DynamicRecursiveASTVisitor {
+class FindCXXThisExpr final : public DynamicRecursiveASTVisitor {
   Sema &S;
 
 public:
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 4d0be8ff41daca..3dfe5d3d33ea41 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -5320,7 +5320,7 @@ SemaObjC::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,
 namespace {
 /// Used by SemaObjC::DiagnoseUnusedBackingIvarInAccessor to check if a property
 /// accessor references the backing ivar.
-class UnusedBackingIvarChecker : public DynamicRecursiveASTVisitor {
+class UnusedBackingIvarChecker final : public DynamicRecursiveASTVisitor {
 public:
   Sema &S;
   const ObjCMethodDecl *Method;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index a4b37ad571b3c7..29c17093889d5c 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -5368,7 +5368,7 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
   return false;
 }
 
-struct ImmediateCallVisitor : DynamicRecursiveASTVisitor {
+struct ImmediateCallVisitor final : DynamicRecursiveASTVisitor {
   const ASTContext &Context;
   ImmediateCallVisitor(const ASTContext &Ctx) : Context(Ctx) {
     ShouldVisitImplicitCode = true;
@@ -17533,7 +17533,7 @@ HandleImmediateInvocations(Sema &SemaRef,
         RemoveNestedImmediateInvocation(SemaRef, Rec, It);
   } else if (Rec.ImmediateInvocationCandidates.size() == 1 &&
              Rec.ReferenceToConsteval.size()) {
-    struct SimpleRemove : DynamicRecursiveASTVisitor {
+    struct SimpleRemove final : DynamicRecursiveASTVisitor {
       llvm::SmallPtrSetImpl<DeclRefExpr *> &DRSet;
       SimpleRemove(llvm::SmallPtrSetImpl<DeclRefExpr *> &S) : DRSet(S) {}
       bool VisitDeclRefExpr(DeclRefExpr *E) override {
@@ -19826,7 +19826,7 @@ namespace {
   // TreeTransforms rebuilding the type in a new context. Rather than
   // duplicating the TreeTransform logic, we should consider reusing it here.
   // Currently that causes problems when rebuilding LambdaExprs.
-class MarkReferencedDecls : public DynamicRecursiveASTVisitor {
+class MarkReferencedDecls final : public DynamicRecursiveASTVisitor {
   Sema &S;
   SourceLocation Loc;
 
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index bbdb534aa9dc9e..8931945b07f4ee 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -8762,7 +8762,7 @@ static ExprResult attemptRecovery(Sema &SemaRef,
 }
 
 namespace {
-class FindTypoExprs : public DynamicRecursiveASTVisitor {
+class FindTypoExprs final : public DynamicRecursiveASTVisitor {
   llvm::SmallSetVector<TypoExpr *, 2> &TypoExprs;
 
 public:
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index fa24644541fc87..356840878585f6 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -356,7 +356,7 @@ static bool isLegalTypeForHLSLSV_DispatchThreadID(QualType T) {
   return true;
 }
 
-void SemaHLSL::handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL) {  
+void SemaHLSL::handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL) {
   auto *VD = cast<ValueDecl>(D);
   if (!isLegalTypeForHLSLSV_DispatchThreadID(VD->getType())) {
     Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
@@ -552,7 +552,7 @@ namespace {
 /// and of all exported functions, and any functions that are referenced
 /// from this AST. In other words, any functions that are reachable from
 /// the entry points.
-class DiagnoseHLSLAvailability : public DynamicRecursiveASTVisitor {
+class DiagnoseHLSLAvailability final : public DynamicRecursiveASTVisitor {
 
   Sema &SemaRef;
 
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 3e8057e30e3855..76a40626342dea 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -3594,7 +3594,7 @@ namespace {
 /// others. Pretend that all local typedefs are always referenced, to not warn
 /// on this. This isn't necessary if f has internal linkage, or the typedef
 /// is private.
-class LocalTypedefNameReferencer : public DynamicRecursiveASTVisitor {
+class LocalTypedefNameReferencer final : public DynamicRecursiveASTVisitor {
 public:
   LocalTypedefNameReferencer(Sema &S) : S(S) {}
   bool VisitRecordType(RecordType *RT) override;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index ce62cb417e1db2..d06fa749610f00 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -2546,7 +2546,7 @@ namespace {
 
 /// A class which looks for a use of a certain level of template
 /// parameter.
-struct DependencyChecker : DynamicRecursiveASTVisitor {
+struct DependencyChecker final : DynamicRecursiveASTVisitor {
   unsigned Depth;
 
   // Whether we're looking for a use of a template parameter that makes the
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0c302e53b62612..dc4045d010075b 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -6228,7 +6228,7 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
 }
 
 namespace {
-struct MarkUsedTemplateParameterVisitor : DynamicRecursiveASTVisitor {
+struct MarkUsedTemplateParameterVisitor final : DynamicRecursiveASTVisitor {
   llvm::SmallBitVector &Used;
   unsigned Depth;
 
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 11462fb362721e..12fe3a660109a1 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -28,7 +28,7 @@ using namespace clang;
 
 namespace {
   /// A class that collects unexpanded parameter packs.
-class CollectUnexpandedParameterPacksVisitor
+class CollectUnexpandedParameterPacksVisitor final
     : public DynamicRecursiveASTVisitor {
   SmallVectorImpl<UnexpandedParameterPack> &Unexpanded;
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
index aa0bd78c1472f5..275442973559e1 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
@@ -23,7 +23,7 @@ using namespace clang;
 using namespace ento;
 
 namespace {
-class CastToStructVisitor : public DynamicRecursiveASTVisitor {
+class CastToStructVisitor final : public DynamicRecursiveASTVisitor {
   BugReporter &BR;
   const CheckerBase *Checker;
   AnalysisDeclContext *AC;
diff --git a/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
index f7dba536b524f3..3ec46f055563d3 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
@@ -32,7 +32,7 @@ using namespace ento;
 namespace {
 
 /// A simple visitor to record what VarDecls occur in EH-handling code.
-class EHCodeVisitor : public DynamicRecursiveASTVisitor {
+class EHCodeVisitor final : public DynamicRecursiveASTVisitor {
 public:
   bool inEH;
   llvm::DenseSet<const VarDecl *> &S;
diff --git a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
index cdda319924563a..a540bc43695a4e 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
@@ -710,7 +710,7 @@ static bool isObjCTypeParamDependent(QualType Type) {
   // It is illegal to typedef parameterized types inside an interface. Therefore
   // an Objective-C type can only be dependent on a type parameter when the type
   // parameter structurally present in the type itself.
-  class IsObjCTypeParamDependentTypeVisitor
+  class IsObjCTypeParamDependentTypeVisitor final
       : public DynamicRecursiveASTVisitor  {
   public:
     IsObjCTypeParamDependentTypeVisitor() = default;
diff --git a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
index fa20766b639dcf..be98a3e58a83f9 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
@@ -32,7 +32,7 @@ static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1,
 //===----------------------------------------------------------------------===//
 
 namespace {
-class FindIdenticalExprVisitor : public DynamicRecursiveASTVisitor {
+class FindIdenticalExprVisitor final : public DynamicRecursiveASTVisitor {
   BugReporter &BR;
   const CheckerBase *Checker;
   AnalysisDeclContext *AC;
diff --git a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
index 342ff7fd6d817a..1dd0fb7b8fbfce 100644
--- a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
@@ -1191,7 +1191,7 @@ namespace {
 class PluralMisuseChecker : public Checker<check::ASTCodeBody> {
 
   // A helper class, which walks the AST
-  class MethodCrawler : public DynamicRecursiveASTVisitor {
+  class MethodCrawler final : public DynamicRecursiveASTVisitor {
     BugReporter &BR;
     const CheckerBase *Checker;
     AnalysisDeclContext *AC;
diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
index dea1b1aea016bf..55e4dcddfdcd88 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
@@ -38,7 +38,7 @@ struct SelectorDescriptor {
 // FindSuperCallVisitor - Identify specific calls to the superclass.
 //===----------------------------------------------------------------------===//
 
-class FindSuperCallVisitor : public DynamicRecursiveASTVisitor {
+class FindSuperCallVisitor final : public DynamicRecursiveASTVisitor {
 public:
   explicit FindSuperCallVisitor(Selector S) : DoesCallSuper(false), Sel(S) {}
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
index 4354f36b397977..9dbf63079e355f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
@@ -45,7 +45,7 @@ class PaddingChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {
     // The calls to checkAST* from AnalysisConsumer don't
     // visit template instantiations or lambda classes. We
     // want to visit those, so we make our own RecursiveASTVisitor.
-    struct LocalVisitor : DynamicRecursiveASTVisitor {
+    struct LocalVisitor final : DynamicRecursiveASTVisitor {
       const PaddingChecker *Checker;
       explicit LocalVisitor(const PaddingChecker *Checker) : Checker(Checker) {
         ShouldVisitTemplateInstantiations = true;
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/NoUncountedMembersChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/NoUncountedMembersChecker.cpp
index 2c30c7825b51e3..62a42234cba130 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/NoUncountedMembersChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/NoUncountedMembersChecker.cpp
@@ -45,7 +45,7 @@ class NoUncountedMemberChecker
     // The calls to checkAST* from AnalysisConsumer don't
     // visit template instantiations or lambda classes. We
     // want to visit those, so we make our own RecursiveASTVisitor.
-    struct LocalVisitor : DynamicRecursiveASTVisitor {
+    struct LocalVisitor final : DynamicRecursiveASTVisitor {
       const NoUncountedMemberChecker *Checker;
       explicit LocalVisitor(const NoUncountedMemberChecker *Checker)
           : Checker(Checker) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp
index c5e1af6e3ce082..9455bad3377505 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp
@@ -140,7 +140,7 @@ class RefCntblBaseVirtualDtorChecker
     // The calls to checkAST* from AnalysisConsumer don't
     // visit template instantiations or lambda classes. We
     // want to visit those, so we make our own RecursiveASTVisitor.
-    struct LocalVisitor : DynamicRecursiveASTVisitor {
+    struct LocalVisitor final : DynamicRecursiveASTVisitor {
       const RefCntblBaseVirtualDtorChecker *Checker;
       explicit LocalVisitor(const RefCntblBaseVirtualDtorChecker *Checker)
           : Checker(Checker) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
index a71027d0acb936..0acdcf8de519cd 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
@@ -43,7 +43,7 @@ class UncountedCallArgsChecker
     // The calls to checkAST* from AnalysisConsumer don't
     // visit template instantiations or lambda classes. We
     // want to visit those, so we make our own RecursiveASTVisitor.
-    struct LocalVisitor : DynamicRecursiveASTVisitor {
+    struct LocalVisitor final : DynamicRecursiveASTVisitor {
       const UncountedCallArgsChecker *Checker;
       explicit LocalVisitor(const UncountedCallArgsChecker *Checker)
           : Checker(Checker) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
index 917c7670c3790e..d2ae43cedff09e 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
@@ -35,7 +35,7 @@ class UncountedLambdaCapturesChecker
     // The calls to checkAST* from AnalysisConsumer don't
     // visit template instantiations or lambda classes. We
     // want to visit those, so we make our own RecursiveASTVisitor.
-    struct LocalVisitor : DynamicRecursiveASTVisitor {
+    struct LocalVisitor final : DynamicRecursiveASTVisitor {
       const UncountedLambdaCapturesChecker *Checker;
       explicit LocalVisitor(const UncountedLambdaCapturesChecker *Checker)
           : Checker(Checker) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp
index e24c67c4d788ea..3748cf15901e9b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp
@@ -119,7 +119,7 @@ class UncountedLocalVarsChecker
     // The calls to checkAST* from AnalysisConsumer don't
     // visit template instantiations or lambda classes. We
     // want to visit those, so we make our own RecursiveASTVisitor.
-    struct LocalVisitor : DynamicRecursiveASTVisitor {
+    struct LocalVisitor final : DynamicRecursiveASTVisitor {
       const UncountedLocalVarsChecker *Checker;
 
       TrivialFunctionAnalysis TFA;
diff --git a/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp b/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp
index 05c99c4a844e9e..319b3f01a41549 100644
--- a/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp
@@ -76,7 +76,7 @@ inline bool fullyContains(SourceRange Larger, SourceRange Smaller,
          isLessOrEqual(Smaller.getEnd(), Larger.getEnd(), SM);
 }
 
-class CacheInitializer : public DynamicRecursiveASTVisitor {
+class CacheInitializer final : public DynamicRecursiveASTVisitor {
 public:
   static void initialize(const Decl *D, Ranges &ToInit) {
     CacheInitializer(ToInit).TraverseDecl(const_cast<Decl *>(D));
diff --git a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
index 0440e47ddb4ae4..ec4f5b94832807 100644
--- a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
+++ b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
@@ -187,7 +187,7 @@ static bool isNodeExcluded(const SourceManager &SrcMgr, T *N) {
 
 namespace {
 // Sets Height, Parent and Children for each node.
-struct PreorderVisitor : DynamicRecursiveASTVisitor {
+struct PreorderVisitor final : DynamicRecursiveASTVisitor {
   int Id = 0, Depth = 0;
   NodeId Parent;
   SyntaxTree::Impl &Tree;
diff --git a/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp b/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp
index a726990d8ff5f2..aa6a571a820007 100644
--- a/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp
+++ b/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp
@@ -97,7 +97,7 @@ namespace {
 
 /// Recursively visits each NamedDecl node to find the declaration with a
 /// specific name.
-class NamedDeclFindingVisitor : public DynamicRecursiveASTVisitor {
+class NamedDeclFindingVisitor final : public DynamicRecursiveASTVisitor {
 public:
   explicit NamedDeclFindingVisitor(StringRef Name) : Name(Name) {}
 
diff --git a/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp b/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
index d7a1f761fc3030..f0f27c005bf9a5 100644
--- a/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ b/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -60,7 +60,7 @@ namespace {
 // AdditionalUSRFinder. AdditionalUSRFinder adds USRs of ctor and dtor if given
 // Decl refers to class and adds USRs of all overridden methods if Decl refers
 // to virtual method.
-class AdditionalUSRFinder : public DynamicRecursiveASTVisitor {
+class AdditionalUSRFinder final : public DynamicRecursiveASTVisitor {
 public:
   AdditionalUSRFinder(const Decl *FoundDecl, ASTContext &Context)
       : FoundDecl(FoundDecl), Context(Context) {
diff --git a/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp b/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
index 8b60134017724f..8e8271648ad08d 100644
--- a/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
+++ b/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
@@ -152,7 +152,7 @@ NestedNameSpecifier *GetNestedNameForType(TypeLoc TL) {
 //
 // This class will traverse the AST and find every AST node whose USR is in the
 // given USRs' set.
-class RenameLocFinder : public DynamicRecursiveASTVisitor {
+class RenameLocFinder final : public DynamicRecursiveASTVisitor {
 public:
   RenameLocFinder(llvm::ArrayRef<std::string> USRs, ASTContext &Context)
       : USRSet(USRs.begin(), USRs.end()), Context(Context) {}
diff --git a/clang/unittests/Analysis/CloneDetectionTest.cpp b/clang/unittests/Analysis/CloneDetectionTest.cpp
index 1b34ee5d6dde1f..a07bbc780ad6a7 100644
--- a/clang/unittests/Analysis/CloneDetectionTest.cpp
+++ b/clang/unittests/Analysis/CloneDetectionTest.cpp
@@ -15,7 +15,7 @@ namespace clang {
 namespace analysis {
 namespace {
 
-class CloneDetectionVisitor : public DynamicRecursiveASTVisitor {
+class CloneDetectionVisitor final : public DynamicRecursiveASTVisitor {
 
   CloneDetector &Detector;
 

>From 19cd49458b3e11086956c59811d3b609acc2c5c8 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 19 Aug 2024 18:18:43 +0200
Subject: [PATCH 19/25] Avoid including RecursiveASTVisitor.h wherever possible

---
 clang/lib/ARCMigrate/Transforms.cpp                 |  1 -
 clang/lib/ASTMatchers/GtestMatchers.cpp             |  1 -
 .../Analysis/FlowSensitive/DataflowEnvironment.cpp  |  1 -
 clang/lib/Sema/SemaConcept.cpp                      |  1 -
 clang/lib/Sema/SemaTemplateDeductionGuide.cpp       | 13 ++++++-------
 5 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/clang/lib/ARCMigrate/Transforms.cpp b/clang/lib/ARCMigrate/Transforms.cpp
index 7363427580c83b..ca24b512b4d9e1 100644
--- a/clang/lib/ARCMigrate/Transforms.cpp
+++ b/clang/lib/ARCMigrate/Transforms.cpp
@@ -10,7 +10,6 @@
 #include "Internals.h"
 #include "clang/ARCMigrate/ARCMT.h"
 #include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
diff --git a/clang/lib/ASTMatchers/GtestMatchers.cpp b/clang/lib/ASTMatchers/GtestMatchers.cpp
index a556d8ef2da066..d2a672535f2c5d 100644
--- a/clang/lib/ASTMatchers/GtestMatchers.cpp
+++ b/clang/lib/ASTMatchers/GtestMatchers.cpp
@@ -18,7 +18,6 @@
 #include "clang/ASTMatchers/GtestMatchers.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringRef.h"
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 295493944ac918..ff2a213f5d753a 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -16,7 +16,6 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/Type.h"
 #include "clang/Analysis/FlowSensitive/ASTOps.h"
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index de24bbe7eb99ce..4873acc82b8251 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -15,7 +15,6 @@
 #include "clang/AST/ASTLambda.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprConcepts.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/Basic/OperatorPrecedence.h"
 #include "clang/Sema/EnterExpressionEvaluationContext.h"
 #include "clang/Sema/Initialization.h"
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index 545da21183c3c4..533be539c446de 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -21,10 +21,10 @@
 #include "clang/AST/DeclFriend.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/DeclarationName.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/OperationKinds.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
@@ -637,8 +637,7 @@ struct ConvertConstructorToDeductionGuideTransform {
 SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList(
     const TemplateParameterList *TemplateParamsList,
     ArrayRef<TemplateArgument> DeducedArgs) {
-  struct TemplateParamsReferencedFinder
-      : public RecursiveASTVisitor<TemplateParamsReferencedFinder> {
+  struct TemplateParamsReferencedFinder final : DynamicRecursiveASTVisitor {
     const TemplateParameterList *TemplateParamList;
     llvm::BitVector ReferencedTemplateParams;
 
@@ -647,22 +646,22 @@ SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList(
         : TemplateParamList(TemplateParamList),
           ReferencedTemplateParams(TemplateParamList->size()) {}
 
-    bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+    bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) override {
       // We use the index and depth to retrieve the corresponding template
       // parameter from the parameter list, which is more robost.
       Mark(TTP->getDepth(), TTP->getIndex());
       return true;
     }
 
-    bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+    bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
       MarkAppeared(DRE->getFoundDecl());
       return true;
     }
 
-    bool TraverseTemplateName(TemplateName Template) {
+    bool TraverseTemplateName(TemplateName Template) override {
       if (auto *TD = Template.getAsTemplateDecl())
         MarkAppeared(TD);
-      return RecursiveASTVisitor::TraverseTemplateName(Template);
+      return DynamicRecursiveASTVisitor::TraverseTemplateName(Template);
     }
 
     void MarkAppeared(NamedDecl *ND) {

>From ad000269b099edec690575128feea2e0f36d05bb Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 19 Aug 2024 18:26:11 +0200
Subject: [PATCH 20/25] Make destructor = default

---
 clang/include/clang/AST/DynamicRecursiveASTVisitor.h | 6 +++---
 clang/lib/AST/DynamicRecursiveASTVisitor.cpp         | 3 +--
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
index 14b60ee0dc3192..1390977c09ea79 100644
--- a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -41,15 +41,15 @@ class DynamicRecursiveASTVisitor {
   DynamicRecursiveASTVisitor() = default;
 
 public:
+  virtual void anchor();
+
   // Copying/moving a polymorphic type is a bad idea.
   DynamicRecursiveASTVisitor(DynamicRecursiveASTVisitor &&) = delete;
   DynamicRecursiveASTVisitor(const DynamicRecursiveASTVisitor &) = delete;
   DynamicRecursiveASTVisitor &operator=(DynamicRecursiveASTVisitor &&) = delete;
   DynamicRecursiveASTVisitor &
   operator=(const DynamicRecursiveASTVisitor &) = delete;
-
-  // Declared out of line as a vtable anchor.
-  virtual ~DynamicRecursiveASTVisitor();
+  virtual ~DynamicRecursiveASTVisitor() = default;
 
   /// Recursively visits an entire AST, starting from the TranslationUnitDecl.
   /// \returns false if visitation was terminated early.
diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
index 7c39c6c58c02f4..133e2762061286 100644
--- a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
+++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
@@ -196,8 +196,7 @@ struct Impl : RecursiveASTVisitor<Impl> {
 };
 } // namespace
 
-// Declared out of line to serve as a vtable anchor.
-DynamicRecursiveASTVisitor::~DynamicRecursiveASTVisitor() = default;
+void DynamicRecursiveASTVisitor::anchor() { }
 
 bool DynamicRecursiveASTVisitor::TraverseAST(ASTContext &AST) {
   return Impl(*this).RecursiveASTVisitor<Impl>::TraverseAST(AST);

>From 1d2fdbabf39799370eeae4ea1c482cc55409788f Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 19 Aug 2024 22:16:50 +0200
Subject: [PATCH 21/25] Revert FallthroughMapper to use CRTP

---
 clang/lib/Sema/AnalysisBasedWarnings.cpp | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index c894b358bf7c26..f5ce8202547680 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -16,13 +16,14 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/EvaluatedExprVisitor.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/ParentMap.h"
-#include "clang/AST/DynamicRecursiveASTVisitor.h"
+#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
 #include "clang/AST/StmtVisitor.h"
@@ -1067,14 +1068,18 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
 }
 
 namespace {
-  class FallthroughMapper final : public DynamicRecursiveASTVisitor {
+  // This is not a dynamic visitor because it ends up traversing an
+  // order of magnitude more statements than every other visitor combined.
+  class FallthroughMapper final
+    : public RecursiveASTVisitor<FallthroughMapper> {
   public:
     FallthroughMapper(Sema &S)
       : FoundSwitchStatements(false),
         S(S) {
-      ShouldWalkTypesOfTypeLocs = false;
     }
 
+    bool shouldWalkTypesOfTypeLocs() const { return false; }
+
     bool foundSwitchStatements() const { return FoundSwitchStatements; }
 
     void markFallthroughVisited(const AttributedStmt *Stmt) {
@@ -1187,23 +1192,23 @@ namespace {
       return !!UnannotatedCnt;
     }
 
-    bool VisitAttributedStmt(AttributedStmt *S) override {
+    bool VisitAttributedStmt(AttributedStmt *S) {
       if (asFallThroughAttr(S))
         FallthroughStmts.insert(S);
       return true;
     }
 
-    bool VisitSwitchStmt(SwitchStmt *S) override {
+    bool VisitSwitchStmt(SwitchStmt *S) {
       FoundSwitchStatements = true;
       return true;
     }
 
     // We don't want to traverse local type declarations. We analyze their
     // methods separately.
-    bool TraverseDecl(Decl *D) override { return true; }
+    bool TraverseDecl(Decl *D) { return true; }
 
     // We analyze lambda bodies separately. Skip them here.
-    bool TraverseLambdaExpr(LambdaExpr *LE) override {
+    bool TraverseLambdaExpr(LambdaExpr *LE) {
       // Traverse the captures, but not the body.
       for (const auto C : zip(LE->captures(), LE->capture_inits()))
         TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));

>From 979eba07448d94966a061ee0323fe152fe6d6f02 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 19 Aug 2024 23:45:49 +0200
Subject: [PATCH 22/25] Revert "Revert FallthroughMapper to use CRTP"

This reverts commit 1d2fdbabf39799370eeae4ea1c482cc55409788f.
---
 clang/lib/Sema/AnalysisBasedWarnings.cpp | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index f5ce8202547680..c894b358bf7c26 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -16,14 +16,13 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
-#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/EvaluatedExprVisitor.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/ParentMap.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
 #include "clang/AST/StmtVisitor.h"
@@ -1068,18 +1067,14 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
 }
 
 namespace {
-  // This is not a dynamic visitor because it ends up traversing an
-  // order of magnitude more statements than every other visitor combined.
-  class FallthroughMapper final
-    : public RecursiveASTVisitor<FallthroughMapper> {
+  class FallthroughMapper final : public DynamicRecursiveASTVisitor {
   public:
     FallthroughMapper(Sema &S)
       : FoundSwitchStatements(false),
         S(S) {
+      ShouldWalkTypesOfTypeLocs = false;
     }
 
-    bool shouldWalkTypesOfTypeLocs() const { return false; }
-
     bool foundSwitchStatements() const { return FoundSwitchStatements; }
 
     void markFallthroughVisited(const AttributedStmt *Stmt) {
@@ -1192,23 +1187,23 @@ namespace {
       return !!UnannotatedCnt;
     }
 
-    bool VisitAttributedStmt(AttributedStmt *S) {
+    bool VisitAttributedStmt(AttributedStmt *S) override {
       if (asFallThroughAttr(S))
         FallthroughStmts.insert(S);
       return true;
     }
 
-    bool VisitSwitchStmt(SwitchStmt *S) {
+    bool VisitSwitchStmt(SwitchStmt *S) override {
       FoundSwitchStatements = true;
       return true;
     }
 
     // We don't want to traverse local type declarations. We analyze their
     // methods separately.
-    bool TraverseDecl(Decl *D) { return true; }
+    bool TraverseDecl(Decl *D) override { return true; }
 
     // We analyze lambda bodies separately. Skip them here.
-    bool TraverseLambdaExpr(LambdaExpr *LE) {
+    bool TraverseLambdaExpr(LambdaExpr *LE) override {
       // Traverse the captures, but not the body.
       for (const auto C : zip(LE->captures(), LE->capture_inits()))
         TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));

>From c50f8d1fcffdfc128e18391fee3142d361a8a376 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 19 Aug 2024 23:51:07 +0200
Subject: [PATCH 23/25] Revert MarkReferencedDecls visitor to use CRTP

---
 clang/lib/Sema/SemaExpr.cpp | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 29c17093889d5c..70aac27f9ce876 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -28,6 +28,7 @@
 #include "clang/AST/ExprOpenMP.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/ParentMapContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Builtins.h"
@@ -19826,14 +19827,15 @@ namespace {
   // TreeTransforms rebuilding the type in a new context. Rather than
   // duplicating the TreeTransform logic, we should consider reusing it here.
   // Currently that causes problems when rebuilding LambdaExprs.
-class MarkReferencedDecls final : public DynamicRecursiveASTVisitor {
+class MarkReferencedDecls final
+  : public RecursiveASTVisitor<MarkReferencedDecls> {
   Sema &S;
   SourceLocation Loc;
 
 public:
   MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) {}
 
-  bool TraverseTemplateArgument(const TemplateArgument &Arg) override;
+  bool TraverseTemplateArgument(const TemplateArgument &Arg);
 };
 }
 
@@ -19851,7 +19853,7 @@ bool MarkReferencedDecls::TraverseTemplateArgument(
     }
   }
 
-  return DynamicRecursiveASTVisitor::TraverseTemplateArgument(Arg);
+  return RecursiveASTVisitor::TraverseTemplateArgument(Arg);
 }
 
 void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) {

>From 42f415f162e9aef704806220233d71076c066ff7 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Tue, 20 Aug 2024 16:10:29 +0200
Subject: [PATCH 24/25] Revert "Revert MarkReferencedDecls visitor to use CRTP"

This reverts commit c50f8d1fcffdfc128e18391fee3142d361a8a376.
---
 clang/lib/Sema/SemaExpr.cpp | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 70aac27f9ce876..29c17093889d5c 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -28,7 +28,6 @@
 #include "clang/AST/ExprOpenMP.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/ParentMapContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Builtins.h"
@@ -19827,15 +19826,14 @@ namespace {
   // TreeTransforms rebuilding the type in a new context. Rather than
   // duplicating the TreeTransform logic, we should consider reusing it here.
   // Currently that causes problems when rebuilding LambdaExprs.
-class MarkReferencedDecls final
-  : public RecursiveASTVisitor<MarkReferencedDecls> {
+class MarkReferencedDecls final : public DynamicRecursiveASTVisitor {
   Sema &S;
   SourceLocation Loc;
 
 public:
   MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) {}
 
-  bool TraverseTemplateArgument(const TemplateArgument &Arg);
+  bool TraverseTemplateArgument(const TemplateArgument &Arg) override;
 };
 }
 
@@ -19853,7 +19851,7 @@ bool MarkReferencedDecls::TraverseTemplateArgument(
     }
   }
 
-  return RecursiveASTVisitor::TraverseTemplateArgument(Arg);
+  return DynamicRecursiveASTVisitor::TraverseTemplateArgument(Arg);
 }
 
 void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) {

>From 8f7d61923b414085d5d1e419cebd46500cef2662 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Tue, 20 Aug 2024 18:23:30 +0200
Subject: [PATCH 25/25] Add missing ObjC includes

---
 clang/lib/Sema/SemaAvailability.cpp     | 4 +++-
 clang/lib/Sema/SemaTemplateVariadic.cpp | 1 +
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp
index d78cb406043e38..f23cd73037e04c 100644
--- a/clang/lib/Sema/SemaAvailability.cpp
+++ b/clang/lib/Sema/SemaAvailability.cpp
@@ -12,9 +12,11 @@
 
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
-#include "clang/AST/StmtObjC.h"
+#include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/DynamicRecursiveASTVisitor.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/StmtObjC.h"
 #include "clang/Basic/DiagnosticSema.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/LangOptions.h"
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 12fe3a660109a1..00e31f137c5662 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -11,6 +11,7 @@
 #include "TypeLocBuilder.h"
 #include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/ParsedTemplate.h"



More information about the cfe-commits mailing list