diff options
author | Doug Gregor <dgregor@gcc.gnu.org> | 2007-10-30 13:36:34 +0000 |
---|---|---|
committer | Doug Gregor <dgregor@gcc.gnu.org> | 2007-10-30 13:36:34 +0000 |
commit | 88b823145ebb0a22cbfd20ffb781a3bca69c8f45 (patch) | |
tree | 7361b26a0031a395f87ecf7275303a233b1042a0 | |
parent | 310750d8ec5621e9f4c33db6b18de319cd7bc7f1 (diff) | |
download | gcc-88b823145ebb0a22cbfd20ffb781a3bca69c8f45.zip gcc-88b823145ebb0a22cbfd20ffb781a3bca69c8f45.tar.gz gcc-88b823145ebb0a22cbfd20ffb781a3bca69c8f45.tar.bz2 |
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
-rw-r--r-- | gcc/cp/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/cp/pt.c | 86 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr31993.C | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr32252.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/crash36.C | 2 |
6 files changed, 89 insertions, 37 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c9b2325..d5b73e7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3e8f6e5..5f6e296 100644 --- a/gcc/cp/pt.c +++ b/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 = diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 19ae6a8..0956218 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31993.C b/gcc/testsuite/g++.dg/cpp0x/pr31993.C new file mode 100644 index 0000000..94fb9cc --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr31993.C @@ -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; +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32252.C b/gcc/testsuite/g++.dg/cpp0x/pr32252.C new file mode 100644 index 0000000..543dc88 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr32252.C @@ -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; diff --git a/gcc/testsuite/g++.dg/parse/crash36.C b/gcc/testsuite/g++.dg/parse/crash36.C index 1e5ab8f..e73e928 100644 --- a/gcc/testsuite/g++.dg/parse/crash36.C +++ b/gcc/testsuite/g++.dg/parse/crash36.C @@ -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" } |