From: Giovanni Bajo Date: Tue, 21 Sep 2004 21:12:49 +0000 (+0000) Subject: re PR c++/14179 (out of memory while parsing array with many initializers) X-Git-Tag: releases/gcc-3.3.5~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=534ed3ce4b7c2096a27e7b48645a1bae4a889221;p=thirdparty%2Fgcc.git 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. From-SVN: r87823 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e21cb0ac08ec..c414de872f2f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2004-09-21 Giovanni Bajo + + PR c++/14179 + * decl.c (reshape_init): Extract array handling into... + (reshape_init_array): New function. Use integers instead of trees + for indices. + 2004-09-13 Gabriel Dos Reis PR c++/15857 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index dfdeb1e51712..c2a4a86a152d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -147,6 +147,7 @@ static int cp_missing_noreturn_ok_p PARAMS ((tree)); static void initialize_local_var (tree, tree); static void expand_static_init (tree, tree); static tree next_initializable_field (tree); +static bool reshape_init_array (tree, tree, tree *, tree); static tree reshape_init (tree, tree *); /* Erroneous argument lists can use this *IFF* they do not modify it. */ @@ -8211,6 +8212,60 @@ 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 = 0; + 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) + { + if (TREE_CODE (designated_index) != INTEGER_CST) + abort (); + 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. @@ -8393,21 +8448,9 @@ reshape_init (tree type, tree *initp) than are allowed. */ max_index = ((TYPE_DOMAIN (type) && (TREE_CODE (type) == ARRAY_TYPE)) ? array_type_nelts (type) : NULL_TREE); - /* 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)) - index = convert (sizetype, TREE_PURPOSE (element_init)); - } + if (!reshape_init_array (TREE_TYPE (type), max_index, + initp, new_init)) + return error_mark_node; } else abort ();