This revision was automatically updated to reflect the committed changes. Closed by commit rG512aa8485010: [clangd] Handle members of anon structs in SelectionTree (authored by kadircet).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D110825/new/ https://reviews.llvm.org/D110825 Files: clang-tools-extra/clangd/Selection.cpp clang-tools-extra/clangd/unittests/XRefsTests.cpp Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -365,6 +365,27 @@ 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 { Index: clang-tools-extra/clangd/Selection.cpp =================================================================== --- clang-tools-extra/clangd/Selection.cpp +++ clang-tools-extra/clangd/Selection.cpp @@ -443,6 +443,15 @@ 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())) {
Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -365,6 +365,27 @@ 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 { Index: clang-tools-extra/clangd/Selection.cpp =================================================================== --- clang-tools-extra/clangd/Selection.cpp +++ clang-tools-extra/clangd/Selection.cpp @@ -443,6 +443,15 @@ 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())) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits