https://github.com/timon-ul updated https://github.com/llvm/llvm-project/pull/206716
>From 3b0399fec94e04741c7057e3d5b50878aa8e8a7e Mon Sep 17 00:00:00 2001 From: Timon Ulrich <[email protected]> Date: Tue, 30 Jun 2026 01:35:56 +0200 Subject: [PATCH 01/10] Initial draft: signature parameter names --- .../clangd/CodeCompletionStrings.cpp | 11 ++++++++ .../clangd/CodeCompletionStrings.h | 3 +++ .../clangd/index/SymbolCollector.cpp | 22 ++++++++++++++++ .../clangd/index/SymbolCollector.h | 2 ++ .../clangd/unittests/CodeCompleteTests.cpp | 18 +++++++++++++ .../clangd/unittests/IndexActionTests.cpp | 25 +++++++++++++++++++ 6 files changed, 81 insertions(+) diff --git a/clang-tools-extra/clangd/CodeCompletionStrings.cpp b/clang-tools-extra/clangd/CodeCompletionStrings.cpp index 9c4241b54057a..bec816ce8d379 100644 --- a/clang-tools-extra/clangd/CodeCompletionStrings.cpp +++ b/clang-tools-extra/clangd/CodeCompletionStrings.cpp @@ -160,6 +160,17 @@ std::string getDeclComment(const ASTContext &Ctx, const NamedDecl &Decl) { return Doc; } +bool isLikelyMissingParameterName(llvm::StringRef Signature) { + size_t LPara = Signature.find('('); + size_t Space = Signature.find(' ', LPara); + size_t RightEnd = Signature.find(',', LPara); + if (Signature.npos == RightEnd) + RightEnd = Signature.find(')', Space); + if (LPara < Space && Space < RightEnd) + return false; + return true; +} + void getSignature(const CodeCompletionString &CCS, std::string *Signature, std::string *Snippet, CodeCompletionResult::ResultKind ResultKind, diff --git a/clang-tools-extra/clangd/CodeCompletionStrings.h b/clang-tools-extra/clangd/CodeCompletionStrings.h index fa81ad64d406c..24b215e5b6c65 100644 --- a/clang-tools-extra/clangd/CodeCompletionStrings.h +++ b/clang-tools-extra/clangd/CodeCompletionStrings.h @@ -35,6 +35,9 @@ std::string getDocComment(const ASTContext &Ctx, /// Similar to getDocComment, but returns the comment for a NamedDecl. std::string getDeclComment(const ASTContext &Ctx, const NamedDecl &D); +/// Heuristic to see if the signature only has types and no parameter names. +bool isLikelyMissingParameterName(llvm::StringRef Signature); + /// Formats the signature for an item, as a display string and snippet. /// e.g. for const_reference std::vector<T>::at(size_type) const, this returns: /// *Signature = "(size_type) const" diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp index b9602b36e2bba..661f93429c7e3 100644 --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -725,6 +725,11 @@ bool SymbolCollector::handleDeclOccurrence( BasicSymbol = addDeclaration(*ND, std::move(ID), IsMainFileOnly); SkipDocCheckInDef = true; } + if (ND != OriginalDecl && + BasicSymbol->Flags & Symbol::IndexedForCodeCompletion && + isLikelyMissingParameterName(BasicSymbol->Signature)) { + getNewSignature(*BasicSymbol, *OriginalDecl); + } if (Roles & static_cast<unsigned>(index::SymbolRole::Definition)) addDefinition(*OriginalDecl, *BasicSymbol, SkipDocCheckInDef); @@ -1065,6 +1070,23 @@ void SymbolCollector::finish() { FilesWithObjCConstructs.clear(); } +void SymbolCollector::getNewSignature(const Symbol &OldSymbol, + const NamedDecl &ND) { + CodeCompletionResult SymbolCompletion(&getTemplateOrThis(ND), 0); + const auto *CCS = SymbolCompletion.CreateCodeCompletionString( + *ASTCtx, *PP, CodeCompletionContext::CCC_Symbol, *CompletionAllocator, + *CompletionTUInfo, + /*IncludeBriefComments*/ false); + std::string Signature; + std::string SnippetSuffix; + getSignature(*CCS, &Signature, &SnippetSuffix, SymbolCompletion.Kind, + SymbolCompletion.CursorKind); + Symbol UpdatedSymbol = OldSymbol; + UpdatedSymbol.Signature = Signature; + UpdatedSymbol.CompletionSnippetSuffix = SnippetSuffix; + Symbols.insert(UpdatedSymbol); +} + const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND, SymbolID ID, bool IsMainFileOnly) { auto &Ctx = ND.getASTContext(); diff --git a/clang-tools-extra/clangd/index/SymbolCollector.h b/clang-tools-extra/clangd/index/SymbolCollector.h index 4d51d747639b1..f9b8e9a7337e3 100644 --- a/clang-tools-extra/clangd/index/SymbolCollector.h +++ b/clang-tools-extra/clangd/index/SymbolCollector.h @@ -165,6 +165,8 @@ class SymbolCollector : public index::IndexDataConsumer { SmallVector<const CXXConstructorDecl *, 1> findIndirectConstructors(const Decl *D); + void getNewSignature(const Symbol &OldSymbol, const NamedDecl &ND); + const Symbol *addDeclaration(const NamedDecl &, SymbolID, bool IsMainFileSymbol); void addDefinition(const NamedDecl &, const Symbol &DeclSymbol, diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 5808b2145965f..037983a80300d 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -698,6 +698,24 @@ TEST(CompletionTest, PrivateMemberDefinition) { snippetSuffix("(int a, int b)")))); } +TEST(CompletionTest, DeclParamName) { + // This is 1/2 regression tests to make sure signatures + // 1) have consistent variable names between header and source file + // 2) find variable names in other declarations + clangd::CodeCompleteOptions Opts; + Opts.EnableSnippets = true; + auto FuncFromSource = completions(R"cpp( + void sun(int); + void sun(int day); + void sun(int); + void position() { + sun^; + } + )cpp", + {}, Opts); + EXPECT_THAT(FuncFromSource.Completions, Contains(signature("(int day)"))); +} + TEST(CompletionTest, DefaultArgsWithValues) { clangd::CodeCompleteOptions Opts; Opts.EnableSnippets = true; diff --git a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp index 025027fdcee5d..5b8029654a73d 100644 --- a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp +++ b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp @@ -11,6 +11,7 @@ #include "URI.h" #include "index/IndexAction.h" #include "index/Serialization.h" +#include "index/Symbol.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Tooling/Tooling.h" @@ -38,6 +39,8 @@ MATCHER_P(hasDigest, Digest, "") { return arg.Digest == Digest; } MATCHER_P(hasName, Name, "") { return arg.Name == Name; } +MATCHER_P(hasSignature, Signature, "") { return arg.Signature == Signature; } + MATCHER(hasSameURI, "") { llvm::StringRef URI = ::testing::get<0>(arg); const std::string &Path = ::testing::get<1>(arg); @@ -258,6 +261,28 @@ TEST_F(IndexActionTest, NoWarnings) { EXPECT_THAT(*IndexFile.Symbols, ElementsAre(hasName("foo"), hasName("bar"))); } +TEST_F(IndexActionTest, DeclParamName) { + // This is 2/2 regression tests to make sure signatures + // 1) have consistent variable names between header and source file + // 2) find variable names in other declarations + std::string MainFilePath = testPath("main.cpp"); + std::string MainCode = R"cpp( #include "zenith.hpp" )cpp"; + std::string HeaderPath = testPath("zenith.hpp"); + std::string HeaderCode = R"cpp( + void moon(int, int); + void moon(int month, int day); + void moon(int, int); + )cpp"; + + addFile(MainFilePath, MainCode); + addFile(HeaderPath, HeaderCode); + + IndexFileIn IndexFile = runIndexingAction(MainFilePath); + + EXPECT_THAT(*IndexFile.Symbols, + ElementsAre(hasSignature("(int month, int day)"))); +} + TEST_F(IndexActionTest, SkipFiles) { std::string MainFilePath = testPath("main.cpp"); addFile(MainFilePath, R"cpp( >From 3dcf8773d0b663388692f4f7a5db0258c1cedfd5 Mon Sep 17 00:00:00 2001 From: Timon Ulrich <[email protected]> Date: Tue, 30 Jun 2026 14:03:01 +0200 Subject: [PATCH 02/10] Better approach for finding the right signature --- .../clangd/CodeCompletionStrings.cpp | 11 ---------- .../clangd/CodeCompletionStrings.h | 3 --- .../clangd/index/SymbolCollector.cpp | 22 ------------------- .../clangd/index/SymbolCollector.h | 2 -- clang/lib/Sema/SemaCodeComplete.cpp | 7 ++++++ 5 files changed, 7 insertions(+), 38 deletions(-) diff --git a/clang-tools-extra/clangd/CodeCompletionStrings.cpp b/clang-tools-extra/clangd/CodeCompletionStrings.cpp index bec816ce8d379..9c4241b54057a 100644 --- a/clang-tools-extra/clangd/CodeCompletionStrings.cpp +++ b/clang-tools-extra/clangd/CodeCompletionStrings.cpp @@ -160,17 +160,6 @@ std::string getDeclComment(const ASTContext &Ctx, const NamedDecl &Decl) { return Doc; } -bool isLikelyMissingParameterName(llvm::StringRef Signature) { - size_t LPara = Signature.find('('); - size_t Space = Signature.find(' ', LPara); - size_t RightEnd = Signature.find(',', LPara); - if (Signature.npos == RightEnd) - RightEnd = Signature.find(')', Space); - if (LPara < Space && Space < RightEnd) - return false; - return true; -} - void getSignature(const CodeCompletionString &CCS, std::string *Signature, std::string *Snippet, CodeCompletionResult::ResultKind ResultKind, diff --git a/clang-tools-extra/clangd/CodeCompletionStrings.h b/clang-tools-extra/clangd/CodeCompletionStrings.h index 24b215e5b6c65..fa81ad64d406c 100644 --- a/clang-tools-extra/clangd/CodeCompletionStrings.h +++ b/clang-tools-extra/clangd/CodeCompletionStrings.h @@ -35,9 +35,6 @@ std::string getDocComment(const ASTContext &Ctx, /// Similar to getDocComment, but returns the comment for a NamedDecl. std::string getDeclComment(const ASTContext &Ctx, const NamedDecl &D); -/// Heuristic to see if the signature only has types and no parameter names. -bool isLikelyMissingParameterName(llvm::StringRef Signature); - /// Formats the signature for an item, as a display string and snippet. /// e.g. for const_reference std::vector<T>::at(size_type) const, this returns: /// *Signature = "(size_type) const" diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp index 661f93429c7e3..b9602b36e2bba 100644 --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -725,11 +725,6 @@ bool SymbolCollector::handleDeclOccurrence( BasicSymbol = addDeclaration(*ND, std::move(ID), IsMainFileOnly); SkipDocCheckInDef = true; } - if (ND != OriginalDecl && - BasicSymbol->Flags & Symbol::IndexedForCodeCompletion && - isLikelyMissingParameterName(BasicSymbol->Signature)) { - getNewSignature(*BasicSymbol, *OriginalDecl); - } if (Roles & static_cast<unsigned>(index::SymbolRole::Definition)) addDefinition(*OriginalDecl, *BasicSymbol, SkipDocCheckInDef); @@ -1070,23 +1065,6 @@ void SymbolCollector::finish() { FilesWithObjCConstructs.clear(); } -void SymbolCollector::getNewSignature(const Symbol &OldSymbol, - const NamedDecl &ND) { - CodeCompletionResult SymbolCompletion(&getTemplateOrThis(ND), 0); - const auto *CCS = SymbolCompletion.CreateCodeCompletionString( - *ASTCtx, *PP, CodeCompletionContext::CCC_Symbol, *CompletionAllocator, - *CompletionTUInfo, - /*IncludeBriefComments*/ false); - std::string Signature; - std::string SnippetSuffix; - getSignature(*CCS, &Signature, &SnippetSuffix, SymbolCompletion.Kind, - SymbolCompletion.CursorKind); - Symbol UpdatedSymbol = OldSymbol; - UpdatedSymbol.Signature = Signature; - UpdatedSymbol.CompletionSnippetSuffix = SnippetSuffix; - Symbols.insert(UpdatedSymbol); -} - const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND, SymbolID ID, bool IsMainFileOnly) { auto &Ctx = ND.getASTContext(); diff --git a/clang-tools-extra/clangd/index/SymbolCollector.h b/clang-tools-extra/clangd/index/SymbolCollector.h index f9b8e9a7337e3..4d51d747639b1 100644 --- a/clang-tools-extra/clangd/index/SymbolCollector.h +++ b/clang-tools-extra/clangd/index/SymbolCollector.h @@ -165,8 +165,6 @@ class SymbolCollector : public index::IndexDataConsumer { SmallVector<const CXXConstructorDecl *, 1> findIndirectConstructors(const Decl *D); - void getNewSignature(const Symbol &OldSymbol, const NamedDecl &ND); - const Symbol *addDeclaration(const NamedDecl &, SymbolID, bool IsMainFileSymbol); void addDefinition(const NamedDecl &, const Symbol &DeclSymbol, diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index bef5eea9ed442..f724fb44f184e 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -3320,6 +3320,13 @@ static void AddFunctionParameterChunks( for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) { const ParmVarDecl *Param = Function->getParamDecl(P); + // Select a parameter with identifier if possible for better signature + if (!Param->getIdentifier()) { + for (auto *Redecl : Function->redecls()) { + if (auto *RParam = Redecl->getParamDecl(P); RParam->getIdentifier()) + Param = RParam; + } + } if (Param->hasDefaultArg() && !InOptional && !IsInDeclarationContext && !AsInformativeChunk) { >From 52df79312bcaee81e898df5e3a14da2ee47772ff Mon Sep 17 00:00:00 2001 From: Timon Ulrich <[email protected]> Date: Tue, 30 Jun 2026 14:28:08 +0200 Subject: [PATCH 03/10] actual consistent results between AST and Index --- .../clangd/unittests/CodeCompleteTests.cpp | 2 +- .../clangd/unittests/IndexActionTests.cpp | 2 +- clang/lib/Sema/SemaCodeComplete.cpp | 10 ++++------ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 037983a80300d..f2eae8a883cd1 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -707,7 +707,7 @@ TEST(CompletionTest, DeclParamName) { auto FuncFromSource = completions(R"cpp( void sun(int); void sun(int day); - void sun(int); + void sun(int night); void position() { sun^; } diff --git a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp index 5b8029654a73d..ef760abe94ea0 100644 --- a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp +++ b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp @@ -271,7 +271,7 @@ TEST_F(IndexActionTest, DeclParamName) { std::string HeaderCode = R"cpp( void moon(int, int); void moon(int month, int day); - void moon(int, int); + void moon(int month, int night); )cpp"; addFile(MainFilePath, MainCode); diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index f724fb44f184e..1b833d37237fa 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -3320,12 +3320,10 @@ static void AddFunctionParameterChunks( for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) { const ParmVarDecl *Param = Function->getParamDecl(P); - // Select a parameter with identifier if possible for better signature - if (!Param->getIdentifier()) { - for (auto *Redecl : Function->redecls()) { - if (auto *RParam = Redecl->getParamDecl(P); RParam->getIdentifier()) - Param = RParam; - } + // Select the first parameter name for consistent results with Index. + for (auto *Redecl : Function->redecls()) { + if (auto *RParam = Redecl->getParamDecl(P); RParam->getIdentifier()) + Param = RParam; } if (Param->hasDefaultArg() && !InOptional && !IsInDeclarationContext && >From fb1b5532a564f70f55250983d5c4a9f4242fef17 Mon Sep 17 00:00:00 2001 From: Timon Ulrich <[email protected]> Date: Wed, 1 Jul 2026 09:58:30 +0200 Subject: [PATCH 04/10] Select first function with any param name --- .../clangd/unittests/CodeCompleteTests.cpp | 2 +- .../clangd/unittests/IndexActionTests.cpp | 2 +- clang/lib/Sema/SemaCodeComplete.cpp | 20 +++++++++++++------ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index f2eae8a883cd1..16545dcebd023 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -706,8 +706,8 @@ TEST(CompletionTest, DeclParamName) { Opts.EnableSnippets = true; auto FuncFromSource = completions(R"cpp( void sun(int); - void sun(int day); void sun(int night); + void sun(int day); void position() { sun^; } diff --git a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp index ef760abe94ea0..f3ff10dcca9a5 100644 --- a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp +++ b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp @@ -270,8 +270,8 @@ TEST_F(IndexActionTest, DeclParamName) { std::string HeaderPath = testPath("zenith.hpp"); std::string HeaderCode = R"cpp( void moon(int, int); - void moon(int month, int day); void moon(int month, int night); + void moon(int month, int day); )cpp"; addFile(MainFilePath, MainCode); diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 1b833d37237fa..f0a431e17d4f1 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -415,6 +415,16 @@ class ResultBuilder { bool IsImpossibleToSatisfy(const NamedDecl *ND) const; //@} }; + +const FunctionDecl *BetterSingature(const FunctionDecl *Function, + unsigned Start) { + // Note that `redecls()` traverses from last to first declaration. + for (auto *Redecl : Function->redecls()) + for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) + if (Redecl->getParamDecl(P)->getIdentifier()) + return Redecl; + return Function; +} } // namespace void PreferredTypeBuilder::enterReturn(Sema &S, SourceLocation Tok) { @@ -3318,13 +3328,11 @@ static void AddFunctionParameterChunks( bool FirstParameter = true; bool AsInformativeChunk = !(FunctionCanBeCall || IsInDeclarationContext); + // Create consistent result between AST and Index. + const FunctionDecl *BetterSignatureDecl = BetterSingature(Function, Start); + for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) { - const ParmVarDecl *Param = Function->getParamDecl(P); - // Select the first parameter name for consistent results with Index. - for (auto *Redecl : Function->redecls()) { - if (auto *RParam = Redecl->getParamDecl(P); RParam->getIdentifier()) - Param = RParam; - } + const ParmVarDecl *Param = BetterSignatureDecl->getParamDecl(P); if (Param->hasDefaultArg() && !InOptional && !IsInDeclarationContext && !AsInformativeChunk) { >From 1b451572eb79da4a57a2d050869687d2e6473c37 Mon Sep 17 00:00:00 2001 From: Timon Ulrich <[email protected]> Date: Wed, 1 Jul 2026 10:14:43 +0200 Subject: [PATCH 05/10] Better test for current behaviour --- clang-tools-extra/clangd/unittests/IndexActionTests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp index f3ff10dcca9a5..c1f580fb892ed 100644 --- a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp +++ b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp @@ -271,7 +271,7 @@ TEST_F(IndexActionTest, DeclParamName) { std::string HeaderCode = R"cpp( void moon(int, int); void moon(int month, int night); - void moon(int month, int day); + void moon(int, int day); )cpp"; addFile(MainFilePath, MainCode); @@ -280,7 +280,7 @@ TEST_F(IndexActionTest, DeclParamName) { IndexFileIn IndexFile = runIndexingAction(MainFilePath); EXPECT_THAT(*IndexFile.Symbols, - ElementsAre(hasSignature("(int month, int day)"))); + ElementsAre(hasSignature("(int, int day)"))); } TEST_F(IndexActionTest, SkipFiles) { >From dbd89e8f2a555957f3e23cfee4d327447c11666c Mon Sep 17 00:00:00 2001 From: Timon Ulrich <[email protected]> Date: Wed, 1 Jul 2026 10:32:34 +0200 Subject: [PATCH 06/10] formatting --- clang-tools-extra/clangd/unittests/IndexActionTests.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp index c1f580fb892ed..43ef5430ae12c 100644 --- a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp +++ b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp @@ -279,8 +279,7 @@ TEST_F(IndexActionTest, DeclParamName) { IndexFileIn IndexFile = runIndexingAction(MainFilePath); - EXPECT_THAT(*IndexFile.Symbols, - ElementsAre(hasSignature("(int, int day)"))); + EXPECT_THAT(*IndexFile.Symbols, ElementsAre(hasSignature("(int, int day)"))); } TEST_F(IndexActionTest, SkipFiles) { >From 52b56bc32ed3fbd59c09f012071934f2d052f049 Mon Sep 17 00:00:00 2001 From: Timon Ulrich <[email protected]> Date: Mon, 6 Jul 2026 15:17:32 +0200 Subject: [PATCH 07/10] start iterating from first decl for consistency --- .../clangd/unittests/CodeCompleteTests.cpp | 4 +++- .../clangd/unittests/IndexActionTests.cpp | 4 +++- clang/lib/Sema/SemaCodeComplete.cpp | 12 ++++++------ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 16545dcebd023..f5c1c84dbb5e9 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -702,12 +702,14 @@ TEST(CompletionTest, DeclParamName) { // This is 1/2 regression tests to make sure signatures // 1) have consistent variable names between header and source file // 2) find variable names in other declarations + // See IndexActionTest.DeclParamName for the other test. clangd::CodeCompleteOptions Opts; Opts.EnableSnippets = true; auto FuncFromSource = completions(R"cpp( void sun(int); - void sun(int night); void sun(int day); + void sun(int night); + void sun(int); void position() { sun^; } diff --git a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp index 43ef5430ae12c..3941f3f0dc96c 100644 --- a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp +++ b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp @@ -265,13 +265,15 @@ TEST_F(IndexActionTest, DeclParamName) { // This is 2/2 regression tests to make sure signatures // 1) have consistent variable names between header and source file // 2) find variable names in other declarations + // See CompletionTest.DeclParamName for the other test. std::string MainFilePath = testPath("main.cpp"); std::string MainCode = R"cpp( #include "zenith.hpp" )cpp"; std::string HeaderPath = testPath("zenith.hpp"); std::string HeaderCode = R"cpp( void moon(int, int); - void moon(int month, int night); void moon(int, int day); + void moon(int month, int day); + void moon(int, int); )cpp"; addFile(MainFilePath, MainCode); diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index f0a431e17d4f1..c45746151677e 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -416,11 +416,12 @@ class ResultBuilder { //@} }; -const FunctionDecl *BetterSingature(const FunctionDecl *Function, +const FunctionDecl *BetterSignature(const FunctionDecl *Function, unsigned Start) { - // Note that `redecls()` traverses from last to first declaration. - for (auto *Redecl : Function->redecls()) - for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) + // Note that `redecls()` traverses in a circular order from the current decl, + // so for consistency we have to first get the first declaration. + for (auto *Redecl : Function->getFirstDecl()->redecls()) + for (unsigned P = Start, N = Redecl->getNumParams(); P != N; ++P) if (Redecl->getParamDecl(P)->getIdentifier()) return Redecl; return Function; @@ -3328,8 +3329,7 @@ static void AddFunctionParameterChunks( bool FirstParameter = true; bool AsInformativeChunk = !(FunctionCanBeCall || IsInDeclarationContext); - // Create consistent result between AST and Index. - const FunctionDecl *BetterSignatureDecl = BetterSingature(Function, Start); + const FunctionDecl *BetterSignatureDecl = BetterSignature(Function, Start); for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) { const ParmVarDecl *Param = BetterSignatureDecl->getParamDecl(P); >From 529ed052643095ea8bfd3a87ac9e2abd477ee004 Mon Sep 17 00:00:00 2001 From: Timon Ulrich <[email protected]> Date: Mon, 6 Jul 2026 15:57:41 +0200 Subject: [PATCH 08/10] wrong order in tests --- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp | 2 +- clang-tools-extra/clangd/unittests/IndexActionTests.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index f5c1c84dbb5e9..860c6d15075b9 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -707,8 +707,8 @@ TEST(CompletionTest, DeclParamName) { Opts.EnableSnippets = true; auto FuncFromSource = completions(R"cpp( void sun(int); - void sun(int day); void sun(int night); + void sun(int day); void sun(int); void position() { sun^; diff --git a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp index 3941f3f0dc96c..64166c50fb069 100644 --- a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp +++ b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp @@ -271,8 +271,8 @@ TEST_F(IndexActionTest, DeclParamName) { std::string HeaderPath = testPath("zenith.hpp"); std::string HeaderCode = R"cpp( void moon(int, int); - void moon(int, int day); void moon(int month, int day); + void moon(int, int day); void moon(int, int); )cpp"; >From 74bc7a2e182f2360112a7be0bfef18010b30d311 Mon Sep 17 00:00:00 2001 From: Timon Ulrich <[email protected]> Date: Wed, 8 Jul 2026 10:49:12 +0200 Subject: [PATCH 09/10] syncinc code completion and signature help --- clang/lib/Sema/SemaCodeComplete.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index c45746151677e..1e8921a332abc 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -418,12 +418,19 @@ class ResultBuilder { const FunctionDecl *BetterSignature(const FunctionDecl *Function, unsigned Start) { + auto ParaCount = Function->getNumParams(); // Note that `redecls()` traverses in a circular order from the current decl, // so for consistency we have to first get the first declaration. - for (auto *Redecl : Function->getFirstDecl()->redecls()) + for (auto *Redecl : Function->getFirstDecl()->redecls()) { + // The callers will expect to be able to use the same index from the initial + // function on the redeclaration. While we do not expect this to happen, + // this is a failsafe. + if (Redecl->getNumParams() > ParaCount) + continue; for (unsigned P = Start, N = Redecl->getNumParams(); P != N; ++P) if (Redecl->getParamDecl(P)->getIdentifier()) return Redecl; + } return Function; } } // namespace @@ -4189,6 +4196,8 @@ static void AddOverloadParameterChunks( bool FirstParameter = true; unsigned NumParams = Function ? Function->getNumParams() : Prototype->getNumParams(); + const FunctionDecl *BetterSignatureDecl = + Function ? BetterSignature(Function, Start) : nullptr; for (unsigned P = Start; P != NumParams; ++P) { if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) { @@ -4225,8 +4234,8 @@ static void AddOverloadParameterChunks( std::string Placeholder; assert(P < Prototype->getNumParams()); if (Function || PrototypeLoc) { - const ParmVarDecl *Param = - Function ? Function->getParamDecl(P) : PrototypeLoc.getParam(P); + const ParmVarDecl *Param = Function ? BetterSignatureDecl->getParamDecl(P) + : PrototypeLoc.getParam(P); Placeholder = FormatFunctionParameter(Policy, Param); if (Param->hasDefaultArg()) Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), >From a68cc7a8270087bcb3cae56430ab2a56934f12b1 Mon Sep 17 00:00:00 2001 From: Timon Ulrich <[email protected]> Date: Thu, 9 Jul 2026 13:58:40 +0200 Subject: [PATCH 10/10] Added test for signature help --- .../clangd/unittests/CodeCompleteTests.cpp | 24 +++++++++++++++++-- .../clangd/unittests/IndexActionTests.cpp | 5 ++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 860c6d15075b9..b39663f8427e3 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -699,10 +699,11 @@ TEST(CompletionTest, PrivateMemberDefinition) { } TEST(CompletionTest, DeclParamName) { - // This is 1/2 regression tests to make sure signatures + // This is 1/3 regression tests to make sure signatures // 1) have consistent variable names between header and source file // 2) find variable names in other declarations - // See IndexActionTest.DeclParamName for the other test. + // See SignatureHelpTest.DeclParamName and IndexActionTest.DeclParamName for + // the other tests. clangd::CodeCompleteOptions Opts; Opts.EnableSnippets = true; auto FuncFromSource = completions(R"cpp( @@ -1696,6 +1697,25 @@ TEST(SignatureHelpTest, Overloads) { EXPECT_EQ(0, Results.activeParameter); } +TEST(SignatureHelpTest, DeclParamName) { + // This is 2/3 regression tests to make sure signatures + // 1) have consistent variable names between header and source file + // 2) find variable names in other declarations + // See CompletionTest.DeclParamName and IndexActionTest.DeclParamName for the + // other tests. + auto FuncFromSource = signatures(R"cpp( + void sun(int); + void sun(int night); + void sun(int day); + void sun(int); + void position() { + sun(^); + } + )cpp"); + EXPECT_THAT(FuncFromSource.signatures, + UnorderedElementsAre(sig("sun([[int day]]) -> void"))); +} + TEST(SignatureHelpTest, FunctionPointers) { llvm::StringLiteral Tests[] = { // Variable of function pointer type diff --git a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp index 64166c50fb069..3cc41be50b53e 100644 --- a/clang-tools-extra/clangd/unittests/IndexActionTests.cpp +++ b/clang-tools-extra/clangd/unittests/IndexActionTests.cpp @@ -262,10 +262,11 @@ TEST_F(IndexActionTest, NoWarnings) { } TEST_F(IndexActionTest, DeclParamName) { - // This is 2/2 regression tests to make sure signatures + // This is 3/3 regression tests to make sure signatures // 1) have consistent variable names between header and source file // 2) find variable names in other declarations - // See CompletionTest.DeclParamName for the other test. + // See CompletionTest.DeclParamName and SignatureHelpTest.DeclParamName for + // the other tests. std::string MainFilePath = testPath("main.cpp"); std::string MainCode = R"cpp( #include "zenith.hpp" )cpp"; std::string HeaderPath = testPath("zenith.hpp"); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
