re PR c++/31993 (ICE with template class in variadic template class)
2007-10-30 Douglas Gregor <doug.gregor@gmail.com> PR c++/31993 PR c++/32252 * pt.c (find_parameter_packs_r): Fix typo in comment. (convert_template_argument): Look at the pattern of a pack expansion to determine what kind of entity we're converting. (coerce_template_parameter_pack): When we have coerced a non-type template parameter pack, substitute into the type of that pack. (tsubst_pack_expansion): When our substitution of a parameter pack is a "trivial" substitution of itself, just substitute into the pack expansion rather than actually expanding. 2007-10-30 Douglas Gregor <doug.gregor@gmail.com> PR c++/31993 PR c++/32252 * g++.dg/cpp0x/pr31993.C: New * g++.dg/cpp0x/pr32252.C: New From-SVN: r129773
This commit is contained in:
parent
310750d8ec
commit
88b823145e
@ -1,3 +1,16 @@
|
||||
2007-10-30 Douglas Gregor <doug.gregor@gmail.com>
|
||||
|
||||
PR c++/31993
|
||||
PR c++/32252
|
||||
* pt.c (find_parameter_packs_r): Fix typo in comment.
|
||||
(convert_template_argument): Look at the pattern of a pack
|
||||
expansion to determine what kind of entity we're converting.
|
||||
(coerce_template_parameter_pack): When we have coerced a non-type
|
||||
template parameter pack, substitute into the type of that pack.
|
||||
(tsubst_pack_expansion): When our substitution of a parameter pack
|
||||
is a "trivial" substitution of itself, just substitute into the
|
||||
pack expansion rather than actually expanding.
|
||||
|
||||
2007-10-29 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/33841
|
||||
|
86
gcc/cp/pt.c
86
gcc/cp/pt.c
@ -2426,9 +2426,9 @@ struct find_parameter_pack_data
|
||||
struct pointer_set_t *visited;
|
||||
};
|
||||
|
||||
/* Identifiers all of the argument packs that occur in a template
|
||||
/* Identifies all of the argument packs that occur in a template
|
||||
argument and appends them to the TREE_LIST inside DATA, which is a
|
||||
find_parameter_pack_Data structure. This is a subroutine of
|
||||
find_parameter_pack_data structure. This is a subroutine of
|
||||
make_pack_expansion and uses_parameter_packs. */
|
||||
static tree
|
||||
find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
|
||||
@ -4668,9 +4668,9 @@ convert_template_argument (tree parm,
|
||||
int i,
|
||||
tree in_decl)
|
||||
{
|
||||
tree orig_arg;
|
||||
tree val;
|
||||
int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
|
||||
tree check_arg = arg;
|
||||
|
||||
if (TREE_CODE (arg) == TREE_LIST
|
||||
&& TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
|
||||
@ -4680,24 +4680,26 @@ convert_template_argument (tree parm,
|
||||
invalid, but static members are OK. In any
|
||||
case, grab the underlying fields/functions
|
||||
and issue an error later if required. */
|
||||
arg = TREE_VALUE (arg);
|
||||
orig_arg = TREE_VALUE (arg);
|
||||
TREE_TYPE (arg) = unknown_type_node;
|
||||
}
|
||||
|
||||
orig_arg = arg;
|
||||
|
||||
requires_tmpl_type = TREE_CODE (parm) == TEMPLATE_DECL;
|
||||
requires_type = (TREE_CODE (parm) == TYPE_DECL
|
||||
|| requires_tmpl_type);
|
||||
|
||||
/* When determining whether an argument pack expansion is a template,
|
||||
look at the pattern. */
|
||||
if (TREE_CODE (check_arg) == TYPE_PACK_EXPANSION)
|
||||
check_arg = PACK_EXPANSION_PATTERN (check_arg);
|
||||
if (TREE_CODE (arg) == TYPE_PACK_EXPANSION)
|
||||
arg = PACK_EXPANSION_PATTERN (arg);
|
||||
|
||||
is_tmpl_type =
|
||||
((TREE_CODE (check_arg) == TEMPLATE_DECL
|
||||
&& TREE_CODE (DECL_TEMPLATE_RESULT (check_arg)) == TYPE_DECL)
|
||||
|| TREE_CODE (check_arg) == TEMPLATE_TEMPLATE_PARM
|
||||
|| TREE_CODE (check_arg) == UNBOUND_CLASS_TEMPLATE);
|
||||
((TREE_CODE (arg) == TEMPLATE_DECL
|
||||
&& TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
|
||||
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|
||||
|| TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
|
||||
|
||||
if (is_tmpl_type
|
||||
&& (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|
||||
@ -4710,12 +4712,13 @@ convert_template_argument (tree parm,
|
||||
&& TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
|
||||
{
|
||||
pedwarn ("to refer to a type member of a template parameter, "
|
||||
"use %<typename %E%>", arg);
|
||||
"use %<typename %E%>", orig_arg);
|
||||
|
||||
arg = make_typename_type (TREE_OPERAND (arg, 0),
|
||||
TREE_OPERAND (arg, 1),
|
||||
typename_type,
|
||||
complain & tf_error);
|
||||
orig_arg = make_typename_type (TREE_OPERAND (arg, 0),
|
||||
TREE_OPERAND (arg, 1),
|
||||
typename_type,
|
||||
complain & tf_error);
|
||||
arg = orig_arg;
|
||||
is_type = 1;
|
||||
}
|
||||
if (is_type != requires_type)
|
||||
@ -4730,11 +4733,11 @@ convert_template_argument (tree parm,
|
||||
if (is_type)
|
||||
error (" expected a constant of type %qT, got %qT",
|
||||
TREE_TYPE (parm),
|
||||
(is_tmpl_type ? DECL_NAME (arg) : arg));
|
||||
(is_tmpl_type ? DECL_NAME (arg) : orig_arg));
|
||||
else if (requires_tmpl_type)
|
||||
error (" expected a class template, got %qE", arg);
|
||||
error (" expected a class template, got %qE", orig_arg);
|
||||
else
|
||||
error (" expected a type, got %qE", arg);
|
||||
error (" expected a type, got %qE", orig_arg);
|
||||
}
|
||||
}
|
||||
return error_mark_node;
|
||||
@ -4749,7 +4752,7 @@ convert_template_argument (tree parm,
|
||||
if (is_tmpl_type)
|
||||
error (" expected a type, got %qT", DECL_NAME (arg));
|
||||
else
|
||||
error (" expected a class template, got %qT", arg);
|
||||
error (" expected a class template, got %qT", orig_arg);
|
||||
}
|
||||
return error_mark_node;
|
||||
}
|
||||
@ -4767,19 +4770,13 @@ convert_template_argument (tree parm,
|
||||
tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
|
||||
tree argparm;
|
||||
|
||||
check_arg = arg;
|
||||
/* When determining whether a pack expansion is a template,
|
||||
look at the pattern. */
|
||||
if (TREE_CODE (check_arg) == TYPE_PACK_EXPANSION)
|
||||
check_arg = PACK_EXPANSION_PATTERN (check_arg);
|
||||
|
||||
argparm = DECL_INNERMOST_TEMPLATE_PARMS (check_arg);
|
||||
argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
|
||||
|
||||
if (coerce_template_template_parms (parmparm, argparm,
|
||||
complain, in_decl,
|
||||
args))
|
||||
{
|
||||
val = arg;
|
||||
val = orig_arg;
|
||||
|
||||
/* TEMPLATE_TEMPLATE_PARM node is preferred over
|
||||
TEMPLATE_DECL. */
|
||||
@ -4788,9 +4785,9 @@ convert_template_argument (tree parm,
|
||||
if (DECL_TEMPLATE_TEMPLATE_PARM_P (val))
|
||||
val = TREE_TYPE (val);
|
||||
else if (TREE_CODE (val) == TYPE_PACK_EXPANSION
|
||||
&& DECL_TEMPLATE_TEMPLATE_PARM_P (check_arg))
|
||||
&& DECL_TEMPLATE_TEMPLATE_PARM_P (arg))
|
||||
{
|
||||
val = TREE_TYPE (check_arg);
|
||||
val = TREE_TYPE (arg);
|
||||
val = make_pack_expansion (val);
|
||||
}
|
||||
}
|
||||
@ -4803,7 +4800,7 @@ convert_template_argument (tree parm,
|
||||
"template parameter list for %qD",
|
||||
i + 1, in_decl);
|
||||
error (" expected a template of type %qD, got %qD",
|
||||
parm, arg);
|
||||
parm, orig_arg);
|
||||
}
|
||||
|
||||
val = error_mark_node;
|
||||
@ -4811,7 +4808,7 @@ convert_template_argument (tree parm,
|
||||
}
|
||||
}
|
||||
else
|
||||
val = arg;
|
||||
val = orig_arg;
|
||||
/* We only form one instance of each template specialization.
|
||||
Therefore, if we use a non-canonical variant (i.e., a
|
||||
typedef), any future messages referring to the type will use
|
||||
@ -4827,7 +4824,7 @@ convert_template_argument (tree parm,
|
||||
if (invalid_nontype_parm_type_p (t, complain))
|
||||
return error_mark_node;
|
||||
|
||||
if (!uses_template_parms (arg) && !uses_template_parms (t))
|
||||
if (!uses_template_parms (orig_arg) && !uses_template_parms (t))
|
||||
/* We used to call digest_init here. However, digest_init
|
||||
will report errors, which we don't want when complain
|
||||
is zero. More importantly, digest_init will try too
|
||||
@ -4838,14 +4835,14 @@ convert_template_argument (tree parm,
|
||||
conversions can occur is part of determining which
|
||||
function template to call, or whether a given explicit
|
||||
argument specification is valid. */
|
||||
val = convert_nontype_argument (t, arg);
|
||||
val = convert_nontype_argument (t, orig_arg);
|
||||
else
|
||||
val = arg;
|
||||
val = orig_arg;
|
||||
|
||||
if (val == NULL_TREE)
|
||||
val = error_mark_node;
|
||||
else if (val == error_mark_node && (complain & tf_error))
|
||||
error ("could not convert template argument %qE to %qT", arg, t);
|
||||
error ("could not convert template argument %qE to %qT", orig_arg, t);
|
||||
}
|
||||
|
||||
return val;
|
||||
@ -4959,7 +4956,8 @@ coerce_template_parameter_pack (tree parms,
|
||||
else
|
||||
{
|
||||
argument_pack = make_node (NONTYPE_ARGUMENT_PACK);
|
||||
TREE_TYPE (argument_pack) = TREE_TYPE (TREE_VALUE (parm));
|
||||
TREE_TYPE (argument_pack)
|
||||
= tsubst (TREE_TYPE (TREE_VALUE (parm)), args, complain, in_decl);
|
||||
TREE_CONSTANT (argument_pack) = 1;
|
||||
}
|
||||
|
||||
@ -7108,6 +7106,22 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
|
||||
return result;
|
||||
}
|
||||
|
||||
if (arg_pack
|
||||
&& TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack)) == 1
|
||||
&& PACK_EXPANSION_P (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), 0)))
|
||||
{
|
||||
tree expansion = TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), 0);
|
||||
tree pattern = PACK_EXPANSION_PATTERN (expansion);
|
||||
if ((TYPE_P (pattern) && same_type_p (pattern, parm_pack))
|
||||
|| (!TYPE_P (pattern) && cp_tree_equal (parm_pack, pattern)))
|
||||
/* The argument pack that the parameter maps to is just an
|
||||
expansion of the parameter itself, such as one would
|
||||
find in the implicit typedef of a class inside the
|
||||
class itself. Consider this parameter "unsubstituted",
|
||||
so that we will maintain the outer pack expansion. */
|
||||
arg_pack = NULL_TREE;
|
||||
}
|
||||
|
||||
if (arg_pack)
|
||||
{
|
||||
int my_len =
|
||||
|
@ -1,3 +1,10 @@
|
||||
2007-10-30 Douglas Gregor <doug.gregor@gmail.com>
|
||||
|
||||
PR c++/31993
|
||||
PR c++/32252
|
||||
* g++.dg/cpp0x/pr31993.C: New
|
||||
* g++.dg/cpp0x/pr32252.C: New
|
||||
|
||||
2007-10-30 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/33723
|
||||
@ -8,6 +15,7 @@
|
||||
* gcc.c-torture/execute/20071030-1.c: New testcase copied from
|
||||
gcc.target/i386/loop-3.c.
|
||||
|
||||
>>>>>>> .r129772
|
||||
2007-10-30 Revital Eres <eres@il.ibm.com>
|
||||
|
||||
* testsuite/gcc.dg/vect/pr33866.c: Require vect_long.
|
||||
|
9
gcc/testsuite/g++.dg/cpp0x/pr31993.C
Normal file
9
gcc/testsuite/g++.dg/cpp0x/pr31993.C
Normal file
@ -0,0 +1,9 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
template<typename...> struct A;
|
||||
|
||||
template<template<int> class... T> struct A<T<0>...>
|
||||
{
|
||||
template<int> struct B {};
|
||||
B<0> b;
|
||||
};
|
8
gcc/testsuite/g++.dg/cpp0x/pr32252.C
Normal file
8
gcc/testsuite/g++.dg/cpp0x/pr32252.C
Normal file
@ -0,0 +1,8 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
int x[5];
|
||||
|
||||
template<int M, int N, int (&... p)[N]> struct A;
|
||||
|
||||
template<int M> struct A<M,5,x> {};
|
||||
|
||||
A<0,5,x> a;
|
@ -5,7 +5,7 @@
|
||||
template <typename... T> struct A // { dg-error "does not include variadic templates" }
|
||||
{
|
||||
static T &t; // { dg-error "not expanded with|T" }
|
||||
static const int i = sizeof (++t); // { dg-error "invalid use of template type parameter" }
|
||||
static const int i = sizeof (++t);
|
||||
};
|
||||
|
||||
int x[A <int>::i]; // { dg-error "is not an integral constant-expression" }
|
||||
|
Loading…
Reference in New Issue
Block a user