aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Parse/ParseTemplate.cpp
diff options
context:
space:
mode:
authorSam McCall <sam.mccall@gmail.com>2021-12-29 04:16:47 +0100
committerSam McCall <sam.mccall@gmail.com>2022-01-03 16:28:16 +0100
commitcd45e8c7bc16dec2eeec9cc71eb3ba87d1bd6bab (patch)
tree3db9bfda04d2f78dc9bf0067bc2b4ebf56c9258a /clang/lib/Parse/ParseTemplate.cpp
parent3a33c0b1ce0db465c9d85c493674efc6c5005dbe (diff)
downloadllvm-cd45e8c7bc16dec2eeec9cc71eb3ba87d1bd6bab.zip
llvm-cd45e8c7bc16dec2eeec9cc71eb3ba87d1bd6bab.tar.gz
llvm-cd45e8c7bc16dec2eeec9cc71eb3ba87d1bd6bab.tar.bz2
[CodeCompletion] Signature help for template argument lists
Provide signature while typing template arguments: Foo< ^here > Here the parameters are e.g. "typename x", and the result type is e.g. "struct" (class template) or "int" (variable template) or "bool (std::string)" (function template). Multiple overloads are possible when a template name is used for several overloaded function templates. Fixes https://github.com/clangd/clangd/issues/299 Differential Revision: https://reviews.llvm.org/D116352
Diffstat (limited to 'clang/lib/Parse/ParseTemplate.cpp')
-rw-r--r--clang/lib/Parse/ParseTemplate.cpp40
1 files changed, 28 insertions, 12 deletions
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index 45af61a..204b534 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -1222,7 +1222,6 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation LAngleLoc,
return false;
}
-
/// Parses a template-id that after the template name has
/// already been parsed.
///
@@ -1234,11 +1233,13 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation LAngleLoc,
/// token that forms the template-id. Otherwise, we will leave the
/// last token in the stream (e.g., so that it can be replaced with an
/// annotation token).
-bool
-Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken,
- SourceLocation &LAngleLoc,
- TemplateArgList &TemplateArgs,
- SourceLocation &RAngleLoc) {
+///
+/// \param NameHint is not required, and merely affects code completion.
+bool Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken,
+ SourceLocation &LAngleLoc,
+ TemplateArgList &TemplateArgs,
+ SourceLocation &RAngleLoc,
+ TemplateTy Template) {
assert(Tok.is(tok::less) && "Must have already parsed the template-name");
// Consume the '<'.
@@ -1251,7 +1252,7 @@ Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken,
if (!Tok.isOneOf(tok::greater, tok::greatergreater,
tok::greatergreatergreater, tok::greaterequal,
tok::greatergreaterequal))
- Invalid = ParseTemplateArgumentList(TemplateArgs);
+ Invalid = ParseTemplateArgumentList(TemplateArgs, Template, LAngleLoc);
if (Invalid) {
// Try to find the closing '>'.
@@ -1332,8 +1333,8 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
TemplateArgList TemplateArgs;
bool ArgsInvalid = false;
if (!TypeConstraint || Tok.is(tok::less)) {
- ArgsInvalid = ParseTemplateIdAfterTemplateName(false, LAngleLoc,
- TemplateArgs, RAngleLoc);
+ ArgsInvalid = ParseTemplateIdAfterTemplateName(
+ false, LAngleLoc, TemplateArgs, RAngleLoc, Template);
// If we couldn't recover from invalid arguments, don't form an annotation
// token -- we don't know how much to annotate.
// FIXME: This can lead to duplicate diagnostics if we retry parsing this
@@ -1585,19 +1586,34 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
/// template-argument-list: [C++ 14.2]
/// template-argument
/// template-argument-list ',' template-argument
-bool
-Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
+///
+/// \param Template is only used for code completion, and may be null.
+bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
+ TemplateTy Template,
+ SourceLocation OpenLoc) {
ColonProtectionRAIIObject ColonProtection(*this, false);
+ auto RunSignatureHelp = [&] {
+ if (!Template)
+ return QualType();
+ CalledSignatureHelp = true;
+ return Actions.ProduceTemplateArgumentSignatureHelp(Template, TemplateArgs,
+ OpenLoc);
+ };
+
do {
+ PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);
ParsedTemplateArgument Arg = ParseTemplateArgument();
SourceLocation EllipsisLoc;
if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc);
- if (Arg.isInvalid())
+ if (Arg.isInvalid()) {
+ if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
+ RunSignatureHelp();
return true;
+ }
// Save this template argument.
TemplateArgs.push_back(Arg);