Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/Changes
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,28 @@ ref-qualifiers. They now leave such types unchanged. For example, with
using F = __add_pointer(F); // Previously a spurious error, now okay.


10/20/26 [GH #173]
CTAD through a template template parameter of an alias template

With the changes for EDGcpfe/28857 (in version 6.9), a decltype in an alias
template that deduces class template arguments through one of the alias
template's template template parameters could trigger an internal error due to
a failed assertion in generic_cast_operand, when the alias was used with
dependent arguments, for example in a requires expression. For example, with
--c++20:

template<typename T> struct S { S(T); };
template<template<typename> class TT> using A = decltype(TT(0));
template<template<typename> class TT>
constexpr bool b = requires { typename A<TT>; };
static_assert(b<S>); // Previously an internal error, now okay.

In addition, deduction now succeeds when the template bound to the template
template parameter has more parameters (with default arguments or packs) than
the parameter itself, and a mismatch is now treated as a deduction failure
rather than an error in contexts where errors are not issued.


10/19/26 [GH #218]
Reachability after a temporary with a "noreturn" constructor or destructor

Expand Down
22 changes: 20 additions & 2 deletions src/il.c
Original file line number Diff line number Diff line change
Expand Up @@ -11172,11 +11172,15 @@ vk_ext, ...) and, for vk_ext, its size_constant.
#endif /* GNU_VECTOR_TYPES_ALLOWED */

a_type_ptr make_class_template_placeholder(a_symbol_ptr class_template,
a_source_position *pos)
a_source_position *pos,
/* Defaulted: */ a_symbol_ptr bound_template)
/*
Create a type entry representing a class template used for C++ 17 class
template argument deduction. The result is a special kind of tk_template_param
entry. pos is used to establish the type entry's position information.
entry. pos is used to establish the type entry's position information. When
class_template is a type template template parameter, bound_template (or the
current argument bound to class_template if bound_template is NULL) is recorded
in the supplement's template_symbol field.
*/
{
a_symbol_ptr sym;
Expand All @@ -11188,6 +11192,16 @@ entry. pos is used to establish the type entry's position information.
a_template_symbol_supplement_ptr
tssp = template_supplement_for_symbol(class_template);

if (bound_template == NULL) {
/* When not created by placeholder substitution, check whether an enclosing
instantiation has bound an argument to a template template parameter
(when unbound, argument_template points to class_template itself). */
a_symbol_ptr arg_sym = template_argument_if_template_template_param(
class_template);
if (arg_sym != class_template) {
bound_template = arg_sym;
} /* if */
} /* if */
if (!alias_ctad_enabled && alias_ctad_allowed &&
is_alias_template_symbol(class_template)) {
if (clang_mode ||
Expand All @@ -11210,7 +11224,11 @@ entry. pos is used to establish the type entry's position information.
sym->decl_scope = class_template->decl_scope;
sym->variant.type.ptr = type;
tpcp->depth = CLASS_TEMPLATE_PLACEHOLDER_NESTING_DEPTH;
/* For a template template parameter, CTAD keeps using the parameter's own
parameter list and defaults, while substitution goes through the template
bound to it. */
tptsp->constraint.class_template_symbol = class_template;
tptsp->template_symbol = bound_template;
set_type_size(type);
set_source_corresp(&type->source_corresp, sym);
if (!class_template->is_error &&
Expand Down
6 changes: 4 additions & 2 deletions src/il.h
Original file line number Diff line number Diff line change
Expand Up @@ -3899,8 +3899,10 @@ a routine.
(con)->variant.address.offset == 0 && !(con)->implicit_cast)

extern
a_type_ptr make_class_template_placeholder(struct a_symbol *class_template,
a_source_position *pos);
a_type_ptr make_class_template_placeholder(
struct a_symbol *class_template,
a_source_position *pos,
struct a_symbol *bound_template = NULL);

extern a_type_ptr make_auto_type(a_source_position *pos,
a_boolean is_decltype_auto);
Expand Down
8 changes: 5 additions & 3 deletions src/il_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -9358,9 +9358,11 @@ typedef struct a_template_param_type_supplement {
*template_symbol;
/* For templates (including C++/CLI generics) points
to the sk_class_template or sk_function_template
symbol of which this is a type parameter. NULL
otherwise. Used in the front end only; cannot
be used in back ends. */
symbol of which this is a type parameter. For a
placeholder type naming a type template template
parameter, points to the bound template argument,
if any. NULL otherwise. Used in the front end
only; cannot be used in back ends. */
#if MICROSOFT_EXTENSIONS_ALLOWED
a_generic_constraint_ptr
generic_constraints;
Expand Down
16 changes: 12 additions & 4 deletions src/overload.c
Original file line number Diff line number Diff line change
Expand Up @@ -30972,19 +30972,25 @@ set to TRUE and FALSE is returned.
if (is_template_template_param_symbol(ct_sym)) {
/* Class template argument deduction for a template template parameter: use
guides synthesized from the class or alias template argument. */
a_symbol_ptr bound_tttp_arg_sym;
a_symbol_ptr bound_tttp_arg_sym, target_sym;
a_boolean is_deducible_template;

target_sym = placeholder_type->variant.template_param.extra_info
->template_symbol;
bound_tttp_arg_sym = bound_template_template_argument(
ct_sym, &is_deducible_template);
target_sym != NULL ? target_sym : ct_sym,
&is_deducible_template);
if (bound_tttp_arg_sym == NULL) {
/* Still dependent. */
*still_dependent = TRUE;
result = FALSE;
goto done;
} else if (!is_deducible_template || bound_tttp_arg_sym->is_error) {
/* Template argument does not name a deducible template. */
pos_sy_error(ec_no_class_template_guide, source_pos, bound_tttp_arg_sym);
if (expr_error_should_be_issued()) {
pos_sy_error(ec_no_class_template_guide, source_pos,
bound_tttp_arg_sym);
} /* if */
*still_dependent = FALSE;
result = FALSE;
goto done;
Expand Down Expand Up @@ -31046,7 +31052,9 @@ set to TRUE and FALSE is returned.
guide_set = ct_tssp->variant.class_template.deduction_guides;
} /* if */
if (guide_set == NULL) {
pos_sy_error(ec_no_class_template_guide, source_pos, ct_sym);
if (expr_error_should_be_issued()) {
pos_sy_error(ec_no_class_template_guide, source_pos, ct_sym);
} /* if */
} else {
selected_sym = select_overloaded_function(
guide_set,
Expand Down
Loading
Loading