[clang-tools-extra] [clangd] Handle DeducedTemplateSpecializationType in HeuristicResolver (PR #119107)

Nathan Ridge via cfe-commits cfe-commits at lists.llvm.org
Sat Dec 7 19:03:58 PST 2024


https://github.com/HighCommander4 created https://github.com/llvm/llvm-project/pull/119107

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

>From 85307a28e99c596afb47059ddea6f1e574ca55bf Mon Sep 17 00:00:00 2001
From: Nathan Ridge <zeratul976 at hotmail.com>
Date: Sat, 7 Dec 2024 22:03:02 -0500
Subject: [PATCH] [clangd] Handle DeducedTemplateSpecializationType in
 HeuristicResolver

Fixes https://github.com/clangd/clangd/issues/2227
---
 clang-tools-extra/clangd/HeuristicResolver.cpp | 18 ++++++++++++++----
 .../clangd/unittests/FindTargetTests.cpp       | 17 +++++++++++++++++
 2 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/clang-tools-extra/clangd/HeuristicResolver.cpp b/clang-tools-extra/clangd/HeuristicResolver.cpp
index 26d54200eeffd2..9eb892e8e4a8ea 100644
--- a/clang-tools-extra/clangd/HeuristicResolver.cpp
+++ b/clang-tools-extra/clangd/HeuristicResolver.cpp
@@ -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.
@@ -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;
 
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index 3220a5a6a98250..fc54f89f4941e1 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -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() {} };
@@ -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) {



More information about the cfe-commits mailing list