Author: Younan Zhang Date: 2023-10-24T09:51:43+08:00 New Revision: 4a540ceed454f9ef364838469ebc94252dba152e
URL: https://github.com/llvm/llvm-project/commit/4a540ceed454f9ef364838469ebc94252dba152e DIFF: https://github.com/llvm/llvm-project/commit/4a540ceed454f9ef364838469ebc94252dba152e.diff LOG: [clangd] Adapt Inlay Hint support for Deducing This (#68177) This is a follow-up for D140828, making Clangd omit the explicit object parameter in a call to member function with Deducing This. Given that the parent patch is still in its infancy and might undergo several reverting-relanding processes, one can feel free to revert this if encountering any CI failure. And please let me know if I should alter anything. Added: Modified: clang-tools-extra/clangd/InlayHints.cpp clang-tools-extra/clangd/unittests/InlayHintTests.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index e6e5e11b889bff8..3da047f95421385 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -528,6 +528,13 @@ static FunctionProtoTypeLoc getPrototypeLoc(Expr *Fn) { return {}; } +ArrayRef<const ParmVarDecl *> +maybeDropCxxExplicitObjectParameters(ArrayRef<const ParmVarDecl *> Params) { + if (!Params.empty() && Params.front()->isExplicitObjectParameter()) + Params = Params.drop_front(1); + return Params; +} + struct Callee { // Only one of Decl or Loc is set. // Loc is for calls through function pointers. @@ -614,15 +621,21 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { // argument expressions present in the function call syntax preceded by the // implied object argument (E). // - // However, we don't have the implied object argument for static - // operator() per clang::Sema::BuildCallToObjectOfClassType. + // As well as the provision from P0847R7 Deducing This [expr.call]p7: + // ...If the function is an explicit object member function and there is an + // implied object argument ([over.call.func]), the list of provided + // arguments is preceded by the implied object argument for the purposes of + // this correspondence... + // + // However, we don't have the implied object argument + // for static operator() per clang::Sema::BuildCallToObjectOfClassType. llvm::ArrayRef<const Expr *> Args = {E->getArgs(), E->getNumArgs()}; - if (IsFunctor) - // We don't have the implied object argument through - // a function pointer either. - if (const CXXMethodDecl *Method = - dyn_cast_or_null<CXXMethodDecl>(Callee.Decl); - Method && Method->isInstance()) + // We don't have the implied object argument through a function pointer + // either. + if (const CXXMethodDecl *Method = + dyn_cast_or_null<CXXMethodDecl>(Callee.Decl)) + if (Method->isInstance() && + (IsFunctor || Method->hasCXXExplicitFunctionObjectParameter())) Args = Args.drop_front(1); processCall(Callee, Args); return true; @@ -849,15 +862,18 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { if (Ctor->isCopyOrMoveConstructor()) return; - auto Params = - Callee.Decl ? Callee.Decl->parameters() : Callee.Loc.getParams(); - + ArrayRef<const ParmVarDecl *> Params, ForwardedParams; // Resolve parameter packs to their forwarded parameter - SmallVector<const ParmVarDecl *> ForwardedParams; - if (Callee.Decl) - ForwardedParams = resolveForwardingParameters(Callee.Decl); - else + SmallVector<const ParmVarDecl *> ForwardedParamsStorage; + if (Callee.Decl) { + Params = maybeDropCxxExplicitObjectParameters(Callee.Decl->parameters()); + ForwardedParamsStorage = resolveForwardingParameters(Callee.Decl); + ForwardedParams = + maybeDropCxxExplicitObjectParameters(ForwardedParamsStorage); + } else { + Params = maybeDropCxxExplicitObjectParameters(Callee.Loc.getParams()); ForwardedParams = {Params.begin(), Params.end()}; + } NameVec ParameterNames = chooseParameterNames(ForwardedParams); @@ -1018,7 +1034,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { return {}; } - NameVec chooseParameterNames(SmallVector<const ParmVarDecl *> Parameters) { + NameVec chooseParameterNames(ArrayRef<const ParmVarDecl *> Parameters) { NameVec ParameterNames; for (const auto *P : Parameters) { if (isExpandedFromParameterPack(P)) { diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp index a8c3546eb80cc85..20c1cdd985dbc01 100644 --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -843,6 +843,34 @@ TEST(ParameterHints, FunctionCallOperator) { ExpectedHint{"a: ", "11"}, ExpectedHint{"b: ", "12"}); } +TEST(ParameterHints, DeducingThis) { + assertParameterHints(R"cpp( + struct S { + template <typename This> + auto operator()(this This &&Self, int Param) { + return 42; + } + + auto function(this auto &Self, int Param) { + return Param; + } + }; + void work() { + S s; + s($1[[42]]); + s.function($2[[42]]); + S()($3[[42]]); + auto lambda = [](this auto &Self, char C) -> void { + return Self(C); + }; + lambda($4[['A']]); + } + )cpp", + ExpectedHint{"Param: ", "1"}, + ExpectedHint{"Param: ", "2"}, + ExpectedHint{"Param: ", "3"}, ExpectedHint{"C: ", "4"}); +} + TEST(ParameterHints, Macros) { // Handling of macros depends on where the call's argument list comes from. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits