[clang] Do not consider the template arguments of bases to be bases themselves

Fixes https://github.com/clangd/clangd/issues/504

Differential Revision: https://reviews.llvm.org/D86424
This commit is contained in:
Nathan Ridge 2020-08-23 22:15:12 -04:00
parent 94948f3c92
commit 7cd6b0c3b5
3 changed files with 43 additions and 0 deletions

View File

@ -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 @@ public:
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<SymbolRelation, 3> 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)

View File

@ -560,3 +560,11 @@ class SubclassOffsetof : public Struct {
};
}
namespace clangd_issue_504 {
class A {};
template <typename> class B {};
class C : B<A> {};
// CHECK: [[@LINE-1]]:13 | class/C++ | A | c:@N@clangd_issue_504@S@A | <no-cgname> | Ref,RelCont | rel: 1
// CHECK-NEXT: RelCont | C | c:@N@clangd_issue_504@S@C
} // namespace clangd_issue_504

View File

@ -334,6 +334,20 @@ TEST(IndexTest, VisitDefaultArgs) {
WrittenAt(Position(3, 20)))));
}
TEST(IndexTest, RelationBaseOf) {
std::string Code = R"cpp(
class A {};
template <typename> class B {};
class C : B<A> {};
)cpp";
auto Index = std::make_shared<Indexer>();
tooling::runToolOnCode(std::make_unique<IndexAction>(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