Skip to content

Commit 141de74

Browse files
authored
[clang][Sema] Populate function template depth at AddTemplateOverloadCandidate (#80395)
This is yet another one-line patch to fix crashes on constraint substitution. ```cpp template <class, class> struct formatter; template <class, class> struct basic_format_context {}; template <typename CharType> concept has_format_function = format(basic_format_context<CharType, CharType>()); template <typename ValueType, typename CharType> requires has_format_function<CharType> struct formatter<ValueType, CharType> { template <typename OutputIt> CharType format(basic_format_context<OutputIt, CharType>); }; ``` In this case, we would build up a `RecoveryExpr` for a call within a constraint expression due to the absence of viable functions. The heuristic algorithm attempted to find such a function inside of a ClassTemplatePartialSpecialization, from which we started to substitute its requires-expression, and it succeeded with a FunctionTemplate such that 1) It has only one parameter, which is dependent. 2) The only one parameter depends on two template parameters. They are, in canonical form, `<template-parameter-1-0>` and `<template-parameter-0-1>` respectively. Before we emit an error, we still want to recover the most viable functions. This goes downhill to deducing template parameters against its arguments, where we would collect the argument type with the same depth as the parameter type into a Deduced set. The size of the set is presumed to be that of function template parameters, which is 1 in this case. However, since we haven't yet properly set the template depth before the dance, we'll end up putting the type for `<template-parameter-0-1>` to the second position of Deduced set, which is unfortunately an access violation! The bug seems to appear since clang 12.0. This fixes [the case](#58548 (comment)).
1 parent 78b4e7c commit 141de74

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ Bug Fixes to C++ Support
190190
- Fix for crash when using a erroneous type in a return statement.
191191
Fixes (`#63244 <https://github.com/llvm/llvm-project/issues/63244>`_)
192192
and (`#79745 <https://github.com/llvm/llvm-project/issues/79745>`_)
193+
- Fixed an out-of-bounds error caused by building a recovery expression for ill-formed
194+
function calls while substituting into constraints.
195+
(`#58548 <https://github.com/llvm/llvm-project/issues/58548>`_)
193196
- Fix incorrect code generation caused by the object argument of ``static operator()`` and ``static operator[]`` calls not being evaluated.
194197
Fixes (`#67976 <https://github.com/llvm/llvm-project/issues/67976>`_)
195198
- Fix crash and diagnostic with const qualified member operator new.

clang/lib/Sema/SemaOverload.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7623,7 +7623,8 @@ void Sema::AddTemplateOverloadCandidate(
76237623
// functions. In such a case, the candidate functions generated from each
76247624
// function template are combined with the set of non-template candidate
76257625
// functions.
7626-
TemplateDeductionInfo Info(CandidateSet.getLocation());
7626+
TemplateDeductionInfo Info(CandidateSet.getLocation(),
7627+
FunctionTemplate->getTemplateDepth());
76277628
FunctionDecl *Specialization = nullptr;
76287629
ConversionSequenceList Conversions;
76297630
if (TemplateDeductionResult Result = DeduceTemplateArguments(

clang/test/SemaTemplate/concepts-recovery-expr.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,30 @@ void StaticMemOVCUse() {
180180
// expected-note@#SMEMOVC3 {{candidate template ignored: constraints not satisfied}}
181181
// expected-note@#SMEMOVC3REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
182182
}
183+
184+
namespace GH58548 {
185+
186+
template <class, class> struct formatter; // #primary-template
187+
template <class, class> struct basic_format_context {};
188+
189+
template <typename CharType>
190+
concept has_format_function =
191+
format(basic_format_context<CharType, CharType>());
192+
193+
template <typename ValueType, typename CharType>
194+
requires has_format_function<CharType>
195+
struct formatter<ValueType, CharType> {
196+
template <typename OutputIt>
197+
CharType format(basic_format_context<OutputIt, CharType>);
198+
};
199+
200+
template <class Ctx> int handle_replacement_field(Ctx arg) {
201+
formatter<decltype(arg), int> ctx; // expected-error {{implicit instantiation of undefined template}}
202+
return 0;
203+
}
204+
205+
int x = handle_replacement_field(0);
206+
// expected-note@-1 {{template specialization 'GH58548::handle_replacement_field<int>' requested here}}
207+
// expected-note@#primary-template {{is declared here}}
208+
209+
} // GH58548

0 commit comments

Comments
 (0)