kadircet updated this revision to Diff 285116.
kadircet added a comment.
- Add tests into clang-lit
- Make sure current number of args is less than overloads param count.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D85826/new/
https://reviews.llvm.org/D85826
Files:
clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
clang/lib/Sema/SemaCodeComplete.cpp
clang/test/CodeCompletion/call.cpp
Index: clang/test/CodeCompletion/call.cpp
===================================================================
--- clang/test/CodeCompletion/call.cpp
+++ clang/test/CodeCompletion/call.cpp
@@ -32,3 +32,17 @@
// CHECK-CC3-NEXT: OVERLOAD: [#void#]f(<#int i#>, int j, int k)
// CHECK-CC3-NEXT: OVERLOAD: [#void#]f(<#float x#>, float y)
}
+
+template <typename T>
+void foo(T t) {
+ f(t, t, t);
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:38:5 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+ // CHECK-CC4: f()
+ // CHECK-CC4-NEXT: f(<#X#>)
+ // CHECK-CC4-NEXT: f(<#int i#>, int j, int k)
+ // CHECK-CC4-NEXT: f(<#float x#>, float y)
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:38:8 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
+ // CHECK-CC5-NOT: f()
+ // CHECK-CC5: f(int i, <#int j#>, int k)
+ // CHECK-CC5-NEXT: f(float x, <#float y#>)
+}
Index: clang/lib/Sema/SemaCodeComplete.cpp
===================================================================
--- clang/lib/Sema/SemaCodeComplete.cpp
+++ clang/lib/Sema/SemaCodeComplete.cpp
@@ -5562,22 +5562,43 @@
// FIXME: Provide support for variadic template functions.
// Ignore type-dependent call expressions entirely.
- if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
- Expr::hasAnyTypeDependentArguments(Args)) {
+ if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args))
return QualType();
+
+ SmallVector<ResultCandidate, 8> Results;
+
+ Expr *NakedFn = Fn->IgnoreParenCasts();
+ // In presence of dependent args we surface all posible signatures, without
+ // performing any semantic checks on availability. That's to improve user
+ // experience, it is better to see all overloads rather than none.
+ if (Expr::hasAnyTypeDependentArguments(Args)) {
+ auto AddIfArgCountChecks = [&Results, &Args](FunctionDecl *FD) {
+ if (FD->getNumParams() < Args.size())
+ return;
+ Results.push_back(ResultCandidate(FD));
+ };
+ if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) {
+ for (auto *D : ULE->decls())
+ AddIfArgCountChecks(D->getAsFunction());
+ } else if (auto *UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
+ for (auto *D : UME->decls())
+ AddIfArgCountChecks(D->getAsFunction());
+ } else if (auto *ME = dyn_cast<MemberExpr>(NakedFn)) {
+ if (auto *FD = ME->getMemberDecl()->getAsFunction())
+ AddIfArgCountChecks(FD);
+ }
+ // FIXME: handle function pointers and lambdas.
+ return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
}
// Build an overload candidate set based on the functions we find.
SourceLocation Loc = Fn->getExprLoc();
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
- SmallVector<ResultCandidate, 8> Results;
-
- Expr *NakedFn = Fn->IgnoreParenCasts();
- if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
+ if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) {
AddOverloadedCallCandidates(ULE, Args, CandidateSet,
/*PartialOverloading=*/true);
- else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
+ } else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
if (UME->hasExplicitTemplateArgs()) {
UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1166,46 +1166,75 @@
}
TEST(SignatureHelpTest, OpeningParen) {
- llvm::StringLiteral Tests[] = {// Recursive function call.
- R"cpp(
- int foo(int a, int b, int c);
- int main() {
- foo(foo $p^( foo(10, 10, 10), ^ )));
- })cpp",
- // Functional type cast.
- R"cpp(
- struct Foo {
- Foo(int a, int b, int c);
- };
- int main() {
- Foo $p^( 10, ^ );
- })cpp",
- // New expression.
- R"cpp(
- struct Foo {
- Foo(int a, int b, int c);
- };
- int main() {
- new Foo $p^( 10, ^ );
- })cpp",
- // Macro expansion.
- R"cpp(
- int foo(int a, int b, int c);
- #define FOO foo(
-
- int main() {
- // Macro expansions.
- $p^FOO 10, ^ );
- })cpp",
- // Macro arguments.
- R"cpp(
- int foo(int a, int b, int c);
- int main() {
- #define ID(X) X
- // FIXME: figure out why ID(foo (foo(10), )) doesn't work when preserving
- // the recovery expression.
- ID(foo $p^( 10, ^ ))
- })cpp"};
+ llvm::StringLiteral Tests[] = {
+ // Recursive function call.
+ R"cpp(
+ int foo(int a, int b, int c);
+ int main() {
+ foo(foo $p^( foo(10, 10, 10), ^ )));
+ })cpp",
+ // Functional type cast.
+ R"cpp(
+ struct Foo {
+ Foo(int a, int b, int c);
+ };
+ int main() {
+ Foo $p^( 10, ^ );
+ })cpp",
+ // New expression.
+ R"cpp(
+ struct Foo {
+ Foo(int a, int b, int c);
+ };
+ int main() {
+ new Foo $p^( 10, ^ );
+ })cpp",
+ // Macro expansion.
+ R"cpp(
+ int foo(int a, int b, int c);
+ #define FOO foo(
+
+ int main() {
+ // Macro expansions.
+ $p^FOO 10, ^ );
+ })cpp",
+ // Macro arguments.
+ R"cpp(
+ int foo(int a, int b, int c);
+ int main() {
+ #define ID(X) X
+ // FIXME: figure out why ID(foo (foo(10), )) doesn't work when preserving
+ // the recovery expression.
+ ID(foo $p^( 10, ^ ))
+ })cpp",
+ // Dependent args.
+ R"cpp(
+ int foo(int a, int b);
+ template <typename T> void bar(T t) {
+ foo$p^(t, ^t);
+ })cpp",
+ // Dependent args on templated func.
+ R"cpp(
+ template <typename T>
+ int foo(T, T);
+ template <typename T> void bar(T t) {
+ foo$p^(t, ^t);
+ })cpp",
+ // Dependent args on member.
+ R"cpp(
+ struct Foo { int foo(int, int); };
+ template <typename T> void bar(T t) {
+ Foo f;
+ f.foo$p^(t, ^t);
+ })cpp",
+ // Dependent args on templated member.
+ R"cpp(
+ struct Foo { template <typename T> int foo(T, T); };
+ template <typename T> void bar(T t) {
+ Foo f;
+ f.foo$p^(t, ^t);
+ })cpp",
+ };
for (auto Test : Tests) {
Annotations Code(Test);
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits