<div dir="ltr"><div>Hm, looks like we can't compile Clang itself after this change (with GCC):</div><div><br></div><a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-autoconf/builds/12237">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-autoconf/builds/12237</a><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Nov 24, 2015 at 3:50 PM, Richard Smith via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Tue Nov 24 17:50:47 2015<br>
New Revision: 254041<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=254041&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=254041&view=rev</a><br>
Log:<br>
Teach RAV to pass its DataRecursionQueue to derived classes if they ask for it,<br>
to allow them to explicitly opt into data recursion despite having overridden<br>
Traverse*Stmt or Traverse*Expr. Use this to reintroduce data recursion to the<br>
one place that lost it when DataRecursiveASTVisitor was removed.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h<br>
    cfe/trunk/tools/libclang/IndexBody.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=254041&r1=254040&r2=254041&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=254041&r1=254040&r2=254041&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)<br>
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Nov 24 17:50:47 2015<br>
@@ -14,6 +14,8 @@<br>
 #ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H<br>
 #define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H<br>
<br>
+#include <type_traits><br>
+<br>
 #include "clang/AST/Attr.h"<br>
 #include "clang/AST/Decl.h"<br>
 #include "clang/AST/DeclCXX.h"<br>
@@ -132,13 +134,13 @@ namespace clang {<br>
 /// instantiations will be visited at the same time as the pattern<br>
 /// from which they were produced.<br>
 template <typename Derived> class RecursiveASTVisitor {<br>
+public:<br>
   /// A queue used for performing data recursion over statements.<br>
   /// Parameters involving this type are used to implement data<br>
   /// recursion over Stmts and Exprs within this class, and should<br>
-  /// not be explicitly specified by derived classes.<br>
+  /// typically not be explicitly specified by derived classes.<br>
   typedef SmallVectorImpl<Stmt *> DataRecursionQueue;<br>
<br>
-public:<br>
   /// \brief Return a reference to the derived class.<br>
   Derived &getDerived() { return *static_cast<Derived *>(this); }<br>
<br>
@@ -274,24 +276,32 @@ public:<br>
 // ---- Methods on Stmts ----<br>
<br>
 private:<br>
-  template<typename T, T X, typename U, U Y><br>
-  struct is_same_member_pointer : std::false_type {};<br>
-  template<typename T, T X><br>
-  struct is_same_member_pointer<T, X, T, X> : std::true_type {};<br>
-<br>
-  // Traverse the given statement. If the traverse function was not overridden,<br>
-  // pass on the data recursion queue information.<br>
+  // Determine if the specified derived-class member M can be passed a<br>
+  // DataRecursionQueue* argument.<br>
+  template<typename P><br>
+  std::false_type callableWithQueue(...);<br>
+  template<typename P, typename M><br>
+  std::true_type callableWithQueue(M m, Derived *d = nullptr, P *p = nullptr,<br>
+                                   DataRecursionQueue *q = nullptr,<br>
+                                   decltype((d->*m)(p, q)) = false);<br>
+<br>
+  // Traverse the given statement. If the most-derived traverse function takes a<br>
+  // data recursion queue, pass it on; otherwise, discard it. Note that the<br>
+  // first branch of this conditional must compile whether or not the derived<br>
+  // class can take a queue, so if we're taking the second arm, make the first<br>
+  // arm call our function rather than the derived class version.<br>
 #define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE)                            \<br>
-  (is_same_member_pointer<decltype(&Derived::Traverse##NAME),                  \<br>
-                          &Derived::Traverse##NAME,                            \<br>
-                          decltype(&RecursiveASTVisitor::Traverse##NAME),      \<br>
-                          &RecursiveASTVisitor::Traverse##NAME>::value         \<br>
-       ? this->Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE)                \<br>
+  (decltype(callableWithQueue<CLASS *>(&Derived::Traverse##NAME))::value       \<br>
+       ? static_cast<typename std::conditional<                                \<br>
+             decltype(                                                         \<br>
+                 callableWithQueue<CLASS *>(&Derived::Traverse##NAME))::value, \<br>
+             Derived &, RecursiveASTVisitor &>::type>(*this)                   \<br>
+             .Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE)                 \<br>
        : getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)))<br>
<br>
-  // Try to traverse the given statement, or enqueue it if we're performing data<br>
-  // recursion in the middle of traversing another statement. Can only be called<br>
-  // from within a DEF_TRAVERSE_STMT body or similar context.<br>
+// Try to traverse the given statement, or enqueue it if we're performing data<br>
+// recursion in the middle of traversing another statement. Can only be called<br>
+// from within a DEF_TRAVERSE_STMT body or similar context.<br>
 #define TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S)                                     \<br>
   do {                                                                         \<br>
     if (!TRAVERSE_STMT_BASE(Stmt, Stmt, S, Queue))                             \<br>
@@ -535,14 +545,6 @@ bool RecursiveASTVisitor<Derived>::Trave<br>
   if (!S)<br>
     return true;<br>
<br>
-  // If TraverseStmt was overridden (and called the base class version), don't<br>
-  // do any data recursion; it would be observable.<br>
-  if (!is_same_member_pointer<decltype(&Derived::TraverseStmt),<br>
-                              &Derived::TraverseStmt,<br>
-                              decltype(&RecursiveASTVisitor::TraverseStmt),<br>
-                              &RecursiveASTVisitor::TraverseStmt>::value)<br>
-    return dataTraverseNode(S, nullptr);<br>
-<br>
   if (Queue) {<br>
     Queue->push_back(S);<br>
     return true;<br>
<br>
Modified: cfe/trunk/tools/libclang/IndexBody.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexBody.cpp?rev=254041&r1=254040&r2=254041&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexBody.cpp?rev=254041&r1=254040&r2=254041&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/tools/libclang/IndexBody.cpp (original)<br>
+++ cfe/trunk/tools/libclang/IndexBody.cpp Tue Nov 24 17:50:47 2015<br>
@@ -125,10 +125,11 @@ public:<br>
     return true;<br>
   }<br>
<br>
-  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E) {<br>
+  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,<br>
+                                   DataRecursionQueue *Q = nullptr) {<br>
     if (E->getOperatorLoc().isInvalid())<br>
       return true; // implicit.<br>
-    return base::TraverseCXXOperatorCallExpr(E);<br>
+    return base::TraverseCXXOperatorCallExpr(E, Q);<br>
   }<br>
<br>
   bool VisitDeclStmt(DeclStmt *S) {<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr">Alexey Samsonov<br><a href="mailto:vonosmas@gmail.com" target="_blank">vonosmas@gmail.com</a></div></div>
</div>