Skip to content

Commit 32ca27b

Browse files
[clang][HeuristicResolver] Default argument heuristic for template parameters
1 parent 23a5c6d commit 32ca27b

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

clang/lib/Sema/HeuristicResolver.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "clang/AST/CXXInheritance.h"
1212
#include "clang/AST/DeclTemplate.h"
1313
#include "clang/AST/ExprCXX.h"
14+
#include "clang/AST/TemplateBase.h"
1415
#include "clang/AST/Type.h"
1516

1617
namespace clang {
@@ -125,6 +126,20 @@ TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) {
125126
if (!T)
126127
return nullptr;
127128

129+
// If T is the type of a template parameter, we can't get a useful TagDecl
130+
// out of it. However, if the template parameter has a default argument,
131+
// as a heuristic we can replace T with the default argument type.
132+
if (const auto *TTPT = dyn_cast<TemplateTypeParmType>(T)) {
133+
if (const auto *TTPD = TTPT->getDecl()) {
134+
if (TTPD->hasDefaultArgument()) {
135+
const auto &DefaultArg = TTPD->getDefaultArgument().getArgument();
136+
if (DefaultArg.getKind() == TemplateArgument::Type) {
137+
T = DefaultArg.getAsType().getTypePtrOrNull();
138+
}
139+
}
140+
}
141+
}
142+
128143
// Unwrap type sugar such as type aliases.
129144
T = T->getCanonicalTypeInternal().getTypePtr();
130145

clang/unittests/Sema/HeuristicResolverTest.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,23 @@ TEST(HeuristicResolver, MemberExpr_HangIssue126536) {
410410
cxxDependentScopeMemberExpr(hasMemberName("foo")).bind("input"));
411411
}
412412

413+
TEST(HeuristicResolver, MemberExpr_DefaultTemplateArgument) {
414+
std::string Code = R"cpp(
415+
struct Default {
416+
void foo();
417+
};
418+
template <typename T = Default>
419+
void bar(T t) {
420+
t.foo();
421+
}
422+
)cpp";
423+
// Test resolution of "foo" in "t.foo()".
424+
expectResolution(
425+
Code, &HeuristicResolver::resolveMemberExpr,
426+
cxxDependentScopeMemberExpr(hasMemberName("foo")).bind("input"),
427+
cxxMethodDecl(hasName("foo")).bind("output"));
428+
}
429+
413430
TEST(HeuristicResolver, DeclRefExpr_StaticMethod) {
414431
std::string Code = R"cpp(
415432
template <typename T>

0 commit comments

Comments
 (0)