]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR c++/90098 - partial specialization and class non-type parms.
authorJason Merrill <jason@redhat.com>
Fri, 19 Jul 2019 08:53:07 +0000 (04:53 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 19 Jul 2019 08:53:07 +0000 (04:53 -0400)
A non-type template parameter of class type used in an expression has
const-qualified type; the pt.c hunks deal with this difference from the
unqualified type of the parameter declaration.  WAhen we use such a
parameter as an argument to another template, we don't want to confuse
things by copying it, we should pass it straight through.  And we might as
well skip copying other classes in constant evaluation context in a
template, too; we'll get the copy semantics at instantiation time.

PR c++/90099
PR c++/90101
* call.c (build_converted_constant_expr_internal): Don't copy.
* pt.c (process_partial_specialization): Allow VIEW_CONVERT_EXPR
around class non-type parameter.
(unify) [TEMPLATE_PARM_INDEX]: Ignore cv-quals.
(invalid_nontype_parm_type_p): Check for dependent class type.

From-SVN: r273597

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp2a/nontype-class18.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/nontype-class19.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/nontype-class20.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/nontype-class21.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/nontype-class22.C [new file with mode: 0644]

index 4b69396e7307f8a08bda08c32fa135f0f280e12d..8621f5733be5820ef68e8e67c6871c9e206dfe86 100644 (file)
@@ -1,5 +1,14 @@
 2019-07-19  Jason Merrill  <jason@redhat.com>
 
+       PR c++/90098 - partial specialization and class non-type parms.
+       PR c++/90099
+       PR c++/90101
+       * call.c (build_converted_constant_expr_internal): Don't copy.
+       * pt.c (process_partial_specialization): Allow VIEW_CONVERT_EXPR
+       around class non-type parameter.
+       (unify) [TEMPLATE_PARM_INDEX]: Ignore cv-quals.
+       (invalid_nontype_parm_type_p): Check for dependent class type.
+
        PR c++/85552 - wrong instantiation of dtor for DMI.
        * typeck2.c (digest_nsdmi_init): Set tf_no_cleanup for direct-init.
 
index 23898f0659fb73de4bb19b7b47b60abf356dc78b..9e22a146a16af3888e28cb603c259417f8f9685b 100644 (file)
@@ -4279,6 +4279,12 @@ build_converted_constant_expr_internal (tree type, tree expr,
 
   if (conv)
     {
+      /* Don't copy a class non-type template parameter.  */
+      if (CLASS_TYPE_P (type) && conv->kind == ck_rvalue
+         && TREE_CODE (expr) == VIEW_CONVERT_EXPR
+         && TREE_CODE (TREE_OPERAND (expr, 0)) == TEMPLATE_PARM_INDEX)
+       conv = next_conversion (conv);
+
       conv->check_narrowing = true;
       conv->check_narrowing_const_only = true;
       expr = convert_like (conv, expr, complain);
index b9137aa0a8290498da6111964ff2632eaf0ae978..7069e2f3047ede6aca1e0f57378eb229cd4c7509 100644 (file)
@@ -4953,7 +4953,8 @@ process_partial_specialization (tree decl)
                  simple identifier' condition and also the `specialized
                  non-type argument' bit.  */
               && TREE_CODE (arg) != TEMPLATE_PARM_INDEX
-             && !(REFERENCE_REF_P (arg)
+             && !((REFERENCE_REF_P (arg)
+                   || TREE_CODE (arg) == VIEW_CONVERT_EXPR)
                   && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_PARM_INDEX))
             {
               if ((!packed_args && tpd.arg_uses_template_parms[i])
@@ -22379,9 +22380,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
        /* Template-parameter dependent expression.  Just accept it for now.
           It will later be processed in convert_template_argument.  */
        ;
-      else if (same_type_p (non_reference (TREE_TYPE (arg)),
-                           non_reference (tparm)))
-       /* OK */;
+      else if (same_type_ignoring_top_level_qualifiers_p
+              (non_reference (TREE_TYPE (arg)),
+               non_reference (tparm)))
+       /* OK.  Ignore top-level quals here because a class-type template
+          parameter object is const.  */;
       else if ((strict & UNIFY_ALLOW_INTEGER)
               && CP_INTEGRAL_TYPE_P (tparm))
        /* Convert the ARG to the type of PARM; the deduced non-type
@@ -25233,6 +25236,8 @@ invalid_nontype_parm_type_p (tree type, tsubst_flags_t complain)
                 "with %<-std=c++2a%> or %<-std=gnu++2a%>");
          return true;
        }
+      if (dependent_type_p (type))
+       return false;
       if (!complete_type_or_else (type, NULL_TREE))
        return true;
       if (!literal_type_p (type))
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class18.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class18.C
new file mode 100644 (file)
index 0000000..22f4788
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/90101
+// { dg-do compile { target c++2a } }
+
+template<typename List>
+struct A;
+
+template<template<auto...> typename List>
+struct A<List<>> {};
+
+template<template<auto...> typename List, auto V>
+struct A<List<V>> {};
+
+template<auto>
+struct B {};
+
+struct X { int value; };
+A<B<X{1}>> a2;
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class19.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class19.C
new file mode 100644 (file)
index 0000000..91267ac
--- /dev/null
@@ -0,0 +1,13 @@
+// PR c++/90099
+// { dg-do compile { target c++2a } }
+
+struct Unit {
+  int value;
+  // auto operator<=>(const Unit&) = default;
+};
+
+template<Unit U, typename... Ts>
+struct X {};
+
+template<Unit U, typename T, typename... Rest>
+struct X<U, T, Rest...> {};
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class20.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class20.C
new file mode 100644 (file)
index 0000000..5d3479c
--- /dev/null
@@ -0,0 +1,13 @@
+// PR c++/90098
+// { dg-do compile { target c++2a } }
+
+struct A {
+  int value;
+  // auto operator<=>(const A&) = default;
+};
+
+template<A... Us>
+struct Z {};
+
+template<A V, A... Rest>
+struct Z<V, Rest...> {};
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class21.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class21.C
new file mode 100644 (file)
index 0000000..c58fe05
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/90101
+// { dg-do compile { target c++2a } }
+
+template<int N>
+struct A{};
+
+template<int N, A<N>>
+struct B {};
+
+B<2,A<2>{}> b;
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class22.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class22.C
new file mode 100644 (file)
index 0000000..026855f
--- /dev/null
@@ -0,0 +1,21 @@
+// PR c++/90100
+// { dg-do compile { target c++2a } }
+
+template<typename T>
+inline constexpr bool is_nontype_list = false;
+
+template<template<auto...> typename T, auto... NonTypes>
+inline constexpr bool is_nontype_list<T<NonTypes...>> = true;
+
+// works
+template<auto...>
+struct A {};
+
+static_assert(is_nontype_list<A<1, 2, 3>>);
+
+// fails
+struct X {
+    int v;
+};
+
+static_assert(is_nontype_list<A<X{1}, X{2}, X{3}>>);