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 @@ -1132,15 +1132,9 @@ using RecursionProtectionSet = llvm::SmallSet; -static Optional -getTypeAncestors(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, - RecursionProtectionSet &RPSet) { - Optional Result = declToTypeHierarchyItem(ASTCtx, CXXRD); - if (!Result) - return Result; - - Result->parents.emplace(); - +static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, + std::vector &SuperTypes, + RecursionProtectionSet &RPSet) { // typeParents() will replace dependent template specializations // with their class template, so to avoid infinite recursion for // certain types of hierarchies, keep the templates encountered @@ -1149,22 +1143,22 @@ auto *Pattern = CXXRD.getDescribedTemplate() ? &CXXRD : nullptr; if (Pattern) { if (!RPSet.insert(Pattern).second) { - return Result; + return; } } for (const CXXRecordDecl *ParentDecl : typeParents(&CXXRD)) { if (Optional ParentSym = - getTypeAncestors(*ParentDecl, ASTCtx, RPSet)) { - Result->parents->emplace_back(std::move(*ParentSym)); + declToTypeHierarchyItem(ASTCtx, *ParentDecl)) { + ParentSym->parents.emplace(); + fillSuperTypes(*ParentDecl, ASTCtx, *ParentSym->parents, RPSet); + SuperTypes.emplace_back(std::move(*ParentSym)); } } if (Pattern) { RPSet.erase(Pattern); } - - return Result; } const CXXRecordDecl *findRecordTypeAt(ParsedAST &AST, Position Pos) { @@ -1231,12 +1225,19 @@ if (!CXXRD) return llvm::None; - RecursionProtectionSet RPSet; Optional Result = - getTypeAncestors(*CXXRD, AST.getASTContext(), RPSet); + declToTypeHierarchyItem(AST.getASTContext(), *CXXRD); if (!Result) return Result; + if (Direction == TypeHierarchyDirection::Parents || + Direction == TypeHierarchyDirection::Both) { + Result->parents.emplace(); + + RecursionProtectionSet RPSet; + fillSuperTypes(*CXXRD, AST.getASTContext(), *Result->parents, RPSet); + } + if ((Direction == TypeHierarchyDirection::Children || Direction == TypeHierarchyDirection::Both) && ResolveLevels > 0) { 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 @@ -630,7 +630,8 @@ ASSERT_TRUE(bool(Result)); EXPECT_THAT( *Result, - AllOf(WithName("Parent"), WithKind(SymbolKind::Struct), Parents(), + AllOf(WithName("Parent"), WithKind(SymbolKind::Struct), + ParentsNotResolved(), Children(AllOf(WithName("Child1"), WithKind(SymbolKind::Struct), ParentsNotResolved(), ChildrenNotResolved()))));