Author: Younan Zhang Date: 2024-01-11T16:59:18+08:00 New Revision: 9ef2ac3ad1bd5aa9e589f63047e8abeac11ad1b2
URL: https://github.com/llvm/llvm-project/commit/9ef2ac3ad1bd5aa9e589f63047e8abeac11ad1b2 DIFF: https://github.com/llvm/llvm-project/commit/9ef2ac3ad1bd5aa9e589f63047e8abeac11ad1b2.diff LOG: [clangd] Handle lambda scopes inside Node::getDeclContext() (#76329) We used to consider the `DeclContext` for selection nodes inside a lambda as the enclosing scope of the lambda expression, rather than the lambda itself. For example, ```cpp void foo(); auto lambda = [] { return ^foo(); }; ``` where `N` is the selection node for the expression `foo()`, `N.getDeclContext()` returns the `TranslationUnitDecl` previously, which IMO is wrong, since the method `operator()` of the lambda is closer. Incidentally, this fixes a glitch in add-using-declaration tweaks. (Thanks @HighCommander4 for the test case.) Added: Modified: clang-tools-extra/clangd/Selection.cpp clang-tools-extra/clangd/unittests/SelectionTests.cpp clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp index 8c6d5750ecefdb..277cb8769a1b12 100644 --- a/clang-tools-extra/clangd/Selection.cpp +++ b/clang-tools-extra/clangd/Selection.cpp @@ -1113,6 +1113,9 @@ const DeclContext &SelectionTree::Node::getDeclContext() const { return *DC; return *Current->getLexicalDeclContext(); } + if (const auto *LE = CurrentNode->ASTNode.get<LambdaExpr>()) + if (CurrentNode != this) + return *LE->getCallOperator(); } llvm_unreachable("A tree must always be rooted at TranslationUnitDecl."); } diff --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp index 4c019a1524f3c3..754e8c287c5148 100644 --- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp +++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp @@ -880,6 +880,19 @@ TEST(SelectionTest, DeclContextIsLexical) { } } +TEST(SelectionTest, DeclContextLambda) { + llvm::Annotations Test(R"cpp( + void foo(); + auto lambda = [] { + return $1^foo(); + }; + )cpp"); + auto AST = TestTU::withCode(Test.code()).build(); + auto ST = SelectionTree::createRight(AST.getASTContext(), AST.getTokens(), + Test.point("1"), Test.point("1")); + EXPECT_TRUE(ST.commonAncestor()->getDeclContext().isFunctionOrMethod()); +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp index 1fd2487378d705..c2dd8e1bb8eefa 100644 --- a/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp +++ b/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp @@ -309,6 +309,29 @@ namespace foo { void fun(); } void foo::fun() { ff(); })cpp"}, + // Inside a lambda. + { + R"cpp( +namespace NS { +void unrelated(); +void foo(); +} + +auto L = [] { + using NS::unrelated; + NS::f^oo(); +};)cpp", + R"cpp( +namespace NS { +void unrelated(); +void foo(); +} + +auto L = [] { + using NS::foo;using NS::unrelated; + foo(); +};)cpp", + }, // If all other using are fully qualified, add :: {R"cpp( #include "test.hpp" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits