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,17 +296,25 @@ return true; } - if (D->getType()->getContainedAutoType()) { - if (!D->getType()->isDependentType()) { + auto T = D->getType(); + 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=*/": "); } } + // Show type hint for decltype, e.g. + // for `decltype(0) i;`, show `decltype(0) i: int;` + if (T->isDecltypeType()) + addTypeHint(D->getLocation(), + llvm::cast(T)->getUnderlyingType(), + /*Prefix=*/": "); + // Handle templates like `int foo(auto x)` with exactly one instantiation. if (auto *PVD = llvm::dyn_cast(D)) { if (D->getIdentifier() && PVD->getType()->isDependentType() && 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 {