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 <timto...@gmail.com> Date: Sat, 27 Jul 2024 16:17:46 -0500 Subject: [PATCH 1/3] 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 <timto...@gmail.com> Date: Sun, 11 Aug 2024 13:02:10 -0500 Subject: [PATCH 2/3] 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+tilob...@users.noreply.github.com> Date: Sat, 7 Sep 2024 15:04:14 -0500 Subject: [PATCH 3/3] remove [[fallthrough]] Co-authored-by: Younan Zhang <zyn7...@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: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits