Commit cdcae745 by Douglas Gregor Committed by Doug Gregor

re PR c++/34751 (ICE with pointer to member and variadic templates)

2008-01-15  Douglas Gregor  <doug.gregor@gmail.com>

	PR c++/34751
	* pt.c (coerce_template_parameter_pack): When substituting into
	the type of a non-type template parameter pack. use the
	deduced/substituted arguments.
	* parser.c (declarator_can_be_parameter_pack): A pointer-to-member
	can be a parameter pack with the ellipsis following it.  When we
	have an erroneous declaration, allow it to be a parameter pack.
	(cp_parser_template_parameter): Complain about default
	arguments on non-type template parameter packs, and parse them
	using the new cp_parser_default_argument.
	(cp_parser_parameter_declaration): Complain about parameter packs
	with default arguments. Move parsing of default arguments into a
	new function, cp_parser_default_argument.
	(cp_parser_default_argument): New; extracted from
	cp_parser_parameter_declaration.

2008-01-15  Douglas Gregor  <doug.gregor@gmail.com>

	PR c++/34751
	* g++.dg/cpp0x/vt-34751.C: New.

From-SVN: r131548
parent 4439d02f
2008-01-15 Douglas Gregor <doug.gregor@gmail.com> 2008-01-15 Douglas Gregor <doug.gregor@gmail.com>
PR c++/34751
* pt.c (coerce_template_parameter_pack): When substituting into
the type of a non-type template parameter pack. use the
deduced/substituted arguments.
* parser.c (declarator_can_be_parameter_pack): A pointer-to-member
can be a parameter pack with the ellipsis following it. When we
have an erroneous declaration, allow it to be a parameter pack.
(cp_parser_template_parameter): Complain about default
arguments on non-type template parameter packs, and parse them
using the new cp_parser_default_argument.
(cp_parser_parameter_declaration): Complain about parameter packs
with default arguments. Move parsing of default arguments into a
new function, cp_parser_default_argument.
(cp_parser_default_argument): New; extracted from
cp_parser_parameter_declaration.
2008-01-15 Douglas Gregor <doug.gregor@gmail.com>
PR c++/34051 PR c++/34051
PR c++/34055 PR c++/34055
PR c++/34102 PR c++/34102
......
...@@ -1071,12 +1071,13 @@ declarator_can_be_parameter_pack (cp_declarator *declarator) ...@@ -1071,12 +1071,13 @@ declarator_can_be_parameter_pack (cp_declarator *declarator)
switch ((int)declarator->kind) switch ((int)declarator->kind)
{ {
case cdk_id: case cdk_id:
case cdk_error:
case cdk_array: case cdk_array:
case cdk_ptrmem:
found = true; found = true;
break; break;
case cdk_error:
return true;
default: default:
declarator = declarator->declarator; declarator = declarator->declarator;
break; break;
...@@ -1734,6 +1735,8 @@ static cp_parameter_declarator *cp_parser_parameter_declaration_list ...@@ -1734,6 +1735,8 @@ static cp_parameter_declarator *cp_parser_parameter_declaration_list
(cp_parser *, bool *); (cp_parser *, bool *);
static cp_parameter_declarator *cp_parser_parameter_declaration static cp_parameter_declarator *cp_parser_parameter_declaration
(cp_parser *, bool, bool *); (cp_parser *, bool, bool *);
static tree cp_parser_default_argument
(cp_parser *, bool);
static void cp_parser_function_body static void cp_parser_function_body
(cp_parser *); (cp_parser *);
static tree cp_parser_initializer static tree cp_parser_initializer
...@@ -9385,7 +9388,7 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type, ...@@ -9385,7 +9388,7 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
/* If the next token is an ellipsis, and we don't already have it /* If the next token is an ellipsis, and we don't already have it
marked as a parameter pack, then we have a parameter pack (that marked as a parameter pack, then we have a parameter pack (that
has no declarator); */ has no declarator). */
if (!*is_parameter_pack 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)) && declarator_can_be_parameter_pack (parameter_declarator->declarator))
...@@ -9395,6 +9398,29 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type, ...@@ -9395,6 +9398,29 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
maybe_warn_variadic_templates (); maybe_warn_variadic_templates ();
*is_parameter_pack = true; *is_parameter_pack = true;
/* Parameter packs cannot have default arguments. However, a
user may try to do so, so we'll parse them and give an
appropriate diagnostic here. */
if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
{
/* Consume the `='. */
cp_lexer_consume_token (parser->lexer);
/* Find the name of the parameter pack. */
cp_declarator *id_declarator = parameter_declarator->declarator;
while (id_declarator && id_declarator->kind != cdk_id)
id_declarator = id_declarator->declarator;
if (id_declarator && id_declarator->kind == cdk_id)
error ("template parameter pack %qD cannot have a default argument",
id_declarator->u.id.unqualified_name);
else
error ("template parameter pack cannot have a default argument");
/* Parse the default argument, but throw away the result. */
cp_parser_default_argument (parser, /*template_parm_p=*/true);
}
} }
parm = grokdeclarator (parameter_declarator->declarator, parm = grokdeclarator (parameter_declarator->declarator,
...@@ -13540,7 +13566,6 @@ cp_parser_parameter_declaration (cp_parser *parser, ...@@ -13540,7 +13566,6 @@ cp_parser_parameter_declaration (cp_parser *parser,
/* If the next token is `=', then process a default argument. */ /* If the next token is `=', then process a default argument. */
if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)) if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
{ {
bool saved_greater_than_is_operator_p;
/* Consume the `='. */ /* Consume the `='. */
cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer);
...@@ -13646,18 +13671,66 @@ cp_parser_parameter_declaration (cp_parser *parser, ...@@ -13646,18 +13671,66 @@ cp_parser_parameter_declaration (cp_parser *parser,
/* Outside of a class definition, we can just parse the /* Outside of a class definition, we can just parse the
assignment-expression. */ assignment-expression. */
else else
default_argument
= cp_parser_default_argument (parser, template_parm_p);
if (!parser->default_arg_ok_p)
{
if (!flag_pedantic_errors)
warning (0, "deprecated use of default argument for parameter of non-function");
else
{
error ("default arguments are only permitted for function parameters");
default_argument = NULL_TREE;
}
}
else if ((declarator && declarator->parameter_pack_p)
|| (decl_specifiers.type
&& PACK_EXPANSION_P (decl_specifiers.type)))
{ {
const char* kind = template_parm_p? "template " : "";
/* Find the name of the parameter pack. */
cp_declarator *id_declarator = declarator;
while (id_declarator && id_declarator->kind != cdk_id)
id_declarator = id_declarator->declarator;
if (id_declarator && id_declarator->kind == cdk_id)
error ("%sparameter pack %qD cannot have a default argument",
kind, id_declarator->u.id.unqualified_name);
else
error ("%sparameter pack cannot have a default argument",
kind);
default_argument = NULL_TREE;
}
}
else
default_argument = NULL_TREE;
return make_parameter_declarator (&decl_specifiers,
declarator,
default_argument);
}
/* Parse a default argument and return it.
TEMPLATE_PARM_P is true if this is a default argument for a
non-type template parameter. */
static tree
cp_parser_default_argument (cp_parser *parser, bool template_parm_p)
{
tree default_argument = NULL_TREE;
bool saved_greater_than_is_operator_p;
bool saved_local_variables_forbidden_p; bool saved_local_variables_forbidden_p;
/* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is
set correctly. */ set correctly. */
saved_greater_than_is_operator_p saved_greater_than_is_operator_p = parser->greater_than_is_operator_p;
= parser->greater_than_is_operator_p; parser->greater_than_is_operator_p = !template_parm_p;
parser->greater_than_is_operator_p = greater_than_is_operator_p;
/* Local variable names (and the `this' keyword) may not /* Local variable names (and the `this' keyword) may not
appear in a default argument. */ appear in a default argument. */
saved_local_variables_forbidden_p saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
= parser->local_variables_forbidden_p;
parser->local_variables_forbidden_p = true; parser->local_variables_forbidden_p = true;
/* The default argument expression may cause implicitly /* The default argument expression may cause implicitly
defined member functions to be synthesized, which will defined member functions to be synthesized, which will
...@@ -13674,28 +13747,10 @@ cp_parser_parameter_declaration (cp_parser *parser, ...@@ -13674,28 +13747,10 @@ cp_parser_parameter_declaration (cp_parser *parser,
pop_deferring_access_checks (); pop_deferring_access_checks ();
/* Restore saved state. */ /* Restore saved state. */
--function_depth; --function_depth;
parser->greater_than_is_operator_p parser->greater_than_is_operator_p = saved_greater_than_is_operator_p;
= saved_greater_than_is_operator_p; parser->local_variables_forbidden_p = saved_local_variables_forbidden_p;
parser->local_variables_forbidden_p
= saved_local_variables_forbidden_p;
}
if (!parser->default_arg_ok_p)
{
if (!flag_pedantic_errors)
warning (0, "deprecated use of default argument for parameter of non-function");
else
{
error ("default arguments are only permitted for function parameters");
default_argument = NULL_TREE;
}
}
}
else
default_argument = NULL_TREE;
return make_parameter_declarator (&decl_specifiers, return default_argument;
declarator,
default_argument);
} }
/* Parse a function-body. /* Parse a function-body.
......
...@@ -5138,7 +5138,7 @@ coerce_template_parameter_pack (tree parms, ...@@ -5138,7 +5138,7 @@ coerce_template_parameter_pack (tree parms,
{ {
argument_pack = make_node (NONTYPE_ARGUMENT_PACK); argument_pack = make_node (NONTYPE_ARGUMENT_PACK);
TREE_TYPE (argument_pack) TREE_TYPE (argument_pack)
= tsubst (TREE_TYPE (TREE_VALUE (parm)), args, complain, in_decl); = tsubst (TREE_TYPE (TREE_VALUE (parm)), new_args, complain, in_decl);
TREE_CONSTANT (argument_pack) = 1; TREE_CONSTANT (argument_pack) = 1;
} }
......
2008-01-15 Douglas Gregor <doug.gregor@gmail.com> 2008-01-15 Douglas Gregor <doug.gregor@gmail.com>
PR c++/34751
* g++.dg/cpp0x/vt-34751.C: New.
2008-01-15 Douglas Gregor <doug.gregor@gmail.com>
PR c++/34051 PR c++/34051
PR c++/34055 PR c++/34055
PR c++/34102 PR c++/34102
// { dg-options "-std=c++0x" }
// PR c++/34751
struct A {};
template<typename... Args = int> // { dg-error "cannot have a default" }
void f(Args... args = 0); // { dg-error "cannot have a default argument" }
template<typename... Args>
void g(Args... = 0); // { dg-error "cannot have a default argument" }
template<int, typename T = A, int T::*...p = 0 > struct B {}; // { dg-error "cannot have a default argument|no default argument" }
B<0> b;
template<int, typename T = A, int T::*... = 0 > struct C {}; // { dg-error "cannot have a default argument|no default argument" }
C<0> c;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment