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
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
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);
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;
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);
break;
}
}
-
+
/* Update ARGS to restore the substitution from parameter packs to
their argument packs. */
for (pack = packs; pack; pack = TREE_CHAIN (pack))
}
}
+ if (very_local_specializations)
+ {
+ htab_delete (local_specializations);
+ local_specializations = NULL;
+ }
+
return result;
}
}
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);
d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name,
d_template_args (di)));
}
+ else if (peek == 's' && d_peek_next_char (di) == 'p')
+ {
+ d_advance (di, 2);
+ return d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION,
+ d_expression (di), NULL);
+ }
else if (peek == 'f' && d_peek_next_char (di) == 'p')
{
/* Function parameter used in a late-specified return type. */
case DEMANGLE_COMPONENT_BUILTIN_TYPE:
case DEMANGLE_COMPONENT_SUB_STD:
case DEMANGLE_COMPONENT_CHARACTER:
+ case DEMANGLE_COMPONENT_FUNCTION_PARAM:
return NULL;
case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
const struct demangle_component *dc)
{
int simple = 0;
- if (dc->type == DEMANGLE_COMPONENT_NAME)
+ if (dc->type == DEMANGLE_COMPONENT_NAME
+ || dc->type == DEMANGLE_COMPONENT_FUNCTION_PARAM)
simple = 1;
if (!simple)
d_append_char (dpi, '(');
case DEMANGLE_COMPONENT_PACK_EXPANSION:
{
- struct demangle_component *a = d_find_pack (dpi, d_left (dc));
- int len = d_pack_length (a);
+ int len;
int i;
+ struct demangle_component *a = d_find_pack (dpi, d_left (dc));
+ if (a == NULL)
+ {
+ /* d_find_pack won't find anything if the only packs involved
+ in this expansion are function parameter packs; in that
+ case, just print the pattern and "...". */
+ d_print_subexpr (dpi, d_left (dc));
+ d_append_string (dpi, "...");
+ return;
+ }
+ len = d_pack_length (a);
dc = d_left (dc);
for (i = 0; i < len; ++i)
{
# decltype/param placeholder test
--format=gnu-v3
_Z3addIidEDTplfp_fp0_ET_T0_
-decltype ((parm#1)+(parm#2)) add<int, double>(int, double)
+decltype (parm#1+parm#2) add<int, double>(int, double)
# decltype/fn call test
--format=gnu-v3
_Z4add3IidEDTclL_Z1gEfp_fp0_EET_T0_
# '.' test
--format=gnu-v3
_Z1hI1AIiEdEDTcldtfp_1gIT0_EEET_S2_
-decltype (((parm#1).(g<double>))()) h<A<int>, double>(A<int>, double)
+decltype ((parm#1.(g<double>))()) h<A<int>, double>(A<int>, double)
# test for typed function in decltype
--format=gnu-v3
_ZN1AIiE1jIiEEDTplfp_clL_Z1xvEEET_
-decltype ((parm#1)+((x())())) A<int>::j<int>(int)
+decltype (parm#1+((x())())) A<int>::j<int>(int)
+# test for expansion of function parameter pack
+--format=gnu-v3
+_Z1gIIidEEDTclL_Z1fEspplfp_Li1EEEDpT_
+decltype (f((parm#1+(1))...)) g<int, double>(int, double)