diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp --- a/clang-tools-extra/clangd/Selection.cpp +++ b/clang-tools-extra/clangd/Selection.cpp @@ -493,6 +493,14 @@ return traverseNode( X, [&] { return Base::TraverseConstructorInitializer(X); }); } + bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &X) { + auto N = DynTypedNode::create(X); + if (canSafelySkipNode(N)) + return true; + push(std::move(N)); + pop(); + return true; + } // Stmt is the same, but this form allows the data recursion optimization. bool dataTraverseStmtPre(Stmt *X) { if (!X || isImplicit(X)) diff --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp --- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp +++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp @@ -261,6 +261,27 @@ )cpp", "StringLiteral", // Not DeclRefExpr to operator()! }, + { + R"cpp( + struct Foo {}; + struct Bar : [[v^ir^tual private Foo]] {}; + )cpp", + "CXXBaseSpecifier", + }, + { + R"cpp( + struct Foo {}; + struct Bar : [[private Fo^o]] {}; + )cpp", + "CXXBaseSpecifier", + }, + { + R"cpp( + struct Foo {}; + struct Bar : [[Fo^o]] {}; + )cpp", + "CXXBaseSpecifier", + }, // Point selections. {"void foo() { [[^foo]](); }", "DeclRefExpr"}, diff --git a/clang/lib/AST/ASTTypeTraits.cpp b/clang/lib/AST/ASTTypeTraits.cpp --- a/clang/lib/AST/ASTTypeTraits.cpp +++ b/clang/lib/AST/ASTTypeTraits.cpp @@ -193,5 +193,7 @@ return TAL->getSourceRange(); if (const auto *C = get()) return SourceRange(C->getBeginLoc(), C->getEndLoc()); + if (const auto *CBS = get()) + return CBS->getSourceRange(); return SourceRange(); }