Skip to content

[clangd] Handle DeducedTemplateSpecializationType in HeuristicResolver #119107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions clang-tools-extra/clangd/HeuristicResolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,16 @@ const Type *resolveDeclsToType(const std::vector<const NamedDecl *> &Decls,
return nullptr;
}

TemplateName getReferencedTemplateName(const Type *T) {
if (const auto *TST = T->getAs<TemplateSpecializationType>()) {
return TST->getTemplateName();
}
if (const auto *DTST = T->getAs<DeducedTemplateSpecializationType>()) {
return DTST->getTemplateName();
}
return TemplateName();
}

// Helper function for HeuristicResolver::resolveDependentMember()
// which takes a possibly-dependent type `T` and heuristically
// resolves it to a CXXRecordDecl in which we can try name lookup.
Expand All @@ -142,12 +152,12 @@ CXXRecordDecl *HeuristicResolverImpl::resolveTypeToRecordDecl(const Type *T) {
if (!T)
return nullptr;

const auto *TST = T->getAs<TemplateSpecializationType>();
if (!TST)
TemplateName TN = getReferencedTemplateName(T);
if (TN.isNull())
return nullptr;

const ClassTemplateDecl *TD = dyn_cast_or_null<ClassTemplateDecl>(
TST->getTemplateName().getAsTemplateDecl());
const ClassTemplateDecl *TD =
dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
if (!TD)
return nullptr;

Expand Down
17 changes: 17 additions & 0 deletions clang-tools-extra/clangd/unittests/FindTargetTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,8 @@ TEST_F(TargetDeclTest, OverloadExpr) {
}

TEST_F(TargetDeclTest, DependentExprs) {
Flags.push_back("--std=c++20");

// Heuristic resolution of method of dependent field
Code = R"cpp(
struct A { void foo() {} };
Expand Down Expand Up @@ -962,6 +964,21 @@ TEST_F(TargetDeclTest, DependentExprs) {
};
)cpp";
EXPECT_DECLS("MemberExpr", "void find()");

// Base expression is the type of a non-type template parameter
// which is deduced using CTAD.
Code = R"cpp(
template <int N>
struct Waldo {
const int found = N;
};

template <Waldo W>
int test() {
return W.[[found]];
}
)cpp";
EXPECT_DECLS("CXXDependentScopeMemberExpr", "const int found = N");
}

TEST_F(TargetDeclTest, DependentTypes) {
Expand Down
Loading