+ if (TYPE_P (t))
+ cp_walk_tree (&TYPE_CONTEXT (t),
+ &find_parameter_packs_r, ppd, ppd->visited);
+
+ /* This switch statement will return immediately if we don't find a
+ parameter pack. */
+ switch (TREE_CODE (t))
+ {
+ case TEMPLATE_PARM_INDEX:
+ return NULL_TREE;
+
+ case BOUND_TEMPLATE_TEMPLATE_PARM:
+ /* Check the template itself. */
+ cp_walk_tree (&TREE_TYPE (TYPE_TI_TEMPLATE (t)),
+ &find_parameter_packs_r, ppd, ppd->visited);
+ /* Check the template arguments. */
+ cp_walk_tree (&TYPE_TI_ARGS (t), &find_parameter_packs_r, ppd,
+ ppd->visited);
+ *walk_subtrees = 0;
+ return NULL_TREE;
+
+ case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
+ return NULL_TREE;
+
+ case PARM_DECL:
+ return NULL_TREE;
+
+ case RECORD_TYPE:
+ if (TYPE_PTRMEMFUNC_P (t))
+ return NULL_TREE;
+ /* Fall through. */
+
+ case UNION_TYPE:
+ case ENUMERAL_TYPE:
+ if (TYPE_TEMPLATE_INFO (t))
+ cp_walk_tree (&TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
+ &find_parameter_packs_r, ppd, ppd->visited);
+
+ *walk_subtrees = 0;
+ return NULL_TREE;
+
+ case TEMPLATE_DECL:
+ cp_walk_tree (&TREE_TYPE (t),
+ &find_parameter_packs_r, ppd, ppd->visited);
+ return NULL_TREE;
+
+ case TYPENAME_TYPE:
+ cp_walk_tree (&TYPENAME_TYPE_FULLNAME (t), &find_parameter_packs_r,
+ ppd, ppd->visited);
+ *walk_subtrees = 0;
+ return NULL_TREE;
+
+ case TYPE_PACK_EXPANSION:
+ case EXPR_PACK_EXPANSION:
+ *walk_subtrees = 0;
+ return NULL_TREE;
+
+ case INTEGER_TYPE:
+ cp_walk_tree (&TYPE_MAX_VALUE (t), &find_parameter_packs_r,
+ ppd, ppd->visited);
+ *walk_subtrees = 0;
+ return NULL_TREE;
+
+ case IDENTIFIER_NODE:
+ cp_walk_tree (&TREE_TYPE (t), &find_parameter_packs_r, ppd,
+ ppd->visited);
+ *walk_subtrees = 0;
+ return NULL_TREE;
+
+ default:
+ return NULL_TREE;
+ }
+
+ return NULL_TREE;
+}
+
+/* Determines if the expression or type T uses any parameter packs. */
+bool
+uses_parameter_packs (tree t)
+{
+ tree parameter_packs = NULL_TREE;
+ struct find_parameter_pack_data ppd;
+ ppd.parameter_packs = ¶meter_packs;
+ ppd.visited = pointer_set_create ();
+ cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
+ pointer_set_destroy (ppd.visited);
+ return parameter_packs != NULL_TREE;
+}
+
+/* Turn ARG, which may be an expression, type, or a TREE_LIST
+ representation a base-class initializer into a parameter pack
+ expansion. If all goes well, the resulting node will be an
+ EXPR_PACK_EXPANSION, TYPE_PACK_EXPANSION, or TREE_LIST,
+ respectively. */
+tree
+make_pack_expansion (tree arg)
+{
+ tree result;
+ tree parameter_packs = NULL_TREE;
+ bool for_types = false;
+ struct find_parameter_pack_data ppd;
+
+ if (!arg || arg == error_mark_node)
+ return arg;
+
+ if (TREE_CODE (arg) == TREE_LIST)
+ {
+ /* The only time we will see a TREE_LIST here is for a base
+ class initializer. In this case, the TREE_PURPOSE will be a
+ _TYPE node (representing the base class expansion we're
+ initializing) and the TREE_VALUE will be a TREE_LIST
+ containing the initialization arguments.
+
+ The resulting expansion looks somewhat different from most
+ expansions. Rather than returning just one _EXPANSION, we
+ return a TREE_LIST whose TREE_PURPOSE is a
+ TYPE_PACK_EXPANSION containing the bases that will be
+ initialized. The TREE_VALUE will be identical to the
+ original TREE_VALUE, which is a list of arguments that will
+ be passed to each base. We do not introduce any new pack
+ expansion nodes into the TREE_VALUE (although it is possible
+ that some already exist), because the TREE_PURPOSE and
+ TREE_VALUE all need to be expanded together with the same
+ _EXPANSION node. Note that the TYPE_PACK_EXPANSION in the
+ resulting TREE_PURPOSE will mention the parameter packs in
+ both the bases and the arguments to the bases. */
+ tree purpose;
+ tree value;
+ tree parameter_packs = NULL_TREE;
+
+ /* Determine which parameter packs will be used by the base
+ class expansion. */
+ ppd.visited = pointer_set_create ();
+ ppd.parameter_packs = ¶meter_packs;
+ cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r,
+ &ppd, ppd.visited);
+
+ if (parameter_packs == NULL_TREE)
+ {
+ error ("base initializer expansion %<%T%> contains no parameter packs", arg);
+ pointer_set_destroy (ppd.visited);
+ return error_mark_node;
+ }
+
+ if (TREE_VALUE (arg) != void_type_node)
+ {
+ /* Collect the sets of parameter packs used in each of the
+ initialization arguments. */
+ for (value = TREE_VALUE (arg); value; value = TREE_CHAIN (value))
+ {
+ /* Determine which parameter packs will be expanded in this
+ argument. */
+ cp_walk_tree (&TREE_VALUE (value), &find_parameter_packs_r,
+ &ppd, ppd.visited);
+ }
+ }
+
+ pointer_set_destroy (ppd.visited);
+
+ /* Create the pack expansion type for the base type. */
+ purpose = make_node (TYPE_PACK_EXPANSION);
+ SET_PACK_EXPANSION_PATTERN (purpose, TREE_PURPOSE (arg));
+ PACK_EXPANSION_PARAMETER_PACKS (purpose) = parameter_packs;
+
+ /* Just use structural equality for these TYPE_PACK_EXPANSIONS;
+ they will rarely be compared to anything. */
+ SET_TYPE_STRUCTURAL_EQUALITY (purpose);
+
+ return tree_cons (purpose, TREE_VALUE (arg), NULL_TREE);
+ }
+
+ if (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL)
+ for_types = true;
+
+ /* Build the PACK_EXPANSION_* node. */
+ result = make_node (for_types ? TYPE_PACK_EXPANSION : EXPR_PACK_EXPANSION);
+ SET_PACK_EXPANSION_PATTERN (result, arg);
+ if (TREE_CODE (result) == EXPR_PACK_EXPANSION)
+ {
+ /* Propagate type and const-expression information. */
+ TREE_TYPE (result) = TREE_TYPE (arg);
+ TREE_CONSTANT (result) = TREE_CONSTANT (arg);
+ }
+ else
+ /* Just use structural equality for these TYPE_PACK_EXPANSIONS;
+ they will rarely be compared to anything. */
+ SET_TYPE_STRUCTURAL_EQUALITY (result);
+
+ /* Determine which parameter packs will be expanded. */
+ ppd.parameter_packs = ¶meter_packs;
+ ppd.visited = pointer_set_create ();
+ cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited);
+ pointer_set_destroy (ppd.visited);
+
+ /* Make sure we found some parameter packs. */
+ if (parameter_packs == NULL_TREE)
+ {
+ if (TYPE_P (arg))
+ error ("expansion pattern %<%T%> contains no argument packs", arg);
+ else
+ error ("expansion pattern %<%E%> contains no argument packs", arg);
+ return error_mark_node;
+ }
+ PACK_EXPANSION_PARAMETER_PACKS (result) = parameter_packs;
+
+ return result;
+}
+
+/* Checks T for any "bare" parameter packs, which have not yet been
+ expanded, and issues an error if any are found. This operation can
+ only be done on full expressions or types (e.g., an expression
+ statement, "if" condition, etc.), because we could have expressions like:
+
+ foo(f(g(h(args)))...)
+
+ where "args" is a parameter pack. check_for_bare_parameter_packs
+ should not be called for the subexpressions args, h(args),
+ g(h(args)), or f(g(h(args))), because we would produce erroneous
+ error messages.
+
+ Returns TRUE and emits an error if there were bare parameter packs,
+ returns FALSE otherwise. */
+bool
+check_for_bare_parameter_packs (tree t)
+{
+ tree parameter_packs = NULL_TREE;
+ struct find_parameter_pack_data ppd;
+
+ if (!processing_template_decl || !t || t == error_mark_node)
+ return false;
+
+ if (TREE_CODE (t) == TYPE_DECL)
+ t = TREE_TYPE (t);
+
+ ppd.parameter_packs = ¶meter_packs;
+ ppd.visited = pointer_set_create ();
+ cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
+ pointer_set_destroy (ppd.visited);
+
+ if (parameter_packs)
+ {
+ error ("parameter packs not expanded with %<...%>:");
+ while (parameter_packs)
+ {
+ tree pack = TREE_VALUE (parameter_packs);
+ tree name = NULL_TREE;
+
+ if (TREE_CODE (pack) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (pack) == TEMPLATE_TEMPLATE_PARM)
+ name = TYPE_NAME (pack);
+ else if (TREE_CODE (pack) == TEMPLATE_PARM_INDEX)
+ name = DECL_NAME (TEMPLATE_PARM_DECL (pack));
+ else
+ name = DECL_NAME (pack);
+
+ if (name)
+ inform (" %qD", name);
+ else
+ inform (" <anonymous>");
+
+ parameter_packs = TREE_CHAIN (parameter_packs);
+ }
+
+ return true;
+ }