From 3d142be23b9b1ce6a479a9c4ef836a3a79d6a650 Mon Sep 17 00:00:00 2001 From: Giovanni Bajo Date: Mon, 20 Sep 2004 23:05:40 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 7 +++ gcc/cp/decl.c | 129 ++++++++++++++++++++++++++++++----------------- 2 files changed, 91 insertions(+), 45 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index be682bc06a8..b989792b87d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2004-09-20 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. Handle out-of-range designated initializers. + 2004-09-20 Steven Bosscher * 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 8047f9e76eb..3098cfdbc19 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 (); -- 2.30.2