The first patch adjusts the C++ front end's current support for the old
GNU designated initializer syntax to support the C99 syntax as well.
The second patch adjusts recog.h/genoutput.c to use a new macro
HAVE_DESIGNATED_UNION_INITIALIZERS instead of
HAVE_DESIGNATED_INITIALIZERS because with the above change, the uses
there work with the C++ compiler, but the uses in dwarf2asm.c still
don't because they involve out-of-order initialization.
I'm applying the first patch to trunk. Is the second patch OK as well,
or should use of designated initializers in recog.h wait until the C++
front end supports the dwarf2asm.c use as well?
Jason
commit 48f78814fd400184a6de1f0287adb79f403c3073
Author: Jason Merrill <ja...@redhat.com>
Date: Wed Jul 20 14:09:17 2011 -0400
* 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.
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/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" }
commit 351d098c503777d9c48906cecb97293b572a558b
Author: Jason Merrill <ja...@redhat.com>
Date: Wed Jul 20 14:09:55 2011 -0400
* system.h (HAVE_DESIGNATED_UNION_INITIALIZERS): New.
* recog.h (struct insn_data_d): Check it instead of
HAVE_DESIGNATED_INITIALIZERS.
* genoutput.c (output_insn_data): Likewise.
diff --git a/gcc/genoutput.c b/gcc/genoutput.c
index 621439f..bc41b7b 100644
--- a/gcc/genoutput.c
+++ b/gcc/genoutput.c
@@ -340,7 +340,7 @@ output_insn_data (void)
switch (d->output_format)
{
case INSN_OUTPUT_FORMAT_NONE:
- printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
+ printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
printf (" { 0 },\n");
printf ("#else\n");
printf (" { 0, 0, 0 },\n");
@@ -351,7 +351,7 @@ output_insn_data (void)
const char *p = d->template_code;
char prev = 0;
- printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
+ printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
printf (" { .single =\n");
printf ("#else\n");
printf (" {\n");
@@ -372,7 +372,7 @@ output_insn_data (void)
++p;
}
printf ("\",\n");
- printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
+ printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
printf (" },\n");
printf ("#else\n");
printf (" 0, 0 },\n");
@@ -380,14 +380,14 @@ output_insn_data (void)
}
break;
case INSN_OUTPUT_FORMAT_MULTI:
- printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
+ printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
printf (" { .multi = output_%d },\n", d->code_number);
printf ("#else\n");
printf (" { 0, output_%d, 0 },\n", d->code_number);
printf ("#endif\n");
break;
case INSN_OUTPUT_FORMAT_FUNCTION:
- printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
+ printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
printf (" { .function = output_%d },\n", d->code_number);
printf ("#else\n");
printf (" { 0, 0, output_%d },\n", d->code_number);
diff --git a/gcc/recog.h b/gcc/recog.h
index cce1321..71dfe2a 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -286,7 +286,7 @@ struct insn_operand_data
struct insn_data_d
{
const char *const name;
-#if HAVE_DESIGNATED_INITIALIZERS
+#if HAVE_DESIGNATED_UNION_INITIALIZERS
union {
const char *single;
const char *const *multi;
diff --git a/gcc/system.h b/gcc/system.h
index e02cbcd..ce027b2 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -500,6 +500,12 @@ extern int vsnprintf(char *, size_t, const char *, va_list);
&& !defined(__cplusplus))
#endif
+#if !defined(HAVE_DESIGNATED_UNION_INITIALIZERS)
+#define HAVE_DESIGNATED_UNION_INITIALIZERS \
+ (((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L)) \
+ && (!defined(__cplusplus) || (GCC_VERSION >= 4007)))
+#endif
+
#if HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif