summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorKirill Bobyrev <kbobyrev@google.com>2019-11-22 12:48:06 +0100
committerKirill Bobyrev <kbobyrev@google.com>2019-11-22 12:48:06 +0100
commit7f0dcf665dd22be296805bc7a1c71a36243c4e09 (patch)
treee7587448ef2ab88b426493594a12b50051d8097a /clang
parent0b0dca9f6fe34333abdb437bd1d3d92c8362a2e6 (diff)
downloadbcm5719-llvm-7f0dcf665dd22be296805bc7a1c71a36243c4e09.tar.gz
bcm5719-llvm-7f0dcf665dd22be296805bc7a1c71a36243c4e09.zip
[clangd] Show lambda signature for lambda autocompletions
The original bug report can be found [here](https://github.com/clangd/clangd/issues/85) Given the following code: ```c++ void function() { auto Lambda = [](int a, double &b) {return 1.f;}; La^ } ``` Triggering the completion at `^` would show `(lambda)` before this patch and would show signature `(int a, double &b) const`, build a snippet etc with this patch. Reviewers: sammccall Reviewed by: sammccall Differential revision: https://reviews.llvm.org/D70445
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Sema/SemaCodeComplete.cpp30
-rw-r--r--clang/test/CodeCompletion/function-templates.cpp14
-rw-r--r--clang/test/CodeCompletion/lambdas.cpp12
3 files changed, 48 insertions, 8 deletions
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 81eed4330cd..e75aca4d81e 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -3315,6 +3315,18 @@ CodeCompletionResult::createCodeCompletionStringForOverride(
return Result.TakeString();
}
+// FIXME: Right now this works well with lambdas. Add support for other functor
+// types like std::function.
+static const NamedDecl *extractFunctorCallOperator(const NamedDecl *ND) {
+ const auto *VD = dyn_cast<VarDecl>(ND);
+ if (!VD)
+ return nullptr;
+ const auto *RecordDecl = VD->getType()->getAsCXXRecordDecl();
+ if (!RecordDecl || !RecordDecl->isLambda())
+ return nullptr;
+ return RecordDecl->getLambdaCallOperator();
+}
+
CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
bool IncludeBriefComments, const CodeCompletionContext &CCContext,
@@ -3339,9 +3351,8 @@ CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
for (const auto *I : ND->specific_attrs<AnnotateAttr>())
Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
- AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
-
- if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
+ auto AddFunctionTypeAndResult = [&](const FunctionDecl *Function) {
+ AddResultTypeChunk(Ctx, Policy, Function, CCContext.getBaseType(), Result);
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
AddTypedNameChunk(Ctx, Policy, ND, Result);
@@ -3349,9 +3360,21 @@ CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
AddFunctionParameterChunks(PP, Policy, Function, Result);
Result.AddChunk(CodeCompletionString::CK_RightParen);
AddFunctionTypeQualsToCompletionString(Result, Function);
+ };
+
+ if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
+ AddFunctionTypeAndResult(Function);
+ return Result.TakeString();
+ }
+
+ if (const auto *CallOperator =
+ dyn_cast_or_null<FunctionDecl>(extractFunctorCallOperator(ND))) {
+ AddFunctionTypeAndResult(CallOperator);
return Result.TakeString();
}
+ AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
+
if (const FunctionTemplateDecl *FunTmpl =
dyn_cast<FunctionTemplateDecl>(ND)) {
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
@@ -3417,6 +3440,7 @@ CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
Result.AddChunk(CodeCompletionString::CK_RightAngle);
return Result.TakeString();
}
+
if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Selector Sel = Method->getSelector();
if (Sel.isUnarySelector()) {
diff --git a/clang/test/CodeCompletion/function-templates.cpp b/clang/test/CodeCompletion/function-templates.cpp
index cdbbf75838e..e7123a33133 100644
--- a/clang/test/CodeCompletion/function-templates.cpp
+++ b/clang/test/CodeCompletion/function-templates.cpp
@@ -1,7 +1,7 @@
namespace std {
template<typename RandomAccessIterator>
void sort(RandomAccessIterator first, RandomAccessIterator last);
-
+
template<class X, class Y>
X* dyn_cast(Y *Val);
}
@@ -11,13 +11,17 @@ public:
template<typename T> T &getAs();
};
+template <typename T, typename U, typename V>
+V doSomething(T t, const U &u, V *v) { return V(); }
+
void f() {
std::sort(1, 2);
Foo().getAs<int>();
- // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:15:8 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:18:8 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: dyn_cast<<#class X#>>(<#Y *Val#>)
// CHECK-CC1: sort(<#RandomAccessIterator first#>, <#RandomAccessIterator last#>
- // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:16:9 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:19:9 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: getAs<<#typename T#>>()
-)
-
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:19:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+ // CHECK-CC3: [#V#]doSomething(<#T t#>, <#const U &u#>, <#V *v#>)
+}
diff --git a/clang/test/CodeCompletion/lambdas.cpp b/clang/test/CodeCompletion/lambdas.cpp
index 05c47b8c2a4..3e431a330f4 100644
--- a/clang/test/CodeCompletion/lambdas.cpp
+++ b/clang/test/CodeCompletion/lambdas.cpp
@@ -60,3 +60,15 @@ void test5() {
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:57:24 %s -o - | FileCheck -check-prefix=CHECK-8 %s
// CHECK-8-NOT: COMPLETION: Pattern : [<#=
}
+
+void test6() {
+ auto my_lambda = [&](int a, double &b) { return 1.f; };
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:65:58 %s -o - | FileCheck -check-prefix=CHECK-9 %s
+ // CHECK-9: [#float#]my_lambda(<#int a#>, <#double &b#>)[# const#]
+}
+
+void test7() {
+ auto generic_lambda = [&](auto a, const auto &b) { return a + b; };
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:71:70 %s -o - | FileCheck -check-prefix=CHECK-10 %s
+ // CHECK-10: [#auto#]generic_lambda(<#auto a#>, <#const auto &b#>)[# const#]
+}
OpenPOWER on IntegriCloud