From 0ca76d0c9c9069ac238c87beac0b7d90cde3905d Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 24 Nov 2015 23:50:47 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@254041 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/RecursiveASTVisitor.h | 52 +++++++++++++------------ tools/libclang/IndexBody.cpp | 5 ++- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 41c1d3aee9..be62999bca 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -14,6 +14,8 @@ #ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H #define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H +#include + #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 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 DataRecursionQueue; -public: /// \brief Return a reference to the derived class. Derived &getDerived() { return *static_cast(this); } @@ -274,24 +276,32 @@ public: // ---- Methods on Stmts ---- private: - template - struct is_same_member_pointer : std::false_type {}; - template - struct is_same_member_pointer : 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 + std::false_type callableWithQueue(...); + template + 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::value \ - ? this->Traverse##NAME(static_cast(VAR), QUEUE) \ + (decltype(callableWithQueue(&Derived::Traverse##NAME))::value \ + ? static_cast(&Derived::Traverse##NAME))::value, \ + Derived &, RecursiveASTVisitor &>::type>(*this) \ + .Traverse##NAME(static_cast(VAR), QUEUE) \ : getDerived().Traverse##NAME(static_cast(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::TraverseStmt(Stmt *S, 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::value) - return dataTraverseNode(S, nullptr); - if (Queue) { Queue->push_back(S); return true; diff --git a/tools/libclang/IndexBody.cpp b/tools/libclang/IndexBody.cpp index a186876947..64df4b85be 100644 --- a/tools/libclang/IndexBody.cpp +++ b/tools/libclang/IndexBody.cpp @@ -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) { -- 2.50.1