gribozavr created this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
gribozavr2 added reviewers: eduucaldas, ymandel.

How does RecursiveASTVisitor call the WalkUp callback for expressions?

- In pre-order traversal mode, RecursiveASTVisitor calls the WalkUp

callback from the default implementation of Traverse callbacks.

- In post-order traversal mode when we don't have a DataRecursionQueue,

RecursiveASTVisitor also calls the WalkUp callback from the default
implementation of Traverse callbacks.

- However, in post-order traversal mode when we have a DataRecursionQueue,

RecursiveASTVisitor calls the WalkUp callback from PostVisitStmt.

As a result, when the user overrides the Traverse callback, in pre-order
traversal mode they never get the corresponding WalkUp callback. However
in the post-order traversal mode the WalkUp callback is invoked or not
depending on whether the data recursion optimization could be applied.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D82486

Files:
  clang/include/clang/AST/RecursiveASTVisitor.h
  clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp

Index: clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp
===================================================================
--- clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp
+++ clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp
@@ -117,18 +117,13 @@
                                       Code,
                                       R"txt(
 TraverseIntegerLiteral IntegerLiteral(1)
-WalkUpFromStmt IntegerLiteral(1)
 TraverseIntegerLiteral IntegerLiteral(2)
-WalkUpFromStmt IntegerLiteral(2)
 TraverseIntegerLiteral IntegerLiteral(3)
-WalkUpFromStmt IntegerLiteral(3)
 WalkUpFromStmt BinaryOperator(+)
 WalkUpFromStmt DeclRefExpr(add)
 WalkUpFromStmt ImplicitCastExpr
 TraverseIntegerLiteral IntegerLiteral(4)
-WalkUpFromStmt IntegerLiteral(4)
 TraverseIntegerLiteral IntegerLiteral(5)
-WalkUpFromStmt IntegerLiteral(5)
 WalkUpFromStmt CallExpr(add)
 WalkUpFromStmt CompoundStmt
 )txt"));
@@ -189,18 +184,13 @@
                                       Code,
                                       R"txt(
 TraverseIntegerLiteral IntegerLiteral(1)
-WalkUpFromIntegerLiteral IntegerLiteral(1)
 TraverseIntegerLiteral IntegerLiteral(2)
-WalkUpFromIntegerLiteral IntegerLiteral(2)
 TraverseIntegerLiteral IntegerLiteral(3)
-WalkUpFromIntegerLiteral IntegerLiteral(3)
 WalkUpFromExpr BinaryOperator(+)
 WalkUpFromExpr DeclRefExpr(add)
 WalkUpFromExpr ImplicitCastExpr
 TraverseIntegerLiteral IntegerLiteral(4)
-WalkUpFromIntegerLiteral IntegerLiteral(4)
 TraverseIntegerLiteral IntegerLiteral(5)
-WalkUpFromIntegerLiteral IntegerLiteral(5)
 WalkUpFromExpr CallExpr(add)
 WalkUpFromStmt CompoundStmt
 )txt"));
@@ -315,7 +305,6 @@
 WalkUpFromStmt IntegerLiteral(1)
 WalkUpFromStmt IntegerLiteral(2)
 WalkUpFromStmt IntegerLiteral(3)
-WalkUpFromStmt BinaryOperator(+)
 WalkUpFromStmt DeclRefExpr(add)
 WalkUpFromStmt ImplicitCastExpr
 WalkUpFromStmt IntegerLiteral(4)
@@ -383,7 +372,6 @@
 WalkUpFromExpr IntegerLiteral(1)
 WalkUpFromExpr IntegerLiteral(2)
 WalkUpFromExpr IntegerLiteral(3)
-WalkUpFromBinaryOperator BinaryOperator(+)
 WalkUpFromExpr DeclRefExpr(add)
 WalkUpFromExpr ImplicitCastExpr
 WalkUpFromExpr IntegerLiteral(4)
@@ -500,7 +488,6 @@
 WalkUpFromStmt IntegerLiteral(3)
 WalkUpFromStmt BinaryOperator(+)
 TraverseCallExpr CallExpr(add)
-WalkUpFromStmt CallExpr(add)
 WalkUpFromStmt CompoundStmt
 )txt"));
 }
@@ -560,7 +547,6 @@
 WalkUpFromExpr IntegerLiteral(3)
 WalkUpFromExpr BinaryOperator(+)
 TraverseCallExpr CallExpr(add)
-WalkUpFromCallExpr CallExpr(add)
 WalkUpFromStmt CompoundStmt
 )txt"));
 }
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -331,6 +331,31 @@
   struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)>
       : std::true_type {};
 
+  template <bool has_same_type> struct is_same_method_impl {
+    static bool isSameMethod(...) { return false; }
+  };
+
+  template <> struct is_same_method_impl<true> {
+    template <typename FirstTy, typename FirstResult, typename... FirstParams,
+              typename SecondTy, typename SecondResult,
+              typename... SecondParams>
+    static bool
+    isSameMethod(FirstResult (FirstTy::*FirstMethodPtr)(FirstParams...),
+                 SecondResult (SecondTy::*SecondMethodPtr)(SecondParams...)) {
+      return FirstMethodPtr == SecondMethodPtr;
+    }
+  };
+
+  /// Returns true if and only if \p FirstMethodPtr and \p SecondMethodPtr
+  /// are pointers to the same non-static member function.
+  template <typename FirstMethodPtrTy, typename SecondMethodPtrTy>
+  bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
+                    SecondMethodPtrTy SecondMethodPtr) {
+    return is_same_method_impl<
+        has_same_member_pointer_type<FirstMethodPtrTy, SecondMethodPtrTy>::
+            value>::isSameMethod(FirstMethodPtr, SecondMethodPtr);
+  }
+
   // 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
@@ -609,17 +634,22 @@
 #define ABSTRACT_STMT(STMT)
 #define STMT(CLASS, PARENT)                                                    \
   case Stmt::CLASS##Class:                                                     \
-    TRY_TO(WalkUpFrom##CLASS(static_cast<CLASS *>(S))); break;
+    if (isSameMethod(&RecursiveASTVisitor::Traverse##CLASS,                    \
+                     &Derived::Traverse##CLASS)) {                             \
+      TRY_TO(WalkUpFrom##CLASS(static_cast<CLASS *>(S)));                      \
+    }                                                                          \
+    break;
 #define INITLISTEXPR(CLASS, PARENT)                                            \
   case Stmt::CLASS##Class:                                                     \
-    {                                                                          \
+    if (isSameMethod(&RecursiveASTVisitor::Traverse##CLASS,                    \
+                     &Derived::Traverse##CLASS)) {                             \
       auto ILE = static_cast<CLASS *>(S);                                      \
       if (auto Syn = ILE->isSemanticForm() ? ILE->getSyntacticForm() : ILE)    \
         TRY_TO(WalkUpFrom##CLASS(Syn));                                        \
       if (auto Sem = ILE->isSemanticForm() ? ILE : ILE->getSemanticForm())     \
         TRY_TO(WalkUpFrom##CLASS(Sem));                                        \
-      break;                                                                   \
-    }
+    }                                                                          \
+    break;
 #include "clang/AST/StmtNodes.inc"
   }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to