Author: Nathan Ridge Date: 2025-03-21T19:15:18-04:00 New Revision: 44573bc1528831b13b17afac158f4860af42570e
URL: https://github.com/llvm/llvm-project/commit/44573bc1528831b13b17afac158f4860af42570e DIFF: https://github.com/llvm/llvm-project/commit/44573bc1528831b13b17afac158f4860af42570e.diff LOG: [clang][HeuristicResolver] Default argument heuristic for template parameters (#132465) Fixes https://github.com/clangd/clangd/discussions/1056 Added: Modified: clang/lib/Sema/HeuristicResolver.cpp clang/unittests/Sema/HeuristicResolverTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/HeuristicResolver.cpp b/clang/lib/Sema/HeuristicResolver.cpp index 7aecd2a73b539..4544d75ea73c4 100644 --- a/clang/lib/Sema/HeuristicResolver.cpp +++ b/clang/lib/Sema/HeuristicResolver.cpp @@ -11,6 +11,7 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" namespace clang { @@ -247,6 +248,20 @@ QualType HeuristicResolverImpl::simplifyType(QualType Type, const Expr *E, } } } + if (const auto *TTPT = dyn_cast_if_present<TemplateTypeParmType>(T.Type)) { + // We can't do much useful with a template parameter (e.g. we cannot look + // up member names inside it). However, if the template parameter has a + // default argument, as a heuristic we can replace T with the default + // argument type. + if (const auto *TTPD = TTPT->getDecl()) { + if (TTPD->hasDefaultArgument()) { + const auto &DefaultArg = TTPD->getDefaultArgument().getArgument(); + if (DefaultArg.getKind() == TemplateArgument::Type) { + return {DefaultArg.getAsType()}; + } + } + } + } return T; }; // As an additional protection against infinite loops, bound the number of diff --git a/clang/unittests/Sema/HeuristicResolverTest.cpp b/clang/unittests/Sema/HeuristicResolverTest.cpp index c7cfe7917c532..f7eb4b23c2ab0 100644 --- a/clang/unittests/Sema/HeuristicResolverTest.cpp +++ b/clang/unittests/Sema/HeuristicResolverTest.cpp @@ -410,6 +410,40 @@ TEST(HeuristicResolver, MemberExpr_HangIssue126536) { cxxDependentScopeMemberExpr(hasMemberName("foo")).bind("input")); } +TEST(HeuristicResolver, MemberExpr_DefaultTemplateArgument) { + std::string Code = R"cpp( + struct Default { + void foo(); + }; + template <typename T = Default> + void bar(T t) { + t.foo(); + } + )cpp"; + // Test resolution of "foo" in "t.foo()". + expectResolution( + Code, &HeuristicResolver::resolveMemberExpr, + cxxDependentScopeMemberExpr(hasMemberName("foo")).bind("input"), + cxxMethodDecl(hasName("foo")).bind("output")); +} + +TEST(HeuristicResolver, MemberExpr_DefaultTemplateArgument_Recursive) { + std::string Code = R"cpp( + struct Default { + void foo(); + }; + template <typename D = Default, typename T = D> + void bar(T t) { + t.foo(); + } + )cpp"; + // Test resolution of "foo" in "t.foo()". + expectResolution( + Code, &HeuristicResolver::resolveMemberExpr, + cxxDependentScopeMemberExpr(hasMemberName("foo")).bind("input"), + cxxMethodDecl(hasName("foo")).bind("output")); +} + TEST(HeuristicResolver, DeclRefExpr_StaticMethod) { std::string Code = R"cpp( template <typename T> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits