Skip to content

Commit 1cf1a10

Browse files
fix: Emit references for dependent members (#295)
Handles some cases for dependent members, but doesn't handle lookup into related semantic contexts. This is important for browsing template-heavy code due to use of inheritance.
1 parent f8ede80 commit 1cf1a10

File tree

5 files changed

+134
-1
lines changed

5 files changed

+134
-1
lines changed

indexer/ClangAstMacros.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525

2626
#define FOR_EACH_EXPR_TO_BE_INDEXED(F) \
2727
F(CXXConstruct) \
28+
F(CXXDependentScopeMember) \
2829
F(DeclRef) \
29-
F(Member)
30+
F(Member) \
31+
F(UnresolvedMember)
3032

3133
#define FOR_EACH_TYPE_TO_BE_INDEXED(F) \
3234
F(Enum) \

indexer/Indexer.cc

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,13 @@ void TuIndexer::saveCXXConstructExpr(
788788
}
789789
}
790790

791+
void TuIndexer::saveCXXDependentScopeMemberExpr(
792+
const clang::CXXDependentScopeMemberExpr &cxxDepScopeMemberExpr) {
793+
this->trySaveMemberReferenceViaLookup(
794+
cxxDepScopeMemberExpr.getBaseType(),
795+
cxxDepScopeMemberExpr.getMemberNameInfo());
796+
}
797+
791798
void TuIndexer::saveDeclRefExpr(const clang::DeclRefExpr &declRefExpr) {
792799
// In the presence of 'using', prefer going to the 'using' instead
793800
// of directly dereferencing.
@@ -826,6 +833,40 @@ void TuIndexer::saveMemberExpr(const clang::MemberExpr &memberExpr) {
826833
this->saveReference(optSymbol.value(), memberExpr.getMemberLoc());
827834
}
828835

836+
void TuIndexer::saveUnresolvedMemberExpr(
837+
const clang::UnresolvedMemberExpr &unresolvedMemberExpr) {
838+
this->trySaveMemberReferenceViaLookup(
839+
unresolvedMemberExpr.getBaseType(),
840+
unresolvedMemberExpr.getMemberNameInfo());
841+
}
842+
843+
void TuIndexer::trySaveMemberReferenceViaLookup(
844+
const clang::QualType &baseType,
845+
const clang::DeclarationNameInfo &memberNameInfo) {
846+
if (baseType.isNull()) {
847+
return;
848+
}
849+
clang::QualType actualBaseType = baseType.getCanonicalType();
850+
// C++23's 'deducing this' feature allows the base type to be a reference
851+
if (baseType->isPointerType() || baseType->isReferenceType()) {
852+
actualBaseType = baseType->getPointeeType();
853+
}
854+
auto *recordDecl = actualBaseType->getAsCXXRecordDecl();
855+
if (!recordDecl) {
856+
return;
857+
}
858+
// FIXME(issue: https://github.com/sourcegraph/scip-clang/issues/296):
859+
// We should try to use more standard code which takes
860+
// inheritance into account.
861+
auto lookupResult = recordDecl->lookup(memberNameInfo.getName());
862+
for (auto *namedDecl : lookupResult) {
863+
auto optSymbol = this->symbolFormatter.getNamedDeclSymbol(*namedDecl);
864+
if (optSymbol) {
865+
this->saveReference(*optSymbol, memberNameInfo.getLoc());
866+
}
867+
}
868+
}
869+
829870
void TuIndexer::emitDocumentOccurrencesAndSymbols(
830871
bool deterministic, clang::FileID fileId, scip::Document &scipDocument) {
831872
auto it = this->documentMap.find({fileId});

indexer/Indexer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ FOR_EACH_TYPE_TO_BE_INDEXED(FORWARD_DECLARE)
3535

3636
class ASTContext;
3737
class Decl;
38+
class DeclarationNameInfo;
3839
class LangOptions;
3940
class MacroDefinition;
4041
class MacroInfo;
@@ -269,6 +270,8 @@ class TuIndexer final {
269270
FOR_EACH_EXPR_TO_BE_INDEXED(SAVE_EXPR)
270271
#undef SAVE_EXPR
271272
void saveNestedNameSpecifierLoc(const clang::NestedNameSpecifierLoc &);
273+
void trySaveMemberReferenceViaLookup(const clang::QualType &,
274+
const clang::DeclarationNameInfo &);
272275

273276
#define SAVE_TYPE_LOC(TypeName) \
274277
void save##TypeName##TypeLoc(const clang::TypeName##TypeLoc &);

test/index/functions/template_body.cc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,35 @@ void f() {
1818
// - Templated function-local classes
1919
// - Templates inside function-local classes
2020
}
21+
22+
template <typename T>
23+
struct Z {
24+
void f0() {}
25+
26+
void f1() {
27+
f0();
28+
}
29+
30+
template <typename U>
31+
void g0() {
32+
f0();
33+
}
34+
35+
template <typename U>
36+
void g1() {
37+
g0<U>();
38+
}
39+
};
40+
41+
template <typename T>
42+
struct ZZ : Z<T> {
43+
void ff0() {
44+
this->f0();
45+
}
46+
47+
template <typename U>
48+
void gg0() {
49+
this->f0();
50+
this->template g0<U>();
51+
}
52+
};

test/index/functions/template_body.snapshot.cc

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@
1717

1818
(void)C().plain_field;
1919
// ^ reference [..] f(49f6e7a06ebc5aa8).C#
20+
// ^^^^^^^^^^^ reference [..] f(49f6e7a06ebc5aa8).C#plain_field.
2021
(void)C().dependent_field;
2122
// ^ reference [..] f(49f6e7a06ebc5aa8).C#
23+
// ^^^^^^^^^^^^^^^ reference [..] f(49f6e7a06ebc5aa8).C#dependent_field.
2224
C().g();
2325
// ^ reference [..] f(49f6e7a06ebc5aa8).C#
26+
// ^ reference [..] f(49f6e7a06ebc5aa8).C#g(49f6e7a06ebc5aa8).
2427

2528
int x = 0;
2629
// ^ definition local 1
@@ -31,3 +34,55 @@
3134
// - Templated function-local classes
3235
// - Templates inside function-local classes
3336
}
37+
38+
template <typename T>
39+
// ^ definition local 2
40+
struct Z {
41+
// ^ definition [..] Z#
42+
void f0() {}
43+
// ^^ definition [..] Z#f0(49f6e7a06ebc5aa8).
44+
45+
void f1() {
46+
// ^^ definition [..] Z#f1(49f6e7a06ebc5aa8).
47+
f0();
48+
// ^^ reference [..] Z#f0(49f6e7a06ebc5aa8).
49+
}
50+
51+
template <typename U>
52+
// ^ definition local 3
53+
void g0() {
54+
// ^^ definition [..] Z#g0(49f6e7a06ebc5aa8).
55+
f0();
56+
// ^^ reference [..] Z#f0(49f6e7a06ebc5aa8).
57+
}
58+
59+
template <typename U>
60+
// ^ definition local 4
61+
void g1() {
62+
// ^^ definition [..] Z#g1(49f6e7a06ebc5aa8).
63+
g0<U>();
64+
// ^^ reference [..] Z#g0(49f6e7a06ebc5aa8).
65+
// ^ reference local 4
66+
}
67+
};
68+
69+
template <typename T>
70+
// ^ definition local 5
71+
struct ZZ : Z<T> {
72+
// ^^ definition [..] ZZ#
73+
// ^ reference [..] Z#
74+
// ^ reference local 5
75+
void ff0() {
76+
// ^^^ definition [..] ZZ#ff0(49f6e7a06ebc5aa8).
77+
this->f0();
78+
}
79+
80+
template <typename U>
81+
// ^ definition local 6
82+
void gg0() {
83+
// ^^^ definition [..] ZZ#gg0(49f6e7a06ebc5aa8).
84+
this->f0();
85+
this->template g0<U>();
86+
// ^ reference local 6
87+
}
88+
};

0 commit comments

Comments
 (0)