parser.c (cp_parser_initializer_list): Handle C99 .id= and [N]= designated initialize...
authorJason Merrill <jason@redhat.com>
Wed, 20 Jul 2011 18:18:03 +0000 (14:18 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 20 Jul 2011 18:18:03 +0000 (14:18 -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.

From-SVN: r176530

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/desig2.C [new file with mode: 0644]

index 6853fbf73e1a765cb48f75686e44f680c708d8c4..e314ae2a6149975dc4fae8fb52f888e1cba95c2f 100644 (file)
@@ -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.
index 2742af5c2bb70f25aee5190f168d2ea1a61c3ac2..067930375a8d0066fadad75bea64960476d34701 100644 (file)
@@ -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)
index b8dc48e04ca15d86940f665559928528aa69974a..285180152e3b5cd4ac746c50d17cf2ac3651180e 100644 (file)
@@ -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.  */
index 5aa4d6b5fa4b0c49c7e6e1713789aead2c3844c5..c5228f29925c08bedd0df71b0488bc5a3284c751 100644 (file)
@@ -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 (file)
index 0000000..229ae52
--- /dev/null
@@ -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" }