[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
tilobyte wrote: ping tagging clangd code owner for review: @sam-mccall https://github.com/llvm/llvm-project/pull/101857 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
https://github.com/tilobyte updated https://github.com/llvm/llvm-project/pull/101857 >From c1afe853ccacae1605fecfe552bb9a263c6b8c1d Mon Sep 17 00:00:00 2001 From: Timothy Akintilo Date: Sat, 27 Jul 2024 16:17:46 -0500 Subject: [PATCH 1/3] use lambda name instead of operator() --- clang-tools-extra/clangd/CodeComplete.cpp | 2 ++ .../clangd/unittests/CodeCompleteTests.cpp| 9 +++ .../include/clang/Sema/CodeCompleteConsumer.h | 18 ++ clang/include/clang/Sema/Overload.h | 5 clang/include/clang/Sema/Sema.h | 22 - clang/lib/Sema/CodeCompleteConsumer.cpp | 10 +++- clang/lib/Sema/SemaCodeComplete.cpp | 17 ++--- clang/lib/Sema/SemaLookup.cpp | 3 ++- clang/lib/Sema/SemaOverload.cpp | 24 +-- 9 files changed, 82 insertions(+), 28 deletions(-) diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 89eee392837af4..4f8a53aa7aae7e 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -1139,6 +1139,8 @@ class SignatureHelpCollector final : public CodeCompleteConsumer { switch (K) { case OC::CK_Aggregate: return 0; + case OC::CK_Lambda: +[[fallthrough]]; case OC::CK_Function: return 1; case OC::CK_FunctionType: diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 96d1ee1f0add73..4f748168d75aa7 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -1437,6 +1437,15 @@ TEST(SignatureHelpTest, Overloads) { EXPECT_EQ(0, Results.activeParameter); } +TEST(SignatureHelpTest, ShowLambdaNameInsteadOfOperatorParens) { + auto const Results = signatures(R"cpp( +auto foo = [](int x, int y){}; +int main() { foo(^); } + )cpp"); + EXPECT_THAT(Results.signatures, + UnorderedElementsAre(sig("foo([[int x]], [[int y]]) -> void"))); +} + TEST(SignatureHelpTest, FunctionPointers) { llvm::StringLiteral Tests[] = { // Variable of function pointer type diff --git a/clang/include/clang/Sema/CodeCompleteConsumer.h b/clang/include/clang/Sema/CodeCompleteConsumer.h index 0924dc27af82b5..a6530c3c93d912 100644 --- a/clang/include/clang/Sema/CodeCompleteConsumer.h +++ b/clang/include/clang/Sema/CodeCompleteConsumer.h @@ -1028,6 +1028,9 @@ class CodeCompleteConsumer { /// The candidate is a function declaration. CK_Function, + // The candidate is a lambda operator(). + CK_Lambda, + /// The candidate is a function template, arguments are being completed. CK_FunctionTemplate, @@ -1055,6 +1058,13 @@ class CodeCompleteConsumer { /// Kind == CK_Function. FunctionDecl *Function; + /// The lambda operator() candidate paired with the + /// lambda variable, available when Kind == CK_Lambda. + struct { +FunctionDecl *OperatorParens; +VarDecl *Var; + } Lambda; + /// The function template overload candidate, available when /// Kind == CK_FunctionTemplate. FunctionTemplateDecl *FunctionTemplate; @@ -1082,6 +1092,12 @@ class CodeCompleteConsumer { assert(Function != nullptr); } +OverloadCandidate(FunctionDecl *LambdaOperatorParens, VarDecl *LambdaVar) +: Kind(CK_Lambda), Lambda{LambdaOperatorParens, LambdaVar} { + assert(Lambda.OperatorParens != nullptr); + assert(Lambda.Var != nullptr); +} + OverloadCandidate(FunctionTemplateDecl *FunctionTemplateDecl) : Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplateDecl) { assert(FunctionTemplateDecl != nullptr); @@ -1112,6 +1128,8 @@ class CodeCompleteConsumer { /// function declaration for a function template. FunctionDecl *getFunction() const; +VarDecl *getLambdaVarDecl() const; + /// Retrieve the function template overload candidate. FunctionTemplateDecl *getFunctionTemplate() const { assert(getKind() == CK_FunctionTemplate && "Not a function template"); diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index d6a6cee62a7528..7c4e82f07de02e 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -876,6 +876,11 @@ class Sema; /// function pointer or reference (C++ [over.call.object]). FunctionDecl *Function; +/// LambdaName - When the OverloadCandidate is for a +/// lambda's operator(), points to the declaration of +/// the lambda variable. +VarDecl *LambdaName{nullptr}; + /// FoundDecl - The original declaration that was looked up / /// invented / otherwise found, together with its access. /// Might be a UsingShadowDecl or a FunctionTemplateDec
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
https://github.com/tilobyte updated https://github.com/llvm/llvm-project/pull/101857 >From c1afe853ccacae1605fecfe552bb9a263c6b8c1d Mon Sep 17 00:00:00 2001 From: Timothy Akintilo Date: Sat, 27 Jul 2024 16:17:46 -0500 Subject: [PATCH 1/7] use lambda name instead of operator() --- clang-tools-extra/clangd/CodeComplete.cpp | 2 ++ .../clangd/unittests/CodeCompleteTests.cpp| 9 +++ .../include/clang/Sema/CodeCompleteConsumer.h | 18 ++ clang/include/clang/Sema/Overload.h | 5 clang/include/clang/Sema/Sema.h | 22 - clang/lib/Sema/CodeCompleteConsumer.cpp | 10 +++- clang/lib/Sema/SemaCodeComplete.cpp | 17 ++--- clang/lib/Sema/SemaLookup.cpp | 3 ++- clang/lib/Sema/SemaOverload.cpp | 24 +-- 9 files changed, 82 insertions(+), 28 deletions(-) diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 89eee392837af4..4f8a53aa7aae7e 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -1139,6 +1139,8 @@ class SignatureHelpCollector final : public CodeCompleteConsumer { switch (K) { case OC::CK_Aggregate: return 0; + case OC::CK_Lambda: +[[fallthrough]]; case OC::CK_Function: return 1; case OC::CK_FunctionType: diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 96d1ee1f0add73..4f748168d75aa7 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -1437,6 +1437,15 @@ TEST(SignatureHelpTest, Overloads) { EXPECT_EQ(0, Results.activeParameter); } +TEST(SignatureHelpTest, ShowLambdaNameInsteadOfOperatorParens) { + auto const Results = signatures(R"cpp( +auto foo = [](int x, int y){}; +int main() { foo(^); } + )cpp"); + EXPECT_THAT(Results.signatures, + UnorderedElementsAre(sig("foo([[int x]], [[int y]]) -> void"))); +} + TEST(SignatureHelpTest, FunctionPointers) { llvm::StringLiteral Tests[] = { // Variable of function pointer type diff --git a/clang/include/clang/Sema/CodeCompleteConsumer.h b/clang/include/clang/Sema/CodeCompleteConsumer.h index 0924dc27af82b5..a6530c3c93d912 100644 --- a/clang/include/clang/Sema/CodeCompleteConsumer.h +++ b/clang/include/clang/Sema/CodeCompleteConsumer.h @@ -1028,6 +1028,9 @@ class CodeCompleteConsumer { /// The candidate is a function declaration. CK_Function, + // The candidate is a lambda operator(). + CK_Lambda, + /// The candidate is a function template, arguments are being completed. CK_FunctionTemplate, @@ -1055,6 +1058,13 @@ class CodeCompleteConsumer { /// Kind == CK_Function. FunctionDecl *Function; + /// The lambda operator() candidate paired with the + /// lambda variable, available when Kind == CK_Lambda. + struct { +FunctionDecl *OperatorParens; +VarDecl *Var; + } Lambda; + /// The function template overload candidate, available when /// Kind == CK_FunctionTemplate. FunctionTemplateDecl *FunctionTemplate; @@ -1082,6 +1092,12 @@ class CodeCompleteConsumer { assert(Function != nullptr); } +OverloadCandidate(FunctionDecl *LambdaOperatorParens, VarDecl *LambdaVar) +: Kind(CK_Lambda), Lambda{LambdaOperatorParens, LambdaVar} { + assert(Lambda.OperatorParens != nullptr); + assert(Lambda.Var != nullptr); +} + OverloadCandidate(FunctionTemplateDecl *FunctionTemplateDecl) : Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplateDecl) { assert(FunctionTemplateDecl != nullptr); @@ -1112,6 +1128,8 @@ class CodeCompleteConsumer { /// function declaration for a function template. FunctionDecl *getFunction() const; +VarDecl *getLambdaVarDecl() const; + /// Retrieve the function template overload candidate. FunctionTemplateDecl *getFunctionTemplate() const { assert(getKind() == CK_FunctionTemplate && "Not a function template"); diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index d6a6cee62a7528..7c4e82f07de02e 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -876,6 +876,11 @@ class Sema; /// function pointer or reference (C++ [over.call.object]). FunctionDecl *Function; +/// LambdaName - When the OverloadCandidate is for a +/// lambda's operator(), points to the declaration of +/// the lambda variable. +VarDecl *LambdaName{nullptr}; + /// FoundDecl - The original declaration that was looked up / /// invented / otherwise found, together with its access. /// Might be a UsingShadowDecl or a FunctionTemplateDec
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
@@ -6292,11 +6298,16 @@ SemaCodeCompletion::ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args, SmallVector ArgExprs(1, NakedFn); ArgExprs.append(ArgsWithoutDependentTypes.begin(), ArgsWithoutDependentTypes.end()); +auto *const LambdaName = +DC->isLambda() ? cast(NakedFn->getReferencedDeclOfCallee()) + : nullptr; SemaRef.AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet, /*ExplicitArgs=*/nullptr, /*SuppressUserConversions=*/false, - /*PartialOverloading=*/true); + /*PartialOverloading=*/true, + /*FirstArgumentIsBase=*/false, + /*LambdaName=*/LambdaName); tilobyte wrote: i see, renamed to `LambdaDecl` https://github.com/llvm/llvm-project/pull/101857 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
@@ -6292,11 +6298,16 @@ SemaCodeCompletion::ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args, SmallVector ArgExprs(1, NakedFn); ArgExprs.append(ArgsWithoutDependentTypes.begin(), ArgsWithoutDependentTypes.end()); +auto *const LambdaName = +DC->isLambda() ? cast(NakedFn->getReferencedDeclOfCallee()) tilobyte wrote: @erichkeane stepping through the test i added for a lambda returned from a function, `NakedFn->getReferencedDeclOfCallee()` returns `nullptr` in the case of a lambda returned from a function. i believe this is because `NakedFn` is an rvalue, so there is no referenced decl to get. using `cast_if_present`/`dyn_cast_if_present` seems to cover that case. @zyn0217 yes, you are correct that `NakedFn` is a `DeclRefExpr` referring to the `VarDecl` of the declaration. `dyn_cast_if_present` indeed works, though i wonder--if `NakedFn->getReferencedDeclOfCallee()` returns `nullptr` in the case of a lambda returned from a function, could we get away with just `cast_if_present`? https://github.com/llvm/llvm-project/pull/101857 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
@@ -1437,6 +1437,15 @@ TEST(SignatureHelpTest, Overloads) { EXPECT_EQ(0, Results.activeParameter); } +TEST(SignatureHelpTest, ShowLambdaNameInsteadOfOperatorParens) { + auto const Results = signatures(R"cpp( +auto foo = [](int x, int y){}; +int main() { foo(^); } tilobyte wrote: yes, added tests for an immediately-invoked lambda and a lambda returned from a function. https://github.com/llvm/llvm-project/pull/101857 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
@@ -9147,7 +9147,8 @@ class Sema final : public SemaBase { /// /// \returns true if lookup succeeded, false if it failed. bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, - bool InUnqualifiedLookup = false); + bool InUnqualifiedLookup = false, + IdentifierInfo const *IdentifierOverride = nullptr); tilobyte wrote: removed, but i'll keep that in mind! https://github.com/llvm/llvm-project/pull/101857 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
@@ -876,6 +876,11 @@ class Sema; /// function pointer or reference (C++ [over.call.object]). FunctionDecl *Function; +/// LambdaName - When the OverloadCandidate is for a +/// lambda's operator(), points to the declaration of +/// the lambda variable. +VarDecl *LambdaName{nullptr}; tilobyte wrote: @erichkeane i added tests for immediately-invoked lambdas. could you give an example of a lambda in a template-pack? i was thinking something like ``` template auto foo(Lambda... lambda) { lambda(^); } ``` but then the lambda has a name. https://github.com/llvm/llvm-project/pull/101857 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
@@ -2390,7 +2390,8 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, } bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, - bool InUnqualifiedLookup) { + bool InUnqualifiedLookup, + IdentifierInfo const *IdentifierOverride) { tilobyte wrote: oops sorry, that's a remnant of another solution i tried earlier. removed https://github.com/llvm/llvm-project/pull/101857 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
@@ -876,6 +876,11 @@ class Sema; /// function pointer or reference (C++ [over.call.object]). FunctionDecl *Function; +/// LambdaName - When the OverloadCandidate is for a +/// lambda's operator(), points to the declaration of +/// the lambda variable. +VarDecl *LambdaName{nullptr}; tilobyte wrote: @zyn0217 unfortunately removing the default initializer breaks a bunch of tests--need to check to confirm but i believe it's due to the check that `LambdaDecl` is `nullptr` here: https://github.com/llvm/llvm-project/blob/d8140f9013f47094a159fd2918128d9252ca3280/clang/lib/Sema/SemaCodeComplete.cpp#L6130 i think the fix would just be setting `LambdaDecl` to `nullptr` everywhere we make an `OverloadCandidate` for a non-lambda, but the `nullptr` default initializer seemed cleaner... let me know if not using a default initializer is preferred. https://github.com/llvm/llvm-project/pull/101857 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
@@ -10204,15 +10205,14 @@ class Sema final : public SemaBase { /// both @c a1 and @c a2. If @p SuppressUserConversions, then don't /// allow user-defined conversions via constructors or conversion /// operators. - void - AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, QualType ObjectType, - Expr::Classification ObjectClassification, - ArrayRef Args, OverloadCandidateSet &CandidateSet, - bool SuppressUserConversions = false, - bool PartialOverloading = false, - ConversionSequenceList EarlyConversions = std::nullopt, - OverloadCandidateParamOrder PO = {}); + void AddMethodCandidate( + CXXMethodDecl *Method, DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, QualType ObjectType, + Expr::Classification ObjectClassification, ArrayRef Args, + OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false, + bool PartialOverloading = false, + ConversionSequenceList EarlyConversions = std::nullopt, + OverloadCandidateParamOrder PO = {}, VarDecl *LambdaName = nullptr); tilobyte wrote: sorry, did not get around to this comment this weekend. to be certain, would we also not want `LambdaName` (now `LambdaDecl`) to be a default argument for `addFunctionCandidates()` above? https://github.com/llvm/llvm-project/pull/101857 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
@@ -876,6 +876,11 @@ class Sema; /// function pointer or reference (C++ [over.call.object]). FunctionDecl *Function; +/// LambdaName - When the OverloadCandidate is for a +/// lambda's operator(), points to the declaration of +/// the lambda variable. +VarDecl *LambdaName{nullptr}; tilobyte wrote: thanks for the example! i don't think this patch affects behavior in this scenario. the current behavior (preserved in this patch) is not to produce any signature help. i believe this is because within `bar()` it is not known that `Ls` has a call operator. unless i'm misunderstanding? https://github.com/user-attachments/assets/f19431e0-3764-4530-8cf7-22cec4f8f228";> https://github.com/llvm/llvm-project/pull/101857 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
tilobyte wrote: > I also wonder if we would better off having `CXXRecordDecl` save its > 'variable' for lambdas (and look it up from there) rather than this. saving the `VarDecl` in the lambda's `CXXRecordDecl` indeed sounds like a cleaner solution--i will try implementing that before making any changes to `AddMethodCandidate()`'s signature, since it wouldn't need the `LambdaDecl` parameter any more with this solution. https://github.com/llvm/llvm-project/pull/101857 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
@@ -876,6 +876,11 @@ class Sema; /// function pointer or reference (C++ [over.call.object]). FunctionDecl *Function; +/// LambdaName - When the OverloadCandidate is for a +/// lambda's operator(), points to the declaration of +/// the lambda variable. +VarDecl *LambdaName{nullptr}; tilobyte wrote: Wait I think I understand now, you mean the signature help when immediately invoking the lambdas within the `bar` function call? E.g., `bar([]{...}(^), ...)` https://github.com/llvm/llvm-project/pull/101857 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
https://github.com/tilobyte updated https://github.com/llvm/llvm-project/pull/101857 >From c1afe853ccacae1605fecfe552bb9a263c6b8c1d Mon Sep 17 00:00:00 2001 From: Timothy Akintilo Date: Sat, 27 Jul 2024 16:17:46 -0500 Subject: [PATCH 1/2] use lambda name instead of operator() --- clang-tools-extra/clangd/CodeComplete.cpp | 2 ++ .../clangd/unittests/CodeCompleteTests.cpp| 9 +++ .../include/clang/Sema/CodeCompleteConsumer.h | 18 ++ clang/include/clang/Sema/Overload.h | 5 clang/include/clang/Sema/Sema.h | 22 - clang/lib/Sema/CodeCompleteConsumer.cpp | 10 +++- clang/lib/Sema/SemaCodeComplete.cpp | 17 ++--- clang/lib/Sema/SemaLookup.cpp | 3 ++- clang/lib/Sema/SemaOverload.cpp | 24 +-- 9 files changed, 82 insertions(+), 28 deletions(-) diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 89eee392837af4..4f8a53aa7aae7e 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -1139,6 +1139,8 @@ class SignatureHelpCollector final : public CodeCompleteConsumer { switch (K) { case OC::CK_Aggregate: return 0; + case OC::CK_Lambda: +[[fallthrough]]; case OC::CK_Function: return 1; case OC::CK_FunctionType: diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 96d1ee1f0add73..4f748168d75aa7 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -1437,6 +1437,15 @@ TEST(SignatureHelpTest, Overloads) { EXPECT_EQ(0, Results.activeParameter); } +TEST(SignatureHelpTest, ShowLambdaNameInsteadOfOperatorParens) { + auto const Results = signatures(R"cpp( +auto foo = [](int x, int y){}; +int main() { foo(^); } + )cpp"); + EXPECT_THAT(Results.signatures, + UnorderedElementsAre(sig("foo([[int x]], [[int y]]) -> void"))); +} + TEST(SignatureHelpTest, FunctionPointers) { llvm::StringLiteral Tests[] = { // Variable of function pointer type diff --git a/clang/include/clang/Sema/CodeCompleteConsumer.h b/clang/include/clang/Sema/CodeCompleteConsumer.h index 0924dc27af82b5..a6530c3c93d912 100644 --- a/clang/include/clang/Sema/CodeCompleteConsumer.h +++ b/clang/include/clang/Sema/CodeCompleteConsumer.h @@ -1028,6 +1028,9 @@ class CodeCompleteConsumer { /// The candidate is a function declaration. CK_Function, + // The candidate is a lambda operator(). + CK_Lambda, + /// The candidate is a function template, arguments are being completed. CK_FunctionTemplate, @@ -1055,6 +1058,13 @@ class CodeCompleteConsumer { /// Kind == CK_Function. FunctionDecl *Function; + /// The lambda operator() candidate paired with the + /// lambda variable, available when Kind == CK_Lambda. + struct { +FunctionDecl *OperatorParens; +VarDecl *Var; + } Lambda; + /// The function template overload candidate, available when /// Kind == CK_FunctionTemplate. FunctionTemplateDecl *FunctionTemplate; @@ -1082,6 +1092,12 @@ class CodeCompleteConsumer { assert(Function != nullptr); } +OverloadCandidate(FunctionDecl *LambdaOperatorParens, VarDecl *LambdaVar) +: Kind(CK_Lambda), Lambda{LambdaOperatorParens, LambdaVar} { + assert(Lambda.OperatorParens != nullptr); + assert(Lambda.Var != nullptr); +} + OverloadCandidate(FunctionTemplateDecl *FunctionTemplateDecl) : Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplateDecl) { assert(FunctionTemplateDecl != nullptr); @@ -1112,6 +1128,8 @@ class CodeCompleteConsumer { /// function declaration for a function template. FunctionDecl *getFunction() const; +VarDecl *getLambdaVarDecl() const; + /// Retrieve the function template overload candidate. FunctionTemplateDecl *getFunctionTemplate() const { assert(getKind() == CK_FunctionTemplate && "Not a function template"); diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index d6a6cee62a7528..7c4e82f07de02e 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -876,6 +876,11 @@ class Sema; /// function pointer or reference (C++ [over.call.object]). FunctionDecl *Function; +/// LambdaName - When the OverloadCandidate is for a +/// lambda's operator(), points to the declaration of +/// the lambda variable. +VarDecl *LambdaName{nullptr}; + /// FoundDecl - The original declaration that was looked up / /// invented / otherwise found, together with its access. /// Might be a UsingShadowDecl or a FunctionTemplateDec
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
tilobyte wrote: Ping https://github.com/llvm/llvm-project/pull/101857 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
https://github.com/tilobyte updated https://github.com/llvm/llvm-project/pull/101857 >From c1afe853ccacae1605fecfe552bb9a263c6b8c1d Mon Sep 17 00:00:00 2001 From: Timothy Akintilo Date: Sat, 27 Jul 2024 16:17:46 -0500 Subject: [PATCH 1/9] use lambda name instead of operator() --- clang-tools-extra/clangd/CodeComplete.cpp | 2 ++ .../clangd/unittests/CodeCompleteTests.cpp| 9 +++ .../include/clang/Sema/CodeCompleteConsumer.h | 18 ++ clang/include/clang/Sema/Overload.h | 5 clang/include/clang/Sema/Sema.h | 22 - clang/lib/Sema/CodeCompleteConsumer.cpp | 10 +++- clang/lib/Sema/SemaCodeComplete.cpp | 17 ++--- clang/lib/Sema/SemaLookup.cpp | 3 ++- clang/lib/Sema/SemaOverload.cpp | 24 +-- 9 files changed, 82 insertions(+), 28 deletions(-) diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 89eee392837af4..4f8a53aa7aae7e 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -1139,6 +1139,8 @@ class SignatureHelpCollector final : public CodeCompleteConsumer { switch (K) { case OC::CK_Aggregate: return 0; + case OC::CK_Lambda: +[[fallthrough]]; case OC::CK_Function: return 1; case OC::CK_FunctionType: diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 96d1ee1f0add73..4f748168d75aa7 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -1437,6 +1437,15 @@ TEST(SignatureHelpTest, Overloads) { EXPECT_EQ(0, Results.activeParameter); } +TEST(SignatureHelpTest, ShowLambdaNameInsteadOfOperatorParens) { + auto const Results = signatures(R"cpp( +auto foo = [](int x, int y){}; +int main() { foo(^); } + )cpp"); + EXPECT_THAT(Results.signatures, + UnorderedElementsAre(sig("foo([[int x]], [[int y]]) -> void"))); +} + TEST(SignatureHelpTest, FunctionPointers) { llvm::StringLiteral Tests[] = { // Variable of function pointer type diff --git a/clang/include/clang/Sema/CodeCompleteConsumer.h b/clang/include/clang/Sema/CodeCompleteConsumer.h index 0924dc27af82b5..a6530c3c93d912 100644 --- a/clang/include/clang/Sema/CodeCompleteConsumer.h +++ b/clang/include/clang/Sema/CodeCompleteConsumer.h @@ -1028,6 +1028,9 @@ class CodeCompleteConsumer { /// The candidate is a function declaration. CK_Function, + // The candidate is a lambda operator(). + CK_Lambda, + /// The candidate is a function template, arguments are being completed. CK_FunctionTemplate, @@ -1055,6 +1058,13 @@ class CodeCompleteConsumer { /// Kind == CK_Function. FunctionDecl *Function; + /// The lambda operator() candidate paired with the + /// lambda variable, available when Kind == CK_Lambda. + struct { +FunctionDecl *OperatorParens; +VarDecl *Var; + } Lambda; + /// The function template overload candidate, available when /// Kind == CK_FunctionTemplate. FunctionTemplateDecl *FunctionTemplate; @@ -1082,6 +1092,12 @@ class CodeCompleteConsumer { assert(Function != nullptr); } +OverloadCandidate(FunctionDecl *LambdaOperatorParens, VarDecl *LambdaVar) +: Kind(CK_Lambda), Lambda{LambdaOperatorParens, LambdaVar} { + assert(Lambda.OperatorParens != nullptr); + assert(Lambda.Var != nullptr); +} + OverloadCandidate(FunctionTemplateDecl *FunctionTemplateDecl) : Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplateDecl) { assert(FunctionTemplateDecl != nullptr); @@ -1112,6 +1128,8 @@ class CodeCompleteConsumer { /// function declaration for a function template. FunctionDecl *getFunction() const; +VarDecl *getLambdaVarDecl() const; + /// Retrieve the function template overload candidate. FunctionTemplateDecl *getFunctionTemplate() const { assert(getKind() == CK_FunctionTemplate && "Not a function template"); diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index d6a6cee62a7528..7c4e82f07de02e 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -876,6 +876,11 @@ class Sema; /// function pointer or reference (C++ [over.call.object]). FunctionDecl *Function; +/// LambdaName - When the OverloadCandidate is for a +/// lambda's operator(), points to the declaration of +/// the lambda variable. +VarDecl *LambdaName{nullptr}; + /// FoundDecl - The original declaration that was looked up / /// invented / otherwise found, together with its access. /// Might be a UsingShadowDecl or a FunctionTemplateDec