[clang] [clang-tools-extra] [clangd] show lambda name instead of operator() in signature help (PR #101857)
Timothy Akintilo via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 11 18:28:15 PDT 2024
https://github.com/tilobyte updated https://github.com/llvm/llvm-project/pull/101857
>From c1afe853ccacae1605fecfe552bb9a263c6b8c1d Mon Sep 17 00:00:00 2001
From: Timothy Akintilo <timtobi1 at gmail.com>
Date: Sat, 27 Jul 2024 16:17:46 -0500
Subject: [PATCH 1/9] use lambda name instead of operator()
---
clang-tools-extra/clangd/CodeComplete.cpp | 2 ++
.../clangd/unittests/CodeCompleteTests.cpp | 9 +++++++
.../include/clang/Sema/CodeCompleteConsumer.h | 18 ++++++++++++++
clang/include/clang/Sema/Overload.h | 5 ++++
clang/include/clang/Sema/Sema.h | 22 ++++++++---------
clang/lib/Sema/CodeCompleteConsumer.cpp | 10 +++++++-
clang/lib/Sema/SemaCodeComplete.cpp | 17 ++++++++++---
clang/lib/Sema/SemaLookup.cpp | 3 ++-
clang/lib/Sema/SemaOverload.cpp | 24 +++++++++----------
9 files changed, 82 insertions(+), 28 deletions(-)
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index 89eee392837af4..4f8a53aa7aae7e 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -1139,6 +1139,8 @@ class SignatureHelpCollector final : public CodeCompleteConsumer {
switch (K) {
case OC::CK_Aggregate:
return 0;
+ case OC::CK_Lambda:
+ [[fallthrough]];
case OC::CK_Function:
return 1;
case OC::CK_FunctionType:
diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index 96d1ee1f0add73..4f748168d75aa7 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1437,6 +1437,15 @@ TEST(SignatureHelpTest, Overloads) {
EXPECT_EQ(0, Results.activeParameter);
}
+TEST(SignatureHelpTest, ShowLambdaNameInsteadOfOperatorParens) {
+ auto const Results = signatures(R"cpp(
+ auto foo = [](int x, int y){};
+ int main() { foo(^); }
+ )cpp");
+ EXPECT_THAT(Results.signatures,
+ UnorderedElementsAre(sig("foo([[int x]], [[int y]]) -> void")));
+}
+
TEST(SignatureHelpTest, FunctionPointers) {
llvm::StringLiteral Tests[] = {
// Variable of function pointer type
diff --git a/clang/include/clang/Sema/CodeCompleteConsumer.h b/clang/include/clang/Sema/CodeCompleteConsumer.h
index 0924dc27af82b5..a6530c3c93d912 100644
--- a/clang/include/clang/Sema/CodeCompleteConsumer.h
+++ b/clang/include/clang/Sema/CodeCompleteConsumer.h
@@ -1028,6 +1028,9 @@ class CodeCompleteConsumer {
/// The candidate is a function declaration.
CK_Function,
+ // The candidate is a lambda operator().
+ CK_Lambda,
+
/// The candidate is a function template, arguments are being completed.
CK_FunctionTemplate,
@@ -1055,6 +1058,13 @@ class CodeCompleteConsumer {
/// Kind == CK_Function.
FunctionDecl *Function;
+ /// The lambda operator() candidate paired with the
+ /// lambda variable, available when Kind == CK_Lambda.
+ struct {
+ FunctionDecl *OperatorParens;
+ VarDecl *Var;
+ } Lambda;
+
/// The function template overload candidate, available when
/// Kind == CK_FunctionTemplate.
FunctionTemplateDecl *FunctionTemplate;
@@ -1082,6 +1092,12 @@ class CodeCompleteConsumer {
assert(Function != nullptr);
}
+ OverloadCandidate(FunctionDecl *LambdaOperatorParens, VarDecl *LambdaVar)
+ : Kind(CK_Lambda), Lambda{LambdaOperatorParens, LambdaVar} {
+ assert(Lambda.OperatorParens != nullptr);
+ assert(Lambda.Var != nullptr);
+ }
+
OverloadCandidate(FunctionTemplateDecl *FunctionTemplateDecl)
: Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplateDecl) {
assert(FunctionTemplateDecl != nullptr);
@@ -1112,6 +1128,8 @@ class CodeCompleteConsumer {
/// function declaration for a function template.
FunctionDecl *getFunction() const;
+ VarDecl *getLambdaVarDecl() const;
+
/// Retrieve the function template overload candidate.
FunctionTemplateDecl *getFunctionTemplate() const {
assert(getKind() == CK_FunctionTemplate && "Not a function template");
diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h
index d6a6cee62a7528..7c4e82f07de02e 100644
--- a/clang/include/clang/Sema/Overload.h
+++ b/clang/include/clang/Sema/Overload.h
@@ -876,6 +876,11 @@ class Sema;
/// function pointer or reference (C++ [over.call.object]).
FunctionDecl *Function;
+ /// LambdaName - When the OverloadCandidate is for a
+ /// lambda's operator(), points to the declaration of
+ /// the lambda variable.
+ VarDecl *LambdaName{nullptr};
+
/// FoundDecl - The original declaration that was looked up /
/// invented / otherwise found, together with its access.
/// Might be a UsingShadowDecl or a FunctionTemplateDecl.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 2ec6367eccea01..2cf1827c2d8585 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9147,7 +9147,8 @@ class Sema final : public SemaBase {
///
/// \returns true if lookup succeeded, false if it failed.
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
- bool InUnqualifiedLookup = false);
+ bool InUnqualifiedLookup = false,
+ IdentifierInfo const *IdentifierOverride = nullptr);
/// Performs qualified name lookup or special type of lookup for
/// "__super::" scope specifier.
@@ -10186,7 +10187,7 @@ class Sema final : public SemaBase {
OverloadCandidateSet &CandidateSet,
TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
bool SuppressUserConversions = false, bool PartialOverloading = false,
- bool FirstArgumentIsBase = false);
+ bool FirstArgumentIsBase = false, VarDecl *LambdaName = nullptr);
/// AddMethodCandidate - Adds a named decl (which is some kind of
/// method) as a method candidate to the given overload set.
@@ -10204,15 +10205,14 @@ class Sema final : public SemaBase {
/// both @c a1 and @c a2. If @p SuppressUserConversions, then don't
/// allow user-defined conversions via constructors or conversion
/// operators.
- void
- AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingContext, QualType ObjectType,
- Expr::Classification ObjectClassification,
- ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet,
- bool SuppressUserConversions = false,
- bool PartialOverloading = false,
- ConversionSequenceList EarlyConversions = std::nullopt,
- OverloadCandidateParamOrder PO = {});
+ void AddMethodCandidate(
+ CXXMethodDecl *Method, DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext, QualType ObjectType,
+ Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
+ bool PartialOverloading = false,
+ ConversionSequenceList EarlyConversions = std::nullopt,
+ OverloadCandidateParamOrder PO = {}, VarDecl *LambdaName = nullptr);
/// Add a C++ member function template as a candidate to the candidate
/// set, using template argument deduction to produce an appropriate member
diff --git a/clang/lib/Sema/CodeCompleteConsumer.cpp b/clang/lib/Sema/CodeCompleteConsumer.cpp
index 91713d71786ee5..c2cb966bff3aff 100644
--- a/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -504,15 +504,23 @@ FunctionDecl *CodeCompleteConsumer::OverloadCandidate::getFunction() const {
return Function;
else if (getKind() == CK_FunctionTemplate)
return FunctionTemplate->getTemplatedDecl();
- else
+ else if (getKind() == CK_Lambda) {
+ return Lambda.OperatorParens;
+ } else
return nullptr;
}
+VarDecl *CodeCompleteConsumer::OverloadCandidate::getLambdaVarDecl() const {
+ return (getKind() == CK_Lambda) ? Lambda.Var : nullptr;
+}
+
const FunctionType *
CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
switch (Kind) {
case CK_Function:
return Function->getType()->getAs<FunctionType>();
+ case CK_Lambda:
+ return Lambda.OperatorParens->getType()->getAs<FunctionType>();
case CK_FunctionTemplate:
return FunctionTemplate->getTemplatedDecl()
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 88d4732c7d5c6a..2bdd1924613586 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -4022,7 +4022,10 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
std::string Name;
llvm::raw_string_ostream OS(Name);
- FDecl->getDeclName().print(OS, Policy);
+ auto const DeclName = (getKind() == CK_Lambda)
+ ? getLambdaVarDecl()->getDeclName()
+ : FDecl->getDeclName();
+ DeclName.print(OS, Policy);
Result.AddTextChunk(Result.getAllocator().CopyString(Name));
} else {
// Function without a declaration. Just give the return type.
@@ -6123,7 +6126,10 @@ static void mergeCandidatesWithResults(
continue;
}
if (Candidate.Viable)
- Results.push_back(ResultCandidate(Candidate.Function));
+ Results.push_back(
+ Candidate.LambdaName == nullptr
+ ? ResultCandidate(Candidate.Function)
+ : ResultCandidate(Candidate.Function, Candidate.LambdaName));
}
}
@@ -6292,11 +6298,16 @@ SemaCodeCompletion::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args,
SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
ArgExprs.append(ArgsWithoutDependentTypes.begin(),
ArgsWithoutDependentTypes.end());
+ auto *const LambdaName =
+ DC->isLambda() ? cast<VarDecl>(NakedFn->getReferencedDeclOfCallee())
+ : nullptr;
SemaRef.AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs,
CandidateSet,
/*ExplicitArgs=*/nullptr,
/*SuppressUserConversions=*/false,
- /*PartialOverloading=*/true);
+ /*PartialOverloading=*/true,
+ /*FirstArgumentIsBase=*/false,
+ /*LambdaName=*/LambdaName);
}
} else {
// Lastly we check whether expression's type is function pointer or
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 7a6a64529f52ec..1262950ab43f62 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -2390,7 +2390,8 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
}
bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
- bool InUnqualifiedLookup) {
+ bool InUnqualifiedLookup,
+ IdentifierInfo const *IdentifierOverride) {
assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context");
if (!R.getLookupName())
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index c5f56ac62b458c..bfae0216d4c32f 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -7295,7 +7295,8 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
TemplateArgumentListInfo *ExplicitTemplateArgs,
bool SuppressUserConversions,
bool PartialOverloading,
- bool FirstArgumentIsBase) {
+ bool FirstArgumentIsBase,
+ VarDecl *LambdaName) {
for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
NamedDecl *D = F.getDecl()->getUnderlyingDecl();
ArrayRef<Expr *> FunctionArgs = Args;
@@ -7331,7 +7332,8 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
ObjectClassification, FunctionArgs, CandidateSet,
- SuppressUserConversions, PartialOverloading);
+ SuppressUserConversions, PartialOverloading,
+ std::nullopt, {}, LambdaName);
}
} else {
// This branch handles both standalone functions and static methods.
@@ -7383,16 +7385,13 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType,
}
}
-void
-Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingContext, QualType ObjectType,
- Expr::Classification ObjectClassification,
- ArrayRef<Expr *> Args,
- OverloadCandidateSet &CandidateSet,
- bool SuppressUserConversions,
- bool PartialOverloading,
- ConversionSequenceList EarlyConversions,
- OverloadCandidateParamOrder PO) {
+void Sema::AddMethodCandidate(
+ CXXMethodDecl *Method, DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext, QualType ObjectType,
+ Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
+ bool PartialOverloading, ConversionSequenceList EarlyConversions,
+ OverloadCandidateParamOrder PO, VarDecl *LambdaName) {
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
assert(Proto && "Methods without a prototype cannot be overloaded");
@@ -7418,6 +7417,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
CandidateSet.addCandidate(Args.size() + 1, EarlyConversions);
Candidate.FoundDecl = FoundDecl;
Candidate.Function = Method;
+ Candidate.LambdaName = LambdaName;
Candidate.RewriteKind =
CandidateSet.getRewriteInfo().getRewriteKind(Method, PO);
Candidate.TookAddressOfOverload =
>From 99c1b280dfc50d6219ae4645c99dd61717238832 Mon Sep 17 00:00:00 2001
From: Timothy Akintilo <timtobi1 at gmail.com>
Date: Sun, 11 Aug 2024 13:02:10 -0500
Subject: [PATCH 2/9] rename OperatorParens -> CallOperator
---
clang/include/clang/Sema/CodeCompleteConsumer.h | 8 ++++----
clang/lib/Sema/CodeCompleteConsumer.cpp | 4 ++--
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang/include/clang/Sema/CodeCompleteConsumer.h b/clang/include/clang/Sema/CodeCompleteConsumer.h
index a6530c3c93d912..d592fd9860ec34 100644
--- a/clang/include/clang/Sema/CodeCompleteConsumer.h
+++ b/clang/include/clang/Sema/CodeCompleteConsumer.h
@@ -1061,7 +1061,7 @@ class CodeCompleteConsumer {
/// The lambda operator() candidate paired with the
/// lambda variable, available when Kind == CK_Lambda.
struct {
- FunctionDecl *OperatorParens;
+ FunctionDecl *CallOperator;
VarDecl *Var;
} Lambda;
@@ -1092,9 +1092,9 @@ class CodeCompleteConsumer {
assert(Function != nullptr);
}
- OverloadCandidate(FunctionDecl *LambdaOperatorParens, VarDecl *LambdaVar)
- : Kind(CK_Lambda), Lambda{LambdaOperatorParens, LambdaVar} {
- assert(Lambda.OperatorParens != nullptr);
+ OverloadCandidate(FunctionDecl *LambdaCallOperator, VarDecl *LambdaVar)
+ : Kind(CK_Lambda), Lambda{LambdaCallOperator, LambdaVar} {
+ assert(Lambda.CallOperator != nullptr);
assert(Lambda.Var != nullptr);
}
diff --git a/clang/lib/Sema/CodeCompleteConsumer.cpp b/clang/lib/Sema/CodeCompleteConsumer.cpp
index c2cb966bff3aff..aac56e8dc68101 100644
--- a/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -505,7 +505,7 @@ FunctionDecl *CodeCompleteConsumer::OverloadCandidate::getFunction() const {
else if (getKind() == CK_FunctionTemplate)
return FunctionTemplate->getTemplatedDecl();
else if (getKind() == CK_Lambda) {
- return Lambda.OperatorParens;
+ return Lambda.CallOperator;
} else
return nullptr;
}
@@ -520,7 +520,7 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
case CK_Function:
return Function->getType()->getAs<FunctionType>();
case CK_Lambda:
- return Lambda.OperatorParens->getType()->getAs<FunctionType>();
+ return Lambda.CallOperator->getType()->getAs<FunctionType>();
case CK_FunctionTemplate:
return FunctionTemplate->getTemplatedDecl()
>From 65b11f7cd91f051653aedd980504b980718b388a Mon Sep 17 00:00:00 2001
From: Timothy Akintilo <3729883+tilobyte at users.noreply.github.com>
Date: Sat, 7 Sep 2024 15:04:14 -0500
Subject: [PATCH 3/9] remove [[fallthrough]]
Co-authored-by: Younan Zhang <zyn7109 at gmail.com>
---
clang-tools-extra/clangd/CodeComplete.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index 4f8a53aa7aae7e..7b068951119739 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -1140,7 +1140,6 @@ class SignatureHelpCollector final : public CodeCompleteConsumer {
case OC::CK_Aggregate:
return 0;
case OC::CK_Lambda:
- [[fallthrough]];
case OC::CK_Function:
return 1;
case OC::CK_FunctionType:
>From 56c2d38fcd46f3f4179433073ebb4812b6b884c9 Mon Sep 17 00:00:00 2001
From: Timothy Akintilo <timtobi1 at gmail.com>
Date: Sat, 7 Sep 2024 20:03:05 -0500
Subject: [PATCH 4/9] remove unnecessary IdentifierOverride
---
clang/include/clang/Sema/Sema.h | 3 +--
clang/lib/Sema/SemaLookup.cpp | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 2cf1827c2d8585..3c50f9324fc3ac 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9147,8 +9147,7 @@ class Sema final : public SemaBase {
///
/// \returns true if lookup succeeded, false if it failed.
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
- bool InUnqualifiedLookup = false,
- IdentifierInfo const *IdentifierOverride = nullptr);
+ bool InUnqualifiedLookup = false);
/// Performs qualified name lookup or special type of lookup for
/// "__super::" scope specifier.
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 1262950ab43f62..7a6a64529f52ec 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -2390,8 +2390,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
}
bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
- bool InUnqualifiedLookup,
- IdentifierInfo const *IdentifierOverride) {
+ bool InUnqualifiedLookup) {
assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context");
if (!R.getLookupName())
>From b2d865325b22aa5f5223fafcafb833e924c1a6b3 Mon Sep 17 00:00:00 2001
From: Timothy Akintilo <timtobi1 at gmail.com>
Date: Sun, 8 Sep 2024 20:12:27 -0500
Subject: [PATCH 5/9] add tests for lambda returned from function and
immediately-invoked lambda
---
.../clangd/unittests/CodeCompleteTests.cpp | 21 ++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index 4f748168d75aa7..9e9792f074d2e7 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1438,7 +1438,7 @@ TEST(SignatureHelpTest, Overloads) {
}
TEST(SignatureHelpTest, ShowLambdaNameInsteadOfOperatorParens) {
- auto const Results = signatures(R"cpp(
+ const auto Results = signatures(R"cpp(
auto foo = [](int x, int y){};
int main() { foo(^); }
)cpp");
@@ -1446,6 +1446,25 @@ TEST(SignatureHelpTest, ShowLambdaNameInsteadOfOperatorParens) {
UnorderedElementsAre(sig("foo([[int x]], [[int y]]) -> void")));
}
+TEST(SignatureHelpTest, ShowOperatorParensForImmediatelyInvokedLambda) {
+ const auto Results = signatures(R"cpp(
+ auto foo = [](int x, int y){}(^);
+ )cpp");
+ EXPECT_THAT(Results.signatures,
+ UnorderedElementsAre(sig("operator()([[int x]], [[int y]]) -> void")));
+}
+
+TEST(SignatureHelpTest, ShowOperatorParensForLambdaReturnedFromFunction) {
+ const auto Results = signatures(R"cpp(
+ auto returnsLambda() {
+ return [](int x, int y){};
+ }
+ int main() { returnsLambda()(^); }
+ )cpp");
+ EXPECT_THAT(Results.signatures,
+ UnorderedElementsAre(sig("operator()([[int x]], [[int y]]) -> void")));
+}
+
TEST(SignatureHelpTest, FunctionPointers) {
llvm::StringLiteral Tests[] = {
// Variable of function pointer type
>From 197845663959309123729fc5b573a63922347114 Mon Sep 17 00:00:00 2001
From: Timothy Akintilo <timtobi1 at gmail.com>
Date: Sun, 8 Sep 2024 20:29:09 -0500
Subject: [PATCH 6/9] get LambdaName using dyn_cast_if_present
---
clang/lib/Sema/SemaCodeComplete.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 2bdd1924613586..56745c01b19360 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6299,7 +6299,7 @@ SemaCodeCompletion::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args,
ArgExprs.append(ArgsWithoutDependentTypes.begin(),
ArgsWithoutDependentTypes.end());
auto *const LambdaName =
- DC->isLambda() ? cast<VarDecl>(NakedFn->getReferencedDeclOfCallee())
+ DC->isLambda() ? dyn_cast_if_present<VarDecl>(NakedFn->getReferencedDeclOfCallee())
: nullptr;
SemaRef.AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs,
CandidateSet,
>From d8140f9013f47094a159fd2918128d9252ca3280 Mon Sep 17 00:00:00 2001
From: Timothy Akintilo <timtobi1 at gmail.com>
Date: Sun, 8 Sep 2024 20:40:58 -0500
Subject: [PATCH 7/9] rename LambdaName -> LambdaDecl
---
clang/include/clang/Sema/Overload.h | 4 ++--
clang/include/clang/Sema/Sema.h | 4 ++--
clang/lib/Sema/SemaCodeComplete.cpp | 8 ++++----
clang/lib/Sema/SemaOverload.cpp | 8 ++++----
4 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h
index 7c4e82f07de02e..e1bac1876817fa 100644
--- a/clang/include/clang/Sema/Overload.h
+++ b/clang/include/clang/Sema/Overload.h
@@ -876,10 +876,10 @@ class Sema;
/// function pointer or reference (C++ [over.call.object]).
FunctionDecl *Function;
- /// LambdaName - When the OverloadCandidate is for a
+ /// LambdaDecl - When the OverloadCandidate is for a
/// lambda's operator(), points to the declaration of
/// the lambda variable.
- VarDecl *LambdaName{nullptr};
+ VarDecl *LambdaDecl{nullptr};
/// FoundDecl - The original declaration that was looked up /
/// invented / otherwise found, together with its access.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 3c50f9324fc3ac..5f1217c9de3e4e 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10186,7 +10186,7 @@ class Sema final : public SemaBase {
OverloadCandidateSet &CandidateSet,
TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
bool SuppressUserConversions = false, bool PartialOverloading = false,
- bool FirstArgumentIsBase = false, VarDecl *LambdaName = nullptr);
+ bool FirstArgumentIsBase = false, VarDecl *LambdaDecl = nullptr);
/// AddMethodCandidate - Adds a named decl (which is some kind of
/// method) as a method candidate to the given overload set.
@@ -10211,7 +10211,7 @@ class Sema final : public SemaBase {
OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
bool PartialOverloading = false,
ConversionSequenceList EarlyConversions = std::nullopt,
- OverloadCandidateParamOrder PO = {}, VarDecl *LambdaName = nullptr);
+ OverloadCandidateParamOrder PO = {}, VarDecl *LambdaDecl = nullptr);
/// Add a C++ member function template as a candidate to the candidate
/// set, using template argument deduction to produce an appropriate member
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 56745c01b19360..36a98a6ec06445 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6127,9 +6127,9 @@ static void mergeCandidatesWithResults(
}
if (Candidate.Viable)
Results.push_back(
- Candidate.LambdaName == nullptr
+ Candidate.LambdaDecl == nullptr
? ResultCandidate(Candidate.Function)
- : ResultCandidate(Candidate.Function, Candidate.LambdaName));
+ : ResultCandidate(Candidate.Function, Candidate.LambdaDecl));
}
}
@@ -6298,7 +6298,7 @@ SemaCodeCompletion::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args,
SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
ArgExprs.append(ArgsWithoutDependentTypes.begin(),
ArgsWithoutDependentTypes.end());
- auto *const LambdaName =
+ auto *const LambdaDecl =
DC->isLambda() ? dyn_cast_if_present<VarDecl>(NakedFn->getReferencedDeclOfCallee())
: nullptr;
SemaRef.AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs,
@@ -6307,7 +6307,7 @@ SemaCodeCompletion::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args,
/*SuppressUserConversions=*/false,
/*PartialOverloading=*/true,
/*FirstArgumentIsBase=*/false,
- /*LambdaName=*/LambdaName);
+ /*LambdaDecl=*/LambdaDecl);
}
} else {
// Lastly we check whether expression's type is function pointer or
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index bfae0216d4c32f..6d1f29fea7d46b 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -7296,7 +7296,7 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
bool SuppressUserConversions,
bool PartialOverloading,
bool FirstArgumentIsBase,
- VarDecl *LambdaName) {
+ VarDecl *LambdaDecl) {
for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
NamedDecl *D = F.getDecl()->getUnderlyingDecl();
ArrayRef<Expr *> FunctionArgs = Args;
@@ -7333,7 +7333,7 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
ObjectClassification, FunctionArgs, CandidateSet,
SuppressUserConversions, PartialOverloading,
- std::nullopt, {}, LambdaName);
+ std::nullopt, {}, LambdaDecl);
}
} else {
// This branch handles both standalone functions and static methods.
@@ -7391,7 +7391,7 @@ void Sema::AddMethodCandidate(
Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
bool PartialOverloading, ConversionSequenceList EarlyConversions,
- OverloadCandidateParamOrder PO, VarDecl *LambdaName) {
+ OverloadCandidateParamOrder PO, VarDecl *LambdaDecl) {
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
assert(Proto && "Methods without a prototype cannot be overloaded");
@@ -7417,7 +7417,7 @@ void Sema::AddMethodCandidate(
CandidateSet.addCandidate(Args.size() + 1, EarlyConversions);
Candidate.FoundDecl = FoundDecl;
Candidate.Function = Method;
- Candidate.LambdaName = LambdaName;
+ Candidate.LambdaDecl = LambdaDecl;
Candidate.RewriteKind =
CandidateSet.getRewriteInfo().getRewriteKind(Method, PO);
Candidate.TookAddressOfOverload =
>From c6e12d02d8735009e7b968275cfcc624d36a9c02 Mon Sep 17 00:00:00 2001
From: Timothy Akintilo <timtobi1 at gmail.com>
Date: Wed, 11 Sep 2024 20:23:59 -0500
Subject: [PATCH 8/9] add test for lambda in parameter pack
---
.../clangd/unittests/CodeCompleteTests.cpp | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index 9e9792f074d2e7..a1317d413c6a76 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1465,6 +1465,17 @@ TEST(SignatureHelpTest, ShowOperatorParensForLambdaReturnedFromFunction) {
UnorderedElementsAre(sig("operator()([[int x]], [[int y]]) -> void")));
}
+TEST(SignatureHelpTest, ShowOperatorParensForLambdaInParameterPack) {
+ const auto Results = signatures(R"cpp(
+ template <typename... Types>
+ auto foo(Types... args) {}
+
+ foo([](int x, int y){}(^))
+ )cpp");
+ EXPECT_THAT(Results.signatures,
+ UnorderedElementsAre(sig("operator()([[int x]], [[int y]]) -> void")));
+}
+
TEST(SignatureHelpTest, FunctionPointers) {
llvm::StringLiteral Tests[] = {
// Variable of function pointer type
>From 0e0a198c1f70e88aa546d34fb0657d3c31a8d71f Mon Sep 17 00:00:00 2001
From: Timothy Akintilo <timtobi1 at gmail.com>
Date: Wed, 11 Sep 2024 20:26:05 -0500
Subject: [PATCH 9/9] format
format
---
.../clangd/unittests/CodeCompleteTests.cpp | 15 +++++++++------
clang/lib/Sema/SemaCodeComplete.cpp | 7 ++++---
2 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index a1317d413c6a76..fd896e2098f0ec 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1450,8 +1450,9 @@ TEST(SignatureHelpTest, ShowOperatorParensForImmediatelyInvokedLambda) {
const auto Results = signatures(R"cpp(
auto foo = [](int x, int y){}(^);
)cpp");
- EXPECT_THAT(Results.signatures,
- UnorderedElementsAre(sig("operator()([[int x]], [[int y]]) -> void")));
+ EXPECT_THAT(
+ Results.signatures,
+ UnorderedElementsAre(sig("operator()([[int x]], [[int y]]) -> void")));
}
TEST(SignatureHelpTest, ShowOperatorParensForLambdaReturnedFromFunction) {
@@ -1461,8 +1462,9 @@ TEST(SignatureHelpTest, ShowOperatorParensForLambdaReturnedFromFunction) {
}
int main() { returnsLambda()(^); }
)cpp");
- EXPECT_THAT(Results.signatures,
- UnorderedElementsAre(sig("operator()([[int x]], [[int y]]) -> void")));
+ EXPECT_THAT(
+ Results.signatures,
+ UnorderedElementsAre(sig("operator()([[int x]], [[int y]]) -> void")));
}
TEST(SignatureHelpTest, ShowOperatorParensForLambdaInParameterPack) {
@@ -1472,8 +1474,9 @@ TEST(SignatureHelpTest, ShowOperatorParensForLambdaInParameterPack) {
foo([](int x, int y){}(^))
)cpp");
- EXPECT_THAT(Results.signatures,
- UnorderedElementsAre(sig("operator()([[int x]], [[int y]]) -> void")));
+ EXPECT_THAT(
+ Results.signatures,
+ UnorderedElementsAre(sig("operator()([[int x]], [[int y]]) -> void")));
}
TEST(SignatureHelpTest, FunctionPointers) {
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 36a98a6ec06445..935a5597bbb6f7 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6298,9 +6298,10 @@ SemaCodeCompletion::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args,
SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
ArgExprs.append(ArgsWithoutDependentTypes.begin(),
ArgsWithoutDependentTypes.end());
- auto *const LambdaDecl =
- DC->isLambda() ? dyn_cast_if_present<VarDecl>(NakedFn->getReferencedDeclOfCallee())
- : nullptr;
+ auto *const LambdaDecl = DC->isLambda()
+ ? dyn_cast_if_present<VarDecl>(
+ NakedFn->getReferencedDeclOfCallee())
+ : nullptr;
SemaRef.AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs,
CandidateSet,
/*ExplicitArgs=*/nullptr,
More information about the cfe-commits
mailing list