[clang-tools-extra] cbd6ac6 - [clangd] Show parameter hints for operator()
Younan Zhang via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 10 00:56:08 PDT 2023
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.
More information about the cfe-commits
mailing list