[clang] 92417ea - [CodeCompletion] Signature help for braced constructor calls
Sam McCall via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 3 11:15:09 PST 2022
Author: Sam McCall
Date: 2022-01-03T20:14:59+01:00
New Revision: 92417eaf3329dc823c905ec6a608b83ac62b4f7c
URL: https://github.com/llvm/llvm-project/commit/92417eaf3329dc823c905ec6a608b83ac62b4f7c
DIFF: https://github.com/llvm/llvm-project/commit/92417eaf3329dc823c905ec6a608b83ac62b4f7c.diff
LOG: [CodeCompletion] Signature help for braced constructor calls
Implementation is based on the "expected type" as used for
designated-initializers in braced init lists. This means it can deduce the type
in some cases where it's not written:
void foo(Widget);
foo({ /*help here*/ });
Only basic constructor calls are in scope of this patch, excluded are:
- aggregate initialization (no help is offered for aggregates)
- initializer_list initialization (no help is offered for these constructors)
Fixes https://github.com/clangd/clangd/issues/306
Differential Revision: https://reviews.llvm.org/D116317
Added:
Modified:
clang-tools-extra/clangd/ClangdLSPServer.cpp
clang-tools-extra/clangd/CodeComplete.cpp
clang-tools-extra/clangd/test/initialize-params.test
clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
clang/include/clang/Sema/CodeCompleteConsumer.h
clang/include/clang/Sema/Sema.h
clang/lib/Frontend/ASTUnit.cpp
clang/lib/Parse/ParseDecl.cpp
clang/lib/Parse/ParseDeclCXX.cpp
clang/lib/Parse/ParseExprCXX.cpp
clang/lib/Parse/ParseInit.cpp
clang/lib/Parse/ParseOpenMP.cpp
clang/lib/Sema/CodeCompleteConsumer.cpp
clang/lib/Sema/SemaCodeComplete.cpp
clang/test/CodeCompletion/ctor-signature.cpp
clang/tools/libclang/CIndexCodeCompletion.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index 774cdea218d00..edde19f96202f 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -555,7 +555,7 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
}},
{"signatureHelpProvider",
llvm::json::Object{
- {"triggerCharacters", {"(", ",", ")", "<", ">"}},
+ {"triggerCharacters", {"(", ")", "{", "}", "<", ">", ","}},
}},
{"declarationProvider", true},
{"definitionProvider", true},
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index bdfa1df194537..53d8f0d6cdeb7 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -921,7 +921,8 @@ class SignatureHelpCollector final : public CodeCompleteConsumer {
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates,
- SourceLocation OpenParLoc) override {
+ SourceLocation OpenParLoc,
+ bool Braced) override {
assert(!OpenParLoc.isInvalid());
SourceManager &SrcMgr = S.getSourceManager();
OpenParLoc = SrcMgr.getFileLoc(OpenParLoc);
@@ -961,8 +962,9 @@ class SignatureHelpCollector final : public CodeCompleteConsumer {
paramIndexForArg(Candidate, SigHelp.activeParameter);
}
- const auto *CCS = Candidate.CreateSignatureString(
- CurrentArg, S, *Allocator, CCTUInfo, true);
+ const auto *CCS =
+ Candidate.CreateSignatureString(CurrentArg, S, *Allocator, CCTUInfo,
+ /*IncludeBriefComment=*/true, Braced);
assert(CCS && "Expected the CodeCompletionString to be non-null");
ScoredSignatures.push_back(processOverloadCandidate(
Candidate, *CCS,
@@ -1163,7 +1165,8 @@ class ParamNameCollector final : public CodeCompleteConsumer {
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates,
- SourceLocation OpenParLoc) override {
+ SourceLocation OpenParLoc,
+ bool Braced) override {
assert(CurrentArg <= (unsigned)std::numeric_limits<int>::max() &&
"too many arguments");
diff --git a/clang-tools-extra/clangd/test/initialize-params.test b/clang-tools-extra/clangd/test/initialize-params.test
index 72823f3a0683d..2affc8b2466dd 100644
--- a/clang-tools-extra/clangd/test/initialize-params.test
+++ b/clang-tools-extra/clangd/test/initialize-params.test
@@ -107,10 +107,12 @@
# CHECK-NEXT: "signatureHelpProvider": {
# CHECK-NEXT: "triggerCharacters": [
# CHECK-NEXT: "(",
-# CHECK-NEXT: ",",
# CHECK-NEXT: ")",
+# CHECK-NEXT: "{",
+# CHECK-NEXT: "}",
# CHECK-NEXT: "<",
# CHECK-NEXT: ">"
+# CHECK-NEXT: ","
# CHECK-NEXT: ]
# CHECK-NEXT: },
# CHECK-NEXT: "textDocumentSync": {
diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index d32950fd6e13f..9d5c57670be1f 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1212,6 +1212,10 @@ struct ExpectedParameter {
std::string Text;
std::pair<unsigned, unsigned> Offsets;
};
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const ExpectedParameter &P) {
+ return OS << P.Text;
+}
MATCHER_P(ParamsAre, P, "") {
if (P.size() != arg.parameters.size())
return false;
@@ -1260,6 +1264,36 @@ TEST(SignatureHelpTest, Overloads) {
EXPECT_EQ(0, Results.activeParameter);
}
+TEST(SignatureHelpTest, Constructors) {
+ std::string Top = R"cpp(
+ struct S {
+ S(int);
+ S(const S &) = delete;
+ };
+ )cpp";
+
+ auto CheckParenInit = [&](std::string Init) {
+ EXPECT_THAT(signatures(Top + Init).signatures,
+ UnorderedElementsAre(Sig("S([[int]])")))
+ << Init;
+ };
+ CheckParenInit("S s(^);");
+ CheckParenInit("auto s = S(^);");
+ CheckParenInit("auto s = new S(^);");
+
+ auto CheckBracedInit = [&](std::string Init) {
+ EXPECT_THAT(signatures(Top + Init).signatures,
+ UnorderedElementsAre(Sig("S{[[int]]}")))
+ << Init;
+ };
+ CheckBracedInit("S s{^};");
+ CheckBracedInit("S s = {^};");
+ CheckBracedInit("auto s = S{^};");
+ // FIXME: doesn't work: no ExpectedType set in ParseCXXNewExpression.
+ // CheckBracedInit("auto s = new S{^};");
+ CheckBracedInit("int x(S); int i = x({^});");
+}
+
TEST(SignatureHelpTest, OverloadInitListRegression) {
auto Results = signatures(R"cpp(
struct A {int x;};
diff --git a/clang/include/clang/Sema/CodeCompleteConsumer.h b/clang/include/clang/Sema/CodeCompleteConsumer.h
index 7a369dfd6a43a..70c34703f0a00 100644
--- a/clang/include/clang/Sema/CodeCompleteConsumer.h
+++ b/clang/include/clang/Sema/CodeCompleteConsumer.h
@@ -1081,11 +1081,11 @@ class CodeCompleteConsumer {
/// Create a new code-completion string that describes the function
/// signature of this overload candidate.
- CodeCompletionString *CreateSignatureString(unsigned CurrentArg,
- Sema &S,
- CodeCompletionAllocator &Allocator,
- CodeCompletionTUInfo &CCTUInfo,
- bool IncludeBriefComments) const;
+ CodeCompletionString *
+ CreateSignatureString(unsigned CurrentArg, Sema &S,
+ CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo,
+ bool IncludeBriefComments, bool Braced) const;
};
CodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts)
@@ -1159,7 +1159,8 @@ class CodeCompleteConsumer {
virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates,
- SourceLocation OpenParLoc) {}
+ SourceLocation OpenParLoc,
+ bool Braced) {}
//@}
/// Retrieve the allocator that will be used to allocate
@@ -1210,7 +1211,8 @@ class PrintingCodeCompleteConsumer : public CodeCompleteConsumer {
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates,
- SourceLocation OpenParLoc) override;
+ SourceLocation OpenParLoc,
+ bool Braced) override;
bool isResultFilteredOut(StringRef Filter, CodeCompletionResult Results) override;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index bb13d9527175d..016a12e3b1fef 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -12542,13 +12542,12 @@ class Sema final {
QualType ProduceConstructorSignatureHelp(Scope *S, QualType Type,
SourceLocation Loc,
ArrayRef<Expr *> Args,
- SourceLocation OpenParLoc);
- QualType ProduceCtorInitMemberSignatureHelp(Scope *S, Decl *ConstructorDecl,
- CXXScopeSpec SS,
- ParsedType TemplateTypeTy,
- ArrayRef<Expr *> ArgExprs,
- IdentifierInfo *II,
- SourceLocation OpenParLoc);
+ SourceLocation OpenParLoc,
+ bool Braced);
+ QualType ProduceCtorInitMemberSignatureHelp(
+ Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS,
+ ParsedType TemplateTypeTy, ArrayRef<Expr *> ArgExprs, IdentifierInfo *II,
+ SourceLocation OpenParLoc, bool Braced);
QualType ProduceTemplateArgumentSignatureHelp(
TemplateTy, ArrayRef<ParsedTemplateArgument>, SourceLocation LAngleLoc);
void CodeCompleteInitializer(Scope *S, Decl *D);
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index 52589677ca28c..e82b7fe6db9e6 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -1922,9 +1922,10 @@ namespace {
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates,
- SourceLocation OpenParLoc) override {
+ SourceLocation OpenParLoc,
+ bool Braced) override {
Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates,
- OpenParLoc);
+ OpenParLoc, Braced);
}
CodeCompletionAllocator &getAllocator() override {
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 0c1f88bc51d1c..5900075e5a907 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2420,7 +2420,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
auto RunSignatureHelp = [&]() {
QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
- ThisDecl->getLocation(), Exprs, T.getOpenLocation());
+ ThisDecl->getLocation(), Exprs, T.getOpenLocation(),
+ /*Braced=*/false);
CalledSignatureHelp = true;
return PreferredType;
};
@@ -2440,7 +2441,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) {
Actions.ProduceConstructorSignatureHelp(
getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
- ThisDecl->getLocation(), Exprs, T.getOpenLocation());
+ ThisDecl->getLocation(), Exprs, T.getOpenLocation(),
+ /*Braced=*/false);
CalledSignatureHelp = true;
}
Actions.ActOnInitializerError(ThisDecl);
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index f5a6ffcff9e9d..942b813b3935f 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -3740,8 +3740,8 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
if (TemplateTypeTy.isInvalid())
return QualType();
QualType PreferredType = Actions.ProduceCtorInitMemberSignatureHelp(
- getCurScope(), ConstructorDecl, SS, TemplateTypeTy.get(), ArgExprs, II,
- T.getOpenLocation());
+ getCurScope(), ConstructorDecl, SS, TemplateTypeTy.get(), ArgExprs,
+ II, T.getOpenLocation(), /*Braced=*/false);
CalledSignatureHelp = true;
return PreferredType;
};
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 9cdc16f8ce8d5..0ba0fd5290027 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1878,7 +1878,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
if (TypeRep)
PreferredType = Actions.ProduceConstructorSignatureHelp(
getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
- DS.getEndLoc(), Exprs, T.getOpenLocation());
+ DS.getEndLoc(), Exprs, T.getOpenLocation(), /*Braced=*/false);
CalledSignatureHelp = true;
return PreferredType;
};
@@ -3168,7 +3168,8 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
if (TypeRep)
PreferredType = Actions.ProduceConstructorSignatureHelp(
getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
- DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen);
+ DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen,
+ /*Braced=*/false);
CalledSignatureHelp = true;
return PreferredType;
};
diff --git a/clang/lib/Parse/ParseInit.cpp b/clang/lib/Parse/ParseInit.cpp
index 9d9c03d28a97c..efb162af642d4 100644
--- a/clang/lib/Parse/ParseInit.cpp
+++ b/clang/lib/Parse/ParseInit.cpp
@@ -459,12 +459,22 @@ ExprResult Parser::ParseBraceInitializer() {
Actions, EnterExpressionEvaluationContext::InitList);
bool InitExprsOk = true;
- DesignatorCompletionInfo DesignatorCompletion{
- InitExprs,
- PreferredType.get(T.getOpenLocation()),
+ QualType LikelyType = PreferredType.get(T.getOpenLocation());
+ DesignatorCompletionInfo DesignatorCompletion{InitExprs, LikelyType};
+ bool CalledSignatureHelp = false;
+ auto RunSignatureHelp = [&] {
+ QualType PreferredType;
+ if (!LikelyType.isNull())
+ PreferredType = Actions.ProduceConstructorSignatureHelp(
+ getCurScope(), LikelyType->getCanonicalTypeInternal(),
+ T.getOpenLocation(), InitExprs, T.getOpenLocation(), /*Braced=*/true);
+ CalledSignatureHelp = true;
+ return PreferredType;
};
while (1) {
+ PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);
+
// Handle Microsoft __if_exists/if_not_exists if necessary.
if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||
Tok.is(tok::kw___if_not_exists))) {
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 7c783ef0b02b2..2500cf834a34d 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -471,7 +471,7 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
- OmpPrivParm->getLocation(), Exprs, LParLoc);
+ OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false);
CalledSignatureHelp = true;
return PreferredType;
};
diff --git a/clang/lib/Sema/CodeCompleteConsumer.cpp b/clang/lib/Sema/CodeCompleteConsumer.cpp
index f0968ed0e503a..bb088fd5fe97f 100644
--- a/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -656,7 +656,7 @@ static std::string getOverloadAsString(const CodeCompletionString &CCS) {
void PrintingCodeCompleteConsumer::ProcessOverloadCandidates(
Sema &SemaRef, unsigned CurrentArg, OverloadCandidate *Candidates,
- unsigned NumCandidates, SourceLocation OpenParLoc) {
+ unsigned NumCandidates, SourceLocation OpenParLoc, bool Braced) {
OS << "OPENING_PAREN_LOC: ";
OpenParLoc.print(OS, SemaRef.getSourceManager());
OS << "\n";
@@ -664,7 +664,7 @@ void PrintingCodeCompleteConsumer::ProcessOverloadCandidates(
for (unsigned I = 0; I != NumCandidates; ++I) {
if (CodeCompletionString *CCS = Candidates[I].CreateSignatureString(
CurrentArg, SemaRef, getAllocator(), CCTUInfo,
- includeBriefComments())) {
+ includeBriefComments(), Braced)) {
OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n";
}
}
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index e81faf6d2a93e..d3c154f189373 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -3833,7 +3833,8 @@ static CodeCompletionString *createTemplateSignatureString(
CodeCompletionString *
CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
- CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
+ CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments,
+ bool Braced) const {
PrintingPolicy Policy = getCompletionPrintingPolicy(S);
// Show signatures of constructors as they are declared:
// vector(int n) rather than vector<string>(int n)
@@ -3857,9 +3858,11 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
const FunctionType *FT = getFunctionType();
Result.AddResultTypeChunk(Result.getAllocator().CopyString(
FT->getReturnType().getAsString(Policy)));
- Result.AddChunk(CodeCompletionString::CK_LeftParen);
+ Result.AddChunk(Braced ? CodeCompletionString::CK_LeftBrace
+ : CodeCompletionString::CK_LeftParen);
Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
- Result.AddChunk(CodeCompletionString::CK_RightParen);
+ Result.AddChunk(Braced ? CodeCompletionString::CK_RightBrace
+ : CodeCompletionString::CK_RightParen);
return Result.TakeString();
}
@@ -3879,10 +3882,12 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Proto->getReturnType().getAsString(Policy)));
}
- Result.AddChunk(CodeCompletionString::CK_LeftParen);
+ Result.AddChunk(Braced ? CodeCompletionString::CK_LeftBrace
+ : CodeCompletionString::CK_LeftParen);
AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
CurrentArg);
- Result.AddChunk(CodeCompletionString::CK_RightParen);
+ Result.AddChunk(Braced ? CodeCompletionString::CK_RightBrace
+ : CodeCompletionString::CK_RightParen);
return Result.TakeString();
}
@@ -5940,12 +5945,14 @@ static QualType getParamType(Sema &SemaRef,
static QualType
ProduceSignatureHelp(Sema &SemaRef, MutableArrayRef<ResultCandidate> Candidates,
- unsigned CurrentArg, SourceLocation OpenParLoc) {
+ unsigned CurrentArg, SourceLocation OpenParLoc,
+ bool Braced) {
if (Candidates.empty())
return QualType();
if (SemaRef.getPreprocessor().isCodeCompletionReached())
SemaRef.CodeCompleter->ProcessOverloadCandidates(
- SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
+ SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc,
+ Braced);
return getParamType(SemaRef, Candidates, CurrentArg);
}
@@ -6047,15 +6054,16 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
}
}
mergeCandidatesWithResults(*this, Results, CandidateSet, Loc, Args.size());
- QualType ParamType =
- ProduceSignatureHelp(*this, Results, Args.size(), OpenParLoc);
+ QualType ParamType = ProduceSignatureHelp(*this, Results, Args.size(),
+ OpenParLoc, /*Braced=*/false);
return !CandidateSet.empty() ? ParamType : QualType();
}
QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
SourceLocation Loc,
ArrayRef<Expr *> Args,
- SourceLocation OpenParLoc) {
+ SourceLocation OpenParLoc,
+ bool Braced) {
if (!CodeCompleter)
return QualType();
@@ -6064,6 +6072,10 @@ QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
if (!RD)
return Type;
+ // FIXME: we don't support signature help for aggregate initialization, so
+ // don't offer a confusing partial list (e.g. the copy constructor).
+ if (Braced && RD->isAggregate())
+ return Type;
// FIXME: Provide support for member initializers.
// FIXME: Provide support for variadic template constructors.
@@ -6072,12 +6084,20 @@ QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
for (NamedDecl *C : LookupConstructors(RD)) {
if (auto *FD = dyn_cast<FunctionDecl>(C)) {
+ // FIXME: we can't yet provide correct signature help for initializer
+ // list constructors, so skip them entirely.
+ if (Braced && LangOpts.CPlusPlus && isInitListConstructor(FD))
+ continue;
AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
CandidateSet,
/*SuppressUserConversions=*/false,
/*PartialOverloading=*/true,
/*AllowExplicit*/ true);
} else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
+ if (Braced && LangOpts.CPlusPlus &&
+ isInitListConstructor(FTD->getTemplatedDecl()))
+ continue;
+
AddTemplateOverloadCandidate(
FTD, DeclAccessPair::make(FTD, C->getAccess()),
/*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
@@ -6088,12 +6108,13 @@ QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
SmallVector<ResultCandidate, 8> Results;
mergeCandidatesWithResults(*this, Results, CandidateSet, Loc, Args.size());
- return ProduceSignatureHelp(*this, Results, Args.size(), OpenParLoc);
+ return ProduceSignatureHelp(*this, Results, Args.size(), OpenParLoc, Braced);
}
QualType Sema::ProduceCtorInitMemberSignatureHelp(
Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
- ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
+ ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc,
+ bool Braced) {
if (!CodeCompleter)
return QualType();
@@ -6106,7 +6127,7 @@ QualType Sema::ProduceCtorInitMemberSignatureHelp(
Constructor->getParent(), SS, TemplateTypeTy, II))
return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
MemberDecl->getLocation(), ArgExprs,
- OpenParLoc);
+ OpenParLoc, Braced);
return QualType();
}
@@ -6159,7 +6180,8 @@ QualType Sema::ProduceTemplateArgumentSignatureHelp(
if (const auto *TD = llvm::dyn_cast<TemplateDecl>(ND))
Consider(TD);
}
- return ProduceSignatureHelp(*this, Results, Args.size(), LAngleLoc);
+ return ProduceSignatureHelp(*this, Results, Args.size(), LAngleLoc,
+ /*Braced=*/false);
}
static QualType getDesignatedType(QualType BaseType, const Designation &Desig) {
diff --git a/clang/test/CodeCompletion/ctor-signature.cpp b/clang/test/CodeCompletion/ctor-signature.cpp
index 4dbd92300566e..b02c8811bbcf0 100644
--- a/clang/test/CodeCompletion/ctor-signature.cpp
+++ b/clang/test/CodeCompletion/ctor-signature.cpp
@@ -15,3 +15,40 @@ void foo() {
// CHECK-CC2: OVERLOAD: Foo(<#const Foo<int *> &#>)
// CHECK-CC2: OVERLOAD: Foo(<#Foo<int *> &&#>
}
+
+namespace std {
+template <typename> struct initializer_list {};
+} // namespace std
+
+struct Bar {
+ // CHECK-BRACED: OVERLOAD: Bar{<#int#>}
+ Bar(int);
+ // CHECK-BRACED: OVERLOAD: Bar{<#double#>, double}
+ Bar(double, double);
+ // FIXME: no support for init-list constructors yet.
+ // CHECK-BRACED-NOT: OVERLOAD: {{.*}}char
+ Bar(std::initializer_list<char> C);
+ // CHECK-BRACED: OVERLOAD: Bar{<#const Bar &#>}
+ // CHECK-BRACED: OVERLOAD: Bar{<#T *Pointer#>}
+ template <typename T> Bar(T *Pointer);
+};
+
+auto b1 = Bar{};
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:36:15 %s | FileCheck -check-prefix=CHECK-BRACED %s
+Bar b2{};
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:38:8 %s | FileCheck -check-prefix=CHECK-BRACED %s
+static int consumeBar(Bar) { return 0; }
+int b3 = consumeBar({});
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:41:22 %s | FileCheck -check-prefix=CHECK-BRACED %s
+
+struct Aggregate {
+ // FIXME: no support for aggregates yet.
+ // CHECK-AGGREGATE-NOT: OVERLOAD: Aggregate{<#const Aggregate &#>}
+ // CHECK-AGGREGATE-NOT: OVERLOAD: {{.*}}first
+ int first;
+ int second;
+};
+
+Aggregate a{};
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:52:13 %s | FileCheck -check-prefix=CHECK-AGGREGATE %s
+
diff --git a/clang/tools/libclang/CIndexCodeCompletion.cpp b/clang/tools/libclang/CIndexCodeCompletion.cpp
index 044cac93563b4..0d75970f2f652 100644
--- a/clang/tools/libclang/CIndexCodeCompletion.cpp
+++ b/clang/tools/libclang/CIndexCodeCompletion.cpp
@@ -656,14 +656,15 @@ namespace {
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates,
- SourceLocation OpenParLoc) override {
+ SourceLocation OpenParLoc,
+ bool Braced) override {
StoredResults.reserve(StoredResults.size() + NumCandidates);
for (unsigned I = 0; I != NumCandidates; ++I) {
- CodeCompletionString *StoredCompletion
- = Candidates[I].CreateSignatureString(CurrentArg, S, getAllocator(),
+ CodeCompletionString *StoredCompletion =
+ Candidates[I].CreateSignatureString(CurrentArg, S, getAllocator(),
getCodeCompletionTUInfo(),
- includeBriefComments());
-
+ includeBriefComments(), Braced);
+
CXCompletionResult R;
R.CursorKind = CXCursor_OverloadCandidate;
R.CompletionString = StoredCompletion;
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index a0cff3cc9bf8e..51f34369c3834 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -995,7 +995,8 @@ class CodeComplete : public CodeCompleteConsumer {
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates,
- SourceLocation OpenParLoc) override {
+ SourceLocation OpenParLoc,
+ bool Braced) override {
// At the moment we don't filter out any overloaded candidates.
}
More information about the cfe-commits
mailing list