Commit 458f8a16 by Jason Merrill Committed by Jason Merrill

parser.c (cp_parser_initializer_list): Handle C99 .id= and [N]= designated initializer syntax.

	* parser.c (cp_parser_initializer_list): Handle C99 .id= and [N]=
	designated initializer syntax.
	* decl.c (check_array_designated_initializer): Add index parm.
	(maybe_deduce_size_from_array_init): Pass it.
	(reshape_init_array_1): Likewise.

From-SVN: r176530
parent cd88bb8c
2011-07-20 Jason Merrill <jason@redhat.com> 2011-07-20 Jason Merrill <jason@redhat.com>
* parser.c (cp_parser_initializer_list): Handle C99 .id= and [N]=
designated initializer syntax.
* decl.c (check_array_designated_initializer): Add index parm.
(maybe_deduce_size_from_array_init): Pass it.
(reshape_init_array_1): Likewise.
PR c++/6709 (DR 743) PR c++/6709 (DR 743)
PR c++/42603 (DR 950) PR c++/42603 (DR 950)
* parser.c (token_is_decltype, cp_lexer_next_token_is_decltype): New. * parser.c (token_is_decltype, cp_lexer_next_token_is_decltype): New.
......
...@@ -4648,7 +4648,8 @@ build_init_list_var_init (tree decl, tree type, tree init, tree *array_init, ...@@ -4648,7 +4648,8 @@ build_init_list_var_init (tree decl, tree type, tree init, tree *array_init,
is valid, i.e., does not have a designated initializer. */ is valid, i.e., does not have a designated initializer. */
static bool static bool
check_array_designated_initializer (const constructor_elt *ce) check_array_designated_initializer (const constructor_elt *ce,
unsigned HOST_WIDE_INT index)
{ {
/* Designated initializers for array elements are not supported. */ /* Designated initializers for array elements are not supported. */
if (ce->index) if (ce->index)
...@@ -4659,8 +4660,13 @@ check_array_designated_initializer (const constructor_elt *ce) ...@@ -4659,8 +4660,13 @@ check_array_designated_initializer (const constructor_elt *ce)
error ("name used in a GNU-style designated " error ("name used in a GNU-style designated "
"initializer for an array"); "initializer for an array");
else if (TREE_CODE (ce->index) == INTEGER_CST) else if (TREE_CODE (ce->index) == INTEGER_CST)
/* An index added by reshape_init. */ {
return true; /* A C99 designator is OK if it matches the current index. */
if (TREE_INT_CST_LOW (ce->index) == index)
return true;
else
sorry ("non-trivial designated initializers not supported");
}
else else
{ {
gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE); gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE);
...@@ -4702,7 +4708,7 @@ maybe_deduce_size_from_array_init (tree decl, tree init) ...@@ -4702,7 +4708,7 @@ maybe_deduce_size_from_array_init (tree decl, tree init)
constructor_elt *ce; constructor_elt *ce;
HOST_WIDE_INT i; HOST_WIDE_INT i;
FOR_EACH_VEC_ELT (constructor_elt, v, i, ce) FOR_EACH_VEC_ELT (constructor_elt, v, i, ce)
if (!check_array_designated_initializer (ce)) if (!check_array_designated_initializer (ce, i))
failure = 1; failure = 1;
} }
...@@ -4961,7 +4967,7 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d, ...@@ -4961,7 +4967,7 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
{ {
tree elt_init; tree elt_init;
check_array_designated_initializer (d->cur); check_array_designated_initializer (d->cur, index);
elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false, elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false,
complain); complain);
if (elt_init == error_mark_node) if (elt_init == error_mark_node)
......
...@@ -16693,8 +16693,13 @@ cp_parser_braced_list (cp_parser* parser, bool* non_constant_p) ...@@ -16693,8 +16693,13 @@ cp_parser_braced_list (cp_parser* parser, bool* non_constant_p)
GNU Extension: GNU Extension:
initializer-list: initializer-list:
identifier : initializer-clause designation initializer-clause ...[opt]
initializer-list, identifier : initializer-clause initializer-list , designation initializer-clause ...[opt]
designation:
. identifier =
identifier :
[ constant-expression ] =
Returns a VEC of constructor_elt. The VALUE of each elt is an expression Returns a VEC of constructor_elt. The VALUE of each elt is an expression
for the initializer. If the INDEX of the elt is non-NULL, it is the for the initializer. If the INDEX of the elt is non-NULL, it is the
...@@ -16713,7 +16718,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) ...@@ -16713,7 +16718,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
while (true) while (true)
{ {
cp_token *token; cp_token *token;
tree identifier; tree designator;
tree initializer; tree initializer;
bool clause_non_constant_p; bool clause_non_constant_p;
...@@ -16728,12 +16733,38 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) ...@@ -16728,12 +16733,38 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
pedwarn (input_location, OPT_pedantic, pedwarn (input_location, OPT_pedantic,
"ISO C++ does not allow designated initializers"); "ISO C++ does not allow designated initializers");
/* Consume the identifier. */ /* Consume the identifier. */
identifier = cp_lexer_consume_token (parser->lexer)->u.value; designator = cp_lexer_consume_token (parser->lexer)->u.value;
/* Consume the `:'. */ /* Consume the `:'. */
cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer);
} }
/* Also handle the C99 syntax, '. id ='. */
else if (cp_parser_allow_gnu_extensions_p (parser)
&& cp_lexer_next_token_is (parser->lexer, CPP_DOT)
&& cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME
&& cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_EQ)
{
/* Warn the user that they are using an extension. */
pedwarn (input_location, OPT_pedantic,
"ISO C++ does not allow C99 designated initializers");
/* Consume the `.'. */
cp_lexer_consume_token (parser->lexer);
/* Consume the identifier. */
designator = cp_lexer_consume_token (parser->lexer)->u.value;
/* Consume the `='. */
cp_lexer_consume_token (parser->lexer);
}
/* Also handle C99 array designators, '[ const ] ='. */
else if (cp_parser_allow_gnu_extensions_p (parser)
&& !c_dialect_objc ()
&& cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
{
cp_lexer_consume_token (parser->lexer);
designator = cp_parser_constant_expression (parser, false, NULL);
cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
cp_parser_require (parser, CPP_EQ, RT_EQ);
}
else else
identifier = NULL_TREE; designator = NULL_TREE;
/* Parse the initializer. */ /* Parse the initializer. */
initializer = cp_parser_initializer_clause (parser, initializer = cp_parser_initializer_clause (parser,
...@@ -16754,7 +16785,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) ...@@ -16754,7 +16785,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
} }
/* Add it to the vector. */ /* Add it to the vector. */
CONSTRUCTOR_APPEND_ELT(v, identifier, initializer); CONSTRUCTOR_APPEND_ELT (v, designator, initializer);
/* If the next token is not a comma, we have reached the end of /* If the next token is not a comma, we have reached the end of
the list. */ the list. */
......
2011-07-20 Jason Merrill <jason@redhat.com>
* g++.dg/ext/desig2.C: New.
2011-07-20 Michael Meissner <meissner@linux.vnet.ibm.com> 2011-07-20 Michael Meissner <meissner@linux.vnet.ibm.com>
* gcc.target/powerpc/ppc-fma-1.c: Adjust to allow non-VSX fmas to * gcc.target/powerpc/ppc-fma-1.c: Adjust to allow non-VSX fmas to
......
// Test for C99-style designated array initializer
union U
{
long l;
const char *p;
};
__extension__ U u = { .p = "" };
__extension__ int i[4] = { [0] = 1, [1] = 2 };
// Currently, except for unions, the C++ front end only supports
// designators that designate the element that would have been initialized
// anyway. While that's true, make sure that we get a sorry rather than
// bad code.
struct A
{
int i;
int j;
};
__extension__ A a = { .j = 1 }; // { dg-message "non-trivial" }
__extension__ int j[2] = { [1] = 1 }; // { dg-message "non-trivial" }
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