https://github.com/Ippo47 created https://github.com/llvm/llvm-project/pull/197139
Parameter hints were not appearing for static operator because the object was always passed as the first argument, making static candidates invalid. Fix by checking each operator candidate individually if it is static, add it without the object argument. >From 9aafa6afd6bf940090eceec5e77b637e86c806f8 Mon Sep 17 00:00:00 2001 From: paarth <[email protected]> Date: Fri, 8 May 2026 15:22:52 +0530 Subject: [PATCH] Fixed signature help for static call operator Fix signature help for static call operator fixed code --- .../clangd/unittests/CodeCompleteTests.cpp | 87 +++++++++++++++++++ clang/lib/Sema/SemaCodeComplete.cpp | 37 ++++++-- 2 files changed, 118 insertions(+), 6 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 386ffb54924a7..7cec75be8faa6 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -3455,6 +3455,93 @@ TEST(SignatureHelpTest, SkipExplicitObjectParameter) { } } +TEST(SignatureHelpTest, StaticCallOperator) { + Annotations Code(R"cpp( + struct Abc { + void operator()(bool a) {} + }; + struct AbcStatic { + static void operator()(bool a) {} + }; + void test() { + Abc abc; + AbcStatic abcStatic; + abc($c1^); + abcStatic($c2^); + } + )cpp"); + auto TU = TestTU::withCode(Code.code()); + TU.ExtraArgs = {"-std=c++23"}; + MockFS FS; + auto Inputs = TU.inputs(FS); + auto Preamble = TU.preamble(); + ASSERT_TRUE(Preamble); + { + // Case 1: non-static + const auto Result = signatureHelp(testPath(TU.Filename), Code.point("c1"), + *Preamble, Inputs, MarkupKind::PlainText); + EXPECT_EQ(1U, Result.signatures.size()); + EXPECT_THAT(Result.signatures[0], AllOf(sig("operator()([[bool a]]) -> void"))); + } + { + // Case 2: static + const auto Result = signatureHelp(testPath(TU.Filename), Code.point("c2"), + *Preamble, Inputs, MarkupKind::PlainText); + EXPECT_EQ(1U, Result.signatures.size()); + EXPECT_THAT(Result.signatures[0], AllOf(sig("operator()([[bool a]]) -> void"))); + } +{ + // Case 3: static template operator() + Annotations TemplateCode(R"cpp( + struct AbcTemplate { + template <typename T> + static void operator()(T a, bool b) {} + }; + void test() { + AbcTemplate abcTemplate; + abcTemplate($c3^); + } + )cpp"); + auto TU2 = TestTU::withCode(TemplateCode.code()); + TU2.ExtraArgs = {"-std=c++23"}; + MockFS FS2; + auto Inputs2 = TU2.inputs(FS2); + auto Preamble2 = TU2.preamble(); + ASSERT_TRUE(Preamble2); + const auto Result = signatureHelp(testPath(TU2.Filename), + TemplateCode.point("c3"), + *Preamble2, Inputs2, + MarkupKind::PlainText); + EXPECT_EQ(1U, Result.signatures.size()); + } + +{ + Annotations TemplateCode2(R"cpp( + struct AbcTemplate2 { + template <typename T> + static void operator()(bool a, bool b) { T c; } + }; + void test() { + AbcTemplate2 abcTemplate2; + abcTemplate2($c4^); + } + )cpp"); + auto TU3 = TestTU::withCode(TemplateCode2.code()); + TU3.ExtraArgs = {"-std=c++23"}; + MockFS FS3; + auto Inputs3 = TU3.inputs(FS3); + auto Preamble3 = TU3.preamble(); + ASSERT_TRUE(Preamble3); + const auto Result = signatureHelp(testPath(TU3.Filename), + TemplateCode2.point("c4"), + *Preamble3, Inputs3, + MarkupKind::PlainText); + EXPECT_EQ(1U, Result.signatures.size()); + EXPECT_THAT(Result.signatures[0], + AllOf(sig("operator()([[bool a]], [[bool b]]) -> void"))); + } +} + TEST(CompletionTest, IncludedCompletionKinds) { Annotations Test(R"cpp(#include "^)cpp"); auto TU = TestTU::withCode(Test.code()); diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 74264ec3906ff..be3ce2baa6afe 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -6472,14 +6472,39 @@ SemaCodeCompletion::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args, LookupResult R(SemaRef, OpName, Loc, Sema::LookupOrdinaryName); SemaRef.LookupQualifiedName(R, DC); R.suppressDiagnostics(); + for (NamedDecl *D : R) { + NamedDecl *UD = D->getUnderlyingDecl(); + if (auto *FD = dyn_cast<FunctionDecl>(UD)) { + if (FD->isStatic()) { + SemaRef.AddOverloadCandidate( + FD, DeclAccessPair::make(FD, FD->getAccess()), + ArgsWithoutDependentTypes, CandidateSet, + /*SuppressUserConversions=*/false, + /*PartialOverloading=*/true); + continue; + } + }else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(UD)) { + if (FTD->getTemplatedDecl()->isStatic()) { + SemaRef.AddTemplateOverloadCandidate( + FTD, DeclAccessPair::make(FTD, FTD->getAccess()), + /*ExplicitTemplateArgs=*/nullptr, + ArgsWithoutDependentTypes, CandidateSet, + /*SuppressUserConversions=*/false, + /*PartialOverloading=*/true); + continue; + } + } SmallVector<Expr *, 12> ArgExprs(1, NakedFn); ArgExprs.append(ArgsWithoutDependentTypes.begin(), ArgsWithoutDependentTypes.end()); - SemaRef.AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, - CandidateSet, - /*ExplicitArgs=*/nullptr, - /*SuppressUserConversions=*/false, - /*PartialOverloading=*/true); + UnresolvedSet<1>Candidate; + Candidate.addDecl(D, D->getAccess()); + SemaRef.AddFunctionCandidates(Candidate, ArgExprs, + CandidateSet, + /*ExplicitArgs=*/nullptr, + /*SuppressUserConversions=*/false, + /*PartialOverloading=*/true); + } } } else { // Lastly we check whether expression's type is function pointer or @@ -6489,7 +6514,7 @@ SemaCodeCompletion::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args, QualType T = NakedFn->getType(); if (!T->getPointeeType().isNull()) T = T->getPointeeType(); - + if (auto FP = T->getAs<FunctionProtoType>()) { if (!SemaRef.TooManyArguments(FP->getNumParams(), ArgsWithoutDependentTypes.size(), _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
