re PR c++/14179 (out of memory while parsing array with many initializers)
authorGiovanni Bajo <giovannibajo@gcc.gnu.org>
Mon, 20 Sep 2004 23:05:40 +0000 (23:05 +0000)
committerGiovanni Bajo <giovannibajo@gcc.gnu.org>
Mon, 20 Sep 2004 23:05:40 +0000 (23:05 +0000)
PR c++/14179
* decl.c (reshape_init): Extract array handling into...
(reshape_init_array): New function. Use integers instead of trees
for indices. Handle out-of-range designated initializers.

From-SVN: r87777

gcc/cp/ChangeLog
gcc/cp/decl.c

index be682bc06a861b687413bfa9d0535e84f02d0371..b989792b87d4ad58f0bc7a2fc60d5dfb14ee212d 100644 (file)
@@ -1,3 +1,10 @@
+2004-09-20  Giovanni Bajo  <giovannibajo@gcc.gnu.org>
+
+       PR c++/14179
+       * decl.c (reshape_init): Extract array handling into...
+       (reshape_init_array): New function. Use integers instead of trees
+       for indices. Handle out-of-range designated initializers.
+
 2004-09-20  Steven Bosscher  <stevenb@suse.de>
 
        * lex.c (cxx_init): Don't set the ridpointer for RID_NULL
index 8047f9e76eb4bfcee02e3a1b561252f1ddaff6ae..3098cfdbc1950ec8298450ab7ffd1639cd80a4b7 100644 (file)
@@ -4146,6 +4146,69 @@ next_initializable_field (tree field)
   return field;
 }
 
+/* Subroutine of reshape_init. Reshape the constructor for an array. INITP
+   is the pointer to the old constructor list (to the CONSTRUCTOR_ELTS of
+   the CONSTRUCTOR we are processing), while NEW_INIT is the CONSTRUCTOR we
+   are building.
+   ELT_TYPE is the element type of the array. MAX_INDEX is an INTEGER_CST
+   representing the size of the array minus one (the maximum index), or
+   NULL_TREE if the array was declared without specifying the size.  */
+
+static bool
+reshape_init_array (tree elt_type, tree max_index,
+                   tree *initp, tree new_init)
+{
+  bool sized_array_p = (max_index != NULL_TREE);
+  HOST_WIDE_INT max_index_cst;
+  HOST_WIDE_INT index;
+
+  if (sized_array_p)
+    /* HWI is either 32bit or 64bit, so it must be enough to represent the
+       array size.  */
+    max_index_cst = tree_low_cst (max_index, 1);
+
+  /* Loop until there are no more initializers.  */
+  for (index = 0;
+       *initp && (!sized_array_p || index <= max_index_cst);
+       ++index)
+    {
+      tree element_init;
+      tree designated_index;
+
+      element_init = reshape_init (elt_type, initp);
+      if (element_init == error_mark_node)
+       return false;
+      TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);
+      CONSTRUCTOR_ELTS (new_init) = element_init;
+      designated_index = TREE_PURPOSE (element_init);
+      if (designated_index)
+      {
+         /* Handle array designated initializers (GNU extension).  */
+         if (TREE_CODE (designated_index) == IDENTIFIER_NODE)
+           {
+             error ("name `%D' used in a GNU-style designated "
+                   "initializer for an array", designated_index);
+             TREE_PURPOSE (element_init) = NULL_TREE;
+           }
+         else
+           {
+             gcc_assert (TREE_CODE (designated_index) == INTEGER_CST);
+             if (sized_array_p
+                 && tree_int_cst_lt (max_index, designated_index))
+               {
+                 error ("Designated initializer `%E' larger than array "
+                        "size", designated_index);
+                 TREE_PURPOSE (element_init) = NULL_TREE;
+               }
+             else
+               index = tree_low_cst (designated_index, 1);
+           }
+       }
+    }
+
+  return true;
+}
+
 /* Undo the brace-elision allowed by [dcl.init.aggr] in a
    brace-enclosed aggregate initializer.
 
@@ -4313,52 +4376,28 @@ reshape_init (tree type, tree *initp)
       else if (TREE_CODE (type) == ARRAY_TYPE
               || TREE_CODE (type) == VECTOR_TYPE)
        {
-         tree index;
-         tree max_index;
-
-         /* If the bound of the array is known, take no more initializers
-            than are allowed.  */
-         max_index = NULL_TREE;
-         if (TREE_CODE (type) == ARRAY_TYPE)
-           {
-             if (TYPE_DOMAIN (type))
-               max_index = array_type_nelts (type);
-           }
-         else
-           {
-             /* For a vector, the representation type is a struct
-                containing a single member which is an array of the
-                appropriate size.  */
-             tree rtype = TYPE_DEBUG_REPRESENTATION_TYPE (type);
-             if (rtype && TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (rtype))))
-               max_index = array_type_nelts (TREE_TYPE (TYPE_FIELDS (rtype)));
-           }
+           /* If the bound of the array is known, take no more initializers
+             than are allowed.  */
+           tree max_index = NULL_TREE;
+           if (TREE_CODE (type) == ARRAY_TYPE)
+             {
+               if (TYPE_DOMAIN (type))
+                 max_index = array_type_nelts (type);
+             }
+           else
+             {
+               /* For a vector, the representation type is a struct
+                 containing a single member which is an array of the
+                 appropriate size.  */
+               tree rtype = TYPE_DEBUG_REPRESENTATION_TYPE (type);
+               if (rtype && TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (rtype))))
+                 max_index = array_type_nelts (TREE_TYPE (TYPE_FIELDS
+                                                          (rtype)));
+             }
 
-         /* Loop through the array elements, gathering initializers.  */
-         for (index = size_zero_node;
-              *initp && (!max_index || !tree_int_cst_lt (max_index, index));
-              index = size_binop (PLUS_EXPR, index, size_one_node))
-           {
-             tree element_init;
-
-             element_init = reshape_init (TREE_TYPE (type), initp);
-             if (element_init == error_mark_node)
-               return error_mark_node;
-             TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);
-             CONSTRUCTOR_ELTS (new_init) = element_init;
-             if (TREE_PURPOSE (element_init))
-               {
-                 tree next_index = TREE_PURPOSE (element_init);
-                 if (TREE_CODE (next_index) == IDENTIFIER_NODE)
-                   {
-                     error ("name `%D' used in a GNU-style designated "
-                            "initializer for an array", next_index);
-                     TREE_PURPOSE (element_init) = NULL_TREE;
-                   }
-                 else
-                   index = next_index;
-               }
-           }
+         if (!reshape_init_array (TREE_TYPE (type), max_index,
+                                  initp, new_init))
+           return error_mark_node;
        }
       else
        gcc_unreachable ();