aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorGiovanni Bajo <giovannibajo@gcc.gnu.org>2004-09-20 23:05:40 +0000
committerGiovanni Bajo <giovannibajo@gcc.gnu.org>2004-09-20 23:05:40 +0000
commit3d142be23b9b1ce6a479a9c4ef836a3a79d6a650 (patch)
tree53a7abf22815133d05ec46e39d738987dca3e92f /gcc
parent2c82eecc7896f50079c2e333fa1d0f76afdbfabf (diff)
downloadgcc-3d142be23b9b1ce6a479a9c4ef836a3a79d6a650.zip
gcc-3d142be23b9b1ce6a479a9c4ef836a3a79d6a650.tar.gz
gcc-3d142be23b9b1ce6a479a9c4ef836a3a79d6a650.tar.bz2
re PR c++/14179 (out of memory while parsing array with many initializers)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/decl.c129
2 files changed, 91 insertions, 45 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index be682bc..b989792 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 8047f9e..3098cfd 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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 ();