llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Christopher Taylor (ct-clmsn)

<details>
<summary>Changes</summary>

@<!-- -->Sirraide : This is my first PR to clang and llvm. The PR creates a 
RecursiveASTVisitor type called `RecursiveASTEnterExitVisitor` that allows 
users to implement Visit methods before visiting an AST node and after visiting 
an AST node. The additional functionality is additive in nature and extends the 
existing work. Users can optionally implement `VisitEnter&lt;AST NodeType&gt;`, 
`Visit&lt;AST NodeType&gt;`, and `VisitExit&lt;AST NodeType&gt;`. This 
functionality makes visitation method behavior explicitly defined.

---

Patch is 268.14 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/136136.diff


39 Files Affected:

- (added) clang/include/clang/AST/RecursiveASTEnterExitVisitor.h (+4187) 
- (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+3) 
- (modified) clang/include/clang/AST/StmtOpenACC.h (+1) 
- (modified) clang/unittests/Tooling/CMakeLists.txt (+34) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTestDeclVisitor.cpp (+138) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTestPostOrderVisitor.cpp 
(+114) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTestTypeLocVisitor.cpp 
(+100) 
- (added) clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/Attr.cpp 
(+51) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/BitfieldInitializer.cpp
 (+34) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/CXXBoolLiteralExpr.cpp
 (+36) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/CXXMemberCall.cpp 
(+97) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/CXXMethodDecl.cpp 
(+73) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/CXXOperatorCallExprTraverser.cpp
 (+36) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/CallbacksBinaryOperator.cpp
 (+211) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/CallbacksCallExpr.cpp 
(+249) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/CallbacksCommon.h 
(+102) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/CallbacksCompoundAssignOperator.cpp
 (+212) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/CallbacksLeaf.cpp 
(+285) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/CallbacksUnaryOperator.cpp
 (+201) 
- (added) clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/Class.cpp 
(+42) 
- (added) clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/Concept.cpp 
(+167) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/ConstructExpr.cpp 
(+66) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/DeclRefExpr.cpp 
(+116) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/DeductionGuide.cpp 
(+83) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/ImplicitCtor.cpp 
(+40) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/ImplicitCtorInitializer.cpp
 (+52) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/InitListExprPostOrder.cpp
 (+36) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/InitListExprPostOrderNoQueue.cpp
 (+40) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/InitListExprPreOrder.cpp
 (+48) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/InitListExprPreOrderNoQueue.cpp
 (+37) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/IntegerLiteral.cpp 
(+32) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/LambdaDefaultCapture.cpp
 (+34) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/LambdaExpr.cpp (+99) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/LambdaTemplateParams.cpp
 (+52) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/MemberPointerTypeLoc.cpp
 (+58) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/NestedNameSpecifiers.cpp
 (+73) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/ParenExpr.cpp (+30) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/TemplateArgumentLocTraverser.cpp
 (+38) 
- (added) 
clang/unittests/Tooling/RecursiveASTEnterExitVisitorTests/TraversalScope.cpp 
(+58) 


``````````diff
diff --git a/clang/include/clang/AST/RecursiveASTEnterExitVisitor.h 
b/clang/include/clang/AST/RecursiveASTEnterExitVisitor.h
new file mode 100644
index 0000000000000..fd275cc75e9a5
--- /dev/null
+++ b/clang/include/clang/AST/RecursiveASTEnterExitVisitor.h
@@ -0,0 +1,4187 @@
+//===--- RecursiveASTEnterExitVisitor.h - Recursive AST Visitor ----------*- 
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
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the RecursiveASTEnterExitVisitor interface, which 
recursively
+//  traverses the entire AST.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_ENTEREXITRECURSIVEASTVISITOR_H
+#define LLVM_CLANG_AST_ENTEREXITRECURSIVEASTVISITOR_H
+
+#include "clang/AST/ASTConcept.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclOpenACC.h"
+#include "clang/AST/DeclOpenMP.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprConcepts.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
+#include "clang/AST/LambdaCapture.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/OpenACCClause.h"
+#include "clang/AST/OpenMPClause.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtOpenACC.h"
+#include "clang/AST/StmtOpenMP.h"
+#include "clang/AST/StmtSYCL.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include <algorithm>
+#include <cstddef>
+#include <type_traits>
+
+namespace clang {
+
+// A helper macro to implement short-circuiting when recursing.  It
+// invokes CALL_EXPR, which must be a method call, on the derived
+// object (s.t. a user of RecursiveASTEnterExitVisitor can override the method
+// in CALL_EXPR).
+#define TRY_TO(CALL_EXPR)                                                      
\
+  do {                                                                         
\
+    if (!getDerived().CALL_EXPR)                                               
\
+      return false;                                                            
\
+  } while (false)
+
+/// A class that does preorder or postorder
+/// depth-first traversal on the entire Clang AST and visits each node.
+///
+/// This class performs three distinct tasks:
+///   1. traverse the AST (i.e. go to each node);
+///   2. at a given node, walk up the class hierarchy, starting from
+///      the node's dynamic type, until the top-most class (e.g. Stmt,
+///      Decl, or Type) is reached.
+///   3. given a (node, class) combination, where 'class' is some base
+///      class of the dynamic type of 'node', call a user-overridable
+///      function to actually visit the node.
+///
+/// These tasks are done by three groups of methods, respectively:
+///   1. TraverseDecl(Decl *x) does task #1.  It is the entry point
+///      for traversing an AST rooted at x.  This method simply
+///      dispatches (i.e. forwards) to TraverseFoo(Foo *x) where Foo
+///      is the dynamic type of *x, which calls WalkUpFromFoo(x) and
+///      then recursively visits the child nodes of x.
+///      TraverseStmt(Stmt *x) and TraverseType(QualType x) work
+///      similarly.
+///   2. WalkUpFromFoo(Foo *x) does task #2.  It does not try to visit
+///      any child node of x.  Instead, it first calls WalkUpFromBar(x)
+///      where Bar is the direct parent class of Foo (unless Foo has
+///      no parent), and then calls VisitFoo(x) (see the next list item).
+///   3. VisitFoo(Foo *x) does task #3.
+///
+/// These three method groups are tiered (Traverse* > WalkUpFrom* >
+/// Visit*).  A method (e.g. Traverse*) may call methods from the same
+/// tier (e.g. other Traverse*) or one tier lower (e.g. WalkUpFrom*).
+/// It may not call methods from a higher tier.
+///
+/// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar
+/// is Foo's super class) before calling VisitFoo(), the result is
+/// that the Visit*() methods for a given node are called in the
+/// top-down order (e.g. for a node of type NamespaceDecl, the order will
+/// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()).
+///
+/// This scheme guarantees that all Visit*() calls for the same AST
+/// node are grouped together.  In other words, Visit*() methods for
+/// different nodes are never interleaved.
+///
+/// Clients of this visitor should subclass the visitor (providing
+/// themselves as the template argument, using the curiously recurring
+/// template pattern) and override any of the Traverse*, WalkUpFrom*,
+/// and Visit* methods for declarations, types, statements,
+/// expressions, or other AST nodes where the visitor should customize
+/// behavior.  Most users only need to override Visit*.  Advanced
+/// users may override Traverse* and WalkUpFrom* to implement custom
+/// traversal strategies.  Returning false from one of these overridden
+/// functions will abort the entire traversal.
+///
+/// By default, this visitor tries to visit every part of the explicit
+/// source code exactly once.  The default policy towards templates
+/// is to descend into the 'pattern' class or function body, not any
+/// explicit or implicit instantiations.  Explicit specializations
+/// are still visited, and the patterns of partial specializations
+/// are visited separately.  This behavior can be changed by
+/// overriding shouldVisitTemplateInstantiations() in the derived class
+/// to return true, in which case all known implicit and explicit
+/// instantiations will be visited at the same time as the pattern
+/// from which they were produced.
+///
+/// By default, this visitor preorder traverses the AST. If postorder traversal
+/// is needed, the \c shouldTraversePostOrder method needs to be overridden
+/// to return \c true.
+template <typename Derived> class RecursiveASTEnterExitVisitor {
+public:
+  /// A queue used for performing data recursion over statements.
+  /// Parameters involving this type are used to implement data
+  /// recursion over Stmts and Exprs within this class, and should
+  /// typically not be explicitly specified by derived classes.
+  /// The bool bit indicates whether the statement has been traversed or not.
+  typedef SmallVectorImpl<llvm::PointerIntPair<Stmt *, 1, bool>>
+    DataRecursionQueue;
+
+  /// Return a reference to the derived class.
+  Derived &getDerived() { return *static_cast<Derived *>(this); }
+
+  /// Return whether this visitor should recurse into
+  /// template instantiations.
+  bool shouldVisitTemplateInstantiations() const { return false; }
+
+  /// Return whether this visitor should recurse into the types of
+  /// TypeLocs.
+  bool shouldWalkTypesOfTypeLocs() const { return true; }
+
+  /// Return whether this visitor should recurse into implicit
+  /// code, e.g., implicit constructors and destructors.
+  bool shouldVisitImplicitCode() const { return false; }
+
+  /// Return whether this visitor should recurse into lambda body
+  bool shouldVisitLambdaBody() const { return true; }
+
+  /// Return whether this visitor should traverse post-order.
+  bool shouldTraversePostOrder() const { return false; }
+
+  /// Recursively visits an entire AST, starting from the TranslationUnitDecl.
+  /// \returns false if visitation was terminated early.
+  bool TraverseAST(ASTContext &AST) {
+    // Currently just an alias for TraverseDecl(TUDecl), but kept in case
+    // we change the implementation again.
+    return getDerived().TraverseDecl(AST.getTranslationUnitDecl());
+  }
+
+  /// 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).
+  bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr);
+
+  /// Invoked before visiting a statement or expression via data recursion.
+  ///
+  /// \returns false to skip visiting the node, true otherwise.
+  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.
+  bool dataTraverseStmtPost(Stmt *S) { return true; }
+
+  /// 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).
+  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).
+  bool TraverseTypeLoc(TypeLoc TL);
+
+  /// 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).
+  bool TraverseAttr(Attr *At);
+
+  /// 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).
+  bool TraverseDecl(Decl *D);
+
+  /// Recursively visit a C++ nested-name-specifier.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
+
+  /// Recursively visit a C++ nested-name-specifier with location
+  /// information.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
+
+  /// Recursively visit a name with its location information.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo);
+
+  /// Recursively visit a template name and dispatch to the
+  /// appropriate method.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  bool TraverseTemplateName(TemplateName Template);
+
+  /// 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.
+  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.
+  bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc);
+
+  /// Recursively visit a set of template arguments.
+  /// This can be overridden by a subclass, but it's not expected that
+  /// will be needed -- this visitor always dispatches to another.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead.
+  bool TraverseTemplateArguments(ArrayRef<TemplateArgument> Args);
+
+  /// Recursively visit a base specifier. This can be overridden by a
+  /// subclass.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base);
+
+  /// 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.
+  bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
+
+  /// 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.
+  bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
+                             Expr *Init);
+
+  /// Recursively visit the syntactic or semantic form of an
+  /// initialization list.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  bool TraverseSynOrSemInitListExpr(InitListExpr *S,
+                                    DataRecursionQueue *Queue = nullptr);
+
+  /// Recursively visit an Objective-C protocol reference with location
+  /// information.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc);
+
+  /// Recursively visit concept reference with location information.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  bool TraverseConceptReference(ConceptReference *CR);
+
+  // Visit concept reference.
+  bool VisitConceptReference(ConceptReference *CR) { return true; }
+  // ---- Methods on Attrs ----
+
+  // Visit an attribute.
+  bool VisitAttr(Attr *A) { return true; }
+
+// Declare Traverse* and empty Visit* for all Attr classes.
+#define ATTR_VISITOR_DECLS_ONLY
+#include "clang/AST/AttrVisitor.inc"
+#undef ATTR_VISITOR_DECLS_ONLY
+
+// ---- Methods on Stmts ----
+
+  Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); }
+
+private:
+  // Traverse the given statement. If the most-derived traverse function takes 
a
+  // data recursion queue, pass it on; otherwise, discard it. Note that the
+  // first branch of this conditional must compile whether or not the derived
+  // class can take a queue, so if we're taking the second arm, make the first
+  // arm call our function rather than the derived class version.
+#define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE)                            
\
+  (::clang::detail::has_same_member_pointer_type<                              
\
+       decltype(&RecursiveASTEnterExitVisitor::Traverse##NAME),                
         \
+       decltype(&Derived::Traverse##NAME)>::value                              
\
+       ? static_cast<std::conditional_t<                                       
\
+             ::clang::detail::has_same_member_pointer_type<                    
\
+                 decltype(&RecursiveASTEnterExitVisitor::Traverse##NAME),      
         \
+                 decltype(&Derived::Traverse##NAME)>::value,                   
\
+             Derived &, RecursiveASTEnterExitVisitor &>>(*this)                
         \
+             .Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE)                 
\
+       : getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)))
+
+// Try to traverse the given statement, or enqueue it if we're performing data
+// recursion in the middle of traversing another statement. Can only be called
+// from within a DEF_TRAVERSE_STMT body or similar context.
+#define TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S)                                     
\
+  do {                                                                         
\
+    if (!TRAVERSE_STMT_BASE(Stmt, Stmt, S, Queue))                             
\
+      return false;                                                            
\
+  } while (false)
+
+public:
+// Declare Traverse*() for all concrete Stmt classes.
+#define ABSTRACT_STMT(STMT)
+#define STMT(CLASS, PARENT) \
+  bool Traverse##CLASS(CLASS *S, DataRecursionQueue *Queue = nullptr);
+#include "clang/AST/StmtNodes.inc"
+  // The above header #undefs ABSTRACT_STMT and STMT upon exit.
+
+  // Define WalkUpFrom*() and empty Visit*() for all Stmt classes.
+  bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitEnterStmt(S) && 
getDerived().VisitStmt(S) && getDerived().VisitExitStmt(S); }
+  bool VisitEnterStmt(Stmt *S) { return true; }
+  bool VisitStmt(Stmt *S) { return true; }
+  bool VisitExitStmt(Stmt *S) { return true; }
+#define STMT(CLASS, PARENT)                                                    
\
+  bool WalkUpFrom##CLASS(CLASS *S) {                                           
\
+    TRY_TO(WalkUpFrom##PARENT(S));                                             
\
+    TRY_TO(VisitEnter##CLASS(S));                                              
\
+    TRY_TO(Visit##CLASS(S));                                                   
\
+    TRY_TO(VisitExit##CLASS(S));                                               
\
+    return true;                                                               
\
+  }                                                                            
\
+  bool VisitEnter##CLASS(CLASS *S) { return true; }                            
\
+  bool Visit##CLASS(CLASS *S) { return true; }                                 
\
+  bool VisitExit##CLASS(CLASS *S) { return true; }
+#include "clang/AST/StmtNodes.inc"
+
+// ---- Methods on Types ----
+// FIXME: revamp to take TypeLoc's rather than Types.
+
+// Declare Traverse*() for all concrete Type classes.
+#define ABSTRACT_TYPE(CLASS, BASE)
+#define TYPE(CLASS, BASE) bool Traverse##CLASS##Type(CLASS##Type *T);
+#include "clang/AST/TypeNodes.inc"
+  // The above header #undefs ABSTRACT_TYPE and TYPE upon exit.
+
+  // Define WalkUpFrom*() and empty Visit*() for all Type classes.
+  bool WalkUpFromType(Type *T) { return getDerived().VisitEnterType(T) && 
getDerived().VisitType(T) && getDerived().VisitExitType(T); }
+  bool VisitEnterType(Type *T) { return true; }
+  bool VisitType(Type *T) { return true; }
+  bool VisitExitType(Type *T) { return true; }
+#define TYPE(CLASS, BASE)                                                      
\
+  bool WalkUpFrom##CLASS##Type(CLASS##Type *T) {                               
\
+    TRY_TO(WalkUpFrom##BASE(T));                                               
\
+    TRY_TO(VisitEnter##CLASS##Type(T));                                        
\
+    TRY_TO(Visit##CLASS##Type(T));                                             
\
+    TRY_TO(VisitExit##CLASS##Type(T));                                         
\
+    return true;                                                               
\
+  }                                                                            
\
+  bool VisitEnter##CLASS##Type(CLASS##Type *T) { return true; }                
\
+  bool Visit##CLASS##Type(CLASS##Type *T) { return true; }                     
\
+  bool VisitExit##CLASS##Type(CLASS##Type *T) { return true; }
+#include "clang/AST/TypeNodes.inc"
+
+// ---- Methods on TypeLocs ----
+// FIXME: this currently just calls the matching Type methods
+
+// Declare Traverse*() for all concrete TypeLoc classes.
+#define ABSTRACT_TYPELOC(CLASS, BASE)
+#define TYPELOC(CLASS, BASE) bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL);
+#include "clang/AST/TypeLocNodes.def"
+  // The above header #undefs ABSTRACT_TYPELOC and TYPELOC upon exit.
+
+  // Define WalkUpFrom*() and empty Visit*() for all TypeLoc classes.
+  bool WalkUpFromTypeLoc(TypeLoc TL) {
+     return getDerived().VisitEnterTypeLoc(TL) &&
+        getDerived().VisitTypeLoc(TL) &&
+        getDerived().VisitExitTypeLoc(TL);
+  }
+  bool VisitEnterTypeLoc(TypeLoc TL) { return true; }
+  bool VisitTypeLoc(TypeLoc TL) { return true; }
+  bool VisitExitTypeLoc(TypeLoc TL) { return true; }
+
+  // QualifiedTypeLoc and UnqualTypeLoc are not declared in
+  // TypeNodes.inc...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/136136
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to