Skip to content

Commit 17a37d9

Browse files
fix: Properly implement Find implementations for classes (#393)
- Emits relationships for the full inheritance graph, not just base classes - Correctly emits relationships if base class is a template
1 parent 1995a07 commit 17a37d9

File tree

9 files changed

+182
-10
lines changed

9 files changed

+182
-10
lines changed

indexer/Indexer.cc

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "clang/Basic/SourceManager.h"
2626
#include "clang/Lex/Lexer.h"
2727
#include "clang/Lex/MacroInfo.h"
28+
#include "llvm/ADT/SmallPtrSet.h"
29+
#include "llvm/ADT/SmallVector.h"
2830

2931
#include "proto/fwd_decls.pb.h"
3032
#include "scip/scip.pb.h"
@@ -662,7 +664,8 @@ void TuIndexer::saveNestedNameSpecifierLoc(
662664
case Kind::Global:
663665
case Kind::Super:
664666
case Kind::TypeSpecWithTemplate:
665-
// NOTE: Adding support for TypeSpecWithTemplate needs extra care
667+
// FIXME(def: template-specialization-support)
668+
// Adding support for TypeSpecWithTemplate needs extra care
666669
// for (partial) template specializations. Example code:
667670
//
668671
// template <typename T0>
@@ -718,23 +721,58 @@ void TuIndexer::saveTagDecl(const clang::TagDecl &tagDecl) {
718721
scip::SymbolInformation symbolInfo{};
719722
this->getDocComment(tagDecl).addTo(symbolInfo);
720723

724+
llvm::SmallPtrSet<const clang::CXXRecordDecl *, 1> seen{};
725+
llvm::SmallVector<const clang::CXXRecordDecl *, 1> stack{};
721726
if (auto *cxxRecordDecl = llvm::dyn_cast<clang::CXXRecordDecl>(&tagDecl)) {
722-
for (const clang::CXXBaseSpecifier &cxxBaseSpecifier :
723-
cxxRecordDecl->bases()) {
724-
if (auto *tagDecl = cxxBaseSpecifier.getType()->getAsTagDecl()) {
725-
auto optRelatedSymbol = this->symbolFormatter.getTagSymbol(*tagDecl);
726-
if (!optRelatedSymbol.has_value()) {
727-
continue;
728-
}
727+
seen.insert(cxxRecordDecl);
728+
stack.push_back(cxxRecordDecl);
729+
}
730+
731+
while (!stack.empty()) {
732+
auto *cxxRecordDecl = stack.back();
733+
stack.pop_back();
734+
if (!cxxRecordDecl) {
735+
continue;
736+
}
737+
if (seen.find(cxxRecordDecl) == seen.end()) {
738+
// See FIXME(ref: template-specialization-support) When we get the decl
739+
// symbol here, we need to handle different kinds of templates
740+
// differently. E.g. in the ImplicitInstantiation case, call
741+
// getTemplateInstantiationPattern and use that rather than using the
742+
// instantiated decl.
743+
if (auto optRelatedSymbol =
744+
this->symbolFormatter.getNamedDeclSymbol(*cxxRecordDecl)) {
729745
scip::Relationship rel{};
730746
auto symbol = optRelatedSymbol->value;
731747
rel.set_symbol(symbol.data(), symbol.size());
732748
rel.set_is_implementation(true);
733749
*symbolInfo.add_relationships() = std::move(rel);
734750
}
751+
seen.insert(cxxRecordDecl);
735752
}
736-
}
737753

754+
for (const clang::CXXBaseSpecifier &cxxBaseSpecifier :
755+
cxxRecordDecl->bases()) {
756+
auto baseType = cxxBaseSpecifier.getType().getCanonicalType();
757+
if (auto *baseRecordType = baseType->getAs<clang::RecordType>()) {
758+
if (auto *baseCxxRecordDecl =
759+
llvm::dyn_cast_or_null<clang::CXXRecordDecl>(
760+
baseRecordType->getDecl())) {
761+
stack.push_back(baseCxxRecordDecl);
762+
}
763+
} else if (auto *baseTemplateSpecType =
764+
baseType->getAs<clang::TemplateSpecializationType>()) {
765+
if (auto *templateDecl =
766+
baseTemplateSpecType->getTemplateName().getAsTemplateDecl()) {
767+
if (auto *baseCxxRecordDecl =
768+
llvm::dyn_cast_or_null<clang::CXXRecordDecl>(
769+
templateDecl->getTemplatedDecl())) {
770+
stack.push_back(baseCxxRecordDecl);
771+
}
772+
}
773+
}
774+
}
775+
}
738776
this->saveDefinition(symbol, tagDecl.getLocation(), std::move(symbolInfo));
739777
}
740778

indexer/Indexer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
#include "clang/AST/RawCommentList.h"
1616
#include "clang/Basic/SourceLocation.h"
17-
#include "llvm/ADT/SmallVector.h"
1817

1918
#include "indexer/ApproximateNameResolver.h"
2019
#include "indexer/ClangAstMacros.h"

test/index/functions/methods.snapshot.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848

4949
struct S2 final: S1_0, S1_1 {
5050
// ^^ definition [..] S2#
51+
// relation implementation [..] S0#
5152
// relation implementation [..] S1_0#
5253
// relation implementation [..] S1_1#
5354
// ^^^^ reference [..] S1_0#

test/index/functions/template_body.snapshot.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
// ^ definition local 5
7171
struct ZZ : Z<T> {
7272
// ^^ definition [..] ZZ#
73+
// relation implementation [..] Z#
7374
// ^ reference [..] Z#
7475
// ^ reference local 5
7576
void ff0() {

test/index/functions/templates.snapshot.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
// ^ definition local 2
1919
struct T1: T0<T> {
2020
// ^^ definition [..] T1#
21+
// relation implementation [..] T0#
2122
// ^^ reference [..] T0#
2223
// ^ reference local 2
2324
void f1(T t) {
@@ -107,6 +108,7 @@
107108
// ^ definition local 12
108109
struct Q1: Q0<T> {
109110
// ^^ definition [..] Q1#
111+
// relation implementation [..] Q0#
110112
// ^^ reference [..] Q0#
111113
// ^ reference local 12
112114
using Base1 = Q0<T>;
@@ -124,6 +126,8 @@
124126
// ^ definition local 13
125127
struct Q2: Q1<T> {
126128
// ^^ definition [..] Q2#
129+
// relation implementation [..] Q0#
130+
// relation implementation [..] Q1#
127131
// ^^ reference [..] Q1#
128132
// ^ reference local 13
129133
using Base2 = Q1<T>;

test/index/types/inheritance.cc

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
struct MonoBase {};
2+
3+
struct MonoDerived: MonoBase {};
4+
5+
struct MonoDerivedTwice: MonoDerived {};
6+
7+
template <typename T>
8+
struct TemplatedBase {};
9+
10+
template <typename T>
11+
struct TemplatedDerived: TemplatedBase<T> {};
12+
13+
struct DerivedFromInstantiation: TemplatedBase<int> {};
14+
15+
template <typename T>
16+
struct SpecializedBase {};
17+
18+
template <>
19+
struct SpecializedBase<int> {};
20+
21+
template <typename T>
22+
struct SpecializedDerived: SpecializedBase<T> {};
23+
24+
struct DerivedFromSpecialization: SpecializedBase<int> {};
25+
26+
template <typename T>
27+
struct CrtpBase { T *t; };
28+
29+
struct CrtpDerivedMono: CrtpBase<CrtpDerivedMono> {};
30+
31+
template <typename T>
32+
struct CrtpDerivedTemplated: CrtpBase<CrtpDerivedTemplated<T>> {};
33+
34+
template <typename T>
35+
struct DerivedFromTemplateParam: T {};
36+
37+
template <template <typename> typename H>
38+
struct DerivedFromTemplateTemplateParam: H<int> {};
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
struct MonoBase {};
2+
//^^^^^^ definition [..] `<file>/inheritance.cc`/
3+
// ^^^^^^^^ definition [..] MonoBase#
4+
5+
struct MonoDerived: MonoBase {};
6+
// ^^^^^^^^^^^ definition [..] MonoDerived#
7+
// relation implementation [..] MonoBase#
8+
// ^^^^^^^^ reference [..] MonoBase#
9+
10+
struct MonoDerivedTwice: MonoDerived {};
11+
// ^^^^^^^^^^^^^^^^ definition [..] MonoDerivedTwice#
12+
// relation implementation [..] MonoBase#
13+
// relation implementation [..] MonoDerived#
14+
// ^^^^^^^^^^^ reference [..] MonoDerived#
15+
16+
template <typename T>
17+
// ^ definition local 0
18+
struct TemplatedBase {};
19+
// ^^^^^^^^^^^^^ definition [..] TemplatedBase#
20+
21+
template <typename T>
22+
// ^ definition local 1
23+
struct TemplatedDerived: TemplatedBase<T> {};
24+
// ^^^^^^^^^^^^^^^^ definition [..] TemplatedDerived#
25+
// relation implementation [..] TemplatedBase#
26+
// ^^^^^^^^^^^^^ reference [..] TemplatedBase#
27+
// ^ reference local 1
28+
29+
struct DerivedFromInstantiation: TemplatedBase<int> {};
30+
// ^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] DerivedFromInstantiation#
31+
// relation implementation [..] TemplatedBase#
32+
// ^^^^^^^^^^^^^ reference [..] TemplatedBase#
33+
34+
template <typename T>
35+
// ^ definition local 2
36+
struct SpecializedBase {};
37+
// ^^^^^^^^^^^^^^^ definition [..] SpecializedBase#
38+
39+
template <>
40+
struct SpecializedBase<int> {};
41+
// ^^^^^^^^^^^^^^^ reference [..] SpecializedBase#
42+
// ^^^^^^^^^^^^^^^ definition [..] SpecializedBase#
43+
44+
template <typename T>
45+
// ^ definition local 3
46+
struct SpecializedDerived: SpecializedBase<T> {};
47+
// ^^^^^^^^^^^^^^^^^^ definition [..] SpecializedDerived#
48+
// relation implementation [..] SpecializedBase#
49+
// ^^^^^^^^^^^^^^^ reference [..] SpecializedBase#
50+
// ^ reference local 3
51+
52+
struct DerivedFromSpecialization: SpecializedBase<int> {};
53+
// ^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] DerivedFromSpecialization#
54+
// relation implementation [..] SpecializedBase#
55+
// ^^^^^^^^^^^^^^^ reference [..] SpecializedBase#
56+
57+
template <typename T>
58+
// ^ definition local 4
59+
struct CrtpBase { T *t; };
60+
// ^^^^^^^^ definition [..] CrtpBase#
61+
// ^ reference local 4
62+
// ^ definition [..] CrtpBase#t.
63+
64+
struct CrtpDerivedMono: CrtpBase<CrtpDerivedMono> {};
65+
// ^^^^^^^^^^^^^^^ definition [..] CrtpDerivedMono#
66+
// relation implementation [..] CrtpBase#
67+
// ^^^^^^^^ reference [..] CrtpBase#
68+
// ^^^^^^^^^^^^^^^ reference [..] CrtpDerivedMono#
69+
70+
template <typename T>
71+
// ^ definition local 5
72+
struct CrtpDerivedTemplated: CrtpBase<CrtpDerivedTemplated<T>> {};
73+
// ^^^^^^^^^^^^^^^^^^^^ definition [..] CrtpDerivedTemplated#
74+
// relation implementation [..] CrtpBase#
75+
// ^^^^^^^^ reference [..] CrtpBase#
76+
// ^^^^^^^^^^^^^^^^^^^^ reference [..] CrtpDerivedTemplated#
77+
// ^ reference local 5
78+
79+
template <typename T>
80+
// ^ definition local 6
81+
struct DerivedFromTemplateParam: T {};
82+
// ^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] DerivedFromTemplateParam#
83+
// ^ reference local 6
84+
85+
template <template <typename> typename H>
86+
// ^ definition local 7
87+
struct DerivedFromTemplateTemplateParam: H<int> {};
88+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] DerivedFromTemplateTemplateParam#
89+
// ^ reference local 7

test/index/types/templates.snapshot.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
// ^ definition local 23
128128
struct M1: M0<T> {
129129
// ^^ definition [..] M1#
130+
// relation implementation [..] M0#
130131
// ^^ reference [..] M0#
131132
// ^ reference local 23
132133
using B = M0<T>;

test/index/types/types.snapshot.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@
317317
// | No documentation available.
318318
// relation implementation [..] Derived1#
319319
// relation implementation [..] Derived2#
320+
// relation implementation [..] DiamondBase#
320321
// ^^^^^^^^ reference [..] Derived1#
321322
// ^^^^^^^^ reference [..] Derived2#
322323

0 commit comments

Comments
 (0)