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 @@ -72,6 +72,19 @@ return true; } + bool VisitFunctionDecl(FunctionDecl *D) { + if (auto *AT = D->getReturnType()->getContainedAutoType()) { + QualType Deduced = AT->getDeducedType(); + if (!Deduced.isNull()) { + addInlayHint(D->getFunctionTypeLoc().getRParenLoc(), + InlayHintKind::TypeHint, + "-> " + D->getReturnType().getAsString(TypeHintPolicy)); + } + } + + return true; + } + bool VisitVarDecl(VarDecl *D) { // Do not show hints for the aggregate in a structured binding. // In the future, we may 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 @@ -478,14 +478,31 @@ } TEST(TypeHints, ReturnTypeDeduction) { - // FIXME: Not handled yet. - // This test is currently here mostly because a naive implementation - // might have us print something not super helpful like the function type. - assertTypeHints(R"cpp( - auto func(int x) { - return x + 1; - } - )cpp"); + assertTypeHints( + R"cpp( + auto f1(int x$ret1a[[)]]; // Hint forward declaration too + auto f1(int x$ret1b[[)]] { return x + 1; } + + // Include pointer operators in hint + int s; + auto& f2($ret2[[)]] { return s; } + + // Do not hint `auto` for trailing return type. + auto f3() -> int; + + // `auto` conversion operator + struct A { + operator auto($retConv[[)]] { return 42; } + }; + + // FIXME: Dependent types do not work yet. + template + struct S { + auto method() { return T(); } + }; + )cpp", + ExpectedHint{"-> int", "ret1a"}, ExpectedHint{"-> int", "ret1b"}, + ExpectedHint{"-> int &", "ret2"}, ExpectedHint{"-> int", "retConv"}); } TEST(TypeHints, DependentType) {