diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -254,17 +254,30 @@ } bool VisitFunctionDecl(FunctionDecl *D) { - if (auto *AT = D->getReturnType()->getContainedAutoType()) { - QualType Deduced = AT->getDeducedType(); - if (!Deduced.isNull()) { - addTypeHint(D->getFunctionTypeLoc().getRParenLoc(), D->getReturnType(), - /*Prefix=*/"-> "); - } + if (auto *FPT = + llvm::dyn_cast(D->getType().getTypePtr())) { + if (!FPT->hasTrailingReturn()) + addReturnTypeHint(D, D->getFunctionTypeLoc().getRParenLoc()); } + return true; + } + bool VisitLambdaExpr(LambdaExpr *E) { + FunctionDecl *D = E->getCallOperator(); + if (!E->hasExplicitResultType()) + addReturnTypeHint(D, E->hasExplicitParameters() + ? D->getFunctionTypeLoc().getRParenLoc() + : E->getIntroducerRange().getEnd()); return true; } + void addReturnTypeHint(FunctionDecl *D, SourceLocation Loc) { + auto *AT = D->getReturnType()->getContainedAutoType(); + if (!AT || AT->getDeducedType().isNull()) + return; + addTypeHint(Loc, D->getReturnType(), /*Prefix=*/"-> "); + } + bool VisitVarDecl(VarDecl *D) { // Do not show hints for the aggregate in a structured binding, // but show hints for the individual bindings. diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -527,13 +527,18 @@ assertTypeHints(R"cpp( void f() { int cap = 42; - auto $L[[L]] = [cap, $init[[init]] = 1 + 1](int a) { + auto $L[[L]] = [cap, $init[[init]] = 1 + 1](int a$ret[[)]] { return a + cap + init; }; } )cpp", ExpectedHint{": (lambda)", "L"}, - ExpectedHint{": int", "init"}); + ExpectedHint{": int", "init"}, ExpectedHint{"-> int", "ret"}); + + // Lambda return hint shown even if no param list. + assertTypeHints("auto $L[[x]] = <:$ret[[:>]]{return 42;};", + ExpectedHint{": (lambda)", "L"}, + ExpectedHint{"-> int", "ret"}); } // Structured bindings tests. @@ -616,6 +621,9 @@ // Do not hint `auto` for trailing return type. auto f3() -> int; + // Do not hint when a trailing return type is specified. + auto f4() -> auto* { return "foo"; } + // `auto` conversion operator struct A { operator auto($retConv[[)]] { return 42; }