diff --git a/clang/lib/Sema/HeuristicResolver.cpp b/clang/lib/Sema/HeuristicResolver.cpp index a7fe4ea28b72c..cbdefaa57aacb 100644 --- a/clang/lib/Sema/HeuristicResolver.cpp +++ b/clang/lib/Sema/HeuristicResolver.cpp @@ -259,6 +259,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(T.Type)) { + if (const auto *TTPD = dyn_cast_if_present( + 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( + 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 0eb14f032f16c..a00632f232ea5 100644 --- a/clang/unittests/Sema/HeuristicResolverTest.cpp +++ b/clang/unittests/Sema/HeuristicResolverTest.cpp @@ -558,6 +558,24 @@ TEST(HeuristicResolver, MemberExpr_DefaultTemplateArgument_Recursive) { cxxMethodDecl(hasName("foo")).bind("output")); } +TEST(HeuristicResolver, MemberExpr_DefaultTemplateTemplateArgument) { + std::string Code = R"cpp( + template + struct vector { + void push_back(T); + }; + template class Container = vector> + void foo(Container 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 {