aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/expr.c
diff options
context:
space:
mode:
authorPaul Thomas <pault@gcc.gnu.org>2007-09-16 09:17:49 +0000
committerPaul Thomas <pault@gcc.gnu.org>2007-09-16 09:17:49 +0000
commit1d6b7f396a30bc20304c97d54379b25f4aa5c92f (patch)
tree0671456d4a0001c3c76dbc6dc8b6b3c8d5ac9a80 /gcc/fortran/expr.c
parent1b95f1f634ddfdc1aae90d49103584a5dd0b8221 (diff)
downloadgcc-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/expr.c')
-rw-r--r--gcc/fortran/expr.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 6ffcf7e..815612e 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -792,6 +792,35 @@ gfc_is_constant_expr (gfc_expr *e)
}
+/* Is true if an array reference is followed by a component or substring
+ reference. */
+bool
+is_subref_array (gfc_expr * e)
+{
+ gfc_ref * ref;
+ bool seen_array;
+
+ if (e->expr_type != EXPR_VARIABLE)
+ return false;
+
+ if (e->symtree->n.sym->attr.subref_array_pointer)
+ return true;
+
+ seen_array = false;
+ for (ref = e->ref; ref; ref = ref->next)
+ {
+ if (ref->type == REF_ARRAY
+ && ref->u.ar.type != AR_ELEMENT)
+ seen_array = true;
+
+ if (seen_array
+ && ref->type != REF_ARRAY)
+ return seen_array;
+ }
+ return false;
+}
+
+
/* Try to collapse intrinsic expressions. */
static try
@@ -2802,6 +2831,9 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue)
return FAILURE;
}
+ if (rvalue->expr_type == EXPR_VARIABLE && is_subref_array (rvalue))
+ lvalue->symtree->n.sym->attr.subref_array_pointer = 1;
+
attr = gfc_expr_attr (rvalue);
if (!attr.target && !attr.pointer)
{