Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -214,6 +214,11 @@ /// should not be set directly. bool InMessageExpression; + /// Gets set to true after calling ProduceSignaturehelp, it is for a + /// workaround to make sure ProduceSignatureHelp is only called at the deepest + /// function call. + bool CalledSignatureHelp = false; + /// The "depth" of the template parameters currently being parsed. unsigned TemplateParameterDepth; Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -2301,11 +2301,15 @@ llvm::function_ref ExprListCompleter; auto ThisVarDecl = dyn_cast_or_null(ThisDecl); - auto ConstructorCompleter = [&, ThisVarDecl] { + auto ConstructorCompleter = [&, ThisVarDecl](bool InsideParam = false) { + if(CalledSignatureHelp) + return; QualType PreferredType = Actions.ProduceConstructorSignatureHelp( getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(), ThisDecl->getLocation(), Exprs, T.getOpenLocation()); - Actions.CodeCompleteExpression(getCurScope(), PreferredType); + CalledSignatureHelp = true; + if(!InsideParam) + Actions.CodeCompleteExpression(getCurScope(), PreferredType); }; if (ThisVarDecl) { // ParseExpressionList can sometimes succeed even when ThisDecl is not @@ -2317,6 +2321,8 @@ } if (ParseExpressionList(Exprs, CommaLocs, ExprListCompleter)) { + if (ThisVarDecl && PP.isCodeCompletionReached()) + ConstructorCompleter(true); Actions.ActOnInitializerError(ThisDecl); SkipUntil(tok::r_paren, StopAtSemi); } else { Index: lib/Parse/ParseExpr.cpp =================================================================== --- lib/Parse/ParseExpr.cpp +++ lib/Parse/ParseExpr.cpp @@ -1652,6 +1652,7 @@ if (Tok.is(tok::code_completion)) { QualType PreferredType = Actions.ProduceCallSignatureHelp( getCurScope(), LHS.get(), None, PT.getOpenLocation()); + CalledSignatureHelp = true; Actions.CodeCompleteExpression(getCurScope(), PreferredType); cutOffParsing(); return ExprError(); @@ -1659,12 +1660,23 @@ if (OpKind == tok::l_paren || !LHS.isInvalid()) { if (Tok.isNot(tok::r_paren)) { - if (ParseExpressionList(ArgExprs, CommaLocs, [&] { - QualType PreferredType = Actions.ProduceCallSignatureHelp( - getCurScope(), LHS.get(), ArgExprs, PT.getOpenLocation()); - Actions.CodeCompleteExpression(getCurScope(), PreferredType); - })) { + auto Completer = [&](bool InsideParam = false) { + if(CalledSignatureHelp) + return; + QualType PreferredType = Actions.ProduceCallSignatureHelp( + getCurScope(), LHS.get(), ArgExprs, PT.getOpenLocation()); + CalledSignatureHelp = true; + if(!InsideParam) + Actions.CodeCompleteExpression(getCurScope(), PreferredType); + }; + if (ParseExpressionList(ArgExprs, CommaLocs, Completer)) { (void)Actions.CorrectDelayedTyposInExpr(LHS); + // If we got an error when parsing expression list, we don't call + // the CodeCompleteCall handler inside the parser. So call it here + // to make sure we get overload suggestions even when we are in the + // middle of a parameter. + if (PP.isCodeCompletionReached()) + Completer(true); LHS = ExprError(); } else if (LHS.isInvalid()) { for (auto &E : ArgExprs) Index: lib/Parse/ParseExprCXX.cpp =================================================================== --- lib/Parse/ParseExprCXX.cpp +++ lib/Parse/ParseExprCXX.cpp @@ -1684,12 +1684,19 @@ CommaLocsTy CommaLocs; if (Tok.isNot(tok::r_paren)) { - if (ParseExpressionList(Exprs, CommaLocs, [&] { - QualType PreferredType = Actions.ProduceConstructorSignatureHelp( - getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), - DS.getEndLoc(), Exprs, T.getOpenLocation()); - Actions.CodeCompleteExpression(getCurScope(), PreferredType); - })) { + auto Completer = [&](bool InsideParam = false) { + if(CalledSignatureHelp) + return; + QualType PreferredType = Actions.ProduceConstructorSignatureHelp( + getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), + DS.getEndLoc(), Exprs, T.getOpenLocation()); + CalledSignatureHelp = true; + if(!InsideParam) + Actions.CodeCompleteExpression(getCurScope(), PreferredType); + }; + if (ParseExpressionList(Exprs, CommaLocs, Completer)) { + if (PP.isCodeCompletionReached()) + Completer(true); SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } @@ -2817,14 +2824,22 @@ ConstructorLParen = T.getOpenLocation(); if (Tok.isNot(tok::r_paren)) { CommaLocsTy CommaLocs; - if (ParseExpressionList(ConstructorArgs, CommaLocs, [&] { - ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), - DeclaratorInfo).get(); - QualType PreferredType = Actions.ProduceConstructorSignatureHelp( - getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), - DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen); - Actions.CodeCompleteExpression(getCurScope(), PreferredType); - })) { + auto Completer = [&](bool InsideParam = false) { + if (CalledSignatureHelp) + return; + ParsedType TypeRep = + Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); + QualType PreferredType = Actions.ProduceConstructorSignatureHelp( + getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), + DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen); + Actions.CodeCompleteExpression(getCurScope(), PreferredType); + CalledSignatureHelp = true; + if (!InsideParam) + Actions.CodeCompleteExpression(getCurScope(), PreferredType); + }; + if (ParseExpressionList(ConstructorArgs, CommaLocs, Completer)) { + if (PP.isCodeCompletionReached()) + Completer(true); SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch); return ExprError(); } Index: lib/Parse/ParseOpenMP.cpp =================================================================== --- lib/Parse/ParseOpenMP.cpp +++ lib/Parse/ParseOpenMP.cpp @@ -416,14 +416,20 @@ CommaLocsTy CommaLocs; SourceLocation LParLoc = T.getOpenLocation(); - if (ParseExpressionList( - Exprs, CommaLocs, [this, OmpPrivParm, LParLoc, &Exprs] { - QualType PreferredType = Actions.ProduceConstructorSignatureHelp( - getCurScope(), - OmpPrivParm->getType()->getCanonicalTypeInternal(), - OmpPrivParm->getLocation(), Exprs, LParLoc); - Actions.CodeCompleteExpression(getCurScope(), PreferredType); - })) { + auto Completer = [this, OmpPrivParm, LParLoc, + &Exprs](bool InsideParam = false) { + if (CalledSignatureHelp) + return; + QualType PreferredType = Actions.ProduceConstructorSignatureHelp( + getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(), + OmpPrivParm->getLocation(), Exprs, LParLoc); + CalledSignatureHelp = true; + if (!InsideParam) + Actions.CodeCompleteExpression(getCurScope(), PreferredType); + }; + if (ParseExpressionList(Exprs, CommaLocs, Completer)) { + if (PP.isCodeCompletionReached()) + Completer(true); Actions.ActOnInitializerError(OmpPrivParm); SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } else { Index: lib/Sema/CodeCompleteConsumer.cpp =================================================================== --- lib/Sema/CodeCompleteConsumer.cpp +++ lib/Sema/CodeCompleteConsumer.cpp @@ -619,6 +619,9 @@ OS << "<#" << C.Text << "#>"; break; + case CodeCompletionString::CK_Optional: + break; + default: OS << C.Text; break; } } Index: test/CodeCompletion/function-overloads.cpp =================================================================== --- /dev/null +++ test/CodeCompletion/function-overloads.cpp @@ -0,0 +1,27 @@ +int f(int i, int j = 2, int k = 5); +int f(float x, float y...); + +class A { + public: + A(int, int, int); +}; + +void test() { + A a(f(1, 2, 3, 4), 2, 3); +} + +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:10 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:17 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:19 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:20 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:21 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s +// CHECK-CC1: OVERLOAD: [#int#]f(<#float x#>, float y) +// CHECK-CC1: OVERLOAD: [#int#]f(<#int i#>) +// CHECK-CC1-NOT, CHECK-CC2-NOT: OVERLOAD: A( +// CHECK-CC2: OVERLOAD: [#int#]f(float x, float y) +// CHECK-CC2-NOT: OVERLOAD: [#int#]f(int i) +// CHECK-CC3: OVERLOAD: A(<#int#>, int, int) +// CHECK-CC3: OVERLOAD: A(<#const A &#>) +// CHECK-CC3: OVERLOAD: A(<#A &&#>) +// CHECK-CC4: OVERLOAD: A(int, <#int#>, int) Index: test/Index/complete-block-property-assignment.m =================================================================== --- test/Index/complete-block-property-assignment.m +++ test/Index/complete-block-property-assignment.m @@ -60,7 +60,6 @@ // RUN: c-index-test -code-completion-at=%s:51:16 %s | FileCheck -check-prefix=CHECK-NO %s // RUN: c-index-test -code-completion-at=%s:52:23 %s | FileCheck -check-prefix=CHECK-NO %s // RUN: c-index-test -code-completion-at=%s:53:12 %s | FileCheck -check-prefix=CHECK-NO %s -// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO %s // RUN: c-index-test -code-completion-at=%s:56:15 %s | FileCheck -check-prefix=CHECK-NO %s // CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35) // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35) @@ -69,4 +68,12 @@ // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35) // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35) +// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO1 %s +// CHECK-NO1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35) +// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35) +// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35) +// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35) +// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35) +// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35) +// CHECK-NO1-NEXT: OverloadCandidate:{ResultType void}{Text func}{LeftParen (}{CurrentParameter int x}{RightParen )} (1) @end