[llvm-branch-commits] [clang] [clang][HeuristicResolver] Default argument heuristic for template template parameters (PR #156404)
Nathan Ridge via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Sep 1 22:09:02 PDT 2025
https://github.com/HighCommander4 created https://github.com/llvm/llvm-project/pull/156404
Fixes https://github.com/clangd/clangd/issues/2478
>From 7c8f310155914c17e8e3c6d485acb4464800ddd1 Mon Sep 17 00:00:00 2001
From: Nathan Ridge <zeratul976 at hotmail.com>
Date: Tue, 2 Sep 2025 01:06:07 -0400
Subject: [PATCH] [clang][HeuristicResolver] Default argument heuristic for
template template parameters
Fixes https://github.com/clangd/clangd/issues/2478
---
clang/lib/Sema/HeuristicResolver.cpp | 19 +++++++++++++++++++
.../unittests/Sema/HeuristicResolverTest.cpp | 18 ++++++++++++++++++
2 files changed, 37 insertions(+)
diff --git a/clang/lib/Sema/HeuristicResolver.cpp b/clang/lib/Sema/HeuristicResolver.cpp
index 8b424610feeda..6bfd1db602d4e 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -260,6 +260,25 @@ QualType HeuristicResolverImpl::simplifyType(QualType Type, const Expr *E,
}
}
}
+
+ // Similarly, heuristically replace a template template parameter with its
+ // default argument if it has one.
+ if (const auto *TST =
+ dyn_cast_if_present<TemplateSpecializationType>(T.Type)) {
+ if (const auto *TTPD = dyn_cast_if_present<TemplateTemplateParmDecl>(
+ TST->getTemplateName().getAsTemplateDecl())) {
+ if (TTPD->hasDefaultArgument()) {
+ const auto &DefaultArg = TTPD->getDefaultArgument().getArgument();
+ if (DefaultArg.getKind() == TemplateArgument::Template) {
+ if (const auto *CTD = dyn_cast_if_present<ClassTemplateDecl>(
+ DefaultArg.getAsTemplate().getAsTemplateDecl())) {
+ return {Ctx.getCanonicalTagType(CTD->getTemplatedDecl())};
+ }
+ }
+ }
+ }
+ }
+
// Check if the expression refers to an explicit object parameter of
// templated type. If so, heuristically treat it as having the type of the
// enclosing class.
diff --git a/clang/unittests/Sema/HeuristicResolverTest.cpp b/clang/unittests/Sema/HeuristicResolverTest.cpp
index cdbb4fe7c7eda..a69605e9f7466 100644
--- a/clang/unittests/Sema/HeuristicResolverTest.cpp
+++ b/clang/unittests/Sema/HeuristicResolverTest.cpp
@@ -545,6 +545,24 @@ TEST(HeuristicResolver, MemberExpr_DefaultTemplateArgument_Recursive) {
cxxMethodDecl(hasName("foo")).bind("output"));
}
+TEST(HeuristicResolver, MemberExpr_DefaultTemplateTemplateArgument) {
+ std::string Code = R"cpp(
+ template <typename T>
+ struct vector {
+ void push_back(T);
+ };
+ template <typename Element, template <typename> class Container = vector>
+ void foo(Container<Element> c, Element e) {
+ c.push_back(e);
+ }
+ )cpp";
+ // Test resolution of "push_back" in "c.push_back(e)".
+ expectResolution(
+ Code, &HeuristicResolver::resolveMemberExpr,
+ cxxDependentScopeMemberExpr(hasMemberName("push_back")).bind("input"),
+ cxxMethodDecl(hasName("push_back")).bind("output"));
+}
+
TEST(HeuristicResolver, MemberExpr_ExplicitObjectParameter) {
std::string Code = R"cpp(
struct Foo {
More information about the llvm-branch-commits
mailing list