[cfe-commits] r155969 - in /cfe/trunk: include/clang/AST/RecursiveASTVisitor.h tools/libclang/IndexBody.cpp unittests/Tooling/RecursiveASTVisitorTest.cpp

Richard Smith richard-llvm at metafoo.co.uk
Tue May 1 17:30:48 PDT 2012


Author: rsmith
Date: Tue May  1 19:30:48 2012
New Revision: 155969

URL: http://llvm.org/viewvc/llvm-project?rev=155969&view=rev
Log:
Unrevert r155951, reverted in r155962, with two changes:
 * Work around build failures due to gcc 4.2 bugs.
 * Remove BodyIndexer::TraverseCXXOperatorCallExpr, which was not being called
   prior to this change, and whose presence disables a RecursiveASTVisitor
   stack space optimization after this change.

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

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=155969&r1=155968&r2=155969&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue May  1 19:30:48 2012
@@ -405,18 +405,14 @@
   bool TraverseFunctionHelper(FunctionDecl *D);
   bool TraverseVarHelper(VarDecl *D);
 
-  bool Walk(Stmt *S);
-
   struct EnqueueJob {
     Stmt *S;
     Stmt::child_iterator StmtIt;
 
-    EnqueueJob(Stmt *S) : S(S), StmtIt() {
-      if (Expr *E = dyn_cast_or_null<Expr>(S))
-        S = E->IgnoreParens();
-    }
+    EnqueueJob(Stmt *S) : S(S), StmtIt() {}
   };
   bool dataTraverse(Stmt *S);
+  bool dataTraverseNode(Stmt *S, bool &EnqueueChildren);
 };
 
 template<typename Derived>
@@ -435,7 +431,12 @@
 
     if (getDerived().shouldUseDataRecursionFor(CurrS)) {
       if (job.StmtIt == Stmt::child_iterator()) {
-        if (!Walk(CurrS)) return false;
+        bool EnqueueChildren = true;
+        if (!dataTraverseNode(CurrS, EnqueueChildren)) return false;
+        if (!EnqueueChildren) {
+          Queue.pop_back();
+          continue;
+        }
         job.StmtIt = CurrS->child_begin();
       } else {
         ++job.StmtIt;
@@ -456,10 +457,18 @@
 }
 
 template<typename Derived>
-bool RecursiveASTVisitor<Derived>::Walk(Stmt *S) {
+bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
+                                                    bool &EnqueueChildren) {
 
+  // Dispatch to the corresponding WalkUpFrom* function only if the derived
+  // class didn't override Traverse* (and thus the traversal is trivial).
+  // The cast here is necessary to work around a bug in old versions of g++.
 #define DISPATCH_WALK(NAME, CLASS, VAR) \
-  return getDerived().WalkUpFrom##NAME(static_cast<CLASS*>(VAR));
+  if (&RecursiveASTVisitor::Traverse##NAME == \
+      (bool (RecursiveASTVisitor::*)(CLASS*))&Derived::Traverse##NAME) \
+    return getDerived().WalkUpFrom##NAME(static_cast<CLASS*>(VAR)); \
+  EnqueueChildren = false; \
+  return getDerived().Traverse##NAME(static_cast<CLASS*>(VAR));
 
   if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
     switch (BinOp->getOpcode()) {

Modified: cfe/trunk/tools/libclang/IndexBody.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexBody.cpp?rev=155969&r1=155968&r2=155969&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/IndexBody.cpp (original)
+++ cfe/trunk/tools/libclang/IndexBody.cpp Tue May  1 19:30:48 2012
@@ -117,12 +117,6 @@
     return true;
   }
 
-  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
-    if (E->getOperatorLoc().isInvalid())
-      return true; // implicit.
-    return base::TraverseCXXOperatorCallExpr(E);
-  }
-
   bool VisitDeclStmt(DeclStmt *S) {
     if (IndexCtx.shouldIndexFunctionLocalSymbols())
       IndexCtx.indexDeclGroupRef(S->getDeclGroup());

Modified: cfe/trunk/unittests/Tooling/RecursiveASTVisitorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/RecursiveASTVisitorTest.cpp?rev=155969&r1=155968&r2=155969&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/RecursiveASTVisitorTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/RecursiveASTVisitorTest.cpp Tue May  1 19:30:48 2012
@@ -165,6 +165,26 @@
   }
 };
 
+class CXXOperatorCallExprTraverser
+  : public ExpectedLocationVisitor<CXXOperatorCallExprTraverser> {
+public:
+  // Use Traverse, not Visit, to check that data recursion optimization isn't
+  // bypassing the call of this function.
+  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {
+    Match(getOperatorSpelling(CE->getOperator()), CE->getExprLoc());
+    return ExpectedLocationVisitor<CXXOperatorCallExprTraverser>::
+        TraverseCXXOperatorCallExpr(CE);
+  }
+};
+
+class ParenExprVisitor : public ExpectedLocationVisitor<ParenExprVisitor> {
+public:
+  bool VisitParenExpr(ParenExpr *Parens) {
+    Match("", Parens->getExprLoc());
+    return true;
+  }
+};
+
 TEST(RecursiveASTVisitor, VisitsBaseClassDeclarations) {
   TypeLocVisitor Visitor;
   Visitor.ExpectMatch("class X", 1, 30);
@@ -345,4 +365,20 @@
     "vector_iterator<int> it_int;\n"));
 }
 
+TEST(RecursiveASTVisitor, TraversesOverloadedOperator) {
+  CXXOperatorCallExprTraverser Visitor;
+  Visitor.ExpectMatch("()", 4, 9);
+  EXPECT_TRUE(Visitor.runOver(
+    "struct A {\n"
+    "  int operator()();\n"
+    "} a;\n"
+    "int k = a();\n"));
+}
+
+TEST(RecursiveASTVisitor, VisitsParensDuringDataRecursion) {
+  ParenExprVisitor Visitor;
+  Visitor.ExpectMatch("", 1, 9);
+  EXPECT_TRUE(Visitor.runOver("int k = (4) + 9;\n"));
+}
+
 } // end namespace clang





More information about the cfe-commits mailing list