forked from OSchip/llvm-project
Sema: code completion for pointer and reference to functions.
llvm-svn: 226865
This commit is contained in:
parent
799ef37d02
commit
c6ccc4fe91
|
@ -3896,7 +3896,6 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
|
||||||
|
|
||||||
// FIXME: Provide support for highlighting optional parameters.
|
// FIXME: Provide support for highlighting optional parameters.
|
||||||
// FIXME: Provide support for variadic template functions.
|
// FIXME: Provide support for variadic template functions.
|
||||||
// FIXME: Provide support for pointers and references to functions.
|
|
||||||
|
|
||||||
// Ignore type-dependent call expressions entirely.
|
// Ignore type-dependent call expressions entirely.
|
||||||
if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
|
if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
|
||||||
|
@ -3928,30 +3927,13 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
|
||||||
AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
|
AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
|
||||||
/*SuppressUsedConversions=*/false,
|
/*SuppressUsedConversions=*/false,
|
||||||
/*PartialOverloading=*/true);
|
/*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<Expr *, 12> ArgExprs(1, NakedFn);
|
|
||||||
ArgExprs.append(Args.begin(), Args.end());
|
|
||||||
AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
|
|
||||||
/*ExplicitArgs=*/nullptr,
|
|
||||||
/*SuppressUsedConversions=*/false,
|
|
||||||
/*PartialOverloading=*/true);
|
|
||||||
} else {
|
} else {
|
||||||
// Lastly we check, as a possibly resolved expression, whether it can be
|
|
||||||
// converted to a function.
|
|
||||||
FunctionDecl *FD = nullptr;
|
FunctionDecl *FD = nullptr;
|
||||||
if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
|
if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
|
||||||
FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
|
FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
|
||||||
else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
|
else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
|
||||||
FD = dyn_cast<FunctionDecl>(DRE->getDecl());
|
FD = dyn_cast<FunctionDecl>(DRE->getDecl());
|
||||||
if (FD) {
|
if (FD) { // We check whether it's a resolved function declaration.
|
||||||
if (!getLangOpts().CPlusPlus ||
|
if (!getLangOpts().CPlusPlus ||
|
||||||
!FD->getType()->getAs<FunctionProtoType>())
|
!FD->getType()->getAs<FunctionProtoType>())
|
||||||
Results.push_back(ResultCandidate(FD));
|
Results.push_back(ResultCandidate(FD));
|
||||||
|
@ -3960,6 +3942,34 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
|
||||||
Args, CandidateSet,
|
Args, CandidateSet,
|
||||||
/*SuppressUsedConversions=*/false,
|
/*SuppressUsedConversions=*/false,
|
||||||
/*PartialOverloading=*/true);
|
/*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<Expr *, 12> 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<FunctionProtoType>()) {
|
||||||
|
if (!TooManyArguments(FP->getNumParams(), Args.size(),
|
||||||
|
/*PartialOverloading=*/true))
|
||||||
|
Results.push_back(ResultCandidate(FP));
|
||||||
|
} else if (auto FT = T->getAs<FunctionType>())
|
||||||
|
Results.push_back(ResultCandidate(FT));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
// Note: the run lines follow their respective tests, since line/column
|
||||||
|
// matter in this test.
|
||||||
|
|
||||||
|
template<class T> void (&foo(T))(T);
|
||||||
|
template<class T> 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
|
Loading…
Reference in New Issue