diff options
author | Dodji Seketeli <dodji@redhat.com> | 2011-09-13 14:39:15 +0000 |
---|---|---|
committer | Dodji Seketeli <dodji@gcc.gnu.org> | 2011-09-13 16:39:15 +0200 |
commit | 1f15c50b16add97555d590e072801b973892e6bc (patch) | |
tree | 4bbac53fbb932d32a31e8816e87d08008b2b6757 /gcc | |
parent | 42f833bc5f567f1e4da1964ebbd177a5a1c697a1 (diff) | |
download | gcc-1f15c50b16add97555d590e072801b973892e6bc.zip gcc-1f15c50b16add97555d590e072801b973892e6bc.tar.gz gcc-1f15c50b16add97555d590e072801b973892e6bc.tar.bz2 |
c++/48320 - Template parameter packs cannot be expanded in default template arguments
gcc/cp/
PR c++/48320
* pt.c (template_parameter_pack_p): Support TEMPLATE_PARM_INDEX
nodes. Add a comment.
(arg_from_parm_pack_p): New static function, factorized out from
tsubst_pack_expansion and extended to support non-type parameter
packs represented with TEMPLATE_PARM_INDEX nodes.
(tsubst_pack_expansion): Use arg_from_parm_pack_p.
gcc/testsuite/
PR c++/48320
* g++.dg/cpp0x/variadic116.C: New test case.
From-SVN: r178811
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/pt.c | 115 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic116.C | 32 |
4 files changed, 115 insertions, 47 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6b6c36d..aa4a31d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2011-09-13 Dodji Seketeli <dodji@redhat.com> + + PR c++/48320 + * pt.c (template_parameter_pack_p): Support TEMPLATE_PARM_INDEX + nodes. Add a comment. + (arg_from_parm_pack_p): New static function, factorized out from + tsubst_pack_expansion and extended to support non-type parameter + packs represented with TEMPLATE_PARM_INDEX nodes. + (tsubst_pack_expansion): Use arg_from_parm_pack_p. + 2011-09-12 Jason Merrill <jason@redhat.com> * pt.c (type_unification_real): Fix handling of DEDUCE_CONV diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 9a5e3dd..1407364 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -203,6 +203,7 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree, static tree listify (tree); static tree listify_autos (tree, tree); static tree template_parm_to_arg (tree t); +static bool arg_from_parm_pack_p (tree, tree); static tree current_template_args (void); static tree fixup_template_type_parm_type (tree, int); static tree fixup_template_parm_index (tree, tree, int); @@ -2741,12 +2742,15 @@ template_parameter_pack_p (const_tree parm) if (TREE_CODE (parm) == PARM_DECL) return (DECL_TEMPLATE_PARM_P (parm) && TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))); + if (TREE_CODE (parm) == TEMPLATE_PARM_INDEX) + return TEMPLATE_PARM_PARAMETER_PACK (parm); /* If this is a list of template parameters, we could get a TYPE_DECL or a TEMPLATE_DECL. */ if (TREE_CODE (parm) == TYPE_DECL || TREE_CODE (parm) == TEMPLATE_DECL) parm = TREE_TYPE (parm); + /* Otherwise it must be a type template parameter. */ return ((TREE_CODE (parm) == TEMPLATE_TYPE_PARM || TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM) && TEMPLATE_TYPE_PARAMETER_PACK (parm)); @@ -4005,6 +4009,63 @@ template_parm_to_arg (tree t) return t; } +/* This function returns TRUE if PARM_PACK is a template parameter + pack and if ARG_PACK is what template_parm_to_arg returned when + passed PARM_PACK. */ + +static bool +arg_from_parm_pack_p (tree arg_pack, tree parm_pack) +{ + /* For clarity in the comments below let's use the representation + argument_pack<elements>' to denote an argument pack and its + elements. + + In the 'if' block below, we want to detect cases where + ARG_PACK is argument_pack<PARM_PACK...>. I.e, we want to + check if ARG_PACK is an argument pack which sole element is + the expansion of PARM_PACK. That argument pack is typically + created by template_parm_to_arg when passed a parameter + pack. */ + + 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); + /* So we have an argument_pack<P...>. We want to test if P + is actually PARM_PACK. We will not use cp_tree_equal to + test P and PARM_PACK because during type fixup (by + fixup_template_parm) P can be a pre-fixup version of a + type and PARM_PACK be its post-fixup version. + cp_tree_equal would consider them as different even + though we would want to consider them compatible for our + precise purpose here. + + Thus we are going to consider that P and PARM_PACK are + compatible if they have the same DECL. */ + if ((/* If ARG_PACK is a type parameter pack named by the + same DECL as parm_pack ... */ + (TYPE_P (pattern) + && TYPE_P (parm_pack) + && TYPE_NAME (pattern) == TYPE_NAME (parm_pack)) + /* ... or if PARM_PACK is a non-type parameter named by the + same DECL as ARG_PACK. Note that PARM_PACK being a + non-type parameter means it's either a PARM_DECL or a + TEMPLATE_PARM_INDEX. */ + || (TREE_CODE (pattern) == TEMPLATE_PARM_INDEX + && ((TREE_CODE (parm_pack) == PARM_DECL + && (TEMPLATE_PARM_DECL (pattern) + == TEMPLATE_PARM_DECL (DECL_INITIAL (parm_pack)))) + || (TREE_CODE (parm_pack) == TEMPLATE_PARM_INDEX + && (TEMPLATE_PARM_DECL (pattern) + == TEMPLATE_PARM_DECL (parm_pack)))))) + && template_parameter_pack_p (pattern)) + return true; + } + return false; +} + /* Within the declaration of a template, return all levels of template parameters that apply. The template parameters are represented as a TREE_VEC, in the form documented in cp-tree.h for template @@ -9105,53 +9166,13 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, return result; } - /* For clarity in the comments below let's use the - representation 'argument_pack<elements>' to denote an - argument pack and its elements. - - In the 'if' block below, we want to detect cases where - ARG_PACK is argument_pack<PARM_PACK...>. I.e, we want to - check if ARG_PACK is an argument pack which sole element is - the expansion of PARM_PACK. That argument pack is typically - created by template_parm_to_arg when passed a parameter - pack. */ - 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); - /* So we have an argument_pack<P...>. We want to test if P - is actually PARM_PACK. We will not use cp_tree_equal to - test P and PARM_PACK because during type fixup (by - fixup_template_parm) P can be a pre-fixup version of a - type and PARM_PACK be its post-fixup version. - cp_tree_equal would consider them as different even - though we would want to consider them compatible for our - precise purpose here. - - Thus we are going to consider that P and PARM_PACK are - compatible if they have the same DECL. */ - if ((/* If ARG_PACK is a type parameter pack named by the - same DECL as parm_pack ... */ - (TYPE_P (pattern) - && TYPE_P (parm_pack) - && TYPE_NAME (pattern) == TYPE_NAME (parm_pack)) - /* ... or if ARG_PACK is a non-type parameter - named by the same DECL as parm_pack ... */ - || (TREE_CODE (pattern) == TEMPLATE_PARM_INDEX - && TREE_CODE (parm_pack) == PARM_DECL - && TEMPLATE_PARM_DECL (pattern) - == TEMPLATE_PARM_DECL (DECL_INITIAL (parm_pack)))) - && template_parameter_pack_p (pattern)) - /* ... then 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_from_parm_pack_p (arg_pack, parm_pack)) + /* 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) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index eea712e..65af046 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-09-13 Dodji Seketeli <dodji@redhat.com> + + PR c++/48320 + * g++.dg/cpp0x/variadic116.C: New test case. + 2011-09-12 Richard Sandiford <rdsandiford@googlemail.com> * gcc.target/mips/mips.exp (mips_option_groups): Add debug options. diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic116.C b/gcc/testsuite/g++.dg/cpp0x/variadic116.C new file mode 100644 index 0000000..079d751 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic116.C @@ -0,0 +1,32 @@ +// Origin: PR c++/48320 +// { dg-options -std=c++0x } + +template<class... T> +struct tuple +{ + typedef int type; +}; + +template<int... Indices> +struct indices +{ +}; + +template<unsigned i, class Tuple> +struct tuple_element +{ + typedef Tuple type; +}; + +template<class Tuple, + int... Indices, + class Result = tuple<typename tuple_element<Indices, Tuple>::type...> > +Result +f(Tuple&&, indices<Indices...>); + + +void +foo() +{ + f(tuple<int, char, unsigned> (), indices<2, 1, 0> ()); +} |