+2007-03-31 Douglas Gregor <doug.gregor@gmail.com>
+
+ PR c++/31138
+ PR c++/31140
+ PR c++/31141
+ * parser.c (declarator_can_be_parameter_pack): New.
+ (cp_parser_template_parameter): Only parse the `...' if the
+ declarator can be a parameter pack.
+ (cp_parser_parameter_declaration): Ditto. Also, handle when TYPE
+ is NULL.
+ * pt.c (find_parameter_packs_r): Look into the bounds on integer
+ types (they could be used as array bounds).
+ (check_for_bare_parameter_packs): Deal with TEMPLATE_PARM_INDEX.
+ (tsubst_pack_expansion): Handle failure to expand parameter
+ packs.
+
2007-03-30 Paolo Carlini <pcarlini@suse.de>
PR c++/26099
return declarator;
}
+/* Determine whether the declarator we've seen so far can be a
+ parameter pack, when followed by an ellipsis. */
+static bool
+declarator_can_be_parameter_pack (cp_declarator *declarator)
+{
+ /* Search for a declarator name, or any other declarator that goes
+ after the point where the ellipsis could appear in a parameter
+ pack. If we find any of these, then this declarator can not be
+ made into a parameter pack. */
+ bool found = false;
+ while (declarator && !found)
+ {
+ switch ((int)declarator->kind)
+ {
+ case cdk_id:
+ case cdk_error:
+ case cdk_array:
+ case cdk_ptrmem:
+ found = true;
+ break;
+
+ default:
+ declarator = declarator->declarator;
+ break;
+ }
+ }
+
+ return !found;
+}
+
cp_parameter_declarator *no_parameters;
/* Create a parameter declarator with the indicated DECL_SPECIFIERS,
marked as a parameter pack, then we have a parameter pack (that
has no declarator); */
if (!*is_parameter_pack
- && cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+ && cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)
+ && declarator_can_be_parameter_pack (parameter_declarator->declarator))
{
-
/* Consume the `...'. */
cp_lexer_consume_token (parser->lexer);
maybe_warn_variadic_templates ();
cp_parser_attributes_opt (parser));
}
- /* If the next token is an ellipsis, and the type of the declarator
- contains parameter packs but it is not a TYPE_PACK_EXPANSION, then
- we actually have a parameter pack expansion expression. Otherwise,
- leave the ellipsis for a C-style variadic function. */
+ /* If the next token is an ellipsis, and we have not seen a
+ declarator name, and the type of the declarator contains parameter
+ packs but it is not a TYPE_PACK_EXPANSION, then we actually have
+ a parameter pack expansion expression. Otherwise, leave the
+ ellipsis for a C-style variadic function. */
token = cp_lexer_peek_token (parser->lexer);
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
{
tree type = decl_specifiers.type;
- if (DECL_P (type))
+ if (type && DECL_P (type))
type = TREE_TYPE (type);
- if (TREE_CODE (type) != TYPE_PACK_EXPANSION
+ if (type
+ && TREE_CODE (type) != TYPE_PACK_EXPANSION
+ && declarator_can_be_parameter_pack (declarator)
&& (!declarator || !declarator->parameter_pack_p)
&& uses_parameter_packs (type))
{
- /* Consume the `...'. */
- cp_lexer_consume_token (parser->lexer);
- maybe_warn_variadic_templates ();
-
- /* Build a pack expansion type */
- if (declarator)
- declarator->parameter_pack_p = true;
- else
- decl_specifiers.type = make_pack_expansion (type);
- }
+ /* Consume the `...'. */
+ cp_lexer_consume_token (parser->lexer);
+ maybe_warn_variadic_templates ();
+
+ /* Build a pack expansion type */
+ if (declarator)
+ declarator->parameter_pack_p = true;
+ else
+ decl_specifiers.type = make_pack_expansion (type);
+ }
}
/* The restriction on defining new types applies only to the type
*walk_subtrees = 0;
return NULL_TREE;
+ case INTEGER_TYPE:
+ walk_tree (&TYPE_MAX_VALUE (t), &find_parameter_packs_r,
+ ppd, ppd->visited);
+ *walk_subtrees = 0;
+ return NULL_TREE;
+
default:
return 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);
inform (" %qD", name);
if (arg_pack && TREE_CODE (arg_pack) == ARGUMENT_PACK_SELECT)
arg_pack = ARGUMENT_PACK_SELECT_FROM_PACK (arg_pack);
+ if (arg_pack && !ARGUMENT_PACK_P (arg_pack))
+ /* This can only happen if we forget to expand an argument
+ pack somewhere else. Just return an error, silently. */
+ {
+ result = make_tree_vec (1);
+ TREE_VEC_ELT (result, 0) = error_mark_node;
+ return result;
+ }
+
if (arg_pack)
{
int my_len =