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);
const VirtSpecifiers *VS = nullptr);
void CodeCompleteBracketDeclarator(Scope *S);
void CodeCompleteCase(Scope *S);
- void CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args,
- SourceLocation OpenParLoc);
- void CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
- ArrayRef<Expr *> 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<Expr *> Args,
+ SourceLocation OpenParLoc);
+ QualType ProduceConstructorSignatureHelp(Scope *S, QualType Type,
+ SourceLocation Loc,
+ ArrayRef<Expr *> Args,
+ SourceLocation OpenParLoc);
void CodeCompleteInitializer(Scope *S, Decl *D);
void CodeCompleteReturn(Scope *S);
void CodeCompleteAfterIf(Scope *S);
llvm::function_ref<void()> ExprListCompleter;
auto ThisVarDecl = dyn_cast_or_null<VarDecl>(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;
}
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();
}
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();
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();
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();
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);
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);
return ParamType;
}
-static void
-CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
- MutableArrayRef<ResultCandidate> 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<ResultCandidate> 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<Expr *> Args,
- SourceLocation OpenParLoc) {
+QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
+ ArrayRef<Expr *> 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.
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<Expr *> Args,
- SourceLocation OpenParLoc) {
+QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
+ SourceLocation Loc,
+ ArrayRef<Expr *> 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.
SmallVector<ResultCandidate, 8> 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) {
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#>)