aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-07-20 14:18:03 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-07-20 14:18:03 -0400
commit458f8a16a14c77d6346bec6eb9d536c4a9977741 (patch)
tree97794ed16cf329b2e4619ee88fdb2e020628e225 /gcc
parentcd88bb8c771788c4f3ad2f1be42e99db5e4a90fe (diff)
downloadgcc-458f8a16a14c77d6346bec6eb9d536c4a9977741.zip
gcc-458f8a16a14c77d6346bec6eb9d536c4a9977741.tar.gz
gcc-458f8a16a14c77d6346bec6eb9d536c4a9977741.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/decl.c16
-rw-r--r--gcc/cp/parser.c43
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/ext/desig2.C25
5 files changed, 83 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6853fbf..e314ae2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
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++/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 2742af5..0679303 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 b8dc48e..2851801 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 5aa4d6b..c5228f2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2011-07-20 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/ext/desig2.C: New.
+
2011-07-20 Michael Meissner <meissner@linux.vnet.ibm.com>
* 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 0000000..229ae52
--- /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" }