[clangd] Handle members of anon structs in SelectionTree

References to fields inside anon structs contain an implicit children
for the container, which has the same SourceLocation with the field.
This was resulting in SelectionTree always picking the anon-struct rather than
the field as the selection.

This patch prevents that by claiming the range for the field early.

https://github.com/clangd/clangd/issues/877.

Differential Revision: https://reviews.llvm.org/D110825
This commit is contained in:
Kadir Cetinkaya 2021-09-30 15:25:42 +02:00
parent 413b7ac6b5
commit 512aa84850
No known key found for this signature in database
GPG Key ID: E39E36B8D2057ED6
2 changed files with 30 additions and 0 deletions

View File

@ -443,6 +443,15 @@ bool isImplicit(const Stmt *S) {
if (auto *CTI = llvm::dyn_cast<CXXThisExpr>(S))
if (CTI->isImplicit())
return true;
// Make sure implicit access of anonymous structs don't end up owning tokens.
if (auto *ME = llvm::dyn_cast<MemberExpr>(S)) {
if (auto *FD = llvm::dyn_cast<FieldDecl>(ME->getMemberDecl()))
if (FD->isAnonymousStructOrUnion())
// If Base is an implicit CXXThis, then the whole MemberExpr has no
// tokens. If it's a normal e.g. DeclRef, we treat the MemberExpr like
// an implicit cast.
return isImplicit(ME->getBase());
}
// Refs to operator() and [] are (almost?) always implicit as part of calls.
if (auto *DRE = llvm::dyn_cast<DeclRefExpr>(S)) {
if (auto *FD = llvm::dyn_cast<FunctionDecl>(DRE->getDecl())) {

View File

@ -365,6 +365,27 @@ TEST(LocateSymbol, WithIndex) {
ElementsAre(Sym("Forward", SymbolHeader.range("forward"), Test.range())));
}
TEST(LocateSymbol, AnonymousStructFields) {
auto Code = Annotations(R"cpp(
struct $2[[Foo]] {
struct { int $1[[x]]; };
void foo() {
// Make sure the implicit base is skipped.
$1^x = 42;
}
};
// Check that we don't skip explicit bases.
int a = $2^Foo{}.x;
)cpp");
TestTU TU = TestTU::withCode(Code.code());
auto AST = TU.build();
EXPECT_THAT(locateSymbolAt(AST, Code.point("1"), TU.index().get()),
UnorderedElementsAre(Sym("x", Code.range("1"), Code.range("1"))));
EXPECT_THAT(
locateSymbolAt(AST, Code.point("2"), TU.index().get()),
UnorderedElementsAre(Sym("Foo", Code.range("2"), Code.range("2"))));
}
TEST(LocateSymbol, FindOverrides) {
auto Code = Annotations(R"cpp(
class Foo {