From: Francisco Lopes da Silva Date: Thu, 22 Jan 2015 21:14:08 +0000 (+0000) Subject: Sema: code completion for pointer and reference to functions. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8f3dd24e4ff099b618beeb1dbc88fda68c1098b4;p=clang Sema: code completion for pointer and reference to functions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@226865 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 3fad2b6b78..add469b97a 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -3896,7 +3896,6 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef Args) { // FIXME: Provide support for highlighting optional parameters. // FIXME: Provide support for variadic template functions. - // FIXME: Provide support for pointers and references to functions. // Ignore type-dependent call expressions entirely. if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) || @@ -3928,30 +3927,13 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef Args) { AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs, /*SuppressUsedConversions=*/false, /*PartialOverloading=*/true); - } else if (auto DC = NakedFn->getType()->getCanonicalTypeInternal() - ->getAsCXXRecordDecl()) { - // If it's a CXXRecordDecl, it may overload the function call operator, - // so we check if it does and add them as candidates. - 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 { - // Lastly we check, as a possibly resolved expression, whether it can be - // converted to a function. 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 (FD) { // We check whether it's a resolved function declaration. if (!getLangOpts().CPlusPlus || !FD->getType()->getAs()) Results.push_back(ResultCandidate(FD)); @@ -3960,6 +3942,34 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef Args) { Args, CandidateSet, /*SuppressUsedConversions=*/false, /*PartialOverloading=*/true); + + } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) { + // If expression's type is CXXRecordDecl, it may overload the function + // call operator, so we check if it does and add them as candidates. + 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 { + // Lastly we check whether expression's type is function pointer or + // function. + QualType T = NakedFn->getType(); + if (!T->getPointeeType().isNull()) + T = T->getPointeeType(); + + if (auto FP = T->getAs()) { + if (!TooManyArguments(FP->getNumParams(), Args.size(), + /*PartialOverloading=*/true)) + Results.push_back(ResultCandidate(FP)); + } else if (auto FT = T->getAs()) + Results.push_back(ResultCandidate(FT)); } } diff --git a/test/Index/complete-pointer-and-reference-to-functions.cpp b/test/Index/complete-pointer-and-reference-to-functions.cpp new file mode 100644 index 0000000000..5d5904ca41 --- /dev/null +++ b/test/Index/complete-pointer-and-reference-to-functions.cpp @@ -0,0 +1,34 @@ +// Note: the run lines follow their respective tests, since line/column +// matter in this test. + +template void (&foo(T))(T); +template void (*bar(T))(T); + +int main() { + foo(42)(42); + bar(42)(42); +} + +// RUN: c-index-test -code-completion-at=%s:8:11 %s | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1: OverloadCandidate:{Text void}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC1: Completion contexts: +// CHECK-CC1-NEXT: Any type +// CHECK-CC1-NEXT: Any value +// CHECK-CC1-NEXT: Enum tag +// CHECK-CC1-NEXT: Union tag +// CHECK-CC1-NEXT: Struct tag +// CHECK-CC1-NEXT: Class name +// CHECK-CC1-NEXT: Nested name specifier +// CHECK-CC1-NEXT: Objective-C interface + +// RUN: c-index-test -code-completion-at=%s:9:11 %s | FileCheck -check-prefix=CHECK-CC2 %s +// CHECK-CC2: OverloadCandidate:{Text void}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC2: Completion contexts: +// CHECK-CC2-NEXT: Any type +// CHECK-CC2-NEXT: Any value +// CHECK-CC2-NEXT: Enum tag +// CHECK-CC2-NEXT: Union tag +// CHECK-CC2-NEXT: Struct tag +// CHECK-CC2-NEXT: Class name +// CHECK-CC2-NEXT: Nested name specifier +// CHECK-CC2-NEXT: Objective-C interface