Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -10231,6 +10231,7 @@ struct CodeCompleteExpressionData; void CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data); + void CodeCompleteExpression(Scope *S, QualType PreferredType); void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, Expr *OtherOpBase, SourceLocation OpLoc, bool IsArrow, bool IsBaseExprStatement); @@ -10241,11 +10242,14 @@ const VirtSpecifiers *VS = nullptr); void CodeCompleteBracketDeclarator(Scope *S); void CodeCompleteCase(Scope *S); - void CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef Args, - SourceLocation OpenParLoc); - void CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc, - ArrayRef Args, - SourceLocation OpenParLoc); + /// Reports signatures for a call to CodeCompleteConsumer and returns the + /// preferred type for the current argument. Returned type can be null. + QualType ProduceCallSignatureHelp(Scope *S, Expr *Fn, ArrayRef Args, + SourceLocation OpenParLoc); + QualType ProduceConstructorSignatureHelp(Scope *S, QualType Type, + SourceLocation Loc, + ArrayRef Args, + SourceLocation OpenParLoc); void CodeCompleteInitializer(Scope *S, Decl *D); void CodeCompleteReturn(Scope *S); void CodeCompleteAfterIf(Scope *S); Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -2302,16 +2302,17 @@ llvm::function_ref ExprListCompleter; auto ThisVarDecl = dyn_cast_or_null(ThisDecl); auto ConstructorCompleter = [&, ThisVarDecl] { - Actions.CodeCompleteConstructor( + QualType PreferredType = Actions.ProduceConstructorSignatureHelp( getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(), ThisDecl->getLocation(), Exprs, T.getOpenLocation()); + Actions.CodeCompleteExpression(getCurScope(), PreferredType); }; if (ThisVarDecl) { // ParseExpressionList can sometimes succeed even when ThisDecl is not // VarDecl. This is an error and it is reported in a call to // Actions.ActOnInitializerError(). However, we call - // CodeCompleteConstructor only on VarDecls, falling back to default - // completer in other cases. + // ProduceConstructorSignatureHelp only on VarDecls, falling back to + // default completer in other cases. ExprListCompleter = ConstructorCompleter; } Index: lib/Parse/ParseExpr.cpp =================================================================== --- lib/Parse/ParseExpr.cpp +++ lib/Parse/ParseExpr.cpp @@ -1650,8 +1650,9 @@ CommaLocsTy CommaLocs; if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteCall(getCurScope(), LHS.get(), None, - PT.getOpenLocation()); + QualType PreferredType = Actions.ProduceCallSignatureHelp( + getCurScope(), LHS.get(), None, PT.getOpenLocation()); + Actions.CodeCompleteExpression(getCurScope(), PreferredType); cutOffParsing(); return ExprError(); } @@ -1659,8 +1660,9 @@ if (OpKind == tok::l_paren || !LHS.isInvalid()) { if (Tok.isNot(tok::r_paren)) { if (ParseExpressionList(ArgExprs, CommaLocs, [&] { - Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs, - PT.getOpenLocation()); + QualType PreferredType = Actions.ProduceCallSignatureHelp( + getCurScope(), LHS.get(), ArgExprs, PT.getOpenLocation()); + Actions.CodeCompleteExpression(getCurScope(), PreferredType); })) { (void)Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); Index: lib/Parse/ParseExprCXX.cpp =================================================================== --- lib/Parse/ParseExprCXX.cpp +++ lib/Parse/ParseExprCXX.cpp @@ -1685,9 +1685,10 @@ if (Tok.isNot(tok::r_paren)) { if (ParseExpressionList(Exprs, CommaLocs, [&] { - Actions.CodeCompleteConstructor( + QualType PreferredType = Actions.ProduceConstructorSignatureHelp( getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), DS.getEndLoc(), Exprs, T.getOpenLocation()); + Actions.CodeCompleteExpression(getCurScope(), PreferredType); })) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); @@ -2819,9 +2820,10 @@ if (ParseExpressionList(ConstructorArgs, CommaLocs, [&] { ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); - Actions.CodeCompleteConstructor( + QualType PreferredType = Actions.ProduceConstructorSignatureHelp( getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen); + Actions.CodeCompleteExpression(getCurScope(), PreferredType); })) { SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch); return ExprError(); Index: lib/Parse/ParseOpenMP.cpp =================================================================== --- lib/Parse/ParseOpenMP.cpp +++ lib/Parse/ParseOpenMP.cpp @@ -418,10 +418,11 @@ SourceLocation LParLoc = T.getOpenLocation(); if (ParseExpressionList( Exprs, CommaLocs, [this, OmpPrivParm, LParLoc, &Exprs] { - Actions.CodeCompleteConstructor( + QualType PreferredType = Actions.ProduceConstructorSignatureHelp( getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(), OmpPrivParm->getLocation(), Exprs, LParLoc); + Actions.CodeCompleteExpression(getCurScope(), PreferredType); })) { Actions.ActOnInitializerError(OmpPrivParm); SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); Index: lib/Sema/SemaCodeComplete.cpp =================================================================== --- lib/Sema/SemaCodeComplete.cpp +++ lib/Sema/SemaCodeComplete.cpp @@ -3752,6 +3752,10 @@ Results.data(), Results.size()); } +void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType) { + return CodeCompleteExpression(S, CodeCompleteExpressionData(PreferredType)); +} + void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) { if (E.isInvalid()) CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction); @@ -4435,42 +4439,28 @@ return ParamType; } -static void -CodeCompleteOverloadResults(Sema &SemaRef, Scope *S, - MutableArrayRef Candidates, - unsigned CurrentArg, SourceLocation OpenParLoc, - bool CompleteExpressionWithCurrentArg = true) { - QualType ParamType; - if (CompleteExpressionWithCurrentArg) - ParamType = getParamType(SemaRef, Candidates, CurrentArg); - - if (ParamType.isNull()) - SemaRef.CodeCompleteOrdinaryName(S, Sema::PCC_Expression); - else - SemaRef.CodeCompleteExpression(S, ParamType); - - if (!Candidates.empty()) - SemaRef.CodeCompleter->ProcessOverloadCandidates( - SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc); +static QualType +ProduceSignatureHelp(Sema &SemaRef, Scope *S, + MutableArrayRef Candidates, + unsigned CurrentArg, SourceLocation OpenParLoc) { + if (Candidates.empty()) + return QualType(); + SemaRef.CodeCompleter->ProcessOverloadCandidates( + SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc); + return getParamType(SemaRef, Candidates, CurrentArg); } -void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef Args, - SourceLocation OpenParLoc) { +QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, + ArrayRef Args, + SourceLocation OpenParLoc) { if (!CodeCompleter) - return; - - // When we're code-completing for a call, we fall back to ordinary - // name code-completion whenever we can't produce specific - // results. We may want to revisit this strategy in the future, - // e.g., by merging the two kinds of results. + return QualType(); // FIXME: Provide support for variadic template functions. - // Ignore type-dependent call expressions entirely. if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) || Expr::hasAnyTypeDependentArguments(Args)) { - CodeCompleteOrdinaryName(S, PCC_Expression); - return; + return QualType(); } // Build an overload candidate set based on the functions we find. @@ -4551,25 +4541,24 @@ Results.push_back(ResultCandidate(FT)); } } - mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); - CodeCompleteOverloadResults(*this, S, Results, Args.size(), OpenParLoc, - !CandidateSet.empty()); + QualType ParamType = + ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc); + return !CandidateSet.empty() ? ParamType : QualType(); } -void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc, - ArrayRef Args, - SourceLocation OpenParLoc) { +QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type, + SourceLocation Loc, + ArrayRef Args, + SourceLocation OpenParLoc) { if (!CodeCompleter) - return; + return QualType(); // A complete type is needed to lookup for constructors. CXXRecordDecl *RD = isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr; - if (!RD) { - CodeCompleteExpression(S, Type); - return; - } + if (!RD) + return Type; // FIXME: Provide support for member initializers. // FIXME: Provide support for variadic template constructors. @@ -4594,7 +4583,7 @@ SmallVector Results; mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); - CodeCompleteOverloadResults(*this, S, Results, Args.size(), OpenParLoc); + return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc); } void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { Index: test/CodeCompletion/call.cpp =================================================================== --- test/CodeCompletion/call.cpp +++ test/CodeCompletion/call.cpp @@ -18,10 +18,10 @@ void test() { f(Y(), 0, 0); // RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:19:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s - // CHECK-CC1: COMPLETION: Pattern : dynamic_cast<<#type#>>(<#expression#>) // CHECK-CC1: f(Y y, <#int ZZ#>) // CHECK-CC1-NEXT: f(int i, <#int j#>, int k) // CHECK-CC1-NEXT: f(float x, <#float y#>) + // CHECK-CC1: COMPLETION: Pattern : dynamic_cast<<#type#>>(<#expression#>) // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:19:13 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s // CHECK-CC2-NOT: f(Y y, int ZZ) // CHECK-CC2: f(int i, int j, <#int k#>)