OSDN Git Service

PR c++/29728
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 5 Dec 2006 21:33:20 +0000 (21:33 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 5 Dec 2006 21:33:20 +0000 (21:33 +0000)
* decl.c (check_array_designated_initializer): New function.
(maybe_deduce_size_from_array_init): Use it.
(reshape_init_array): Likewise.
PR c++/29728
* g++.dg/template/crash62.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119558 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 8c57d4f..d9de361 100644 (file)
@@ -1,3 +1,10 @@
+2006-12-05  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/29728
+       * decl.c (check_array_designated_initializer): New function.
+       (maybe_deduce_size_from_array_init): Use it.
+       (reshape_init_array): Likewise.
+
 2006-12-05  Aldy Hernandez  <aldyh@redhat.com>
 
        Merge from gimple-tuples-branch.
index 8a55e41..1edd7ea 100644 (file)
@@ -4092,6 +4092,30 @@ grok_reference_init (tree decl, tree type, tree init, tree *cleanup)
   return NULL_TREE;
 }
 
+/* Designated initializers in arrays are not supported in GNU C++.
+   The parser cannot detect this error since it does not know whether
+   a given brace-enclosed initializer is for a class type or for an
+   array.  This function checks that CE does not use a designated
+   initializer.  If it does, an error is issued.  Returns true if CE
+   is valid, i.e., does not have a designated initializer.  */
+
+static bool
+check_array_designated_initializer (const constructor_elt *ce)
+{
+  /* Designated initializers for array elements arenot supported.  */
+  if (ce->index)
+    {
+      /* The parser only allows identifiers as designated
+        intializers.  */
+      gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE);
+      error ("name %qD used in a GNU-style designated "
+            "initializer for an array", ce->index);
+      return false;
+    }
+
+  return true;
+}
+
 /* When parsing `int a[] = {1, 2};' we don't know the size of the
    array until we finish parsing the initializer.  If that's the
    situation we're in, update DECL accordingly.  */
@@ -4109,32 +4133,52 @@ maybe_deduce_size_from_array_init (tree decl, tree init)
         But let's leave it here to ease the eventual merge.  */
       int do_default = !DECL_EXTERNAL (decl);
       tree initializer = init ? init : DECL_INITIAL (decl);
-      int failure = cp_complete_array_type (&TREE_TYPE (decl), initializer,
-                                           do_default);
+      int failure = 0;
 
-      if (failure == 1)
+      /* Check that there are no designated initializers in INIT, as
+        those are not supported in GNU C++, and as the middle-end
+        will crash if presented with a non-numeric designated
+        initializer.  */
+      if (initializer && TREE_CODE (initializer) == CONSTRUCTOR)
        {
-         error ("initializer fails to determine size of %qD", decl);
-         TREE_TYPE (decl) = error_mark_node;
+         VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initializer);
+         constructor_elt *ce;
+         HOST_WIDE_INT i;
+         for (i = 0; 
+              VEC_iterate (constructor_elt, v, i, ce);
+              ++i)
+           if (!check_array_designated_initializer (ce))
+             failure = 1;
        }
-      else if (failure == 2)
+
+      if (!failure)
        {
-         if (do_default)
+         failure = cp_complete_array_type (&TREE_TYPE (decl), initializer,
+                                           do_default);
+         if (failure == 1)
            {
-             error ("array size missing in %qD", decl);
+             error ("initializer fails to determine size of %qD", decl);
+             TREE_TYPE (decl) = error_mark_node;
+           }
+         else if (failure == 2)
+           {
+             if (do_default)
+               {
+                 error ("array size missing in %qD", decl);
+                 TREE_TYPE (decl) = error_mark_node;
+               }
+             /* If a `static' var's size isn't known, make it extern as
+                well as static, so it does not get allocated.  If it's not
+                `static', then don't mark it extern; finish_incomplete_decl
+                will give it a default size and it will get allocated.  */
+             else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
+               DECL_EXTERNAL (decl) = 1;
+           }
+         else if (failure == 3)
+           {
+             error ("zero-size array %qD", decl);
              TREE_TYPE (decl) = error_mark_node;
            }
-         /* If a `static' var's size isn't known, make it extern as
-            well as static, so it does not get allocated.  If it's not
-            `static', then don't mark it extern; finish_incomplete_decl
-            will give it a default size and it will get allocated.  */
-         else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
-           DECL_EXTERNAL (decl) = 1;
-       }
-      else if (failure == 3)
-       {
-         error ("zero-size array %qD", decl);
-         TREE_TYPE (decl) = error_mark_node;
        }
 
       cp_apply_type_quals_to_decl (cp_type_quals (TREE_TYPE (decl)), decl);
@@ -4346,18 +4390,7 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d)
     {
       tree elt_init;
 
-      if (d->cur->index)
-       {
-         /* Handle array designated initializers (GNU extension).  */
-         if (TREE_CODE (d->cur->index) == IDENTIFIER_NODE)
-           {
-             error ("name %qD used in a GNU-style designated "
-                    "initializer for an array", d->cur->index);
-           }
-         else
-           gcc_unreachable ();
-       }
-
+      check_array_designated_initializer (d->cur);
       elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false);
       if (elt_init == error_mark_node)
        return error_mark_node;
index dc199b6..d7bae48 100644 (file)
@@ -1,3 +1,8 @@
+2006-12-05  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/29728
+       * g++.dg/template/crash62.C: New test.
+
 2006-12-05  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/30003
diff --git a/gcc/testsuite/g++.dg/template/crash62.C b/gcc/testsuite/g++.dg/template/crash62.C
new file mode 100644 (file)
index 0000000..bd8a0f4
--- /dev/null
@@ -0,0 +1,6 @@
+// PR c++/29728
+
+template<int> void foo()
+{
+  int a[] = { X: 0 }; // { dg-error "designated initializer" }
+}