aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaCodeComplete.cpp
diff options
context:
space:
mode:
authorKadir Cetinkaya <kadircet@google.com>2020-08-11 21:10:57 +0200
committerKadir Cetinkaya <kadircet@google.com>2020-08-17 10:06:36 +0200
commit53c593c2c893a40083771789e3d3e164eea1892d (patch)
treee851f195f12ba4293559a46bfc30754f4c1244bd /clang/lib/Sema/SemaCodeComplete.cpp
parent24fc3177c1767535aeb494511a13dabf9f6de647 (diff)
downloadllvm-53c593c2c893a40083771789e3d3e164eea1892d.zip
llvm-53c593c2c893a40083771789e3d3e164eea1892d.tar.gz
llvm-53c593c2c893a40083771789e3d3e164eea1892d.tar.bz2
[clang] Make signature help work with dependent args
Fixes https://github.com/clangd/clangd/issues/490 Differential Revision: https://reviews.llvm.org/D85826
Diffstat (limited to 'clang/lib/Sema/SemaCodeComplete.cpp')
-rw-r--r--clang/lib/Sema/SemaCodeComplete.cpp53
1 files changed, 35 insertions, 18 deletions
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 0a8a270..cf38b10 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -5500,7 +5500,7 @@ typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
static void mergeCandidatesWithResults(
Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,
- OverloadCandidateSet &CandidateSet, SourceLocation Loc) {
+ OverloadCandidateSet &CandidateSet, SourceLocation Loc, size_t ArgSize) {
// Sort the overload candidate set by placing the best overloads first.
llvm::stable_sort(CandidateSet, [&](const OverloadCandidate &X,
const OverloadCandidate &Y) {
@@ -5510,8 +5510,19 @@ static void mergeCandidatesWithResults(
// Add the remaining viable overload candidates as code-completion results.
for (OverloadCandidate &Candidate : CandidateSet) {
- if (Candidate.Function && Candidate.Function->isDeleted())
- continue;
+ if (Candidate.Function) {
+ if (Candidate.Function->isDeleted())
+ continue;
+ if (!Candidate.Function->isVariadic() &&
+ Candidate.Function->getNumParams() <= ArgSize &&
+ // Having zero args is annoying, normally we don't surface a function
+ // with 2 params, if you already have 2 params, because you are
+ // inserting the 3rd now. But with zero, it helps the user to figure
+ // out there are no overloads that take any arguments. Hence we are
+ // keeping the overload.
+ ArgSize > 0)
+ continue;
+ }
if (Candidate.Viable)
Results.push_back(ResultCandidate(Candidate.Function));
}
@@ -5562,22 +5573,25 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
// FIXME: Provide support for variadic template functions.
// Ignore type-dependent call expressions entirely.
- if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
- Expr::hasAnyTypeDependentArguments(Args)) {
+ if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args))
return QualType();
- }
+ // In presence of dependent args we surface all possible signatures using the
+ // non-dependent args in the prefix. Afterwards we do a post filtering to make
+ // sure provided candidates satisfy parameter count restrictions.
+ auto ArgsWithoutDependentTypes =
+ Args.take_while([](Expr *Arg) { return !Arg->isTypeDependent(); });
+ SmallVector<ResultCandidate, 8> Results;
+
+ Expr *NakedFn = Fn->IgnoreParenCasts();
// Build an overload candidate set based on the functions we find.
SourceLocation Loc = Fn->getExprLoc();
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
- SmallVector<ResultCandidate, 8> Results;
-
- Expr *NakedFn = Fn->IgnoreParenCasts();
- if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
- AddOverloadedCallCandidates(ULE, Args, CandidateSet,
+ if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) {
+ AddOverloadedCallCandidates(ULE, ArgsWithoutDependentTypes, CandidateSet,
/*PartialOverloading=*/true);
- else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
+ } else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
if (UME->hasExplicitTemplateArgs()) {
UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
@@ -5587,7 +5601,8 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
// Add the base as first argument (use a nullptr if the base is implicit).
SmallVector<Expr *, 12> ArgExprs(
1, UME->isImplicitAccess() ? nullptr : UME->getBase());
- ArgExprs.append(Args.begin(), Args.end());
+ ArgExprs.append(ArgsWithoutDependentTypes.begin(),
+ ArgsWithoutDependentTypes.end());
UnresolvedSet<8> Decls;
Decls.append(UME->decls_begin(), UME->decls_end());
const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
@@ -5606,7 +5621,7 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
Results.push_back(ResultCandidate(FD));
else
AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
- Args, CandidateSet,
+ ArgsWithoutDependentTypes, CandidateSet,
/*SuppressUserConversions=*/false,
/*PartialOverloading=*/true);
@@ -5621,7 +5636,8 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
LookupQualifiedName(R, DC);
R.suppressDiagnostics();
SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
- ArgExprs.append(Args.begin(), Args.end());
+ ArgExprs.append(ArgsWithoutDependentTypes.begin(),
+ ArgsWithoutDependentTypes.end());
AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
/*ExplicitArgs=*/nullptr,
/*SuppressUserConversions=*/false,
@@ -5635,7 +5651,8 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
T = T->getPointeeType();
if (auto FP = T->getAs<FunctionProtoType>()) {
- if (!TooManyArguments(FP->getNumParams(), Args.size(),
+ if (!TooManyArguments(FP->getNumParams(),
+ ArgsWithoutDependentTypes.size(),
/*PartialOverloading=*/true) ||
FP->isVariadic())
Results.push_back(ResultCandidate(FP));
@@ -5644,7 +5661,7 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
Results.push_back(ResultCandidate(FT));
}
}
- mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
+ mergeCandidatesWithResults(*this, Results, CandidateSet, Loc, Args.size());
QualType ParamType =
ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
return !CandidateSet.empty() ? ParamType : QualType();
@@ -5685,7 +5702,7 @@ QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
}
SmallVector<ResultCandidate, 8> Results;
- mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
+ mergeCandidatesWithResults(*this, Results, CandidateSet, Loc, Args.size());
return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
}