diff --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp --- a/clang/lib/Index/IndexTypeSourceInfo.cpp +++ b/clang/lib/Index/IndexTypeSourceInfo.cpp @@ -8,6 +8,7 @@ #include "IndexingContext.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "llvm/ADT/ScopeExit.h" using namespace clang; using namespace index; @@ -160,6 +161,26 @@ return true; } + bool TraverseTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { + if (!WalkUpFromTemplateSpecializationTypeLoc(TL)) + return false; + if (!TraverseTemplateName(TL.getTypePtr()->getTemplateName())) + return false; + + // The relations we have to `Parent` do not apply to our template arguments, + // so clear them while visiting the args. + SmallVector SavedRelations = Relations; + Relations.clear(); + auto ResetSavedRelations = + llvm::make_scope_exit([&] { this->Relations = SavedRelations; }); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { + if (!TraverseTemplateArgumentLoc(TL.getArgLoc(I))) + return false; + } + + return true; + } + bool VisitDeducedTemplateSpecializationTypeLoc(DeducedTemplateSpecializationTypeLoc TL) { auto *T = TL.getTypePtr(); if (!T) diff --git a/clang/test/Index/Core/index-source.cpp b/clang/test/Index/Core/index-source.cpp --- a/clang/test/Index/Core/index-source.cpp +++ b/clang/test/Index/Core/index-source.cpp @@ -560,3 +560,11 @@ }; } + +namespace clangd_issue_504 { + class A {}; + template class B {}; + class C : B {}; +// CHECK: [[@LINE-1]]:15 | class/C++ | A | c:@N@clangd_issue_504@S@A | | Ref,RelCont | rel: 1 +// CHECK-NEXT: RelCont | C | c:@N@clangd_issue_504@S@C +} diff --git a/clang/unittests/Index/IndexTests.cpp b/clang/unittests/Index/IndexTests.cpp --- a/clang/unittests/Index/IndexTests.cpp +++ b/clang/unittests/Index/IndexTests.cpp @@ -334,6 +334,20 @@ WrittenAt(Position(3, 20))))); } +TEST(IndexTest, RelationBaseOf) { + std::string Code = R"cpp( + class A {}; + template class B {}; + class C : B {}; + )cpp"; + auto Index = std::make_shared(); + tooling::runToolOnCode(std::make_unique(Index), Code); + // A should not be the base of anything. + EXPECT_THAT(Index->Symbols, + Contains(AllOf(QName("A"), HasRole(SymbolRole::Reference), + Not(HasRole(SymbolRole::RelationBaseOf))))); +} + } // namespace } // namespace index } // namespace clang