This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: PATCHes to accept C99 designated initializer syntax in C++


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 <jason@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 <jason@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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]