Skip to content

Commit a642eb8

Browse files
authored
[Clang][Sema] Fix crash when using name of UnresolvedUsingValueDecl with template arguments (llvm#83842)
The following snippet causes a crash: ``` template<typename T> struct A : T { using T::f; void f(); void g() { f<int>(); // crash here } }; ``` This happens because we cast the result of `getAsTemplateNameDecl` as a `TemplateDecl` in `Sema::ClassifyName`, which we cannot do for an `UnresolvedUsingValueDecl`. This patch fixes the crash by considering a name to be that of a template if _any_ function declaration is found per [temp.names] p3.3.
1 parent 894f52f commit a642eb8

File tree

4 files changed

+42
-5
lines changed

4 files changed

+42
-5
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,8 @@ Bug Fixes to C++ Support
305305
our attention by an attempt to fix in (#GH77703). Fixes (#GH83385).
306306
- Fix evaluation of some immediate calls in default arguments.
307307
Fixes (#GH80630)
308+
- Fix a crash when an explicit template argument list is used with a name for which lookup
309+
finds a non-template function and a dependent using declarator.
308310

309311
Bug Fixes to AST Handling
310312
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaDecl.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,9 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
11101110
// unqualified-id followed by a < and name lookup finds either one
11111111
// or more functions or finds nothing.
11121112
if (!IsFilteredTemplateName)
1113-
FilterAcceptableTemplateNames(Result);
1113+
FilterAcceptableTemplateNames(Result,
1114+
/*AllowFunctionTemplates=*/true,
1115+
/*AllowDependent=*/true);
11141116

11151117
bool IsFunctionTemplate;
11161118
bool IsVarTemplate;
@@ -1120,6 +1122,7 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
11201122
Template = Context.getOverloadedTemplateName(Result.begin(),
11211123
Result.end());
11221124
} else if (!Result.empty()) {
1125+
assert(!Result.isUnresolvableResult());
11231126
auto *TD = cast<TemplateDecl>(getAsTemplateNameDecl(
11241127
*Result.begin(), /*AllowFunctionTemplates=*/true,
11251128
/*AllowDependent=*/false));

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -491,18 +491,20 @@ bool Sema::LookupTemplateName(LookupResult &Found,
491491
// To keep our behavior consistent, we apply the "finds nothing" part in
492492
// all language modes, and diagnose the empty lookup in ActOnCallExpr if we
493493
// successfully form a call to an undeclared template-id.
494-
bool AllFunctions =
495-
getLangOpts().CPlusPlus20 && llvm::all_of(Found, [](NamedDecl *ND) {
494+
bool AnyFunctions =
495+
getLangOpts().CPlusPlus20 && llvm::any_of(Found, [](NamedDecl *ND) {
496496
return isa<FunctionDecl>(ND->getUnderlyingDecl());
497497
});
498-
if (AllFunctions || (Found.empty() && !IsDependent)) {
498+
if (AnyFunctions || (Found.empty() && !IsDependent)) {
499499
// If lookup found any functions, or if this is a name that can only be
500500
// used for a function, then strongly assume this is a function
501501
// template-id.
502502
*ATK = (Found.empty() && Found.getLookupName().isIdentifier())
503503
? AssumedTemplateKind::FoundNothing
504504
: AssumedTemplateKind::FoundFunctions;
505-
Found.clear();
505+
FilterAcceptableTemplateNames(Found,
506+
/*AllowFunctionTemplates*/ true,
507+
/*AllowDependent*/ true);
506508
return false;
507509
}
508510
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
2+
3+
template<typename T>
4+
struct A : T {
5+
using T::f;
6+
using T::g;
7+
using T::h;
8+
9+
void f();
10+
void g();
11+
12+
void i() {
13+
f<int>();
14+
g<int>(); // expected-error{{no member named 'g' in 'A<B>'}}
15+
h<int>(); // expected-error{{expected '(' for function-style cast or type construction}}
16+
// expected-error@-1{{expected expression}}
17+
}
18+
};
19+
20+
struct B {
21+
template<typename T>
22+
void f();
23+
24+
void g();
25+
26+
template<typename T>
27+
void h();
28+
};
29+
30+
template struct A<B>; // expected-note{{in instantiation of member function 'A<B>::i' requested here}}

0 commit comments

Comments
 (0)