PR c++/79960 - alias templates and partial ordering
authorJason Merrill <jason@redhat.com>
Fri, 10 Mar 2017 17:35:54 +0000 (12:35 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 10 Mar 2017 17:35:54 +0000 (12:35 -0500)
* pt.c (comp_template_args): Add partial_order parm.
(template_args_equal): Likewise.
(comp_template_args_porder): New.
(get_partial_spec_bindings): Use it.

From-SVN: r246042

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp0x/alias-decl-57.C [new file with mode: 0644]

index 69b49e60b36e3d7f0895fb182a8446d0a11039e7..92b430d33518fd2c3dc65e253de872cc7377e998 100644 (file)
@@ -1,3 +1,11 @@
+2017-03-10  Jason Merrill  <jason@redhat.com>
+
+       PR c++/79960 - alias templates and partial ordering
+       * pt.c (comp_template_args): Add partial_order parm.
+       (template_args_equal): Likewise.
+       (comp_template_args_porder): New.
+       (get_partial_spec_bindings): Use it.
+
 2017-03-10  Marek Polacek  <polacek@redhat.com>
 
        PR c++/79967
index 68f2722d6da916c2c7d61edcc171e226caaa34c3..5be5dfe246d0a9534661b7dc88fa295f382e44ed 100644 (file)
@@ -6208,8 +6208,8 @@ extern int is_specialization_of                   (tree, tree);
 extern bool is_specialization_of_friend                (tree, tree);
 extern tree get_pattern_parm                   (tree, tree);
 extern int comp_template_args                  (tree, tree, tree * = NULL,
-                                                tree * = NULL);
-extern int template_args_equal                  (tree, tree);
+                                                tree * = NULL, bool = false);
+extern int template_args_equal                  (tree, tree, bool = false);
 extern tree maybe_process_partial_specialization (tree);
 extern tree most_specialized_instantiation     (tree);
 extern void print_candidates                   (tree);
index 416f1323f4fa5ff3e89549cc27322c00a9875ce3..b8ce9fedf429f25ecc3d97fc6b59c5604b8495d2 100644 (file)
@@ -8240,7 +8240,7 @@ coerce_innermost_template_parms (tree parms,
 /* Returns 1 if template args OT and NT are equivalent.  */
 
 int
-template_args_equal (tree ot, tree nt)
+template_args_equal (tree ot, tree nt, bool partial_order /* = false */)
 {
   if (nt == ot)
     return 1;
@@ -8288,8 +8288,13 @@ template_args_equal (tree ot, tree nt)
         template argument; we need them to be distinct so that we
         substitute into the specialization arguments at instantiation
         time.  And aliases can't be equivalent without being ==, so
-        we don't need to look any deeper.  */
-      if (TYPE_ALIAS_P (nt) || TYPE_ALIAS_P (ot))
+        we don't need to look any deeper.
+
+         During partial ordering, however, we need to treat them normally so
+         that we can order uses of the same alias with different
+         cv-qualification (79960).  */
+      if (!partial_order
+         && (TYPE_ALIAS_P (nt) || TYPE_ALIAS_P (ot)))
        return false;
       else
        return same_type_p (ot, nt);
@@ -8321,7 +8326,8 @@ template_args_equal (tree ot, tree nt)
 
 int
 comp_template_args (tree oldargs, tree newargs,
-                   tree *oldarg_ptr, tree *newarg_ptr)
+                   tree *oldarg_ptr, tree *newarg_ptr,
+                   bool partial_order)
 {
   int i;
 
@@ -8339,7 +8345,7 @@ comp_template_args (tree oldargs, tree newargs,
       tree nt = TREE_VEC_ELT (newargs, i);
       tree ot = TREE_VEC_ELT (oldargs, i);
 
-      if (! template_args_equal (ot, nt))
+      if (! template_args_equal (ot, nt, partial_order))
        {
          if (oldarg_ptr != NULL)
            *oldarg_ptr = ot;
@@ -8351,6 +8357,12 @@ comp_template_args (tree oldargs, tree newargs,
   return 1;
 }
 
+inline bool
+comp_template_args_porder (tree oargs, tree nargs)
+{
+  return comp_template_args (oargs, nargs, NULL, NULL, true);
+}
+
 static void
 add_pending_template (tree d)
 {
@@ -21584,8 +21596,8 @@ get_partial_spec_bindings (tree tmpl, tree spec_tmpl, tree args)
   if (spec_args == error_mark_node
       /* We only need to check the innermost arguments; the other
         arguments will always agree.  */
-      || !comp_template_args (INNERMOST_TEMPLATE_ARGS (spec_args),
-                             INNERMOST_TEMPLATE_ARGS (args)))
+      || !comp_template_args_porder (INNERMOST_TEMPLATE_ARGS (spec_args),
+                                    INNERMOST_TEMPLATE_ARGS (args)))
     return NULL_TREE;
 
   /* Now that we have bindings for all of the template arguments,
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-57.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-57.C
new file mode 100644 (file)
index 0000000..f257e62
--- /dev/null
@@ -0,0 +1,30 @@
+// PR c++/79960
+// { dg-do compile { target c++11 } }
+
+using size_t = decltype(sizeof(0));
+
+template<typename T> struct tuple_size;
+
+template<typename T, size_t U = tuple_size<T>::value>
+  using __has_tuple_size = T;
+
+template<typename T> struct tuple_size<const __has_tuple_size<T>> {
+  static constexpr size_t value = tuple_size<T>::value;
+};
+
+template<typename T> struct tuple_size<volatile __has_tuple_size<T>> {
+  static constexpr size_t value = tuple_size<T>::value;
+};
+
+template<typename T> struct tuple_size<const __has_tuple_size<volatile T>> {
+  static constexpr size_t value = tuple_size<T>::value;
+};
+
+template<typename... T> struct tuple { };
+template<typename... T> struct tuple_size<tuple<T...>> {
+  static constexpr size_t value = sizeof...(T);
+};
+
+static_assert( tuple_size<const tuple<>>::value == 0, "" );  // OK
+static_assert( tuple_size<volatile tuple<>>::value == 0, "" ); // OK
+static_assert( tuple_size<const volatile tuple<>>::value == 0, "" ); // FAIL