Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -2278,8 +2278,9 @@ void AddFunctionCandidates(const UnresolvedSetImpl &Functions, ArrayRef Args, OverloadCandidateSet &CandidateSet, + TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, bool SuppressUserConversions = false, - TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr); + bool PartialOverloading = false); void AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, Expr::Classification ObjectClassification, Index: lib/Sema/SemaCodeComplete.cpp =================================================================== --- lib/Sema/SemaCodeComplete.cpp +++ lib/Sema/SemaCodeComplete.cpp @@ -3825,7 +3825,6 @@ // results. This will do "parameter completion" solely. // FIXME: Provide support for constructors - // FIXME: Extend support of functors beyond bare indentifier based functors Expr *Fn = (Expr *)FnIn; @@ -3845,7 +3844,7 @@ Expr *NakedFn = Fn->IgnoreParenCasts(); if (UnresolvedLookupExpr *ULE = dyn_cast(NakedFn)) AddOverloadedCallCandidates(ULE, Args, CandidateSet, - /*PartialOverloading=*/ true); + /*PartialOverloading=*/true); else if (auto UnresExpr = dyn_cast(NakedFn)) { CXXMethodDecl *Method = nullptr; QualType ObjectType = UnresExpr->getBaseType(); @@ -3891,54 +3890,33 @@ /*PartialOverloading=*/true); } } - } else if (auto DRE = dyn_cast(NakedFn)) { - if (auto FDecl = dyn_cast(DRE->getDecl())) { + } else if (auto DC = NakedFn->getType()->getCanonicalTypeInternal() + ->getAsCXXRecordDecl()) { + DeclarationName OpName = Context.DeclarationNames + .getCXXOperatorName(OO_Call); + LookupResult R(*this, OpName, Loc, LookupOrdinaryName); + LookupQualifiedName(R, DC); + R.suppressDiagnostics(); + SmallVector ArgExprs(1, NakedFn); + ArgExprs.append(Args.begin(), Args.end()); + AddFunctionCandidates(R.asUnresolvedSet(), + ArgExprs, + CandidateSet, + /*ExplicitArgs=*/nullptr, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); + } else { + FunctionDecl *FD = nullptr; + if (auto MCE = dyn_cast(NakedFn)) + FD = dyn_cast(MCE->getMemberDecl()); + else if (auto DRE = dyn_cast(NakedFn)) + FD = dyn_cast(DRE->getDecl()); + if (FD) { if (!getLangOpts().CPlusPlus || - !FDecl->getType()->getAs()) - Results.push_back(ResultCandidate(FDecl)); + !FD->getType()->getAs()) + Results.push_back(ResultCandidate(FD)); else - // FIXME: access? - AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), - Args, CandidateSet, - /*SuppressUsedConversions=*/false, - /*PartialOverloading=*/true); - } else if (auto Record = DRE->getType()->getAs()) { - QualType ObjectType = DRE->getType(); - Expr::Classification ObjectClassification = DRE->Classify(Context); - DeclarationName OpName = Context - .DeclarationNames - .getCXXOperatorName(OO_Call); - - LookupResult R(*this, OpName, DRE->getLocEnd(), LookupOrdinaryName); - LookupQualifiedName(R, Record->getDecl()); - R.suppressDiagnostics(); - for (auto I = R.begin(), E = R.end(); I != E; ++I) { - NamedDecl *Func = *I; - CXXRecordDecl *ActingDC = cast(Func->getDeclContext()); - if (isa(Func)) - Func = cast(Func)->getTargetDecl(); - - if (auto Method = dyn_cast(I.getDecl())) { - CXXRecordDecl *ActingDC = cast(I.getDecl()->getDeclContext()); - AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType, - ObjectClassification, Args, CandidateSet, - /*SuppressUserConversions=*/false, - /*PartialOverloading=*/true); - } else if (auto TemplateMethod = cast(Func)) { - AddMethodTemplateCandidate(TemplateMethod, - I.getPair(), ActingDC, - /*ExplicitArgs=*/nullptr, - ObjectType, ObjectClassification, - Args, CandidateSet, - /*SuppressUsedConversions=*/false, - /*PartialOverloading=*/true); - } - } - } - } else if (auto MCE = dyn_cast(NakedFn)) { - if (auto FDecl = dyn_cast(MCE->getMemberDecl())) { - // FIXME: access? - AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), + AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()), Args, CandidateSet, /*SuppressUsedConversions=*/false, /*PartialOverloading=*/true); Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -5851,34 +5851,39 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, ArrayRef Args, OverloadCandidateSet& CandidateSet, + TemplateArgumentListInfo *ExplicitTemplateArgs, bool SuppressUserConversions, - TemplateArgumentListInfo *ExplicitTemplateArgs) { + bool PartialOverloading) { for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) { NamedDecl *D = F.getDecl()->getUnderlyingDecl(); if (FunctionDecl *FD = dyn_cast(D)) { - if (isa(FD) && !cast(FD)->isStatic()) + if (isa(FD) && !cast(FD)->isStatic() && + !isa(FD)) AddMethodCandidate(cast(FD), F.getPair(), cast(FD)->getParent(), Args[0]->getType(), Args[0]->Classify(Context), Args.slice(1), CandidateSet, - SuppressUserConversions); + SuppressUserConversions, PartialOverloading); else AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet, - SuppressUserConversions); + SuppressUserConversions, PartialOverloading); } else { - FunctionTemplateDecl *FunTmpl = cast(D); - if (isa(FunTmpl->getTemplatedDecl()) && - !cast(FunTmpl->getTemplatedDecl())->isStatic()) - AddMethodTemplateCandidate(FunTmpl, F.getPair(), - cast(FunTmpl->getDeclContext()), + FunctionTemplateDecl *FTD = cast(D); + if (isa(FTD->getTemplatedDecl()) && + !cast(FTD->getTemplatedDecl())->isStatic() && + !isa(FTD->getTemplatedDecl())) + AddMethodTemplateCandidate(FTD, F.getPair(), + cast(FTD->getDeclContext()), ExplicitTemplateArgs, Args[0]->getType(), Args[0]->Classify(Context), Args.slice(1), - CandidateSet, SuppressUserConversions); + CandidateSet, SuppressUserConversions, + PartialOverloading); else - AddTemplateOverloadCandidate(FunTmpl, F.getPair(), + AddTemplateOverloadCandidate(FTD, F.getPair(), ExplicitTemplateArgs, Args, - CandidateSet, SuppressUserConversions); + CandidateSet, SuppressUserConversions, + PartialOverloading); } } } @@ -6074,10 +6079,18 @@ if (TemplateDeductionResult Result = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info, PartialOverloading)) { - OverloadCandidate &Candidate = CandidateSet.addCandidate(); + bool ShouldAdd = PartialOverloading && Result == TDK_TooManyArguments; + OverloadCandidate &Candidate = + CandidateSet.addCandidate(ShouldAdd ? Args.size() + 1 : 0); + for (unsigned I = 0; I < Args.size() + 1 && ShouldAdd; ++I) { + // (C++ 13.3.2p2): For the purposes of overload resolution, any + // argument for which there is no corresponding parameter is + // considered to ""match the ellipsis" (C+ 13.3.3.1.3). + Candidate.Conversions[I].setEllipsis(); + } Candidate.FoundDecl = FoundDecl; Candidate.Function = MethodTmpl->getTemplatedDecl(); - Candidate.Viable = PartialOverloading && Result == TDK_TooManyArguments; + Candidate.Viable = ShouldAdd; Candidate.FailureKind = ovl_fail_bad_deduction; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; @@ -6125,7 +6138,15 @@ if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info, PartialOverloading)) { - OverloadCandidate &Candidate = CandidateSet.addCandidate(); + bool ShouldAdd = PartialOverloading && Result == TDK_TooManyArguments; + OverloadCandidate &Candidate = + CandidateSet.addCandidate(ShouldAdd ? Args.size() : 0); + for (unsigned I = 0; I < Args.size() && ShouldAdd; ++I) { + // (C++ 13.3.2p2): For the purposes of overload resolution, any + // argument for which there is no corresponding parameter is + // considered to ""match the ellipsis" (C+ 13.3.3.1.3). + Candidate.Conversions[I].setEllipsis(); + } Candidate.FoundDecl = FoundDecl; Candidate.Function = FunctionTemplate->getTemplatedDecl(); Candidate.Viable = PartialOverloading && Result == TDK_TooManyArguments; @@ -10904,7 +10925,7 @@ OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator); // Add the candidates from the given function set. - AddFunctionCandidates(Fns, ArgsArray, CandidateSet, false); + AddFunctionCandidates(Fns, ArgsArray, CandidateSet); // Add operator candidates that are member functions. AddMemberOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet); @@ -11113,7 +11134,7 @@ OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator); // Add the candidates from the given function set. - AddFunctionCandidates(Fns, Args, CandidateSet, false); + AddFunctionCandidates(Fns, Args, CandidateSet); // Add operator candidates that are member functions. AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet); @@ -12157,8 +12178,8 @@ OverloadCandidateSet CandidateSet(UDSuffixLoc, OverloadCandidateSet::CSK_Normal); - AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, true, - TemplateArgs); + AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, TemplateArgs, + /*SuppressUserConversions=*/true); bool HadMultipleCandidates = (CandidateSet.size() > 1); Index: test/Index/complete-functor-call.cpp =================================================================== --- test/Index/complete-functor-call.cpp +++ test/Index/complete-functor-call.cpp @@ -3,9 +3,10 @@ template struct S { - void operator()(int); - template void operator()(T); - template void operator()(V, T, T); + void operator()(int) const {} + template void operator()(T) const {} + template void operator()(V, T, T) const {} + template const S *operator()(const S &s) const { return &s; } }; int main() { @@ -13,13 +14,14 @@ s(42); s(s); s(0, s, s); + (*S()(S()))(42, 42, 42); s(42,); s(s,); s(0, 42, 42,); } -// RUN: c-index-test -code-completion-at=%s:13:5 %s | FileCheck -check-prefix=CHECK-CC1 %s +// RUN: c-index-test -code-completion-at=%s:14:5 %s | FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{CurrentParameter int}{RightParen )} (1) // CHECK-CC1: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{CurrentParameter T}{RightParen )} (1) // CHECK-CC1: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{CurrentParameter void *}{Comma , }{Text T}{Comma , }{Text T}{RightParen )} (1) @@ -33,7 +35,7 @@ // CHECK-CC1-NEXT: Nested name specifier // CHECK-CC1-NEXT: Objective-C interface -// RUN: c-index-test -code-completion-at=%s:14:5 %s | FileCheck -check-prefix=CHECK-CC2 %s +// RUN: c-index-test -code-completion-at=%s:15:5 %s | FileCheck -check-prefix=CHECK-CC2 %s // CHECK-CC2: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{CurrentParameter int}{RightParen )} (1) // CHECK-CC2: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{CurrentParameter T}{RightParen )} (1) // CHECK-CC2: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{CurrentParameter void *}{Comma , }{Text T}{Comma , }{Text T}{RightParen )} (1) @@ -47,7 +49,7 @@ // CHECK-CC2-NEXT: Nested name specifier // CHECK-CC2-NEXT: Objective-C interface -// RUN: c-index-test -code-completion-at=%s:15:5 %s | FileCheck -check-prefix=CHECK-CC3 %s +// RUN: c-index-test -code-completion-at=%s:16:5 %s | FileCheck -check-prefix=CHECK-CC3 %s // CHECK-CC3: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{CurrentParameter int}{RightParen )} (1) // CHECK-CC3: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{CurrentParameter T}{RightParen )} (1) // CHECK-CC3: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{CurrentParameter void *}{Comma , }{Text T}{Comma , }{Text T}{RightParen )} (1) @@ -61,9 +63,10 @@ // CHECK-CC3-NEXT: Nested name specifier // CHECK-CC3-NEXT: Objective-C interface -// RUN: c-index-test -code-completion-at=%s:15:7 %s | FileCheck -check-prefix=CHECK-CC4 %s -// CHECK-CC4: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text T}{RightParen )} (1) +// RUN: c-index-test -code-completion-at=%s:16:7 %s | FileCheck -check-prefix=CHECK-CC4 %s // CHECK-CC4: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text void *}{Comma , }{CurrentParameter T}{Comma , }{Text T}{RightParen )} (1) +// CHECK-CC4: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text T}{RightParen )} (1) +// CHECK-CC4: NotImplemented:{ResultType const S *}{Text operator()}{LeftParen (}{Text const S &s}{RightParen )} (1) // CHECK-CC4: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text int}{RightParen )} (1) // CHECK-CC4: Completion contexts: // CHECK-CC4-NEXT: Any type @@ -75,9 +78,10 @@ // CHECK-CC4-NEXT: Nested name specifier // CHECK-CC4-NEXT: Objective-C interface -// RUN: c-index-test -code-completion-at=%s:15:10 %s | FileCheck -check-prefix=CHECK-CC5 %s -// CHECK-CC5: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text T}{RightParen )} (1) +// RUN: c-index-test -code-completion-at=%s:16:10 %s | FileCheck -check-prefix=CHECK-CC5 %s // CHECK-CC5: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text void *}{Comma , }{Text S}{Comma , }{CurrentParameter S}{RightParen )} (1) +// CHECK-CC5: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text T}{RightParen )} (1) +// CHECK-CC5: NotImplemented:{ResultType const S *}{Text operator()}{LeftParen (}{Text const S &s}{RightParen )} (1) // CHECK-CC5: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text int}{RightParen )} (1) // CHECK-CC5: Completion contexts: // CHECK-CC5-NEXT: Any type @@ -89,9 +93,11 @@ // CHECK-CC5-NEXT: Nested name specifier // CHECK-CC5-NEXT: Objective-C interface -// RUN: c-index-test -code-completion-at=%s:17:8 %s | FileCheck -check-prefix=CHECK-CC6 %s -// CHECK-CC6: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text T}{RightParen )} (1) -// CHECK-CC6: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text int}{RightParen )} (1) +// RUN: c-index-test -code-completion-at=%s:17:17 %s | FileCheck -check-prefix=CHECK-CC6 %s +// CHECK-CC6: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC6: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{CurrentParameter T}{RightParen )} (1) +// CHECK-CC6: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{CurrentParameter void *}{Comma , }{Text T}{Comma , }{Text T}{RightParen )} (1) +// CHECK-CC6: NotImplemented:{ResultType const S *}{Text operator()}{LeftParen (}{CurrentParameter const S &s}{RightParen )} (1) // CHECK-CC6: Completion contexts: // CHECK-CC6-NEXT: Any type // CHECK-CC6-NEXT: Any value @@ -102,9 +108,11 @@ // CHECK-CC6-NEXT: Nested name specifier // CHECK-CC6-NEXT: Objective-C interface -// RUN: c-index-test -code-completion-at=%s:18:7 %s | FileCheck -check-prefix=CHECK-CC7 %s -// CHECK-CC7: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text T}{RightParen )} (1) -// CHECK-CC7: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text int}{RightParen )} (1) +// RUN: c-index-test -code-completion-at=%s:17:28 %s | FileCheck -check-prefix=CHECK-CC7 %s +// CHECK-CC7: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC7: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{CurrentParameter T}{RightParen )} (1) +// CHECK-CC7: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{CurrentParameter int}{Comma , }{Text T}{Comma , }{Text T}{RightParen )} (1) +// CHECK-CC7: NotImplemented:{ResultType const S *}{Text operator()}{LeftParen (}{CurrentParameter const S &s}{RightParen )} (1) // CHECK-CC7: Completion contexts: // CHECK-CC7-NEXT: Any type // CHECK-CC7-NEXT: Any value @@ -115,9 +123,10 @@ // CHECK-CC7-NEXT: Nested name specifier // CHECK-CC7-NEXT: Objective-C interface -// RUN: c-index-test -code-completion-at=%s:19:15 %s | FileCheck -check-prefix=CHECK-CC8 %s +// RUN: c-index-test -code-completion-at=%s:17:31 %s | FileCheck -check-prefix=CHECK-CC8 %s +// CHECK-CC8: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text int}{Comma , }{CurrentParameter T}{Comma , }{Text T}{RightParen )} (1) // CHECK-CC8: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text T}{RightParen )} (1) -// CHECK-CC8: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text void *}{Comma , }{Text T}{Comma , }{Text T}{RightParen )} (1) +// CHECK-CC8: NotImplemented:{ResultType const S *}{Text operator()}{LeftParen (}{Text const S &s}{RightParen )} (1) // CHECK-CC8: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text int}{RightParen )} (1) // CHECK-CC8: Completion contexts: // CHECK-CC8-NEXT: Any type @@ -128,3 +137,58 @@ // CHECK-CC8-NEXT: Class name // CHECK-CC8-NEXT: Nested name specifier // CHECK-CC8-NEXT: Objective-C interface + +// RUN: c-index-test -code-completion-at=%s:17:35 %s | FileCheck -check-prefix=CHECK-CC9 %s +// CHECK-CC9: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text int}{Comma , }{Text int}{Comma , }{CurrentParameter int}{RightParen )} (1) +// CHECK-CC9: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text T}{RightParen )} (1) +// CHECK-CC9: NotImplemented:{ResultType const S *}{Text operator()}{LeftParen (}{Text const S &s}{RightParen )} (1) +// CHECK-CC9: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text int}{RightParen )} (1) +// CHECK-CC9: Completion contexts: +// CHECK-CC9-NEXT: Any type +// CHECK-CC9-NEXT: Any value +// CHECK-CC9-NEXT: Enum tag +// CHECK-CC9-NEXT: Union tag +// CHECK-CC9-NEXT: Struct tag +// CHECK-CC9-NEXT: Class name +// CHECK-CC9-NEXT: Nested name specifier +// CHECK-CC9-NEXT: Objective-C interface + +// RUN: c-index-test -code-completion-at=%s:19:8 %s | FileCheck -check-prefix=CHECK-CC10 %s +// CHECK-CC10: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text T}{RightParen )} (1) +// CHECK-CC10: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text int}{RightParen )} (1) +// CHECK-CC10: Completion contexts: +// CHECK-CC10-NEXT: Any type +// CHECK-CC10-NEXT: Any value +// CHECK-CC10-NEXT: Enum tag +// CHECK-CC10-NEXT: Union tag +// CHECK-CC10-NEXT: Struct tag +// CHECK-CC10-NEXT: Class name +// CHECK-CC10-NEXT: Nested name specifier +// CHECK-CC10-NEXT: Objective-C interface + +// RUN: c-index-test -code-completion-at=%s:20:7 %s | FileCheck -check-prefix=CHECK-CC11 %s +// CHECK-CC11: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text T}{RightParen )} (1) +// CHECK-CC11: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text int}{RightParen )} (1) +// CHECK-CC11: Completion contexts: +// CHECK-CC11-NEXT: Any type +// CHECK-CC11-NEXT: Any value +// CHECK-CC11-NEXT: Enum tag +// CHECK-CC11-NEXT: Union tag +// CHECK-CC11-NEXT: Struct tag +// CHECK-CC11-NEXT: Class name +// CHECK-CC11-NEXT: Nested name specifier +// CHECK-CC11-NEXT: Objective-C interface + +// RUN: c-index-test -code-completion-at=%s:21:15 %s | FileCheck -check-prefix=CHECK-CC12 %s +// CHECK-CC12: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text T}{RightParen )} (1) +// CHECK-CC12: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text void *}{Comma , }{Text T}{Comma , }{Text T}{RightParen )} (1) +// CHECK-CC12: NotImplemented:{ResultType void}{Text operator()}{LeftParen (}{Text int}{RightParen )} (1) +// CHECK-CC12: Completion contexts: +// CHECK-CC12-NEXT: Any type +// CHECK-CC12-NEXT: Any value +// CHECK-CC12-NEXT: Enum tag +// CHECK-CC12-NEXT: Union tag +// CHECK-CC12-NEXT: Struct tag +// CHECK-CC12-NEXT: Class name +// CHECK-CC12-NEXT: Nested name specifier +// CHECK-CC12-NEXT: Objective-C interface