aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2019-07-19 02:52:47 -0400
committerJason Merrill <jason@gcc.gnu.org>2019-07-19 02:52:47 -0400
commit59febe0ece37bedab7f42ae51b9f2b7a372d2950 (patch)
tree450126733d15b4766d37285fd778df24af4ec88b /gcc
parenta349418ef5247fdc0063d0daee96f6e8b5fb4a28 (diff)
downloadgcc-59febe0ece37bedab7f42ae51b9f2b7a372d2950.zip
gcc-59febe0ece37bedab7f42ae51b9f2b7a372d2950.tar.gz
gcc-59febe0ece37bedab7f42ae51b9f2b7a372d2950.tar.bz2
PR c++/90098 - partial specialization and class non-type parms.
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. From-SVN: r273591
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/call.c5
-rw-r--r--gcc/cp/pt.c11
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class18.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class19.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class20.C13
6 files changed, 65 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c9091f5..cef36b2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+2019-07-18 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.
+
2019-07-16 Jason Merrill <jason@redhat.com>
* parser.c (make_location): Add overload taking cp_lexer* as last
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index e597d7a..38d229b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4278,6 +4278,11 @@ build_converted_constant_expr_internal (tree type, tree expr,
if (conv)
{
+ /* Don't copy a class in a template. */
+ if (CLASS_TYPE_P (type) && conv->kind == ck_rvalue
+ && processing_template_decl)
+ conv = next_conversion (conv);
+
conv->check_narrowing = true;
conv->check_narrowing_const_only = true;
expr = convert_like (conv, expr, complain);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e23c0aa..53aaad1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -4954,7 +4954,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])
@@ -22371,9 +22372,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
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class18.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class18.C
new file mode 100644
index 0000000..22f4788
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class18.C
@@ -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
index 0000000..91267ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class19.C
@@ -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
index 0000000..5d3479c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class20.C
@@ -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...> {};