Author: Younan Zhang Date: 2023-09-10T15:56:00+08:00 New Revision: cbd6ac6165e683f2eed4a5066c1ccf53bed0696d
URL: https://github.com/llvm/llvm-project/commit/cbd6ac6165e683f2eed4a5066c1ccf53bed0696d DIFF: https://github.com/llvm/llvm-project/commit/cbd6ac6165e683f2eed4a5066c1ccf53bed0696d.diff LOG: [clangd] Show parameter hints for operator() Closes https://github.com/clangd/clangd/issues/1742 Reviewed By: nridge Differential Revision: https://reviews.llvm.org/D158926 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 56f85ee155cb236..e6e5e11b889bff8 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -586,11 +586,13 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { if (!Cfg.InlayHints.Parameters) return true; - // Do not show parameter hints for operator calls written using operator - // syntax or user-defined literals. (Among other reasons, the resulting + bool IsFunctor = isFunctionObjectCallExpr(E); + // Do not show parameter hints for user-defined literals or + // operator calls except for operator(). (Among other reasons, the resulting // hints can look awkward, e.g. the expression can itself be a function // argument and then we'd get two hints side by side). - if (isa<CXXOperatorCallExpr>(E) || isa<UserDefinedLiteral>(E)) + if ((isa<CXXOperatorCallExpr>(E) && !IsFunctor) || + isa<UserDefinedLiteral>(E)) return true; auto CalleeDecls = Resolver->resolveCalleeOfCallExpr(E); @@ -607,7 +609,22 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { else return true; - processCall(Callee, {E->getArgs(), E->getNumArgs()}); + // N4868 [over.call.object]p3 says, + // The argument list submitted to overload resolution consists of the + // 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. + 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()) + Args = Args.drop_front(1); + processCall(Callee, Args); return true; } @@ -1203,6 +1220,12 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { return Range{HintStart, HintEnd}; } + static bool isFunctionObjectCallExpr(CallExpr *E) noexcept { + if (auto *CallExpr = dyn_cast<CXXOperatorCallExpr>(E)) + return CallExpr->getOperator() == OverloadedOperatorKind::OO_Call; + return false; + } + std::vector<InlayHint> &Results; ASTContext &AST; const syntax::TokenBuffer &Tokens; diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp index 1d12db3661c9ebb..a8c3546eb80cc85 100644 --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -89,7 +89,7 @@ void assertHintsWithHeader(InlayHintKind Kind, llvm::StringRef AnnotatedSource, ExpectedHints... Expected) { Annotations Source(AnnotatedSource); TestTU TU = TestTU::withCode(Source.code()); - TU.ExtraArgs.push_back("-std=c++20"); + TU.ExtraArgs.push_back("-std=c++23"); TU.HeaderCode = HeaderContent; auto AST = TU.build(); @@ -807,6 +807,42 @@ TEST(ParameterHints, Operator) { )cpp"); } +TEST(ParameterHints, FunctionCallOperator) { + assertParameterHints(R"cpp( + struct W { + void operator()(int x); + }; + struct S : W { + using W::operator(); + static void operator()(int x, int y); + }; + void bar() { + auto l1 = [](int x) {}; + auto l2 = [](int x) static {}; + + S s; + s($1[[1]]); + s.operator()($2[[1]]); + s.operator()($3[[1]], $4[[2]]); + S::operator()($5[[1]], $6[[2]]); + + l1($7[[1]]); + l1.operator()($8[[1]]); + l2($9[[1]]); + l2.operator()($10[[1]]); + + void (*ptr)(int a, int b) = &S::operator(); + ptr($11[[1]], $12[[2]]); + } + )cpp", + ExpectedHint{"x: ", "1"}, ExpectedHint{"x: ", "2"}, + ExpectedHint{"x: ", "3"}, ExpectedHint{"y: ", "4"}, + ExpectedHint{"x: ", "5"}, ExpectedHint{"y: ", "6"}, + ExpectedHint{"x: ", "7"}, ExpectedHint{"x: ", "8"}, + ExpectedHint{"x: ", "9"}, ExpectedHint{"x: ", "10"}, + ExpectedHint{"a: ", "11"}, ExpectedHint{"b: ", "12"}); +} + 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