Skip to content

Commit 4a540ce

Browse files
authored
[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.
1 parent d5b0ad6 commit 4a540ce

File tree

2 files changed

+60
-16
lines changed

2 files changed

+60
-16
lines changed

clang-tools-extra/clangd/InlayHints.cpp

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,13 @@ static FunctionProtoTypeLoc getPrototypeLoc(Expr *Fn) {
528528
return {};
529529
}
530530

531+
ArrayRef<const ParmVarDecl *>
532+
maybeDropCxxExplicitObjectParameters(ArrayRef<const ParmVarDecl *> Params) {
533+
if (!Params.empty() && Params.front()->isExplicitObjectParameter())
534+
Params = Params.drop_front(1);
535+
return Params;
536+
}
537+
531538
struct Callee {
532539
// Only one of Decl or Loc is set.
533540
// Loc is for calls through function pointers.
@@ -614,15 +621,21 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
614621
// argument expressions present in the function call syntax preceded by the
615622
// implied object argument (E).
616623
//
617-
// However, we don't have the implied object argument for static
618-
// operator() per clang::Sema::BuildCallToObjectOfClassType.
624+
// As well as the provision from P0847R7 Deducing This [expr.call]p7:
625+
// ...If the function is an explicit object member function and there is an
626+
// implied object argument ([over.call.func]), the list of provided
627+
// arguments is preceded by the implied object argument for the purposes of
628+
// this correspondence...
629+
//
630+
// However, we don't have the implied object argument
631+
// for static operator() per clang::Sema::BuildCallToObjectOfClassType.
619632
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())
633+
// We don't have the implied object argument through a function pointer
634+
// either.
635+
if (const CXXMethodDecl *Method =
636+
dyn_cast_or_null<CXXMethodDecl>(Callee.Decl))
637+
if (Method->isInstance() &&
638+
(IsFunctor || Method->hasCXXExplicitFunctionObjectParameter()))
626639
Args = Args.drop_front(1);
627640
processCall(Callee, Args);
628641
return true;
@@ -849,15 +862,18 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
849862
if (Ctor->isCopyOrMoveConstructor())
850863
return;
851864

852-
auto Params =
853-
Callee.Decl ? Callee.Decl->parameters() : Callee.Loc.getParams();
854-
865+
ArrayRef<const ParmVarDecl *> Params, ForwardedParams;
855866
// Resolve parameter packs to their forwarded parameter
856-
SmallVector<const ParmVarDecl *> ForwardedParams;
857-
if (Callee.Decl)
858-
ForwardedParams = resolveForwardingParameters(Callee.Decl);
859-
else
867+
SmallVector<const ParmVarDecl *> ForwardedParamsStorage;
868+
if (Callee.Decl) {
869+
Params = maybeDropCxxExplicitObjectParameters(Callee.Decl->parameters());
870+
ForwardedParamsStorage = resolveForwardingParameters(Callee.Decl);
871+
ForwardedParams =
872+
maybeDropCxxExplicitObjectParameters(ForwardedParamsStorage);
873+
} else {
874+
Params = maybeDropCxxExplicitObjectParameters(Callee.Loc.getParams());
860875
ForwardedParams = {Params.begin(), Params.end()};
876+
}
861877

862878
NameVec ParameterNames = chooseParameterNames(ForwardedParams);
863879

@@ -1018,7 +1034,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
10181034
return {};
10191035
}
10201036

1021-
NameVec chooseParameterNames(SmallVector<const ParmVarDecl *> Parameters) {
1037+
NameVec chooseParameterNames(ArrayRef<const ParmVarDecl *> Parameters) {
10221038
NameVec ParameterNames;
10231039
for (const auto *P : Parameters) {
10241040
if (isExpandedFromParameterPack(P)) {

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,34 @@ TEST(ParameterHints, FunctionCallOperator) {
843843
ExpectedHint{"a: ", "11"}, ExpectedHint{"b: ", "12"});
844844
}
845845

846+
TEST(ParameterHints, DeducingThis) {
847+
assertParameterHints(R"cpp(
848+
struct S {
849+
template <typename This>
850+
auto operator()(this This &&Self, int Param) {
851+
return 42;
852+
}
853+
854+
auto function(this auto &Self, int Param) {
855+
return Param;
856+
}
857+
};
858+
void work() {
859+
S s;
860+
s($1[[42]]);
861+
s.function($2[[42]]);
862+
S()($3[[42]]);
863+
auto lambda = [](this auto &Self, char C) -> void {
864+
return Self(C);
865+
};
866+
lambda($4[['A']]);
867+
}
868+
)cpp",
869+
ExpectedHint{"Param: ", "1"},
870+
ExpectedHint{"Param: ", "2"},
871+
ExpectedHint{"Param: ", "3"}, ExpectedHint{"C: ", "4"});
872+
}
873+
846874
TEST(ParameterHints, Macros) {
847875
// Handling of macros depends on where the call's argument list comes from.
848876

0 commit comments

Comments
 (0)