]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: alias template equivalence and CTAD [PR103852]
authorJason Merrill <jason@redhat.com>
Mon, 4 Apr 2022 15:56:38 +0000 (11:56 -0400)
committerJason Merrill <jason@redhat.com>
Tue, 5 Apr 2022 16:29:33 +0000 (12:29 -0400)
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.

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
gcc/testsuite/g++.dg/cpp1z/class-deduction-alias1.C

index 1f0231f70e67cbe69e00c8392cdf32db01212663..eeebc4c1ef34293185818812700c0a2b077a6e8a 100644 (file)
@@ -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;
index 1ec90b58e3a006bec52de77f655d499afe4ec4af..ffa5f2bad945a0fec3bd40106911b0bf5f8db966 100644 (file)
@@ -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