Skip to content

Commit 43ec53b

Browse files
[clang][HeuristicResolver] Default argument heuristic for template template parameters (#156404)
Fixes clangd/clangd#2478
1 parent f3c9c6c commit 43ec53b

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

clang/lib/Sema/HeuristicResolver.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,25 @@ QualType HeuristicResolverImpl::simplifyType(QualType Type, const Expr *E,
259259
}
260260
}
261261
}
262+
263+
// Similarly, heuristically replace a template template parameter with its
264+
// default argument if it has one.
265+
if (const auto *TST =
266+
dyn_cast_if_present<TemplateSpecializationType>(T.Type)) {
267+
if (const auto *TTPD = dyn_cast_if_present<TemplateTemplateParmDecl>(
268+
TST->getTemplateName().getAsTemplateDecl())) {
269+
if (TTPD->hasDefaultArgument()) {
270+
const auto &DefaultArg = TTPD->getDefaultArgument().getArgument();
271+
if (DefaultArg.getKind() == TemplateArgument::Template) {
272+
if (const auto *CTD = dyn_cast_if_present<ClassTemplateDecl>(
273+
DefaultArg.getAsTemplate().getAsTemplateDecl())) {
274+
return {Ctx.getCanonicalTagType(CTD->getTemplatedDecl())};
275+
}
276+
}
277+
}
278+
}
279+
}
280+
262281
// Check if the expression refers to an explicit object parameter of
263282
// templated type. If so, heuristically treat it as having the type of the
264283
// enclosing class.

clang/unittests/Sema/HeuristicResolverTest.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,24 @@ TEST(HeuristicResolver, MemberExpr_DefaultTemplateArgument_Recursive) {
558558
cxxMethodDecl(hasName("foo")).bind("output"));
559559
}
560560

561+
TEST(HeuristicResolver, MemberExpr_DefaultTemplateTemplateArgument) {
562+
std::string Code = R"cpp(
563+
template <typename T>
564+
struct vector {
565+
void push_back(T);
566+
};
567+
template <typename Element, template <typename> class Container = vector>
568+
void foo(Container<Element> c, Element e) {
569+
c.push_back(e);
570+
}
571+
)cpp";
572+
// Test resolution of "push_back" in "c.push_back(e)".
573+
expectResolution(
574+
Code, &HeuristicResolver::resolveMemberExpr,
575+
cxxDependentScopeMemberExpr(hasMemberName("push_back")).bind("input"),
576+
cxxMethodDecl(hasName("push_back")).bind("output"));
577+
}
578+
561579
TEST(HeuristicResolver, MemberExpr_ExplicitObjectParameter) {
562580
std::string Code = R"cpp(
563581
struct Foo {

0 commit comments

Comments
 (0)