diff options
author | Richard Kenner <kenner@vlsi1.ultra.nyu.edu> | 2004-04-12 21:25:55 +0000 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 2004-04-12 17:25:55 -0400 |
commit | 1c9766da11d71cb57f8962a2eb88833c1ca966f5 (patch) | |
tree | fc6c6b14412060a9d6d90d3f45c768a4648b7f4b /gcc | |
parent | 040e098a5de9115501bd76ce0ea7adc9a0eded21 (diff) | |
download | gcc-1c9766da11d71cb57f8962a2eb88833c1ca966f5.zip gcc-1c9766da11d71cb57f8962a2eb88833c1ca966f5.tar.gz gcc-1c9766da11d71cb57f8962a2eb88833c1ca966f5.tar.bz2 |
c-decl.c (finish_decl): Make a decl_stmt for a variable-sized TYPE_DECL.
* c-decl.c (finish_decl): Make a decl_stmt for a variable-sized
TYPE_DECL.
* c-semantics.c (genrtl_decl_stmt): Handle TYPE_DECL.
* stmt.c (expand_decl): Remove redundant expansion of TYPE_DOMAIN.
* stor-layout.c (variable_size): Don't check for MINUS_EXPR.
Use skip_simple_arithmetic to find SAVE_EXPR.
(force_type_save_exprs, force_type_save_exprs_1): New functions.
* tree-inline.c (remap_type, case POINTER_TYPE, case REFERENCE_TYPE):
Properly chain multiple pointers.
(copy_tree_r): Copy a TYPE_DECL.
* tree.c (variably_modified_type_p): Add some missing tests and
make some other minor changes.
* tree.h (force_type_save_exprs): New declaration.
* gcc.c-torture/execute/20040411-1.c: New test.
From-SVN: r80629
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/c-decl.c | 8 | ||||
-rw-r--r-- | gcc/c-semantics.c | 2 | ||||
-rw-r--r-- | gcc/stmt.c | 9 | ||||
-rw-r--r-- | gcc/stor-layout.c | 63 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/20040411-1.c | 23 | ||||
-rw-r--r-- | gcc/tree-inline.c | 10 | ||||
-rw-r--r-- | gcc/tree.c | 52 | ||||
-rw-r--r-- | gcc/tree.h | 5 |
10 files changed, 160 insertions, 32 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ac9f0c9..72ec5b5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2004-04-12 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> + + * c-decl.c (finish_decl): Make a decl_stmt for a variable-sized + TYPE_DECL. + * c-semantics.c (genrtl_decl_stmt): Handle TYPE_DECL. + * stmt.c (expand_decl): Remove redundant expansion of TYPE_DOMAIN. + * stor-layout.c (variable_size): Don't check for MINUS_EXPR. + Use skip_simple_arithmetic to find SAVE_EXPR. + (force_type_save_exprs, force_type_save_exprs_1): New functions. + * tree-inline.c (remap_type, case POINTER_TYPE, case REFERENCE_TYPE): + Properly chain multiple pointers. + (copy_tree_r): Copy a TYPE_DECL. + * tree.c (variably_modified_type_p): Add some missing tests and + make some other minor changes. + * tree.h (force_type_save_exprs): New declaration. + 2004-04-12 Roger Sayle <roger@eyesopen.com> * simplify-rtx.c (simplify_binary_operation) <UDIV, DIV, UMOD, MOD>: diff --git a/gcc/c-decl.c b/gcc/c-decl.c index de96be3..8f19647 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -2979,7 +2979,13 @@ finish_decl (tree decl, tree init, tree asmspec_tree) mark_referenced (DECL_ASSEMBLER_NAME (decl)); if (TREE_CODE (decl) == TYPE_DECL) - rest_of_decl_compilation (decl, NULL, DECL_FILE_SCOPE_P (decl), 0); + { + if (!DECL_FILE_SCOPE_P (decl) + && variably_modified_type_p (TREE_TYPE (decl))) + add_decl_stmt (decl); + + rest_of_decl_compilation (decl, NULL, DECL_FILE_SCOPE_P (decl), 0); + } /* At the end of a declaration, throw away any variable type sizes of types defined inside that declaration. There is no use diff --git a/gcc/c-semantics.c b/gcc/c-semantics.c index 17a301c..a8693f9 100644 --- a/gcc/c-semantics.c +++ b/gcc/c-semantics.c @@ -389,6 +389,8 @@ genrtl_decl_stmt (tree t) else if (TREE_CODE (decl) == LABEL_DECL && C_DECLARED_LABEL_FLAG (decl)) declare_nonlocal_label (decl); + else if (TREE_CODE (decl) == TYPE_DECL) + force_type_save_exprs (TREE_TYPE (decl)); else if (lang_expand_decl_stmt) (*lang_expand_decl_stmt) (t); } @@ -4013,13 +4013,8 @@ expand_decl (tree decl) do_pending_stack_adjust (); save_stack_pointer (); - /* In function-at-a-time mode, variable_size doesn't expand this, - so do it now. */ - if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type)) - expand_expr (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), - const0_rtx, VOIDmode, 0); - - /* Compute the variable's size, in bytes. */ + /* Compute the variable's size, in bytes. This will expand any + needed SAVE_EXPRs for the first time. */ size = expand_expr (DECL_SIZE_UNIT (decl), NULL_RTX, VOIDmode, 0); free_temp_slots (); diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 2baa364..d19fc9f 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -66,6 +66,7 @@ static void place_union_field (record_layout_info, tree); static int excess_unit_span (HOST_WIDE_INT, HOST_WIDE_INT, HOST_WIDE_INT, HOST_WIDE_INT, tree); #endif +static void force_type_save_exprs_1 (tree); static unsigned int update_alignment_for_field (record_layout_info, tree, unsigned int); extern void debug_rli (record_layout_info); @@ -146,12 +147,7 @@ variable_size (tree size) || CONTAINS_PLACEHOLDER_P (size)) return size; - if (TREE_CODE (size) == MINUS_EXPR && integer_onep (TREE_OPERAND (size, 1))) - /* If this is the upper bound of a C array, leave the minus 1 outside - the SAVE_EXPR so it can be folded away. */ - TREE_OPERAND (size, 0) = save = save_expr (TREE_OPERAND (size, 0)); - else - size = save = save_expr (size); + size = save_expr (size); /* If an array with a variable number of elements is declared, and the elements require destruction, we will emit a cleanup for the @@ -161,6 +157,7 @@ variable_size (tree size) `unsaved', i.e., all SAVE_EXPRs are recalculated. However, we do not wish to do that here; the array-size is the same in both places. */ + save = skip_simple_arithmetic (size); if (TREE_CODE (save) == SAVE_EXPR) SAVE_EXPR_PERSISTENT_P (save) = 1; @@ -185,6 +182,60 @@ variable_size (tree size) return size; } + +/* Given a type T, force elaboration of any SAVE_EXPRs used in the definition + of that type. */ + +void +force_type_save_exprs (tree t) +{ + tree field; + + switch (TREE_CODE (t)) + { + case ERROR_MARK: + return; + + case ARRAY_TYPE: + case SET_TYPE: + case VECTOR_TYPE: + /* It's probably overly-conservative to force elaboration of bounds and + also the sizes, but it's better to be safe than sorry. */ + force_type_save_exprs_1 (TYPE_MIN_VALUE (TYPE_DOMAIN (t))); + force_type_save_exprs_1 (TYPE_MAX_VALUE (TYPE_DOMAIN (t))); + break; + + case RECORD_TYPE: + case UNION_TYPE: + case QUAL_UNION_TYPE: + for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL) + { + force_type_save_exprs (TREE_TYPE (field)); + force_type_save_exprs_1 (DECL_FIELD_OFFSET (field)); + } + break; + + default: + break; + } + + force_type_save_exprs_1 (TYPE_SIZE (t)); + force_type_save_exprs_1 (TYPE_SIZE_UNIT (t)); +} + +/* Utility routine of above, to verify that SIZE has been elaborated and + do so it it is a SAVE_EXPR and has not been. */ + +static void +force_type_save_exprs_1 (tree size) +{ + if (size + && (size = skip_simple_arithmetic (size)) + && TREE_CODE (size) == SAVE_EXPR + && !SAVE_EXPR_RTL (size)) + expand_expr (size, NULL_RTX, VOIDmode, 0); +} #ifndef MAX_FIXED_MODE_SIZE #define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (DImode) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 040aac8..df7d2e1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2004-04-12 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> + + * gcc.c-torture/execute/20040411-1.c: New test. + 2004-04-10 Joseph S. Myers <jsm@polyomino.org.uk> * gcc.dg/c90-intprom-1.c, gcc.dg/c99-intprom-1.c: New tests. diff --git a/gcc/testsuite/gcc.c-torture/execute/20040411-1.c b/gcc/testsuite/gcc.c-torture/execute/20040411-1.c new file mode 100644 index 0000000..8db4562 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20040411-1.c @@ -0,0 +1,23 @@ +int +sub1 (int i, int j) +{ + typedef int c[i+2]; + int x[10], y[10]; + + if (j == 2) + { + memcpy (x, y, 10 * sizeof (int)); + return sizeof (c); + } + else + return sizeof (c) * 3; +} + +int +main () +{ + if (sub1 (20, 3) != 66 * sizeof (int)) + abort (); + + return 0; +} diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index d9aeefe..622ae18 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -271,6 +271,7 @@ remap_type (tree type, inline_data *id) t = TYPE_MIN_VALUE (new); if (t && TREE_CODE (t) != INTEGER_CST) walk_tree (&TYPE_MIN_VALUE (new), copy_body_r, id, NULL); + t = TYPE_MAX_VALUE (new); if (t && TREE_CODE (t) != INTEGER_CST) walk_tree (&TYPE_MAX_VALUE (new), copy_body_r, id, NULL); @@ -278,14 +279,14 @@ remap_type (tree type, inline_data *id) case POINTER_TYPE: TREE_TYPE (new) = t = remap_type (TREE_TYPE (new), id); - if (TYPE_MODE (new) == ptr_mode) - TYPE_POINTER_TO (t) = new; + TYPE_NEXT_PTR_TO (new) = TYPE_POINTER_TO (t); + TYPE_POINTER_TO (t) = new; return new; case REFERENCE_TYPE: TREE_TYPE (new) = t = remap_type (TREE_TYPE (new), id); - if (TYPE_MODE (new) == ptr_mode) - TYPE_REFERENCE_TO (t) = new; + TYPE_NEXT_REF_TO (new) = TYPE_REFERENCE_TO (t); + TYPE_REFERENCE_TO (t) = new; return new; case METHOD_TYPE: @@ -2082,6 +2083,7 @@ copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) || TREE_CODE_CLASS (code) == 'c' || code == TREE_LIST || code == TREE_VEC + || code == TYPE_DECL || lang_hooks.tree_inlining.tree_chain_matters_p (*tp)) { /* Because the chain gets clobbered when we make a copy, we save it @@ -4629,38 +4629,62 @@ variably_modified_type_p (tree type) case POINTER_TYPE: case REFERENCE_TYPE: case ARRAY_TYPE: - /* If TYPE is a pointer or reference, it is variably modified if - the type pointed to is variably modified. Similarly for arrays; - note that VLAs are handled by the TYPE_SIZE check above. */ - return variably_modified_type_p (TREE_TYPE (type)); + case SET_TYPE: + case VECTOR_TYPE: + if (variably_modified_type_p (TREE_TYPE (type))) + return true; + break; case FUNCTION_TYPE: case METHOD_TYPE: /* If TYPE is a function type, it is variably modified if any of the parameters or the return type are variably modified. */ - { - tree parm; + if (variably_modified_type_p (TREE_TYPE (type))) + return true; - if (variably_modified_type_p (TREE_TYPE (type))) + for (t = TYPE_ARG_TYPES (type); + t && t != void_list_node; + t = TREE_CHAIN (t)) + if (variably_modified_type_p (TREE_VALUE (t))) return true; - for (parm = TYPE_ARG_TYPES (type); - parm && parm != void_list_node; - parm = TREE_CHAIN (parm)) - if (variably_modified_type_p (TREE_VALUE (parm))) - return true; - } break; case INTEGER_TYPE: + case REAL_TYPE: + case ENUMERAL_TYPE: + case BOOLEAN_TYPE: + case CHAR_TYPE: /* Scalar types are variably modified if their end points aren't constant. */ t = TYPE_MIN_VALUE (type); if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST) return true; + t = TYPE_MAX_VALUE (type); if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST) return true; - return false; + break; + + case RECORD_TYPE: + case UNION_TYPE: + case QUAL_UNION_TYPE: + /* We can't see if any of the field are variably-modified by the + definition we normally use, since that would produce infinite + recursion via pointers. */ + /* This is variably modified if some field's type is. */ + for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t)) + if (TREE_CODE (t) == FIELD_DECL) + { + tree t1 = DECL_FIELD_OFFSET (t); + + if (t1 && t1 != error_mark_node && TREE_CODE (t1) != INTEGER_CST) + return true; + + t1 = DECL_SIZE (t); + if (t1 && t1 != error_mark_node && TREE_CODE (t1) != INTEGER_CST) + return true; + } + break; default: break; @@ -2768,6 +2768,11 @@ extern tree substitute_placeholder_in_expr (tree, tree); extern tree variable_size (tree); +/* Given a type T, force elaboration of any SAVE_EXPRs used in the definition + of that type. */ + +extern void force_type_save_exprs (tree); + /* stabilize_reference (EXP) returns a reference equivalent to EXP but it can be used multiple times and only evaluate the subexpressions once. */ |