r254041 - Teach RAV to pass its DataRecursionQueue to derived classes if they ask for it,

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 24 15:50:47 PST 2015


Author: rsmith
Date: Tue Nov 24 17:50:47 2015
New Revision: 254041

URL: http://llvm.org/viewvc/llvm-project?rev=254041&view=rev
Log:
Teach RAV to pass its DataRecursionQueue to derived classes if they ask for it,
to allow them to explicitly opt into data recursion despite having overridden
Traverse*Stmt or Traverse*Expr. Use this to reintroduce data recursion to the
one place that lost it when DataRecursiveASTVisitor was removed.

Modified:
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/tools/libclang/IndexBody.cpp

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=254041&r1=254040&r2=254041&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Nov 24 17:50:47 2015
@@ -14,6 +14,8 @@
 #ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
 #define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
 
+#include <type_traits>
+
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
@@ -132,13 +134,13 @@ namespace clang {
 /// instantiations will be visited at the same time as the pattern
 /// from which they were produced.
 template <typename Derived> class RecursiveASTVisitor {
+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
-  /// not be explicitly specified by derived classes.
+  /// typically not be explicitly specified by derived classes.
   typedef SmallVectorImpl<Stmt *> DataRecursionQueue;
 
-public:
   /// \brief Return a reference to the derived class.
   Derived &getDerived() { return *static_cast<Derived *>(this); }
 
@@ -274,24 +276,32 @@ public:
 // ---- Methods on Stmts ----
 
 private:
-  template<typename T, T X, typename U, U Y>
-  struct is_same_member_pointer : std::false_type {};
-  template<typename T, T X>
-  struct is_same_member_pointer<T, X, T, X> : std::true_type {};
-
-  // Traverse the given statement. If the traverse function was not overridden,
-  // pass on the data recursion queue information.
+  // Determine if the specified derived-class member M can be passed a
+  // DataRecursionQueue* argument.
+  template<typename P>
+  std::false_type callableWithQueue(...);
+  template<typename P, typename M>
+  std::true_type callableWithQueue(M m, Derived *d = nullptr, P *p = nullptr,
+                                   DataRecursionQueue *q = nullptr,
+                                   decltype((d->*m)(p, q)) = false);
+
+  // 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)                            \
-  (is_same_member_pointer<decltype(&Derived::Traverse##NAME),                  \
-                          &Derived::Traverse##NAME,                            \
-                          decltype(&RecursiveASTVisitor::Traverse##NAME),      \
-                          &RecursiveASTVisitor::Traverse##NAME>::value         \
-       ? this->Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE)                \
+  (decltype(callableWithQueue<CLASS *>(&Derived::Traverse##NAME))::value       \
+       ? static_cast<typename std::conditional<                                \
+             decltype(                                                         \
+                 callableWithQueue<CLASS *>(&Derived::Traverse##NAME))::value, \
+             Derived &, RecursiveASTVisitor &>::type>(*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.
+// 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))                             \
@@ -535,14 +545,6 @@ bool RecursiveASTVisitor<Derived>::Trave
   if (!S)
     return true;
 
-  // If TraverseStmt was overridden (and called the base class version), don't
-  // do any data recursion; it would be observable.
-  if (!is_same_member_pointer<decltype(&Derived::TraverseStmt),
-                              &Derived::TraverseStmt,
-                              decltype(&RecursiveASTVisitor::TraverseStmt),
-                              &RecursiveASTVisitor::TraverseStmt>::value)
-    return dataTraverseNode(S, nullptr);
-
   if (Queue) {
     Queue->push_back(S);
     return true;

Modified: cfe/trunk/tools/libclang/IndexBody.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexBody.cpp?rev=254041&r1=254040&r2=254041&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/IndexBody.cpp (original)
+++ cfe/trunk/tools/libclang/IndexBody.cpp Tue Nov 24 17:50:47 2015
@@ -125,10 +125,11 @@ public:
     return true;
   }
 
-  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
+                                   DataRecursionQueue *Q = nullptr) {
     if (E->getOperatorLoc().isInvalid())
       return true; // implicit.
-    return base::TraverseCXXOperatorCallExpr(E);
+    return base::TraverseCXXOperatorCallExpr(E, Q);
   }
 
   bool VisitDeclStmt(DeclStmt *S) {




More information about the cfe-commits mailing list