Index: cfe/trunk/include/clang/Parse/Parser.h =================================================================== --- cfe/trunk/include/clang/Parse/Parser.h +++ cfe/trunk/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: cfe/trunk/lib/Parse/ParseDecl.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseDecl.cpp +++ cfe/trunk/lib/Parse/ParseDecl.cpp @@ -2305,6 +2305,7 @@ QualType PreferredType = Actions.ProduceConstructorSignatureHelp( getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(), ThisDecl->getLocation(), Exprs, T.getOpenLocation()); + CalledSignatureHelp = true; Actions.CodeCompleteExpression(getCurScope(), PreferredType); }; if (ThisVarDecl) { @@ -2317,6 +2318,12 @@ } if (ParseExpressionList(Exprs, CommaLocs, ExprListCompleter)) { + if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) { + Actions.ProduceConstructorSignatureHelp( + getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(), + ThisDecl->getLocation(), Exprs, T.getOpenLocation()); + CalledSignatureHelp = true; + } Actions.ActOnInitializerError(ThisDecl); SkipUntil(tok::r_paren, StopAtSemi); } else { Index: cfe/trunk/lib/Parse/ParseExpr.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseExpr.cpp +++ cfe/trunk/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(); @@ -1662,9 +1663,19 @@ if (ParseExpressionList(ArgExprs, CommaLocs, [&] { QualType PreferredType = Actions.ProduceCallSignatureHelp( getCurScope(), LHS.get(), ArgExprs, PT.getOpenLocation()); + CalledSignatureHelp = true; Actions.CodeCompleteExpression(getCurScope(), PreferredType); })) { (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() && !CalledSignatureHelp) { + Actions.ProduceCallSignatureHelp(getCurScope(), LHS.get(), + ArgExprs, PT.getOpenLocation()); + CalledSignatureHelp = true; + } LHS = ExprError(); } else if (LHS.isInvalid()) { for (auto &E : ArgExprs) Index: cfe/trunk/lib/Parse/ParseExprCXX.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseExprCXX.cpp +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp @@ -1688,8 +1688,15 @@ QualType PreferredType = Actions.ProduceConstructorSignatureHelp( getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), DS.getEndLoc(), Exprs, T.getOpenLocation()); + CalledSignatureHelp = true; Actions.CodeCompleteExpression(getCurScope(), PreferredType); })) { + if (PP.isCodeCompletionReached() && !CalledSignatureHelp) { + Actions.ProduceConstructorSignatureHelp( + getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), + DS.getEndLoc(), Exprs, T.getOpenLocation()); + CalledSignatureHelp = true; + } SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } @@ -2818,13 +2825,22 @@ if (Tok.isNot(tok::r_paren)) { CommaLocsTy CommaLocs; if (ParseExpressionList(ConstructorArgs, CommaLocs, [&] { - ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), - DeclaratorInfo).get(); + ParsedType TypeRep = + Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); QualType PreferredType = Actions.ProduceConstructorSignatureHelp( getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen); + CalledSignatureHelp = true; Actions.CodeCompleteExpression(getCurScope(), PreferredType); - })) { + })) { + if (PP.isCodeCompletionReached() && !CalledSignatureHelp) { + ParsedType TypeRep = + Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); + Actions.ProduceConstructorSignatureHelp( + getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), + DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen); + CalledSignatureHelp = true; + } SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch); return ExprError(); } Index: cfe/trunk/lib/Parse/ParseOpenMP.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseOpenMP.cpp +++ cfe/trunk/lib/Parse/ParseOpenMP.cpp @@ -422,8 +422,15 @@ getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(), OmpPrivParm->getLocation(), Exprs, LParLoc); + CalledSignatureHelp = true; Actions.CodeCompleteExpression(getCurScope(), PreferredType); })) { + if (PP.isCodeCompletionReached() && !CalledSignatureHelp) { + Actions.ProduceConstructorSignatureHelp( + getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(), + OmpPrivParm->getLocation(), Exprs, LParLoc); + CalledSignatureHelp = true; + } Actions.ActOnInitializerError(OmpPrivParm); SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } else { Index: cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp =================================================================== --- cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp +++ cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp @@ -619,6 +619,10 @@ OS << "<#" << C.Text << "#>"; break; + // FIXME: We can also print optional parameters of an overload. + case CodeCompletionString::CK_Optional: + break; + default: OS << C.Text; break; } } Index: cfe/trunk/test/CodeCompletion/function-overloads.cpp =================================================================== --- cfe/trunk/test/CodeCompletion/function-overloads.cpp +++ cfe/trunk/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: cfe/trunk/test/Index/complete-block-property-assignment.m =================================================================== --- cfe/trunk/test/Index/complete-block-property-assignment.m +++ cfe/trunk/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