Skip to content

Commit 7c8f310

Browse files
[clang][HeuristicResolver] Default argument heuristic for template template parameters
Fixes clangd/clangd#2478
1 parent 6791b7a commit 7c8f310

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

clang/unittests/Sema/HeuristicResolverTest.cpp

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

548+
TEST(HeuristicResolver, MemberExpr_DefaultTemplateTemplateArgument) {
549+
std::string Code = R"cpp(
550+
template <typename T>
551+
struct vector {
552+
void push_back(T);
553+
};
554+
template <typename Element, template <typename> class Container = vector>
555+
void foo(Container<Element> c, Element e) {
556+
c.push_back(e);
557+
}
558+
)cpp";
559+
// Test resolution of "push_back" in "c.push_back(e)".
560+
expectResolution(
561+
Code, &HeuristicResolver::resolveMemberExpr,
562+
cxxDependentScopeMemberExpr(hasMemberName("push_back")).bind("input"),
563+
cxxMethodDecl(hasName("push_back")).bind("output"));
564+
}
565+
548566
TEST(HeuristicResolver, MemberExpr_ExplicitObjectParameter) {
549567
std::string Code = R"cpp(
550568
struct Foo {

0 commit comments

Comments
 (0)