r366672 - [AST] Treat semantic form of InitListExpr as implicit code in traversals

Ilya Biryukov via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 22 02:58:55 PDT 2019


Author: ibiryukov
Date: Mon Jul 22 02:58:53 2019
New Revision: 366672

URL: http://llvm.org/viewvc/llvm-project?rev=366672&view=rev
Log:
[AST] Treat semantic form of InitListExpr as implicit code in traversals

Summary:
In particular, do not traverse the semantic form if shouldVisitImplicitCode()
returns false.

This simplifies the common case of traversals, avoiding the need to
worry about some expressions being traversed twice.

No tests break after the change, the change would allow to simplify at
least one of the usages, i.e. r366070 which had to handle this in
clangd.

Reviewers: gribozavr

Reviewed By: gribozavr

Subscribers: kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D64762

Modified:
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=366672&r1=366671&r2=366672&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Mon Jul 22 02:58:53 2019
@@ -2308,19 +2308,30 @@ bool RecursiveASTVisitor<Derived>::Trave
   return true;
 }
 
-// This method is called once for each pair of syntactic and semantic
-// InitListExpr, and it traverses the subtrees defined by the two forms. This
-// may cause some of the children to be visited twice, if they appear both in
-// the syntactic and the semantic form.
+// If shouldVisitImplicitCode() returns false, this method traverses only the
+// syntactic form of InitListExpr.
+// If shouldVisitImplicitCode() return true, this method is called once for
+// each pair of syntactic and semantic InitListExpr, and it traverses the
+// subtrees defined by the two forms. This may cause some of the children to be
+// visited twice, if they appear both in the syntactic and the semantic form.
 //
 // There is no guarantee about which form \p S takes when this method is called.
 template <typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(
     InitListExpr *S, DataRecursionQueue *Queue) {
+  if (S->isSemanticForm() && S->isSyntacticForm()) {
+    // `S` does not have alternative forms, traverse only once.
+    TRY_TO(TraverseSynOrSemInitListExpr(S, Queue));
+    return true;
+  }
   TRY_TO(TraverseSynOrSemInitListExpr(
       S->isSemanticForm() ? S->getSyntacticForm() : S, Queue));
-  TRY_TO(TraverseSynOrSemInitListExpr(
-      S->isSemanticForm() ? S : S->getSemanticForm(), Queue));
+  if (getDerived().shouldVisitImplicitCode()) {
+    // Only visit the semantic form if the clients are interested in implicit
+    // compiler-generated.
+    TRY_TO(TraverseSynOrSemInitListExpr(
+        S->isSemanticForm() ? S : S->getSemanticForm(), Queue));
+  }
   return true;
 }
 

Modified: cfe/trunk/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp?rev=366672&r1=366671&r2=366672&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp (original)
+++ cfe/trunk/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp Mon Jul 22 02:58:53 2019
@@ -17,19 +17,36 @@ namespace {
 class InitListExprPreOrderVisitor
     : public ExpectedLocationVisitor<InitListExprPreOrderVisitor> {
 public:
+  InitListExprPreOrderVisitor(bool VisitImplicitCode)
+      : VisitImplicitCode(VisitImplicitCode) {}
+
+  bool shouldVisitImplicitCode() const { return VisitImplicitCode; }
+
   bool VisitInitListExpr(InitListExpr *ILE) {
     Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc());
     return true;
   }
+
+private:
+  bool VisitImplicitCode;
 };
 
 TEST(RecursiveASTVisitor, InitListExprIsPreOrderVisitedTwice) {
-  InitListExprPreOrderVisitor Visitor;
+  InitListExprPreOrderVisitor Visitor(/*VisitImplicitCode=*/true);
   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, InitListExprVisitedOnceWhenNoImplicit) {
+  InitListExprPreOrderVisitor Visitor(/*VisitImplicitCode=*/false);
+  Visitor.ExpectMatch("syntactic", 2, 21);
+  Visitor.DisallowMatch("semantic", 2, 21);
+  EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
+                              "static struct S s = {.x = 0};\n",
+                              InitListExprPreOrderVisitor::Lang_C));
 }
 
 } // end anonymous namespace




More information about the cfe-commits mailing list