aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDodji Seketeli <dodji@redhat.com>2011-09-13 14:39:15 +0000
committerDodji Seketeli <dodji@gcc.gnu.org>2011-09-13 16:39:15 +0200
commit1f15c50b16add97555d590e072801b973892e6bc (patch)
tree4bbac53fbb932d32a31e8816e87d08008b2b6757 /gcc
parent42f833bc5f567f1e4da1964ebbd177a5a1c697a1 (diff)
downloadgcc-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/ChangeLog10
-rw-r--r--gcc/cp/pt.c115
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic116.C32
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> ());
+}