jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet.
Herald added a project: clang.

RecursiveASTVisitor was visiting implcit constructor initializers. This caused 
semantic highlighting in clangd to emit error logs. Fixes this by checking if 
the constructor is written or if the visitor should visit implicit decls.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65735

Files:
  clang/include/clang/AST/RecursiveASTVisitor.h
  clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp


Index: clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
===================================================================
--- clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
+++ clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
@@ -22,11 +22,19 @@
 
   bool shouldVisitImplicitCode() const { return VisitImplicitCode; }
 
+  bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
+    if (Init->getSourceLocation().isInvalid())
+      InvalidLocsVisited = true;
+    Match("initializer", Init->getSourceLocation());
+    return true;
+  }
+
   bool VisitInitListExpr(InitListExpr *ILE) {
     Match(ILE->isSemanticForm() ? "semantic" : "syntactic", 
ILE->getBeginLoc());
     return true;
   }
 
+  bool InvalidLocsVisited = false;
 private:
   bool VisitImplicitCode;
 };
@@ -49,4 +57,22 @@
                               InitListExprPreOrderVisitor::Lang_C));
 }
 
+TEST(RecursiveASTVisitor, CXXCtorInitializerVisitNoImplicit) {
+  std::vector<bool> Config{true, false};
+  for (bool VisitImplCode : Config) {
+    InitListExprPreOrderVisitor Visitor(VisitImplCode);
+    Visitor.ExpectMatch("initializer", 7, 17);
+    EXPECT_TRUE(Visitor.runOver(R"cpp(
+        class A {};
+        class B : public A {
+          B() {};
+        };
+        class C : public A {
+          C() : A() {}
+        };
+      )cpp",
+                                InitListExprPreOrderVisitor::Lang_CXX));
+    EXPECT_EQ(Visitor.InvalidLocsVisited, VisitImplCode);
+  }
+}
 } // end anonymous namespace
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2023,7 +2023,8 @@
   if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
     // Constructor initializers.
     for (auto *I : Ctor->inits()) {
-      TRY_TO(TraverseConstructorInitializer(I));
+      if (I->isWritten() || getDerived().shouldVisitImplicitCode())
+        TRY_TO(TraverseConstructorInitializer(I));
     }
   }
 


Index: clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
===================================================================
--- clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
+++ clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
@@ -22,11 +22,19 @@
 
   bool shouldVisitImplicitCode() const { return VisitImplicitCode; }
 
+  bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
+    if (Init->getSourceLocation().isInvalid())
+      InvalidLocsVisited = true;
+    Match("initializer", Init->getSourceLocation());
+    return true;
+  }
+
   bool VisitInitListExpr(InitListExpr *ILE) {
     Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc());
     return true;
   }
 
+  bool InvalidLocsVisited = false;
 private:
   bool VisitImplicitCode;
 };
@@ -49,4 +57,22 @@
                               InitListExprPreOrderVisitor::Lang_C));
 }
 
+TEST(RecursiveASTVisitor, CXXCtorInitializerVisitNoImplicit) {
+  std::vector<bool> Config{true, false};
+  for (bool VisitImplCode : Config) {
+    InitListExprPreOrderVisitor Visitor(VisitImplCode);
+    Visitor.ExpectMatch("initializer", 7, 17);
+    EXPECT_TRUE(Visitor.runOver(R"cpp(
+        class A {};
+        class B : public A {
+          B() {};
+        };
+        class C : public A {
+          C() : A() {}
+        };
+      )cpp",
+                                InitListExprPreOrderVisitor::Lang_CXX));
+    EXPECT_EQ(Visitor.InvalidLocsVisited, VisitImplCode);
+  }
+}
 } // end anonymous namespace
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2023,7 +2023,8 @@
   if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
     // Constructor initializers.
     for (auto *I : Ctor->inits()) {
-      TRY_TO(TraverseConstructorInitializer(I));
+      if (I->isWritten() || getDerived().shouldVisitImplicitCode())
+        TRY_TO(TraverseConstructorInitializer(I));
     }
   }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to