diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -1082,10 +1082,22 @@ auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Alias, AST.getHeuristicResolver()); if (!Decls.empty()) { - HI = getHoverContents(Decls.front(), PP, Index, TB); + // For using-declarations, e.g. + // namespace ns { void foo(); } + // void bar() { using ns::foo; f^oo(); } + // The first declaration in Decls will refer to the using declaration, + // which isn't really useful for Hover. So check if we have something + // better, which in this example would be the actual declaration of foo. + auto *DeclToUse = Decls.begin(); + while (llvm::isa(*DeclToUse) && + std::next(DeclToUse) != Decls.end()) { + ++DeclToUse; + } + + HI = getHoverContents(*DeclToUse, PP, Index, TB); // Layout info only shown when hovering on the field/class itself. - if (Decls.front() == N->ASTNode.get()) - addLayoutInfo(*Decls.front(), *HI); + if (*DeclToUse == N->ASTNode.get()) + addLayoutInfo(**DeclToUse, *HI); // Look for a close enclosing expression to show the value of. if (!HI->Value) HI->Value = printExprValue(N, AST.getASTContext()); diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -1630,6 +1630,26 @@ HI.Type = "int"; HI.Definition = "int foo"; }}, + { + R"cpp(// Function definition via using declaration + namespace ns { + void foo(); + } + int main() { + using ns::foo; + ^[[foo]](); + } + )cpp", + [](HoverInfo &HI) { + HI.Name = "foo"; + HI.Kind = index::SymbolKind::Function; + HI.NamespaceScope = "ns::"; + HI.Type = "void ()"; + HI.Definition = "void foo()"; + HI.Documentation = ""; + HI.ReturnType = "void"; + HI.Parameters = std::vector{}; + }}, { R"cpp(// Macro #define MACRO 0 @@ -1734,6 +1754,25 @@ HI.Definition = "ONE"; HI.Value = "0"; }}, + { + R"cpp(// C++20's using enum + enum class Hello { + ONE, TWO, THREE, + }; + void foo() { + using enum Hello; + Hello hello = [[O^NE]]; + } + )cpp", + [](HoverInfo &HI) { + HI.Name = "ONE"; + HI.Kind = index::SymbolKind::EnumConstant; + HI.NamespaceScope = ""; + HI.LocalScope = "Hello::"; + HI.Type = "enum Hello"; + HI.Definition = "ONE"; + HI.Value = "0"; + }}, { R"cpp(// Enumerator in anonymous enum enum {