diff options
author | Paul Thomas <pault@gcc.gnu.org> | 2007-09-16 09:17:49 +0000 |
---|---|---|
committer | Paul Thomas <pault@gcc.gnu.org> | 2007-09-16 09:17:49 +0000 |
commit | 1d6b7f396a30bc20304c97d54379b25f4aa5c92f (patch) | |
tree | 0671456d4a0001c3c76dbc6dc8b6b3c8d5ac9a80 /gcc/fortran/trans.c | |
parent | 1b95f1f634ddfdc1aae90d49103584a5dd0b8221 (diff) | |
download | gcc-1d6b7f396a30bc20304c97d54379b25f4aa5c92f.zip gcc-1d6b7f396a30bc20304c97d54379b25f4aa5c92f.tar.gz gcc-1d6b7f396a30bc20304c97d54379b25f4aa5c92f.tar.bz2 |
re PR fortran/29396 (segfault with character pointer association)
2007-09-16 Paul Thomas <pault@gcc.gnu.org>
PR fortran/29396
PR fortran/29606
PR fortran/30625
PR fortran/30871
* trans.h : Add extra argument to gfc_build_array_ref. Rename
gfc_conv_aliased_arg to gfc_conv_subref_array_arg. Move
prototype of is_aliased_array to gfortran.h and rename it
gfc_is_subref_array. Add field span to lang_decl, add a new
decl lang specific flag accessed by GFC_DECL_SUBREF_ARRAY_P
and a new type flag GFC_DECL_SUBREF_ARRAY_P.
* trans.c (gfc_build_array_ref): Add the new argument, decl.
If this is a subreference array pointer, use the lang_decl
field 'span' to calculate the offset in bytes and use pointer
arithmetic to address the element.
* trans-array.c (gfc_conv_scalarized_array_ref,
gfc_conv_array_ref): Add the backend declaration as the third
field, if it is likely to be a subreference array pointer.
(gfc_conv_descriptor_dimension, gfc_trans_array_ctor_element,
gfc_trans_array_constructor_element, structure_alloc_comps,
gfc_conv_array_index_offset): For all other references to
gfc_build_array_ref, set the third argument to NULL.
(gfc_get_dataptr_offset): New function.
(gfc_conv_expr_descriptor): If the rhs of a pointer assignment
is a subreference array, then calculate the offset to the
subreference of the first element and set the descriptor data
pointer to this, using gfc_get_dataptr_offset.
trans-expr.c (gfc_get_expr_charlen): Use the expression for the
character length for a character subreference.
(gfc_conv_substring, gfc_conv_subref_array_arg): Add NULL for
third argument in call to gfc_build_array_ref.
(gfc_conv_aliased_arg): Rename to gfc_conv_subref_array_arg.
(is_aliased_array): Remove.
(gfc_conv_function_call): Change reference to is_aliased_array
to gfc_is_subref_array and reference to gfc_conv_aliased_arg to
gfc_conv_subref_array_arg.
(gfc_trans_pointer_assignment): Add the array element length to
the lang_decl 'span' field.
* gfortran.h : Add subref_array_pointer to symbol_attribute and
add the prototype for gfc_is_subref_array.
* trans-stmt.c : Add NULL for third argument in all references
to gfc_build_array_ref.
* expr.c (gfc_is_subref_array): Renamed is_aliased_array.
If this is a subreference array pointer, return true.
(gfc_check_pointer_assign): If the rhs is a subreference array,
set the lhs subreference_array_pointer attribute.
* trans-decl.c (gfc_get_symbol_decl): Allocate the lang_decl
field if the symbol is a subreference array pointer and set an
initial value of zero for the 'span' field.
* trans-io.c (set_internal_unit): Refer to is_subref_array and
gfc_conv_subref_array_arg.
(nml_get_addr_expr): Add NULL third argument to
gfc_build_array_ref.
(gfc_trans_transfer): Use the scalarizer for a subreference
array.
2007-09-16 Paul Thomas <pault@gcc.gnu.org>
PR fortran/29396
PR fortran/29606
PR fortran/30625
PR fortran/30871
* gfortran.dg/subref_array_pointer_1.f90: New test.
* gfortran.dg/subref_array_pointer_2.f90: New test.
From-SVN: r128523
Diffstat (limited to 'gcc/fortran/trans.c')
-rw-r--r-- | gcc/fortran/trans.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c index b9fd2df..0d036aa 100644 --- a/gcc/fortran/trans.c +++ b/gcc/fortran/trans.c @@ -309,9 +309,11 @@ gfc_build_addr_expr (tree type, tree t) /* Build an ARRAY_REF with its natural type. */ tree -gfc_build_array_ref (tree base, tree offset) +gfc_build_array_ref (tree base, tree offset, tree decl) { tree type = TREE_TYPE (base); + tree tmp; + gcc_assert (TREE_CODE (type) == ARRAY_TYPE); type = TREE_TYPE (type); @@ -321,7 +323,28 @@ gfc_build_array_ref (tree base, tree offset) /* Strip NON_LVALUE_EXPR nodes. */ STRIP_TYPE_NOPS (offset); - return build4 (ARRAY_REF, type, base, offset, NULL_TREE, NULL_TREE); + /* If the array reference is to a pointer, whose target contains a + subreference, use the span that is stored with the backend decl + and reference the element with pointer arithmetic. */ + if (decl && (TREE_CODE (decl) == FIELD_DECL + || TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == PARM_DECL) + && GFC_DECL_SUBREF_ARRAY_P (decl) + && !integer_zerop (GFC_DECL_SPAN(decl))) + { + offset = fold_build2 (MULT_EXPR, gfc_array_index_type, + offset, GFC_DECL_SPAN(decl)); + tmp = gfc_build_addr_expr (pvoid_type_node, base); + tmp = fold_build2 (POINTER_PLUS_EXPR, pvoid_type_node, + tmp, fold_convert (sizetype, offset)); + tmp = fold_convert (build_pointer_type (type), tmp); + if (!TYPE_STRING_FLAG (type)) + tmp = build_fold_indirect_ref (tmp); + return tmp; + } + else + /* Otherwise use a straightforward array reference. */ + return build4 (ARRAY_REF, type, base, offset, NULL_TREE, NULL_TREE); } |