]> granicus.if.org Git - clang/commitdiff
Unrevert r155951, reverted in r155962, with two changes:
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 2 May 2012 00:30:48 +0000 (00:30 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 2 May 2012 00:30:48 +0000 (00:30 +0000)
 * 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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155969 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/RecursiveASTVisitor.h
tools/libclang/IndexBody.cpp
unittests/Tooling/RecursiveASTVisitorTest.cpp

index 93363b1715283d9e6ce05c919c9e1dbbd9a1868d..8a6e85f226abb709b7cd0ff9eb2f54ab2ad11a2b 100644 (file)
@@ -405,18 +405,14 @@ private:
   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 @@ bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) {
 
     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 @@ bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) {
 }
 
 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()) {
index 239dde21bd4e2f07caa970a92c2001d2c245d07e..e975a6d1be401a7c4e83ea7ad1593dc04d8943c9 100644 (file)
@@ -117,12 +117,6 @@ public:
     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());
index d4fda73ccb8dbfcff8267bac6ab37992ace56ace..953817e61fb6934183150bc3f1fd1df25abc14a5 100644 (file)
@@ -165,6 +165,26 @@ public:
   }
 };
 
+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 @@ TEST(RecursiveASTVisitor, NoRecursionInSelfFriend) {
     "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