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