Index: clang-tools-extra/trunk/clangd/CodeComplete.cpp =================================================================== --- clang-tools-extra/trunk/clangd/CodeComplete.cpp +++ clang-tools-extra/trunk/clangd/CodeComplete.cpp @@ -714,7 +714,15 @@ "too many arguments"); SigHelp.activeParameter = static_cast(CurrentArg); for (unsigned I = 0; I < NumCandidates; ++I) { - const auto &Candidate = Candidates[I]; + OverloadCandidate Candidate = Candidates[I]; + // We want to avoid showing instantiated signatures, because they may be + // long in some cases (e.g. when 'T' is substituted with 'std::string', we + // would get 'std::basic_string'). + if (auto *Func = Candidate.getFunction()) { + if (auto *Pattern = Func->getTemplateInstantiationPattern()) + Candidate = OverloadCandidate(Pattern); + } + const auto *CCS = Candidate.CreateSignatureString( CurrentArg, S, *Allocator, CCTUInfo, true); assert(CCS && "Expected the CodeCompletionString to be non-null"); Index: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp =================================================================== --- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp +++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp @@ -1537,6 +1537,59 @@ EXPECT_EQ(0, Results.activeParameter); } +TEST(SignatureHelpTest, InstantiatedSignatures) { + EXPECT_THAT(signatures(R"cpp( + template + void foo(T, T, T); + + int main() { + foo(^); + } + )cpp") + .signatures, + ElementsAre(Sig("foo(T, T, T) -> void", {"T", "T", "T"}))); + + EXPECT_THAT(signatures(R"cpp( + template + void foo(T, T, T); + + int main() { + foo(10, ^); + })cpp") + .signatures, + ElementsAre(Sig("foo(T, T, T) -> void", {"T", "T", "T"}))); + + EXPECT_THAT(signatures(R"cpp( + template + void foo(T...); + + int main() { + foo(^); + } + )cpp") + .signatures, + ElementsAre(Sig("foo(T...) -> void", {"T..."}))); + + // It is debatable whether we should substitute the outer template parameter + // ('T') in that case. Currently we don't substitute it in signature help, but + // do substitute in code complete. + // FIXME: make code complete and signature help consistent, figure out which + // way is better. + EXPECT_THAT(signatures(R"cpp( + template + struct X { + template + void foo(T, U); + }; + + int main() { + X().foo(^) + } + )cpp") + .signatures, + ElementsAre(Sig("foo(T, U) -> void", {"T", "U"}))); +} + } // namespace } // namespace clangd } // namespace clang