c++: alias-tmpl equivalence and default targs [PR103852]
authorJason Merrill <jason@redhat.com>
Fri, 1 Apr 2022 19:55:21 +0000 (15:55 -0400)
committerJason Merrill <jason@redhat.com>
Mon, 4 Apr 2022 14:43:33 +0000 (10:43 -0400)
The suggested resolution for CWG1286, which we implemented, ignores default
template arguments, but this PR is an example of why that doesn't make
sense: the templates aren't functionally equivalent.

PR c++/103852
DR 1286

gcc/cp/ChangeLog:

* pt.cc (get_underlying_template): Compare default template args.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/alias-decl-dr1286a.C: Default args now matter.
* g++.dg/cpp1z/class-deduction-alias1.C: New test.

gcc/cp/pt.cc
gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1286a.C
gcc/testsuite/g++.dg/cpp1z/class-deduction-alias1.C [new file with mode: 0644]

index 75ed9a3..1f0231f 100644 (file)
@@ -6637,6 +6637,18 @@ get_underlying_template (tree tmpl)
       if (!comp_template_args (TI_ARGS (tinfo), alias_args))
        break;
 
+      /* Are any default template arguments equivalent?  */
+      tree aparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
+      tree uparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (underlying));
+      const int nparms = TREE_VEC_LENGTH (aparms);
+      for (int i = 0; i < nparms; ++i)
+       {
+         tree adefarg = TREE_PURPOSE (TREE_VEC_ELT (aparms, i));
+         tree udefarg = TREE_PURPOSE (TREE_VEC_ELT (uparms, i));
+         if (!template_args_equal (adefarg, udefarg))
+           goto top_break;
+       }
+
       /* If TMPL adds or changes any constraints, it isn't equivalent.  I think
         it's appropriate to treat a less-constrained alias as equivalent.  */
       if (!at_least_as_constrained (underlying, tmpl))
@@ -6645,6 +6657,7 @@ get_underlying_template (tree tmpl)
       /* Alias is equivalent.  Strip it and repeat.  */
       tmpl = underlying;
     }
+  top_break:;
 
   return tmpl;
 }
index 1780c9a..fbd63d8 100644 (file)
@@ -11,13 +11,13 @@ template<typename T, typename U = T> struct A;
 template<template <class...> class> struct X;
 
 // equivalent to A
-template<typename V, typename W>
+template<typename V, typename W = V>
 using B = A<V, W>;
 
 same<X<A>,X<B>> s1;
 
 // not equivalent to A: not all parameters used
-template<typename V, typename W>
+template<typename V, typename W = V>
 using C = A<V>;
 
 different<X<A>,X<C>> d1;
@@ -29,32 +29,32 @@ using D = A<V>;
 different<X<A>,X<D>> d2;
 
 // not equivalent to A: template-arguments in wrong order
-template<typename V, typename W>
+template<typename V, typename W = V>
 using E = A<W, V>;
 
 different<X<A>,X<E>> d3;
 
-// equivalent to A: default arguments not considered
+// NOT equivalent to A: default arguments now considered
 template<typename V, typename W = int>
 using F = A<V, W>;
 
-same<X<A>,X<F>> s2;
+different<X<A>,X<F>> s2;
 
 // equivalent to A and B
-template<typename V, typename W>
+template<typename V, typename W = V>
 using G = A<V, W>;
 
 same<X<A>,X<G>> s3;
 same<X<B>,X<G>> s3b;
 
 // equivalent to E
-template<typename V, typename W>
+template<typename V, typename W = V>
 using H = E<V, W>;
 
 same<X<E>,X<H>> s4;
 
 // not equivalent to A: argument not identifier
-template<typename V, typename W>
+template<typename V, typename W = V>
 using I = A<V, typename W::type>;
 
 different<X<A>,X<I>> d4;
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction-alias1.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction-alias1.C
new file mode 100644 (file)
index 0000000..1ec90b5
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/103852
+// { dg-do compile { target c++17 } }
+
+template <class T> struct b{};
+template <class T, class T1 = b<T>>
+struct s
+{
+    s(T);
+};
+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
+
+template <class T, class T1 = T>
+using ss2 = s<T, T1>;       // different default arg makes it non-equivalent
+ss2 tt2(1); // { dg-error "alias template deduction" "" { target c++17_only } }