diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e3e54f8c0a8db33b7e6ac6719e8944b2db0a09e0..fbd8351723a4084c69b23f83e5fbc7da39369482 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2005-03-29 Richard Henderson <rth@redhat.com> + + PR c/20519 + * c-decl.c (c_finish_incomplete_decl): Update complete_array_type call. + (build_compound_literal): Likewise. Propagate decl type into the + initializer. + (finish_decl): Likewise. Use new return value from complete_array_type + for zero sized arrays. + (complete_array_type): Move ... + * c-common.c (complete_array_type): ... here. Change first argument + to pointer-to-type-node. Consistently use sizetype for the index + except for zero sized arrays. Detect zero sized arrays for pedantic + mode diagnostics. Create a new type node instead of modifying the + old node in place. + * c-tree.h (complete_array_type): Move decl ... + * c-common.h (complete_array_type): ... here. + 2005-03-29 Richard Henderson <rth@redhat.com> PR tree-opt/19108 diff --git a/gcc/c-common.c b/gcc/c-common.c index ec7b04d6f325baebf03552285dfa668e66a89ee6..5705f4d1eb282f76476d30990a236910fbb51b60 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -5756,5 +5756,94 @@ lvalue_error (enum lvalue_use use) gcc_unreachable (); } } + +/* *PTYPE is an incomplete array. Complete it with a domain based on + INITIAL_VALUE. If INITIAL_VALUE is not present, use 1 if DO_DEFAULT + is true. Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered, + 2 if INITIAL_VALUE was NULL, and 3 if INITIAL_VALUE was empty. */ + +int +complete_array_type (tree *ptype, tree initial_value, bool do_default) +{ + tree maxindex, type, main_type, elt, unqual_elt; + int failure = 0, quals; + + maxindex = size_zero_node; + if (initial_value) + { + if (TREE_CODE (initial_value) == STRING_CST) + { + int eltsize + = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value))); + maxindex = size_int (TREE_STRING_LENGTH (initial_value)/eltsize - 1); + } + else if (TREE_CODE (initial_value) == CONSTRUCTOR) + { + tree elts = CONSTRUCTOR_ELTS (initial_value); + + if (elts == NULL) + { + if (pedantic) + failure = 3; + maxindex = integer_minus_one_node; + } + else + { + tree curindex; + + if (TREE_PURPOSE (elts)) + maxindex = fold_convert (sizetype, TREE_PURPOSE (elts)); + curindex = maxindex; + + for (elts = TREE_CHAIN (elts); elts; elts = TREE_CHAIN (elts)) + { + if (TREE_PURPOSE (elts)) + curindex = fold_convert (sizetype, TREE_PURPOSE (elts)); + else + curindex = size_binop (PLUS_EXPR, curindex, size_one_node); + + if (tree_int_cst_lt (maxindex, curindex)) + maxindex = curindex; + } + } + } + else + { + /* Make an error message unless that happened already. */ + if (initial_value != error_mark_node) + failure = 1; + } + } + else + { + failure = 2; + if (!do_default) + return failure; + } + + type = *ptype; + elt = TREE_TYPE (type); + quals = TYPE_QUALS (strip_array_types (elt)); + if (quals == 0) + unqual_elt = elt; + else + unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED); + + /* Using build_distinct_type_copy and modifying things afterward instead + of using build_array_type to create a new type preserves all of the + TYPE_LANG_FLAG_? bits that the front end may have set. */ + main_type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type)); + TREE_TYPE (main_type) = unqual_elt; + TYPE_DOMAIN (main_type) = build_index_type (maxindex); + layout_type (main_type); + + if (quals == 0) + type = main_type; + else + type = c_build_qualified_type (main_type, quals); + + *ptype = type; + return failure; +} #include "gt-c-common.h" diff --git a/gcc/c-common.h b/gcc/c-common.h index 63dcb10b40cb09c5293ca214b79bf573adbf85ff..7794adedbeb57ab6e0fb2f48e4be9a32794d2ed4 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -888,6 +888,8 @@ enum lvalue_use { extern void lvalue_error (enum lvalue_use); +extern int complete_array_type (tree *, tree, bool); + /* In c-gimplify.c */ extern void c_genericize (tree); extern int c_gimplify_expr (tree *, tree *, tree *); diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 0b86086992e268b7b46f44a8ff9573353847e683..cc45e26c2fd586359880193d1cfd6c2b6981c17d 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -529,7 +529,7 @@ c_finish_incomplete_decl (tree decl) { warning ("%Jarray %qD assumed to have one element", decl, decl); - complete_array_type (type, NULL_TREE, 1); + complete_array_type (&TREE_TYPE (decl), NULL_TREE, true); layout_decl (decl, 0); } @@ -3168,14 +3168,15 @@ finish_decl (tree decl, tree init, tree asmspec_tree) && TYPE_DOMAIN (type) == 0 && TREE_CODE (decl) != TYPE_DECL) { - int do_default + bool do_default = (TREE_STATIC (decl) /* Even if pedantic, an external linkage array may have incomplete type at first. */ ? pedantic && !TREE_PUBLIC (decl) : !DECL_EXTERNAL (decl)); int failure - = complete_array_type (type, DECL_INITIAL (decl), do_default); + = complete_array_type (&TREE_TYPE (decl), DECL_INITIAL (decl), + do_default); /* Get the completed type made by complete_array_type. */ type = TREE_TYPE (decl); @@ -3196,14 +3197,12 @@ finish_decl (tree decl, tree init, tree asmspec_tree) else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl)) DECL_EXTERNAL (decl) = 1; } - - /* TYPE_MAX_VALUE is always one less than the number of elements - in the array, because we start counting at zero. Therefore, - warn only if the value is less than zero. */ - else if (pedantic && TYPE_DOMAIN (type) != 0 - && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0) + else if (failure == 3) error ("%Jzero or negative size array %qD", decl, decl); + if (DECL_INITIAL (decl)) + TREE_TYPE (DECL_INITIAL (decl)) = type; + layout_decl (decl, 0); } @@ -3491,17 +3490,19 @@ build_compound_literal (tree type, tree init) if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type)) { - int failure = complete_array_type (type, DECL_INITIAL (decl), 1); - + int failure = complete_array_type (&TREE_TYPE (decl), + DECL_INITIAL (decl), true); gcc_assert (!failure); + + type = TREE_TYPE (decl); + TREE_TYPE (DECL_INITIAL (decl)) = type; } - type = TREE_TYPE (decl); if (type == error_mark_node || !COMPLETE_TYPE_P (type)) return error_mark_node; stmt = build_stmt (DECL_EXPR, decl); - complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt); + complit = build1 (COMPOUND_LITERAL_EXPR, type, stmt); TREE_SIDE_EFFECTS (complit) = 1; layout_decl (decl, 0); @@ -3527,73 +3528,6 @@ build_compound_literal (tree type, tree init) return complit; } -/* Make TYPE a complete type based on INITIAL_VALUE. - Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered, - 2 if there was no information (in which case assume 1 if DO_DEFAULT). */ - -int -complete_array_type (tree type, tree initial_value, int do_default) -{ - tree maxindex = NULL_TREE; - int value = 0; - - if (initial_value) - { - /* Note MAXINDEX is really the maximum index, - one less than the size. */ - if (TREE_CODE (initial_value) == STRING_CST) - { - int eltsize - = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value))); - maxindex = build_int_cst (NULL_TREE, - (TREE_STRING_LENGTH (initial_value) - / eltsize) - 1); - } - else if (TREE_CODE (initial_value) == CONSTRUCTOR) - { - tree elts = CONSTRUCTOR_ELTS (initial_value); - maxindex = build_int_cst (NULL_TREE, -1); - for (; elts; elts = TREE_CHAIN (elts)) - { - if (TREE_PURPOSE (elts)) - maxindex = TREE_PURPOSE (elts); - else - maxindex = fold (build2 (PLUS_EXPR, integer_type_node, - maxindex, integer_one_node)); - } - } - else - { - /* Make an error message unless that happened already. */ - if (initial_value != error_mark_node) - value = 1; - - /* Prevent further error messages. */ - maxindex = build_int_cst (NULL_TREE, 0); - } - } - - if (!maxindex) - { - if (do_default) - maxindex = build_int_cst (NULL_TREE, 0); - value = 2; - } - - if (maxindex) - { - TYPE_DOMAIN (type) = build_index_type (maxindex); - - gcc_assert (TREE_TYPE (maxindex)); - } - - /* Lay out the type now that we can get the real answer. */ - - layout_type (type); - - return value; -} - /* Determine whether TYPE is a structure with a flexible array member, or a union containing such a structure (possibly recursively). */ diff --git a/gcc/c-tree.h b/gcc/c-tree.h index bbfed6abbafc20638264ff63993882942adc8837..41b624ec5b777a5b264c88a4c09487f2b5d74eb7 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -378,7 +378,6 @@ extern struct c_declarator *build_array_declarator (tree, struct c_declspecs *, extern tree build_enumerator (tree, tree); extern void check_for_loop_decls (void); extern void mark_forward_parm_decls (void); -extern int complete_array_type (tree, tree, int); extern void declare_parm_level (void); extern void undeclared_variable (tree, location_t); extern tree declare_label (tree); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d7697372ecdfd292b94c367fd370242d120ff22c..859be9d0d39e8cbca6d253620134c0a48e8807d8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2005-03-29 Richard Henderson <rth@redhat.com> + + PR c/20519 + * decl.c (cp_complete_array_type): Rename from complete_array_type. + Use the new complete_array_type in c-common.c. Update all callers. + * cp-tree.h (cp_complete_array_type): Update to match. + 2005-03-24 Geoffrey Keating <geoffk@apple.com> * typeck.c (build_static_cast_1): Allow scalar_cast between diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 22e9ee0f8a05fdc7651f5e64e41d4158db3e7d23..ac025d676749b0ff94d4771bf103419ada13c6d2 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3787,7 +3787,7 @@ extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *, int, extern void start_decl_1 (tree); extern void cp_finish_decl (tree, tree, tree, int); extern void finish_decl (tree, tree, tree); -extern int complete_array_type (tree, tree, int); +extern int cp_complete_array_type (tree *, tree, bool); extern tree build_ptrmemfunc_type (tree); extern tree build_ptrmem_type (tree, tree); /* the grokdeclarator prototype is in decl.h */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 1c4568da9d237ad737e0ad665edba60a5f2c418b..eef2cb1744af11051fbedea623d1f5574369faec 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3913,7 +3913,8 @@ 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 = complete_array_type (type, initializer, do_default); + int failure = cp_complete_array_type (&TREE_TYPE (decl), initializer, + do_default); if (failure == 1) error ("initializer fails to determine size of %qD", decl); @@ -5331,102 +5332,41 @@ expand_static_init (tree decl, tree init) 3 if the initializer list is empty (in pedantic mode). */ int -complete_array_type (tree type, tree initial_value, int do_default) +cp_complete_array_type (tree *ptype, tree initial_value, bool do_default) { - tree maxindex = NULL_TREE; - int value = 0; + int failure; + tree type, elt_type; if (initial_value) { /* An array of character type can be initialized from a brace-enclosed string constant. */ - if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))) + if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype))) && TREE_CODE (initial_value) == CONSTRUCTOR && CONSTRUCTOR_ELTS (initial_value) && (TREE_CODE (TREE_VALUE (CONSTRUCTOR_ELTS (initial_value))) == STRING_CST) && TREE_CHAIN (CONSTRUCTOR_ELTS (initial_value)) == NULL_TREE) initial_value = TREE_VALUE (CONSTRUCTOR_ELTS (initial_value)); - - /* Note MAXINDEX is really the maximum index, one less than the - size. */ - if (TREE_CODE (initial_value) == STRING_CST) - { - int eltsize - = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value))); - maxindex = build_int_cst (NULL_TREE, - (TREE_STRING_LENGTH (initial_value) - / eltsize) - 1); - } - else if (TREE_CODE (initial_value) == CONSTRUCTOR) - { - tree elts = CONSTRUCTOR_ELTS (initial_value); - - maxindex = ssize_int (-1); - for (; elts; elts = TREE_CHAIN (elts)) - { - if (TREE_PURPOSE (elts)) - maxindex = TREE_PURPOSE (elts); - else - maxindex = size_binop (PLUS_EXPR, maxindex, ssize_int (1)); - } - - if (pedantic && tree_int_cst_equal (maxindex, ssize_int (-1))) - value = 3; - } - else - { - /* Make an error message unless that happened already. */ - if (initial_value != error_mark_node) - value = 1; - else - initial_value = NULL_TREE; - - /* Prevent further error messages. */ - maxindex = build_int_cst (NULL_TREE, 0); - } } - if (!maxindex) - { - if (do_default) - maxindex = build_int_cst (NULL_TREE, 0); - value = 2; - } + failure = complete_array_type (ptype, initial_value, do_default); - if (maxindex) + /* We can create the array before the element type is complete, which + means that we didn't have these two bits set in the original type + either. In completing the type, we are expected to propagate these + bits. See also complete_type which does the same thing for arrays + of fixed size. */ + type = *ptype; + if (TYPE_DOMAIN (type)) { - tree itype; - tree domain; - tree elt_type; - - domain = build_index_type (maxindex); - TYPE_DOMAIN (type) = domain; - - if (initial_value) - itype = TREE_TYPE (initial_value); - else - itype = NULL; - if (itype && !TYPE_DOMAIN (itype)) - TYPE_DOMAIN (itype) = domain; - /* The type of the main variant should never be used for arrays - of different sizes. It should only ever be completed with the - size of the array. */ - if (! TYPE_DOMAIN (TYPE_MAIN_VARIANT (type))) - TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = domain; - elt_type = TREE_TYPE (type); - TYPE_NEEDS_CONSTRUCTING (type) - = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type)); + TYPE_NEEDS_CONSTRUCTING (type) = TYPE_NEEDS_CONSTRUCTING (elt_type); TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type) - = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type)); + = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (elt_type); } - /* Lay out the type now that we can get the real answer. */ - - layout_type (type); - - return value; + return failure; } /* Return zero if something is declared to be a member of type diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index f0dc8c2f7d616e721945af3bfdb9da5cea0ed017..07f614bedd34fb08408ddb3b056541ac82cd2efe 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1996,7 +1996,8 @@ finish_compound_literal (tree type, tree initializer_list) implies that the array has two elements. */ if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type)) - complete_array_type (type, compound_literal, 1); + cp_complete_array_type (&TREE_TYPE (compound_literal), + compound_literal, 1); } return compound_literal; diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 8017af3dd250a95b4f2c7b7fc7a6003cf3d7fb5f..daa23993425d5259fddf73eaadcd0db2206a46f5 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1123,7 +1123,7 @@ process_init_constructor (tree type, tree init, tree* elts) result = build_constructor (type, nreverse (members)); if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == NULL_TREE) - complete_array_type (type, result, /*do_default=*/0); + cp_complete_array_type (&TREE_TYPE (result), result, /*do_default=*/0); if (init) TREE_HAS_CONSTRUCTOR (result) = TREE_HAS_CONSTRUCTOR (init); if (allconstant)