Skip to content

Commit cbd6ac6

Browse files
committed
[clangd] Show parameter hints for operator()
Closes clangd/clangd#1742 Reviewed By: nridge Differential Revision: https://reviews.llvm.org/D158926
1 parent 17bd806 commit cbd6ac6

File tree

2 files changed

+64
-5
lines changed

2 files changed

+64
-5
lines changed

clang-tools-extra/clangd/InlayHints.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -586,11 +586,13 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
586586
if (!Cfg.InlayHints.Parameters)
587587
return true;
588588

589-
// Do not show parameter hints for operator calls written using operator
590-
// syntax or user-defined literals. (Among other reasons, the resulting
589+
bool IsFunctor = isFunctionObjectCallExpr(E);
590+
// Do not show parameter hints for user-defined literals or
591+
// operator calls except for operator(). (Among other reasons, the resulting
591592
// hints can look awkward, e.g. the expression can itself be a function
592593
// argument and then we'd get two hints side by side).
593-
if (isa<CXXOperatorCallExpr>(E) || isa<UserDefinedLiteral>(E))
594+
if ((isa<CXXOperatorCallExpr>(E) && !IsFunctor) ||
595+
isa<UserDefinedLiteral>(E))
594596
return true;
595597

596598
auto CalleeDecls = Resolver->resolveCalleeOfCallExpr(E);
@@ -607,7 +609,22 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
607609
else
608610
return true;
609611

610-
processCall(Callee, {E->getArgs(), E->getNumArgs()});
612+
// N4868 [over.call.object]p3 says,
613+
// The argument list submitted to overload resolution consists of the
614+
// argument expressions present in the function call syntax preceded by the
615+
// implied object argument (E).
616+
//
617+
// However, we don't have the implied object argument for static
618+
// operator() per clang::Sema::BuildCallToObjectOfClassType.
619+
llvm::ArrayRef<const Expr *> Args = {E->getArgs(), E->getNumArgs()};
620+
if (IsFunctor)
621+
// We don't have the implied object argument through
622+
// a function pointer either.
623+
if (const CXXMethodDecl *Method =
624+
dyn_cast_or_null<CXXMethodDecl>(Callee.Decl);
625+
Method && Method->isInstance())
626+
Args = Args.drop_front(1);
627+
processCall(Callee, Args);
611628
return true;
612629
}
613630

@@ -1203,6 +1220,12 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
12031220
return Range{HintStart, HintEnd};
12041221
}
12051222

1223+
static bool isFunctionObjectCallExpr(CallExpr *E) noexcept {
1224+
if (auto *CallExpr = dyn_cast<CXXOperatorCallExpr>(E))
1225+
return CallExpr->getOperator() == OverloadedOperatorKind::OO_Call;
1226+
return false;
1227+
}
1228+
12061229
std::vector<InlayHint> &Results;
12071230
ASTContext &AST;
12081231
const syntax::TokenBuffer &Tokens;

clang-tools-extra/clangd/unittests/InlayHintTests.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ void assertHintsWithHeader(InlayHintKind Kind, llvm::StringRef AnnotatedSource,
8989
ExpectedHints... Expected) {
9090
Annotations Source(AnnotatedSource);
9191
TestTU TU = TestTU::withCode(Source.code());
92-
TU.ExtraArgs.push_back("-std=c++20");
92+
TU.ExtraArgs.push_back("-std=c++23");
9393
TU.HeaderCode = HeaderContent;
9494
auto AST = TU.build();
9595

@@ -807,6 +807,42 @@ TEST(ParameterHints, Operator) {
807807
)cpp");
808808
}
809809

810+
TEST(ParameterHints, FunctionCallOperator) {
811+
assertParameterHints(R"cpp(
812+
struct W {
813+
void operator()(int x);
814+
};
815+
struct S : W {
816+
using W::operator();
817+
static void operator()(int x, int y);
818+
};
819+
void bar() {
820+
auto l1 = [](int x) {};
821+
auto l2 = [](int x) static {};
822+
823+
S s;
824+
s($1[[1]]);
825+
s.operator()($2[[1]]);
826+
s.operator()($3[[1]], $4[[2]]);
827+
S::operator()($5[[1]], $6[[2]]);
828+
829+
l1($7[[1]]);
830+
l1.operator()($8[[1]]);
831+
l2($9[[1]]);
832+
l2.operator()($10[[1]]);
833+
834+
void (*ptr)(int a, int b) = &S::operator();
835+
ptr($11[[1]], $12[[2]]);
836+
}
837+
)cpp",
838+
ExpectedHint{"x: ", "1"}, ExpectedHint{"x: ", "2"},
839+
ExpectedHint{"x: ", "3"}, ExpectedHint{"y: ", "4"},
840+
ExpectedHint{"x: ", "5"}, ExpectedHint{"y: ", "6"},
841+
ExpectedHint{"x: ", "7"}, ExpectedHint{"x: ", "8"},
842+
ExpectedHint{"x: ", "9"}, ExpectedHint{"x: ", "10"},
843+
ExpectedHint{"a: ", "11"}, ExpectedHint{"b: ", "12"});
844+
}
845+
810846
TEST(ParameterHints, Macros) {
811847
// Handling of macros depends on where the call's argument list comes from.
812848

0 commit comments

Comments
 (0)