@@ -29909,8 +29909,6 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
&& CLASS_PLACEHOLDER_TEMPLATE (TREE_TYPE (init)) == tmpl)
return cp_build_qualified_type (TREE_TYPE (init), cp_type_quals (ptype));
- /* Look through alias templates that just rename another template. */
- tmpl = get_underlying_template (tmpl);
if (!ctad_template_p (tmpl))
{
if (complain & tf_error)
@@ -29920,15 +29918,33 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
else if (cxx_dialect < cxx20 && DECL_ALIAS_TEMPLATE_P (tmpl))
{
if (complain & tf_error)
- error ("alias template deduction only available "
- "with %<-std=c++20%> or %<-std=gnu++20%>");
- return error_mark_node;
+ {
+ /* Be permissive with equivalent alias templates. */
+ tree u = get_underlying_template (tmpl);
+ diagnostic_t dk = (u == tmpl) ? DK_ERROR : DK_PEDWARN;
+ bool complained
+ = emit_diagnostic (dk, input_location, 0,
+ "alias template deduction only available "
+ "with %<-std=c++20%> or %<-std=gnu++20%>");
+ if (u == tmpl)
+ return error_mark_node;
+ else if (complained)
+ {
+ inform (input_location, "use %qD directly instead", u);
+ tmpl = u;
+ }
+ }
+ else
+ return error_mark_node;
}
/* Wait until the initializer is non-dependent. */
if (type_dependent_expression_p (init))
return ptype;
+ /* Don't bother with the alias rules for an equivalent template. */
+ tmpl = get_underlying_template (tmpl);
+
tree type = TREE_TYPE (tmpl);
bool try_list_ctor = false;
@@ -1,5 +1,6 @@
// PR c++/103852
// { dg-do compile { target c++17 } }
+// { dg-options "" }
template <class T> struct b{};
template <class T, class T1 = b<T>>
@@ -10,7 +11,7 @@ struct s
s c(100);
template <class T, class T1 = b<T>>
using ss = s<T, T1>; // equivalent under proposed resolution of DR 1286
-ss tt(1); // OK
+ss tt(1); // { dg-warning "alias template deduction" "" { target c++17_only } }
template <class T, class T1 = T>
using ss2 = s<T, T1>; // different default arg makes it non-equivalent