https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109531
--- Comment #12 from Patrick Palka <ppalka at gcc dot gnu.org> --- I suppose we're just neglecting to canonicalize a bound ttp's substituted args before determining its canonical type. Adding a call to coerce_template_parms or canonicalize_type_argument seems to fix it: diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index fcc8e0d1d57..5ff91414f69 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -16285,9 +16285,18 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) return error_mark_node; tree argvec = tsubst (TI_ARGS (tinfo), args, complain, in_decl); + // this fixes it + tree tparms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl); + argvec = coerce_template_parms (tparms, argvec, + tmpl, complain); if (argvec == error_mark_node) return error_mark_node; + // or this + for (tree& arg : tree_vec_range (argvec)) + if (TYPE_P (arg)) + arg = canonicalize_type_argument (arg, complain); + TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (r) = build_template_info (tmpl, argvec); }