Skip to content

Commit 73adf26

Browse files
[clangd] Handle DeducedTemplateSpecializationType in HeuristicResolver (llvm#119107)
Fixes clangd/clangd#2227
1 parent 83cb3db commit 73adf26

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

clang-tools-extra/clangd/HeuristicResolver.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,16 @@ const Type *resolveDeclsToType(const std::vector<const NamedDecl *> &Decls,
118118
return nullptr;
119119
}
120120

121+
TemplateName getReferencedTemplateName(const Type *T) {
122+
if (const auto *TST = T->getAs<TemplateSpecializationType>()) {
123+
return TST->getTemplateName();
124+
}
125+
if (const auto *DTST = T->getAs<DeducedTemplateSpecializationType>()) {
126+
return DTST->getTemplateName();
127+
}
128+
return TemplateName();
129+
}
130+
121131
// Helper function for HeuristicResolver::resolveDependentMember()
122132
// which takes a possibly-dependent type `T` and heuristically
123133
// resolves it to a CXXRecordDecl in which we can try name lookup.
@@ -142,12 +152,12 @@ CXXRecordDecl *HeuristicResolverImpl::resolveTypeToRecordDecl(const Type *T) {
142152
if (!T)
143153
return nullptr;
144154

145-
const auto *TST = T->getAs<TemplateSpecializationType>();
146-
if (!TST)
155+
TemplateName TN = getReferencedTemplateName(T);
156+
if (TN.isNull())
147157
return nullptr;
148158

149-
const ClassTemplateDecl *TD = dyn_cast_or_null<ClassTemplateDecl>(
150-
TST->getTemplateName().getAsTemplateDecl());
159+
const ClassTemplateDecl *TD =
160+
dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
151161
if (!TD)
152162
return nullptr;
153163

clang-tools-extra/clangd/unittests/FindTargetTests.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,8 @@ TEST_F(TargetDeclTest, OverloadExpr) {
842842
}
843843

844844
TEST_F(TargetDeclTest, DependentExprs) {
845+
Flags.push_back("--std=c++20");
846+
845847
// Heuristic resolution of method of dependent field
846848
Code = R"cpp(
847849
struct A { void foo() {} };
@@ -962,6 +964,21 @@ TEST_F(TargetDeclTest, DependentExprs) {
962964
};
963965
)cpp";
964966
EXPECT_DECLS("MemberExpr", "void find()");
967+
968+
// Base expression is the type of a non-type template parameter
969+
// which is deduced using CTAD.
970+
Code = R"cpp(
971+
template <int N>
972+
struct Waldo {
973+
const int found = N;
974+
};
975+
976+
template <Waldo W>
977+
int test() {
978+
return W.[[found]];
979+
}
980+
)cpp";
981+
EXPECT_DECLS("CXXDependentScopeMemberExpr", "const int found = N");
965982
}
966983

967984
TEST_F(TargetDeclTest, DependentTypes) {

0 commit comments

Comments
 (0)