diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -674,9 +674,19 @@ const SourceManager &SM = AST.getSourceManager(); SourceLocation SourceLocationBeg = SM.getMacroArgExpandedLocation( getBeginningOfIdentifier(Pos, SM, AST.getLangOpts())); + // First, try to find a template instantiation. This will give us + // the ClassTemplateSpecializationDecl for a non-dependent + // specialization, allowing us to produce a more accurate type + // hierarchy specific to that specialization. DeclRelationSet Relations = - DeclRelation::TemplatePattern | DeclRelation::Underlying; + DeclRelation::TemplateInstantiation | DeclRelation::Underlying; auto Decls = getDeclAtPosition(AST, SourceLocationBeg, Relations); + if (Decls.empty()) { + // For a dependent specialization, there is no specialization Decl + // to produce, so get the template pattern instead. + Relations = DeclRelation::TemplatePattern | DeclRelation::Underlying; + Decls = getDeclAtPosition(AST, SourceLocationBeg, Relations); + } if (Decls.empty()) return nullptr; diff --git a/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp b/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp --- a/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp +++ b/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp @@ -409,17 +409,13 @@ ASSERT_TRUE(!AST.getDiagnostics().empty()); // Make sure getTypeHierarchy() doesn't get into an infinite recursion. - // FIXME(nridge): It would be preferable if the type hierarchy gave us type - // names (e.g. "S<0>" for the child and "S<1>" for the parent) rather than - // template names (e.g. "S"). + // Here, we actually don't get any parents, because the unbounded hierarchy + // causes instantiation of the base specifier to fail. llvm::Optional Result = getTypeHierarchy( AST, Source.points()[0], 0, TypeHierarchyDirection::Parents); ASSERT_TRUE(bool(Result)); - EXPECT_THAT( - *Result, - AllOf(WithName("S"), WithKind(SymbolKind::Struct), - Parents(AllOf(WithName("S"), WithKind(SymbolKind::Struct), - SelectionRangeIs(Source.range("SDef")), Parents())))); + EXPECT_THAT(*Result, + AllOf(WithName("S<0>"), WithKind(SymbolKind::Struct), Parents())); } TEST(TypeHierarchy, RecursiveHierarchyBounded) { @@ -449,9 +445,12 @@ ASSERT_TRUE(bool(Result)); EXPECT_THAT( *Result, - AllOf(WithName("S"), WithKind(SymbolKind::Struct), - Parents(AllOf(WithName("S"), WithKind(SymbolKind::Struct), - SelectionRangeIs(Source.range("SDef")), Parents())))); + AllOf(WithName("S<2>"), WithKind(SymbolKind::Struct), + Parents(AllOf( + WithName("S<1>"), WithKind(SymbolKind::Struct), + SelectionRangeIs(Source.range("SDef")), + Parents(AllOf(WithName("S<0>"), WithKind(SymbolKind::Struct), + Parents())))))); Result = getTypeHierarchy(AST, Source.point("SRefDependent"), 0, TypeHierarchyDirection::Parents); ASSERT_TRUE(bool(Result));