aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-03-23 17:03:01 -0400
committerJason Merrill <jason@gcc.gnu.org>2009-03-23 17:03:01 -0400
commit6afcfe0a8080cf3816e841f0f1c2b96a73baed43 (patch)
treeea6d54ba1fb63d8cc661d04df277796e02ed2ac1 /gcc
parent6ab282f65064d9d22b04a89b0958fefbec50ebc3 (diff)
downloadgcc-6afcfe0a8080cf3816e841f0f1c2b96a73baed43.zip
gcc-6afcfe0a8080cf3816e841f0f1c2b96a73baed43.tar.gz
gcc-6afcfe0a8080cf3816e841f0f1c2b96a73baed43.tar.bz2
pt.c (make_fnparm_pack): Split out from...
* gcc/cp/pt.c (make_fnparm_pack): Split out from... (instantiate_decl): ...here. (tsubst_pack_expansion): Handle being called in a late-specified return type. * libiberty/cp-demangle.c (d_expression): Handle pack expansion. (d_find_pack): Handle DEMANGLE_COMPONENT_FUNCTION_PARAM. (d_print_subexpr): Don't wrap function parms in (). (d_print_comp) [DEMANGLE_COMPONENT_PACK_EXPANSION]: Handle not finding a pack. From-SVN: r145013
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/pt.c94
-rw-r--r--gcc/testsuite/ChangeLog2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto12.C11
4 files changed, 83 insertions, 29 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 77c195a..e9e424d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
2009-03-23 Jason Merrill <jason@redhat.com>
+ * pt.c (make_fnparm_pack): Split out from...
+ (instantiate_decl): ...here.
+ (tsubst_pack_expansion): Handle being called in a late-specified
+ return type.
+
PR c++/39526
* name-lookup.c (pushdecl_maybe_friend): Don't warn about shadowing
a parm with a parm.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 1c408237..5092c72 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -174,6 +174,7 @@ static tree tsubst (tree, tree, tsubst_flags_t, tree);
static tree tsubst_expr (tree, tree, tsubst_flags_t, tree, bool);
static tree tsubst_copy (tree, tree, tsubst_flags_t, tree);
static tree tsubst_pack_expansion (tree, tree, tsubst_flags_t, tree);
+static tree tsubst_decl (tree, tree, tsubst_flags_t);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
@@ -7435,6 +7436,37 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return r;
}
+/* Give a chain SPEC_PARM of PARM_DECLs, pack them into a
+ NONTYPE_ARGUMENT_PACK. */
+
+static tree
+make_fnparm_pack (tree spec_parm)
+{
+ /* Collect all of the extra "packed" parameters into an
+ argument pack. */
+ tree parmvec;
+ tree parmtypevec;
+ tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
+ tree argtypepack = make_node (TYPE_ARGUMENT_PACK);
+ int i, len = list_length (spec_parm);
+
+ /* Fill in PARMVEC and PARMTYPEVEC with all of the parameters. */
+ parmvec = make_tree_vec (len);
+ parmtypevec = make_tree_vec (len);
+ for (i = 0; i < len; i++, spec_parm = TREE_CHAIN (spec_parm))
+ {
+ TREE_VEC_ELT (parmvec, i) = spec_parm;
+ TREE_VEC_ELT (parmtypevec, i) = TREE_TYPE (spec_parm);
+ }
+
+ /* Build the argument packs. */
+ SET_ARGUMENT_PACK_ARGS (argpack, parmvec);
+ SET_ARGUMENT_PACK_ARGS (argtypepack, parmtypevec);
+ TREE_TYPE (argpack) = argtypepack;
+
+ return argpack;
+}
+
/* Substitute ARGS into T, which is an pack expansion
(i.e. TYPE_PACK_EXPANSION or EXPR_PACK_EXPANSION). Returns a
TREE_VEC with the substituted arguments, a PACK_EXPANSION_* node
@@ -7449,6 +7481,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
tree first_arg_pack; int i, len = -1;
tree result;
int incomplete = 0;
+ bool very_local_specializations = false;
gcc_assert (PACK_EXPANSION_P (t));
pattern = PACK_EXPANSION_PATTERN (t);
@@ -7465,7 +7498,18 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
tree orig_arg = NULL_TREE;
if (TREE_CODE (parm_pack) == PARM_DECL)
- arg_pack = retrieve_local_specialization (parm_pack);
+ {
+ arg_pack = retrieve_local_specialization (parm_pack);
+ if (arg_pack == NULL_TREE)
+ {
+ /* This can happen for a parameter name used later in a function
+ declaration (such as in a late-specified return type). Just
+ make a dummy decl, since it's only used for its type. */
+ gcc_assert (skip_evaluation);
+ arg_pack = tsubst_decl (parm_pack, args, complain);
+ arg_pack = make_fnparm_pack (arg_pack);
+ }
+ }
else
{
int level, idx, levels;
@@ -7559,6 +7603,17 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
if (len < 0)
return error_mark_node;
+ if (!local_specializations)
+ {
+ /* We're in a late-specified return type, so we don't have a local
+ specializations table. Create one for doing this expansion. */
+ very_local_specializations = true;
+ local_specializations = htab_create (37,
+ hash_local_specialization,
+ eq_local_specializations,
+ NULL);
+ }
+
/* For each argument in each argument pack, substitute into the
pattern. */
result = make_tree_vec (len + incomplete);
@@ -7620,7 +7675,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
break;
}
}
-
+
/* Update ARGS to restore the substitution from parameter packs to
their argument packs. */
for (pack = packs; pack; pack = TREE_CHAIN (pack))
@@ -7643,6 +7698,12 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
}
}
+ if (very_local_specializations)
+ {
+ htab_delete (local_specializations);
+ local_specializations = NULL;
+ }
+
return result;
}
@@ -15477,37 +15538,12 @@ instantiate_decl (tree d, int defer_ok,
}
if (tmpl_parm && FUNCTION_PARAMETER_PACK_P (tmpl_parm))
{
- /* Collect all of the extra "packed" parameters into an
- argument pack. */
- tree parmvec;
- tree parmtypevec;
- tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
- tree argtypepack = make_node (TYPE_ARGUMENT_PACK);
- int i, len = 0;
- tree t;
-
- /* Count how many parameters remain. */
- for (t = spec_parm; t; t = TREE_CHAIN (t))
- len++;
-
- /* Fill in PARMVEC and PARMTYPEVEC with all of the parameters. */
- parmvec = make_tree_vec (len);
- parmtypevec = make_tree_vec (len);
- for(i = 0; i < len; i++, spec_parm = TREE_CHAIN (spec_parm))
- {
- TREE_VEC_ELT (parmvec, i) = spec_parm;
- TREE_VEC_ELT (parmtypevec, i) = TREE_TYPE (spec_parm);
- }
-
- /* Build the argument packs. */
- SET_ARGUMENT_PACK_ARGS (argpack, parmvec);
- SET_ARGUMENT_PACK_ARGS (argtypepack, parmtypevec);
- TREE_TYPE (argpack) = argtypepack;
-
/* Register the (value) argument pack as a specialization of
TMPL_PARM, then move on. */
+ tree argpack = make_fnparm_pack (spec_parm);
register_local_specialization (argpack, tmpl_parm);
tmpl_parm = TREE_CHAIN (tmpl_parm);
+ spec_parm = NULL_TREE;
}
gcc_assert (!spec_parm);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 16a2c54..40205fa 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,7 @@
2009-03-23 Jason Merrill <jason@redhat.com>
+ * g++.dg/cpp0x/auto12.C: Add variadic test.
+
PR c++/39526
* g++.dg/warn/Wshadow-4.C: New test.
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto12.C b/gcc/testsuite/g++.dg/cpp0x/auto12.C
index 45ceedf..34dc8c9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto12.C
@@ -35,6 +35,15 @@ auto A<T>::f(U u) -> decltype (u + i)
return u + i;
}
+template <class... Args>
+int f (Args... args);
+
+template <class... Args>
+auto g (Args... args) -> decltype (f ((args+1)...))
+{
+ return (f ((args+1)...));
+}
+
int main()
{
// { dg-final { scan-assembler "_ZN1AIiE1fIiEEDTplfp_L_ZNS0_1iEEET_" } }
@@ -49,4 +58,6 @@ int main()
A<int>().h(1);
// { dg-final { scan-assembler "_ZN1AIiE1jIiEEDTplfp_clL_Z1xvEEET_" } }
A<int>().j(1);
+ // { dg-final { scan-assembler "_Z1gIIidEEDTclL_Z1fEspplfp_Li1EEEDpT_" } }
+ g(42, 1.0);
}