re PR c++/54440 ([c++11] g++ prematurely applying rule that a template parameter pack cannot be followed by a template parameter)
PR c++/54440 * pt.c (get_template_parm_index): New. (fixed_parameter_pack_p_1, fixed_parameter_pack_p): New. (process_template_parm): Allow bare packs in template template parm template parms. (coerce_template_parameter_pack): Handle fixed template template parm packs and fixed packs not at the end of the parm list. (coerce_template_parms): Handle template parm packs not at the end of the parm list. (gen_elem_of_pack_expansion_instantiation): Handle a decl expansion. From-SVN: r208178
This commit is contained in:
parent
f3417723b7
commit
b0ff7fe1d2
|
@ -1,5 +1,16 @@
|
||||||
2014-02-26 Jason Merrill <jason@redhat.com>
|
2014-02-26 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
PR c++/54440
|
||||||
|
* pt.c (get_template_parm_index): New.
|
||||||
|
(fixed_parameter_pack_p_1, fixed_parameter_pack_p): New.
|
||||||
|
(process_template_parm): Allow bare packs in template template
|
||||||
|
parm template parms.
|
||||||
|
(coerce_template_parameter_pack): Handle fixed template template
|
||||||
|
parm packs and fixed packs not at the end of the parm list.
|
||||||
|
(coerce_template_parms): Handle template parm packs not at the end
|
||||||
|
of the parm list.
|
||||||
|
(gen_elem_of_pack_expansion_instantiation): Handle a decl expansion.
|
||||||
|
|
||||||
PR c++/60182
|
PR c++/60182
|
||||||
* pt.c (unify): Ignore alias templates when deducing a template
|
* pt.c (unify): Ignore alias templates when deducing a template
|
||||||
template parameter.
|
template parameter.
|
||||||
|
|
229
gcc/cp/pt.c
229
gcc/cp/pt.c
|
@ -3697,7 +3697,10 @@ process_template_parm (tree list, location_t parm_loc, tree parm,
|
||||||
return chainon (list, err_parm_list);
|
return chainon (list, err_parm_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uses_parameter_packs (TREE_TYPE (parm)) && !is_parameter_pack)
|
if (uses_parameter_packs (TREE_TYPE (parm)) && !is_parameter_pack
|
||||||
|
/* If we're in a nested template parameter list, the template
|
||||||
|
template parameter could be a parameter pack. */
|
||||||
|
&& processing_template_parmlist == 1)
|
||||||
{
|
{
|
||||||
/* This template parameter is not a parameter pack, but it
|
/* This template parameter is not a parameter pack, but it
|
||||||
should be. Complain about "bare" parameter packs. */
|
should be. Complain about "bare" parameter packs. */
|
||||||
|
@ -4326,6 +4329,77 @@ process_partial_specialization (tree decl)
|
||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* PARM is a template parameter of some form; return the corresponding
|
||||||
|
TEMPLATE_PARM_INDEX. */
|
||||||
|
|
||||||
|
static tree
|
||||||
|
get_template_parm_index (tree parm)
|
||||||
|
{
|
||||||
|
if (TREE_CODE (parm) == PARM_DECL
|
||||||
|
|| TREE_CODE (parm) == CONST_DECL)
|
||||||
|
parm = DECL_INITIAL (parm);
|
||||||
|
else if (TREE_CODE (parm) == TYPE_DECL
|
||||||
|
|| TREE_CODE (parm) == TEMPLATE_DECL)
|
||||||
|
parm = TREE_TYPE (parm);
|
||||||
|
if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
|
||||||
|
|| TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM)
|
||||||
|
parm = TEMPLATE_TYPE_PARM_INDEX (parm);
|
||||||
|
gcc_assert (TREE_CODE (parm) == TEMPLATE_PARM_INDEX);
|
||||||
|
return parm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Subroutine of fixed_parameter_pack_p below. Look for any template
|
||||||
|
parameter packs used by the template parameter PARM. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
fixed_parameter_pack_p_1 (tree parm, struct find_parameter_pack_data *ppd)
|
||||||
|
{
|
||||||
|
/* A type parm can't refer to another parm. */
|
||||||
|
if (TREE_CODE (parm) == TYPE_DECL)
|
||||||
|
return;
|
||||||
|
else if (TREE_CODE (parm) == PARM_DECL)
|
||||||
|
{
|
||||||
|
cp_walk_tree (&TREE_TYPE (parm), &find_parameter_packs_r,
|
||||||
|
ppd, ppd->visited);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gcc_assert (TREE_CODE (parm) == TEMPLATE_DECL);
|
||||||
|
|
||||||
|
tree vec = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (parm));
|
||||||
|
for (int i = 0; i < TREE_VEC_LENGTH (vec); ++i)
|
||||||
|
fixed_parameter_pack_p_1 (TREE_VALUE (TREE_VEC_ELT (vec, i)), ppd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PARM is a template parameter pack. Return any parameter packs used in
|
||||||
|
its type or the type of any of its template parameters. If there are
|
||||||
|
any such packs, it will be instantiated into a fixed template parameter
|
||||||
|
list by partial instantiation rather than be fully deduced. */
|
||||||
|
|
||||||
|
tree
|
||||||
|
fixed_parameter_pack_p (tree parm)
|
||||||
|
{
|
||||||
|
/* This can only be true in a member template. */
|
||||||
|
if (TEMPLATE_PARM_ORIG_LEVEL (get_template_parm_index (parm)) < 2)
|
||||||
|
return NULL_TREE;
|
||||||
|
/* This can only be true for a parameter pack. */
|
||||||
|
if (!template_parameter_pack_p (parm))
|
||||||
|
return NULL_TREE;
|
||||||
|
/* A type parm can't refer to another parm. */
|
||||||
|
if (TREE_CODE (parm) == TYPE_DECL)
|
||||||
|
return NULL_TREE;
|
||||||
|
|
||||||
|
tree parameter_packs = NULL_TREE;
|
||||||
|
struct find_parameter_pack_data ppd;
|
||||||
|
ppd.parameter_packs = ¶meter_packs;
|
||||||
|
ppd.visited = pointer_set_create ();
|
||||||
|
|
||||||
|
fixed_parameter_pack_p_1 (parm, &ppd);
|
||||||
|
|
||||||
|
pointer_set_destroy (ppd.visited);
|
||||||
|
return parameter_packs;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check that a template declaration's use of default arguments and
|
/* Check that a template declaration's use of default arguments and
|
||||||
parameter packs is not invalid. Here, PARMS are the template
|
parameter packs is not invalid. Here, PARMS are the template
|
||||||
parameters. IS_PRIMARY is true if DECL is the thing declared by
|
parameters. IS_PRIMARY is true if DECL is the thing declared by
|
||||||
|
@ -4431,7 +4505,10 @@ check_default_tmpl_args (tree decl, tree parms, bool is_primary,
|
||||||
&& parm_level == parms
|
&& parm_level == parms
|
||||||
&& TREE_CODE (decl) == TYPE_DECL
|
&& TREE_CODE (decl) == TYPE_DECL
|
||||||
&& i < ntparms - 1
|
&& i < ntparms - 1
|
||||||
&& template_parameter_pack_p (TREE_VALUE (parm)))
|
&& template_parameter_pack_p (TREE_VALUE (parm))
|
||||||
|
/* A fixed parameter pack will be partially
|
||||||
|
instantiated into a fixed length list. */
|
||||||
|
&& !fixed_parameter_pack_p (TREE_VALUE (parm)))
|
||||||
{
|
{
|
||||||
/* A primary class template can only have one
|
/* A primary class template can only have one
|
||||||
parameter pack, at the end of the template
|
parameter pack, at the end of the template
|
||||||
|
@ -6531,58 +6608,53 @@ coerce_template_parameter_pack (tree parms,
|
||||||
int nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
|
int nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
|
||||||
tree packed_args;
|
tree packed_args;
|
||||||
tree argument_pack;
|
tree argument_pack;
|
||||||
tree packed_types = NULL_TREE;
|
tree packed_parms = NULL_TREE;
|
||||||
|
|
||||||
if (arg_idx > nargs)
|
if (arg_idx > nargs)
|
||||||
arg_idx = nargs;
|
arg_idx = nargs;
|
||||||
|
|
||||||
packed_args = make_tree_vec (nargs - arg_idx);
|
if (tree packs = fixed_parameter_pack_p (TREE_VALUE (parm)))
|
||||||
|
|
||||||
if (TREE_CODE (TREE_VALUE (parm)) == PARM_DECL
|
|
||||||
&& uses_parameter_packs (TREE_TYPE (TREE_VALUE (parm))))
|
|
||||||
{
|
{
|
||||||
/* When the template parameter is a non-type template
|
/* When the template parameter is a non-type template parameter pack
|
||||||
parameter pack whose type uses parameter packs, we need
|
or template template parameter pack whose type or template
|
||||||
to look at each of the template arguments
|
parameters use parameter packs, we know exactly how many arguments
|
||||||
separately. Build a vector of the types for these
|
we are looking for. Build a vector of the instantiated decls for
|
||||||
non-type template parameters in PACKED_TYPES. */
|
these template parameters in PACKED_PARMS. */
|
||||||
tree expansion
|
/* We can't use make_pack_expansion here because it would interpret a
|
||||||
= make_pack_expansion (TREE_TYPE (TREE_VALUE (parm)));
|
_DECL as a use rather than a declaration. */
|
||||||
packed_types = tsubst_pack_expansion (expansion, args,
|
tree decl = TREE_VALUE (parm);
|
||||||
complain, in_decl);
|
tree exp = cxx_make_type (TYPE_PACK_EXPANSION);
|
||||||
|
SET_PACK_EXPANSION_PATTERN (exp, decl);
|
||||||
|
PACK_EXPANSION_PARAMETER_PACKS (exp) = packs;
|
||||||
|
SET_TYPE_STRUCTURAL_EQUALITY (exp);
|
||||||
|
|
||||||
if (packed_types == error_mark_node)
|
TREE_VEC_LENGTH (args)--;
|
||||||
|
packed_parms = tsubst_pack_expansion (exp, args, complain, decl);
|
||||||
|
TREE_VEC_LENGTH (args)++;
|
||||||
|
|
||||||
|
if (packed_parms == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
/* Check that we have the right number of arguments. */
|
/* If we're doing a partial instantiation of a member template,
|
||||||
if (arg_idx < nargs
|
|
||||||
&& !PACK_EXPANSION_P (TREE_VEC_ELT (inner_args, arg_idx))
|
|
||||||
&& nargs - arg_idx != TREE_VEC_LENGTH (packed_types))
|
|
||||||
{
|
|
||||||
int needed_parms
|
|
||||||
= TREE_VEC_LENGTH (parms) - 1 + TREE_VEC_LENGTH (packed_types);
|
|
||||||
error ("wrong number of template arguments (%d, should be %d)",
|
|
||||||
nargs, needed_parms);
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we aren't able to check the actual arguments now
|
|
||||||
(because they haven't been expanded yet), we can at least
|
|
||||||
verify that all of the types used for the non-type
|
verify that all of the types used for the non-type
|
||||||
template parameter pack are, in fact, valid for non-type
|
template parameter pack are, in fact, valid for non-type
|
||||||
template parameters. */
|
template parameters. */
|
||||||
if (arg_idx < nargs
|
if (arg_idx < nargs
|
||||||
&& PACK_EXPANSION_P (TREE_VEC_ELT (inner_args, arg_idx)))
|
&& PACK_EXPANSION_P (TREE_VEC_ELT (inner_args, arg_idx)))
|
||||||
{
|
{
|
||||||
int j, len = TREE_VEC_LENGTH (packed_types);
|
int j, len = TREE_VEC_LENGTH (packed_parms);
|
||||||
for (j = 0; j < len; ++j)
|
for (j = 0; j < len; ++j)
|
||||||
{
|
{
|
||||||
tree t = TREE_VEC_ELT (packed_types, j);
|
tree t = TREE_TYPE (TREE_VEC_ELT (packed_parms, j));
|
||||||
if (invalid_nontype_parm_type_p (t, complain))
|
if (invalid_nontype_parm_type_p (t, complain))
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packed_args = make_tree_vec (TREE_VEC_LENGTH (packed_parms));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
packed_args = make_tree_vec (nargs - arg_idx);
|
||||||
|
|
||||||
/* Convert the remaining arguments, which will be a part of the
|
/* Convert the remaining arguments, which will be a part of the
|
||||||
parameter pack "parm". */
|
parameter pack "parm". */
|
||||||
|
@ -6590,18 +6662,19 @@ coerce_template_parameter_pack (tree parms,
|
||||||
{
|
{
|
||||||
tree arg = TREE_VEC_ELT (inner_args, arg_idx);
|
tree arg = TREE_VEC_ELT (inner_args, arg_idx);
|
||||||
tree actual_parm = TREE_VALUE (parm);
|
tree actual_parm = TREE_VALUE (parm);
|
||||||
|
int pack_idx = arg_idx - parm_idx;
|
||||||
|
|
||||||
if (packed_types && !PACK_EXPANSION_P (arg))
|
if (packed_parms)
|
||||||
{
|
{
|
||||||
/* When we have a vector of types (corresponding to the
|
/* Once we've packed as many args as we have types, stop. */
|
||||||
non-type template parameter pack that uses parameter
|
if (pack_idx >= TREE_VEC_LENGTH (packed_parms))
|
||||||
packs in its type, as mention above), and the
|
break;
|
||||||
argument is not an expansion (which expands to a
|
else if (PACK_EXPANSION_P (arg))
|
||||||
currently unknown number of arguments), clone the
|
/* We don't know how many args we have yet, just
|
||||||
parm and give it the next type in PACKED_TYPES. */
|
use the unconverted ones for now. */
|
||||||
actual_parm = copy_node (actual_parm);
|
return NULL_TREE;
|
||||||
TREE_TYPE (actual_parm) =
|
else
|
||||||
TREE_VEC_ELT (packed_types, arg_idx - parm_idx);
|
actual_parm = TREE_VEC_ELT (packed_parms, pack_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg == error_mark_node)
|
if (arg == error_mark_node)
|
||||||
|
@ -6615,7 +6688,15 @@ coerce_template_parameter_pack (tree parms,
|
||||||
in_decl);
|
in_decl);
|
||||||
if (arg == error_mark_node)
|
if (arg == error_mark_node)
|
||||||
(*lost)++;
|
(*lost)++;
|
||||||
TREE_VEC_ELT (packed_args, arg_idx - parm_idx) = arg;
|
TREE_VEC_ELT (packed_args, pack_idx) = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg_idx - parm_idx < TREE_VEC_LENGTH (packed_args)
|
||||||
|
&& TREE_VEC_LENGTH (packed_args) > 0)
|
||||||
|
{
|
||||||
|
error ("wrong number of template arguments (%d, should be %d)",
|
||||||
|
arg_idx - parm_idx, TREE_VEC_LENGTH (packed_args));
|
||||||
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
|
if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
|
||||||
|
@ -6676,6 +6757,7 @@ coerce_template_parms (tree parms,
|
||||||
bool use_default_args)
|
bool use_default_args)
|
||||||
{
|
{
|
||||||
int nparms, nargs, parm_idx, arg_idx, lost = 0;
|
int nparms, nargs, parm_idx, arg_idx, lost = 0;
|
||||||
|
tree orig_inner_args;
|
||||||
tree inner_args;
|
tree inner_args;
|
||||||
tree new_args;
|
tree new_args;
|
||||||
tree new_inner_args;
|
tree new_inner_args;
|
||||||
|
@ -6705,7 +6787,7 @@ coerce_template_parms (tree parms,
|
||||||
++variadic_p;
|
++variadic_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
inner_args = INNERMOST_TEMPLATE_ARGS (args);
|
inner_args = orig_inner_args = INNERMOST_TEMPLATE_ARGS (args);
|
||||||
/* If there are no parameters that follow a parameter pack, we need to
|
/* If there are no parameters that follow a parameter pack, we need to
|
||||||
expand any argument packs so that we can deduce a parameter pack from
|
expand any argument packs so that we can deduce a parameter pack from
|
||||||
some non-packed args followed by an argument pack, as in variadic85.C.
|
some non-packed args followed by an argument pack, as in variadic85.C.
|
||||||
|
@ -6783,6 +6865,7 @@ coerce_template_parms (tree parms,
|
||||||
c_inhibit_evaluation_warnings = 0;
|
c_inhibit_evaluation_warnings = 0;
|
||||||
new_inner_args = make_tree_vec (nparms);
|
new_inner_args = make_tree_vec (nparms);
|
||||||
new_args = add_outermost_template_args (args, new_inner_args);
|
new_args = add_outermost_template_args (args, new_inner_args);
|
||||||
|
int pack_adjust = 0;
|
||||||
for (parm_idx = 0, arg_idx = 0; parm_idx < nparms; parm_idx++, arg_idx++)
|
for (parm_idx = 0, arg_idx = 0; parm_idx < nparms; parm_idx++, arg_idx++)
|
||||||
{
|
{
|
||||||
tree arg;
|
tree arg;
|
||||||
|
@ -6806,22 +6889,36 @@ coerce_template_parms (tree parms,
|
||||||
if (template_parameter_pack_p (TREE_VALUE (parm))
|
if (template_parameter_pack_p (TREE_VALUE (parm))
|
||||||
&& !(arg && ARGUMENT_PACK_P (arg)))
|
&& !(arg && ARGUMENT_PACK_P (arg)))
|
||||||
{
|
{
|
||||||
/* All remaining arguments will be placed in the
|
/* Some arguments will be placed in the
|
||||||
template parameter pack PARM. */
|
template parameter pack PARM. */
|
||||||
arg = coerce_template_parameter_pack (parms, parm_idx, args,
|
arg = coerce_template_parameter_pack (parms, parm_idx, args,
|
||||||
inner_args, arg_idx,
|
inner_args, arg_idx,
|
||||||
new_args, &lost,
|
new_args, &lost,
|
||||||
in_decl, complain);
|
in_decl, complain);
|
||||||
|
|
||||||
/* Store this argument. */
|
if (arg == NULL_TREE)
|
||||||
if (arg == error_mark_node)
|
{
|
||||||
lost++;
|
/* We don't know how many args we have yet, just use the
|
||||||
if (lost)
|
unconverted (and still packed) ones for now. */
|
||||||
break;
|
new_inner_args = orig_inner_args;
|
||||||
|
arg_idx = nargs;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
TREE_VEC_ELT (new_inner_args, parm_idx) = arg;
|
TREE_VEC_ELT (new_inner_args, parm_idx) = arg;
|
||||||
|
|
||||||
/* We are done with all of the arguments. */
|
/* Store this argument. */
|
||||||
arg_idx = nargs;
|
if (arg == error_mark_node)
|
||||||
|
{
|
||||||
|
lost++;
|
||||||
|
/* We are done with all of the arguments. */
|
||||||
|
arg_idx = nargs;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pack_adjust = TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg)) - 1;
|
||||||
|
arg_idx += pack_adjust;
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -6832,6 +6929,7 @@ coerce_template_parms (tree parms,
|
||||||
/* We don't know how many args we have yet, just
|
/* We don't know how many args we have yet, just
|
||||||
use the unconverted ones for now. */
|
use the unconverted ones for now. */
|
||||||
new_inner_args = inner_args;
|
new_inner_args = inner_args;
|
||||||
|
arg_idx = nargs;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6844,7 +6942,8 @@ coerce_template_parms (tree parms,
|
||||||
is also the number of non-defaulted arguments in NEW_INNER_ARGS.
|
is also the number of non-defaulted arguments in NEW_INNER_ARGS.
|
||||||
Record that. */
|
Record that. */
|
||||||
if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args))
|
if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args))
|
||||||
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args, arg_idx);
|
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args,
|
||||||
|
arg_idx - pack_adjust);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
@ -6868,11 +6967,23 @@ coerce_template_parms (tree parms,
|
||||||
|
|
||||||
if (arg == error_mark_node)
|
if (arg == error_mark_node)
|
||||||
lost++;
|
lost++;
|
||||||
TREE_VEC_ELT (new_inner_args, arg_idx) = arg;
|
TREE_VEC_ELT (new_inner_args, arg_idx - pack_adjust) = arg;
|
||||||
}
|
}
|
||||||
cp_unevaluated_operand = saved_unevaluated_operand;
|
cp_unevaluated_operand = saved_unevaluated_operand;
|
||||||
c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
|
c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
|
||||||
|
|
||||||
|
if (variadic_p && arg_idx < nargs)
|
||||||
|
{
|
||||||
|
if (complain & tf_error)
|
||||||
|
{
|
||||||
|
error ("wrong number of template arguments "
|
||||||
|
"(%d, should be %d)", nargs, arg_idx);
|
||||||
|
if (in_decl)
|
||||||
|
error ("provided for %q+D", in_decl);
|
||||||
|
}
|
||||||
|
return error_mark_node;
|
||||||
|
}
|
||||||
|
|
||||||
if (lost)
|
if (lost)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
|
@ -9509,7 +9620,11 @@ gen_elem_of_pack_expansion_instantiation (tree pattern,
|
||||||
|
|
||||||
/* Substitute into the PATTERN with the (possibly altered)
|
/* Substitute into the PATTERN with the (possibly altered)
|
||||||
arguments. */
|
arguments. */
|
||||||
if (!TYPE_P (pattern))
|
if (pattern == in_decl)
|
||||||
|
/* Expanding a fixed parameter pack from
|
||||||
|
coerce_template_parameter_pack. */
|
||||||
|
t = tsubst_decl (pattern, args, complain);
|
||||||
|
else if (!TYPE_P (pattern))
|
||||||
t = tsubst_expr (pattern, args, complain, in_decl,
|
t = tsubst_expr (pattern, args, complain, in_decl,
|
||||||
/*integral_constant_expression_p=*/false);
|
/*integral_constant_expression_p=*/false);
|
||||||
else
|
else
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
// PR c++/54440
|
||||||
|
// { dg-do compile { target c++11 } }
|
||||||
|
|
||||||
|
template <class...T> struct A
|
||||||
|
{
|
||||||
|
template <T... t, class U> struct B { };
|
||||||
|
};
|
||||||
|
|
||||||
|
A<int,char>::B<42,'a',float> b;
|
|
@ -0,0 +1,12 @@
|
||||||
|
// PR c++/54440
|
||||||
|
// { dg-do compile { target c++11 } }
|
||||||
|
|
||||||
|
template <class...T> struct A
|
||||||
|
{
|
||||||
|
template <template <T> class... TP, class U> struct B { };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int I> struct C { };
|
||||||
|
template <char C> struct D { };
|
||||||
|
|
||||||
|
A<int,char>::B<C,D,float> b;
|
|
@ -24,3 +24,5 @@ A<int*, float*>::X<&i> apple2; // { dg-error "wrong number of template arguments
|
||||||
A<int*, float*>::X<&i, &f, &f> apple3; // { dg-error "wrong number of template arguments" "wrong number" }
|
A<int*, float*>::X<&i, &f, &f> apple3; // { dg-error "wrong number of template arguments" "wrong number" }
|
||||||
// { dg-error "invalid type" "invalid" { target *-*-* } 24 }
|
// { dg-error "invalid type" "invalid" { target *-*-* } 24 }
|
||||||
A<int, float> apple4;
|
A<int, float> apple4;
|
||||||
|
|
||||||
|
// { dg-prune-output "provided for" }
|
||||||
|
|
Loading…
Reference in New Issue