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
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to