I had been thinking about DR1286 "equivalence" as meaning generally
interchangeable, but looking back at the proposed resolution in the context
of this PR, I see that it's just about use as a template argument.  So let's
give a pedwarn if we look through a renaming alias.

Tested x86_64-pc-linux-gnu, applying to trunk.

        PR c++/103852
        DR 1286

gcc/cp/ChangeLog:

        * pt.cc (do_class_deduction): Pedwarn for renaming alias in C++17.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp1z/class-deduction-alias1.C: Expect warning.
---
 gcc/cp/pt.cc                                  | 26 +++++++++++++++----
 .../g++.dg/cpp1z/class-deduction-alias1.C     |  3 ++-
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 1f0231f70e6..eeebc4c1ef3 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -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;
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction-alias1.C 
b/gcc/testsuite/g++.dg/cpp1z/class-deduction-alias1.C
index 1ec90b58e3a..ffa5f2bad94 100644
--- a/gcc/testsuite/g++.dg/cpp1z/class-deduction-alias1.C
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction-alias1.C
@@ -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

base-commit: 1de6612d994ada8edaab18bbc6afd8e9a57413aa
-- 
2.27.0

Reply via email to