Skip to content

Commit 7915434

Browse files
nv-cmeerwdaveedvdv-nvidia
authored andcommitted
CTAD through a template template parameter of an alias template [GH edgcpp#173]
1 parent 8360528 commit 7915434

13 files changed

Lines changed: 881 additions & 45 deletions

File tree

‎src/Changes‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,28 @@ ref-qualifiers. They now leave such types unchanged. For example, with
1212
using F = __add_pointer(F); // Previously a spurious error, now okay.
1313

1414

15+
10/20/26 [GH #173]
16+
CTAD through a template template parameter of an alias template
17+
18+
With the changes for EDGcpfe/28857 (in version 6.9), a decltype in an alias
19+
template that deduces class template arguments through one of the alias
20+
template's template template parameters could trigger an internal error due to
21+
a failed assertion in generic_cast_operand, when the alias was used with
22+
dependent arguments, for example in a requires expression. For example, with
23+
--c++20:
24+
25+
template<typename T> struct S { S(T); };
26+
template<template<typename> class TT> using A = decltype(TT(0));
27+
template<template<typename> class TT>
28+
constexpr bool b = requires { typename A<TT>; };
29+
static_assert(b<S>); // Previously an internal error, now okay.
30+
31+
In addition, deduction now succeeds when the template bound to the template
32+
template parameter has more parameters (with default arguments or packs) than
33+
the parameter itself, and a mismatch is now treated as a deduction failure
34+
rather than an error in contexts where errors are not issued.
35+
36+
1537
10/19/26 [GH #218]
1638
Reachability after a temporary with a "noreturn" constructor or destructor
1739

‎src/il.c‎

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11172,11 +11172,15 @@ vk_ext, ...) and, for vk_ext, its size_constant.
1117211172
#endif /* GNU_VECTOR_TYPES_ALLOWED */
1117311173

1117411174
a_type_ptr make_class_template_placeholder(a_symbol_ptr class_template,
11175-
a_source_position *pos)
11175+
a_source_position *pos,
11176+
/* Defaulted: */ a_symbol_ptr bound_template)
1117611177
/*
1117711178
Create a type entry representing a class template used for C++ 17 class
1117811179
template argument deduction. The result is a special kind of tk_template_param
11179-
entry. pos is used to establish the type entry's position information.
11180+
entry. pos is used to establish the type entry's position information. When
11181+
class_template is a type template template parameter, bound_template (or the
11182+
current argument bound to class_template if bound_template is NULL) is recorded
11183+
in the supplement's template_symbol field.
1118011184
*/
1118111185
{
1118211186
a_symbol_ptr sym;
@@ -11188,6 +11192,16 @@ entry. pos is used to establish the type entry's position information.
1118811192
a_template_symbol_supplement_ptr
1118911193
tssp = template_supplement_for_symbol(class_template);
1119011194

11195+
if (bound_template == NULL) {
11196+
/* When not created by placeholder substitution, check whether an enclosing
11197+
instantiation has bound an argument to a template template parameter
11198+
(when unbound, argument_template points to class_template itself). */
11199+
a_symbol_ptr arg_sym = template_argument_if_template_template_param(
11200+
class_template);
11201+
if (arg_sym != class_template) {
11202+
bound_template = arg_sym;
11203+
} /* if */
11204+
} /* if */
1119111205
if (!alias_ctad_enabled && alias_ctad_allowed &&
1119211206
is_alias_template_symbol(class_template)) {
1119311207
if (clang_mode ||
@@ -11210,7 +11224,11 @@ entry. pos is used to establish the type entry's position information.
1121011224
sym->decl_scope = class_template->decl_scope;
1121111225
sym->variant.type.ptr = type;
1121211226
tpcp->depth = CLASS_TEMPLATE_PLACEHOLDER_NESTING_DEPTH;
11227+
/* For a template template parameter, CTAD keeps using the parameter's own
11228+
parameter list and defaults, while substitution goes through the template
11229+
bound to it. */
1121311230
tptsp->constraint.class_template_symbol = class_template;
11231+
tptsp->template_symbol = bound_template;
1121411232
set_type_size(type);
1121511233
set_source_corresp(&type->source_corresp, sym);
1121611234
if (!class_template->is_error &&

‎src/il.h‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3899,8 +3899,10 @@ a routine.
38993899
(con)->variant.address.offset == 0 && !(con)->implicit_cast)
39003900

39013901
extern
3902-
a_type_ptr make_class_template_placeholder(struct a_symbol *class_template,
3903-
a_source_position *pos);
3902+
a_type_ptr make_class_template_placeholder(
3903+
struct a_symbol *class_template,
3904+
a_source_position *pos,
3905+
struct a_symbol *bound_template = NULL);
39043906

39053907
extern a_type_ptr make_auto_type(a_source_position *pos,
39063908
a_boolean is_decltype_auto);

‎src/il_def.h‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9358,9 +9358,11 @@ typedef struct a_template_param_type_supplement {
93589358
*template_symbol;
93599359
/* For templates (including C++/CLI generics) points
93609360
to the sk_class_template or sk_function_template
9361-
symbol of which this is a type parameter. NULL
9362-
otherwise. Used in the front end only; cannot
9363-
be used in back ends. */
9361+
symbol of which this is a type parameter. For a
9362+
placeholder type naming a type template template
9363+
parameter, points to the bound template argument,
9364+
if any. NULL otherwise. Used in the front end
9365+
only; cannot be used in back ends. */
93649366
#if MICROSOFT_EXTENSIONS_ALLOWED
93659367
a_generic_constraint_ptr
93669368
generic_constraints;

‎src/overload.c‎

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30972,19 +30972,25 @@ set to TRUE and FALSE is returned.
3097230972
if (is_template_template_param_symbol(ct_sym)) {
3097330973
/* Class template argument deduction for a template template parameter: use
3097430974
guides synthesized from the class or alias template argument. */
30975-
a_symbol_ptr bound_tttp_arg_sym;
30975+
a_symbol_ptr bound_tttp_arg_sym, target_sym;
3097630976
a_boolean is_deducible_template;
3097730977

30978+
target_sym = placeholder_type->variant.template_param.extra_info
30979+
->template_symbol;
3097830980
bound_tttp_arg_sym = bound_template_template_argument(
30979-
ct_sym, &is_deducible_template);
30981+
target_sym != NULL ? target_sym : ct_sym,
30982+
&is_deducible_template);
3098030983
if (bound_tttp_arg_sym == NULL) {
3098130984
/* Still dependent. */
3098230985
*still_dependent = TRUE;
3098330986
result = FALSE;
3098430987
goto done;
3098530988
} else if (!is_deducible_template || bound_tttp_arg_sym->is_error) {
3098630989
/* Template argument does not name a deducible template. */
30987-
pos_sy_error(ec_no_class_template_guide, source_pos, bound_tttp_arg_sym);
30990+
if (expr_error_should_be_issued()) {
30991+
pos_sy_error(ec_no_class_template_guide, source_pos,
30992+
bound_tttp_arg_sym);
30993+
} /* if */
3098830994
*still_dependent = FALSE;
3098930995
result = FALSE;
3099030996
goto done;
@@ -31046,7 +31052,9 @@ set to TRUE and FALSE is returned.
3104631052
guide_set = ct_tssp->variant.class_template.deduction_guides;
3104731053
} /* if */
3104831054
if (guide_set == NULL) {
31049-
pos_sy_error(ec_no_class_template_guide, source_pos, ct_sym);
31055+
if (expr_error_should_be_issued()) {
31056+
pos_sy_error(ec_no_class_template_guide, source_pos, ct_sym);
31057+
} /* if */
3105031058
} else {
3105131059
selected_sym = select_overloaded_function(
3105231060
guide_set,

0 commit comments

Comments
 (0)