From 458f8a16a14c77d6346bec6eb9d536c4a9977741 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 20 Jul 2011 14:18:03 -0400 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 6 +++++ gcc/cp/decl.c | 16 ++++++++---- gcc/cp/parser.c | 43 ++++++++++++++++++++++++++----- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/g++.dg/ext/desig2.C | 25 ++++++++++++++++++ 5 files changed, 83 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/desig2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6853fbf73e1..e314ae2a614 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2011-07-20 Jason Merrill + * 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++/42603 (DR 950) * parser.c (token_is_decltype, cp_lexer_next_token_is_decltype): New. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 2742af5c2bb..067930375a8 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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. */ 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. */ if (ce->index) @@ -4659,8 +4660,13 @@ check_array_designated_initializer (const constructor_elt *ce) error ("name used in a GNU-style designated " "initializer for an array"); 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 { gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE); @@ -4702,7 +4708,7 @@ maybe_deduce_size_from_array_init (tree decl, tree init) constructor_elt *ce; HOST_WIDE_INT i; FOR_EACH_VEC_ELT (constructor_elt, v, i, ce) - if (!check_array_designated_initializer (ce)) + if (!check_array_designated_initializer (ce, i)) failure = 1; } @@ -4961,7 +4967,7 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d, { 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, complain); if (elt_init == error_mark_node) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b8dc48e04ca..285180152e3 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -16693,8 +16693,13 @@ cp_parser_braced_list (cp_parser* parser, bool* non_constant_p) GNU Extension: initializer-list: - identifier : initializer-clause - initializer-list, identifier : initializer-clause + designation initializer-clause ...[opt] + 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 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) while (true) { cp_token *token; - tree identifier; + tree designator; tree initializer; bool clause_non_constant_p; @@ -16728,12 +16733,38 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) pedwarn (input_location, OPT_pedantic, "ISO C++ does not allow designated initializers"); /* Consume the identifier. */ - identifier = cp_lexer_consume_token (parser->lexer)->u.value; + designator = cp_lexer_consume_token (parser->lexer)->u.value; /* Consume the `:'. */ 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 - identifier = NULL_TREE; + designator = NULL_TREE; /* Parse the initializer. */ initializer = cp_parser_initializer_clause (parser, @@ -16754,7 +16785,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) } /* 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 the list. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5aa4d6b5fa4..c5228f29925 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2011-07-20 Jason Merrill + + * g++.dg/ext/desig2.C: New. + 2011-07-20 Michael Meissner * gcc.target/powerpc/ppc-fma-1.c: Adjust to allow non-VSX fmas to diff --git a/gcc/testsuite/g++.dg/ext/desig2.C b/gcc/testsuite/g++.dg/ext/desig2.C new file mode 100644 index 00000000000..229ae527d77 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/desig2.C @@ -0,0 +1,25 @@ +// 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" } -- 2.30.2