Commit 59febe0e by Jason Merrill Committed by Jason Merrill

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
parent a349418e
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> 2019-07-16 Jason Merrill <jason@redhat.com>
* parser.c (make_location): Add overload taking cp_lexer* as last * parser.c (make_location): Add overload taking cp_lexer* as last
......
...@@ -4278,6 +4278,11 @@ build_converted_constant_expr_internal (tree type, tree expr, ...@@ -4278,6 +4278,11 @@ build_converted_constant_expr_internal (tree type, tree expr,
if (conv) 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 = true;
conv->check_narrowing_const_only = true; conv->check_narrowing_const_only = true;
expr = convert_like (conv, expr, complain); expr = convert_like (conv, expr, complain);
......
...@@ -4954,7 +4954,8 @@ process_partial_specialization (tree decl) ...@@ -4954,7 +4954,8 @@ process_partial_specialization (tree decl)
simple identifier' condition and also the `specialized simple identifier' condition and also the `specialized
non-type argument' bit. */ non-type argument' bit. */
&& TREE_CODE (arg) != TEMPLATE_PARM_INDEX && 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)) && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_PARM_INDEX))
{ {
if ((!packed_args && tpd.arg_uses_template_parms[i]) if ((!packed_args && tpd.arg_uses_template_parms[i])
...@@ -22371,9 +22372,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, ...@@ -22371,9 +22372,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
/* Template-parameter dependent expression. Just accept it for now. /* Template-parameter dependent expression. Just accept it for now.
It will later be processed in convert_template_argument. */ It will later be processed in convert_template_argument. */
; ;
else if (same_type_p (non_reference (TREE_TYPE (arg)), else if (same_type_ignoring_top_level_qualifiers_p
non_reference (tparm))) (non_reference (TREE_TYPE (arg)),
/* OK */; non_reference (tparm)))
/* OK. Ignore top-level quals here because a class-type template
parameter object is const. */;
else if ((strict & UNIFY_ALLOW_INTEGER) else if ((strict & UNIFY_ALLOW_INTEGER)
&& CP_INTEGRAL_TYPE_P (tparm)) && CP_INTEGRAL_TYPE_P (tparm))
/* Convert the ARG to the type of PARM; the deduced non-type /* Convert the ARG to the type of PARM; the deduced non-type
......
// 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;
// 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...> {};
// 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...> {};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment