[AST] Fix RecursiveASTVisitor visiting implicit constructor initializers.

Summary: 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.

Reviewers: hokein, ilya-biryukov

Subscribers: kadircet, cfe-commits

Tags: #clang

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

llvm-svn: 367839
This commit is contained in:
Johan Vikstrom 2019-08-05 12:20:43 +00:00
parent 068f8c74e4
commit be60f97d23
3 changed files with 60 additions and 1 deletions

View File

@ -2023,7 +2023,8 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
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));
}
}

View File

@ -31,6 +31,7 @@ add_clang_unittest(ToolingTests
RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp
RecursiveASTVisitorTests/DeclRefExpr.cpp
RecursiveASTVisitorTests/ImplicitCtor.cpp
RecursiveASTVisitorTests/ImplicitCtorInitializer.cpp
RecursiveASTVisitorTests/InitListExprPostOrder.cpp
RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
RecursiveASTVisitorTests/InitListExprPreOrder.cpp

View File

@ -0,0 +1,57 @@
//=- unittest/Tooling/RecursiveASTVisitorTests/ImplicitCtorInitializer.cpp -=//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "TestVisitor.h"
using namespace clang;
namespace {
class CXXCtorInitializerVisitor
: public ExpectedLocationVisitor<CXXCtorInitializerVisitor> {
public:
CXXCtorInitializerVisitor(bool VisitImplicitCode)
: VisitImplicitCode(VisitImplicitCode) {}
bool shouldVisitImplicitCode() const { return VisitImplicitCode; }
bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
if (!Init->isWritten())
VisitedImplicitInitializer = true;
Match("initializer", Init->getSourceLocation());
return ExpectedLocationVisitor<
CXXCtorInitializerVisitor>::TraverseConstructorInitializer(Init);
}
bool VisitedImplicitInitializer = false;
private:
bool VisitImplicitCode;
};
// Check to ensure that CXXCtorInitializer is not visited when implicit code
// should not be visited and that it is visited when implicit code should be
// visited.
TEST(RecursiveASTVisitor, CXXCtorInitializerVisitNoImplicit) {
for (bool VisitImplCode : {true, false}) {
CXXCtorInitializerVisitor 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",
CXXCtorInitializerVisitor::Lang_CXX));
EXPECT_EQ(Visitor.VisitedImplicitInitializer, VisitImplCode);
}
}
} // end anonymous namespace