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 @@ -296,14 +296,24 @@ return true; } - if (D->getType()->getContainedAutoType()) { - if (!D->getType()->isDependentType()) { + auto T = D->getType(); + + // Show type hint for `decltype(expr)`, e.g. + // for `decltype(0) i;`, show `decltype(0) i: int;` + if (const auto *DT = llvm::dyn_cast(T)) { + if (auto UT = DT->getUnderlyingType(); !UT->isDependentType()) + addTypeHint(D->getLocation(), UT, /*Prefix=*/": "); + return true; + } + + if (T->getContainedAutoType()) { + if (!T->isDependentType()) { // Our current approach is to place the hint on the variable // and accordingly print the full type // (e.g. for `const auto& x = 42`, print `const int&`). // Alternatively, we could place the hint on the `auto` // (and then just print the type deduced for the `auto`). - addTypeHint(D->getLocation(), D->getType(), /*Prefix=*/": "); + addTypeHint(D->getLocation(), T, /*Prefix=*/": "); } } 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 @@ -1141,6 +1141,10 @@ ExpectedHint{": int &", "z"}); } +TEST(TypeHints, Decltype) { + assertTypeHints("decltype(0) $i[[i]];", ExpectedHint{": int", "i"}); +} + TEST(TypeHints, NoQualifiers) { assertTypeHints(R"cpp( namespace A {