r306374 - Make sure TraverseInitListExpr visits InitListExpr exactly twice

Stephan Bergmann via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 27 01:04:08 PDT 2017


Author: sberg
Date: Tue Jun 27 01:04:08 2017
New Revision: 306374

URL: http://llvm.org/viewvc/llvm-project?rev=306374&view=rev
Log:
Make sure TraverseInitListExpr visits InitListExpr exactly twice

... once each for the syntactic and semantic form. Without this fix, behavior
of the newly added tests would have been

InitListExprIsPreOrderVisitedTwice:
 syntactic: 1
 semantic: 2

InitListExprIsPostOrderVisitedTwice:
 syntactic: 0
 semantic: 1

InitListExprIsPreOrderNoQueueVisitedTwice:
 syntactic: 1
 semantic: 2

InitListExprIsPostOrderNoQueueVisitedTwice:
 syntactic: 0
 semantic: 2

Modified:
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    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=306374&r1=306373&r2=306374&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Jun 27 01:04:08 2017
@@ -593,6 +593,16 @@ bool RecursiveASTVisitor<Derived>::PostV
 #define STMT(CLASS, PARENT)                                                    \
   case Stmt::CLASS##Class:                                                     \
     TRY_TO(WalkUpFrom##CLASS(static_cast<CLASS *>(S))); break;
+#define INITLISTEXPR(CLASS, PARENT)                                            \
+  case Stmt::CLASS##Class:                                                     \
+    {                                                                          \
+      auto ILE = static_cast<CLASS *>(S);                                      \
+      if (auto Syn = ILE->isSemanticForm() ? ILE->getSyntacticForm() : ILE)    \
+        TRY_TO(WalkUpFrom##CLASS(Syn));                                        \
+      if (auto Sem = ILE->isSemanticForm() ? ILE : ILE->getSemanticForm())     \
+        TRY_TO(WalkUpFrom##CLASS(Sem));                                        \
+      break;                                                                   \
+    }
 #include "clang/AST/StmtNodes.inc"
   }
 
@@ -2220,13 +2230,15 @@ bool RecursiveASTVisitor<Derived>::Trave
 // the syntactic and the semantic form.
 //
 // There is no guarantee about which form \p S takes when this method is called.
-DEF_TRAVERSE_STMT(InitListExpr, {
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(
+    InitListExpr *S, DataRecursionQueue *Queue) {
   TRY_TO(TraverseSynOrSemInitListExpr(
       S->isSemanticForm() ? S->getSyntacticForm() : S, Queue));
   TRY_TO(TraverseSynOrSemInitListExpr(
       S->isSemanticForm() ? S : S->getSemanticForm(), Queue));
-  ShouldVisitChildren = false;
-})
+  return true;
+}
 
 // GenericSelectionExpr is a special case because the types and expressions
 // are interleaved.  We also need to watch out for null types (default

Modified: cfe/trunk/unittests/Tooling/RecursiveASTVisitorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/RecursiveASTVisitorTest.cpp?rev=306374&r1=306373&r2=306374&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/RecursiveASTVisitorTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/RecursiveASTVisitorTest.cpp Tue Jun 27 01:04:08 2017
@@ -158,4 +158,90 @@ TEST(RecursiveASTVisitor, DefaultArgumen
                               "static int k = f();\n"));
 }
 
+// Check to ensure that InitListExpr is visited twice, once each for the
+// syntactic and semantic form.
+class InitListExprPreOrderVisitor
+    : public ExpectedLocationVisitor<InitListExprPreOrderVisitor> {
+public:
+  bool VisitInitListExpr(InitListExpr *ILE) {
+    Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+    return true;
+  }
+};
+
+class InitListExprPostOrderVisitor
+    : public ExpectedLocationVisitor<InitListExprPostOrderVisitor> {
+public:
+  bool shouldTraversePostOrder() const { return true; }
+
+  bool VisitInitListExpr(InitListExpr *ILE) {
+    Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+    return true;
+  }
+};
+
+class InitListExprPreOrderNoQueueVisitor
+    : public ExpectedLocationVisitor<InitListExprPreOrderNoQueueVisitor> {
+public:
+  bool TraverseInitListExpr(InitListExpr *ILE) {
+    return ExpectedLocationVisitor::TraverseInitListExpr(ILE);
+  }
+
+  bool VisitInitListExpr(InitListExpr *ILE) {
+    Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+    return true;
+  }
+};
+
+class InitListExprPostOrderNoQueueVisitor
+    : public ExpectedLocationVisitor<InitListExprPostOrderNoQueueVisitor> {
+public:
+  bool shouldTraversePostOrder() const { return true; }
+
+  bool TraverseInitListExpr(InitListExpr *ILE) {
+    return ExpectedLocationVisitor::TraverseInitListExpr(ILE);
+  }
+
+  bool VisitInitListExpr(InitListExpr *ILE) {
+    Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+    return true;
+  }
+};
+
+TEST(RecursiveASTVisitor, InitListExprIsPreOrderVisitedTwice) {
+  InitListExprPreOrderVisitor Visitor;
+  Visitor.ExpectMatch("syntactic", 2, 21);
+  Visitor.ExpectMatch("semantic", 2, 21);
+  EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
+                              "static struct S s = {.x = 0};\n",
+                              InitListExprPreOrderVisitor::Lang_C));
+}
+
+TEST(RecursiveASTVisitor, InitListExprIsPostOrderVisitedTwice) {
+  InitListExprPostOrderVisitor Visitor;
+  Visitor.ExpectMatch("syntactic", 2, 21);
+  Visitor.ExpectMatch("semantic", 2, 21);
+  EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
+                              "static struct S s = {.x = 0};\n",
+                              InitListExprPostOrderVisitor::Lang_C));
+}
+
+TEST(RecursiveASTVisitor, InitListExprIsPreOrderNoQueueVisitedTwice) {
+  InitListExprPreOrderNoQueueVisitor Visitor;
+  Visitor.ExpectMatch("syntactic", 2, 21);
+  Visitor.ExpectMatch("semantic", 2, 21);
+  EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
+                              "static struct S s = {.x = 0};\n",
+                              InitListExprPreOrderNoQueueVisitor::Lang_C));
+}
+
+TEST(RecursiveASTVisitor, InitListExprIsPostOrderNoQueueVisitedTwice) {
+  InitListExprPostOrderNoQueueVisitor Visitor;
+  Visitor.ExpectMatch("syntactic", 2, 21);
+  Visitor.ExpectMatch("semantic", 2, 21);
+  EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
+                              "static struct S s = {.x = 0};\n",
+                              InitListExprPostOrderNoQueueVisitor::Lang_C));
+}
+
 } // end anonymous namespace




More information about the cfe-commits mailing list