aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/dependency.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard@codesourcery.com>2005-09-09 06:34:08 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2005-09-09 06:34:08 +0000
commit7a70c12d9b2ba6d2c7e154053ef19ac316f3c34e (patch)
tree6320cd48af2ca2f1553a582aa75b00c42d833159 /gcc/fortran/dependency.c
parent62ab4a54994341ab463149da427a51d70d2fbc70 (diff)
downloadgcc-7a70c12d9b2ba6d2c7e154053ef19ac316f3c34e.zip
gcc-7a70c12d9b2ba6d2c7e154053ef19ac316f3c34e.tar.gz
gcc-7a70c12d9b2ba6d2c7e154053ef19ac316f3c34e.tar.bz2
re PR fortran/19239 ([4.0 only] gfortran ICE on vector subscript expressions)
PR fortran/19239 * Makefile.in (fortran/trans-expr.o): Depend on dependency.h. * dependency.h (gfc_ref_needs_temporary_p): Declare. * dependency.c (gfc_ref_needs_temporary_p): New function. (gfc_check_fncall_dependency): Use it instead of inlined check. By so doing, take advantage of the fact that character substrings within an array reference also need a temporary. * trans.h (GFC_SS_VECTOR): Adjust comment. * trans-array.c (gfc_free_ss): Remove GFC_SS_VECTOR case. (gfc_set_vector_loop_bounds): New function. (gfc_add_loop_ss_code): Call it after evaluating the subscripts of a GFC_SS_SECTION. Deal with the GFC_SS_VECTOR case by evaluating the vector expression and caching its descriptor for use within the loop. (gfc_conv_array_index_ref, gfc_conv_vector_array_index): Delete. (gfc_conv_array_index_offset): Handle scalar, vector and range dimensions as separate cases of a switch statement. In the vector case, use the loop variable to calculate a vector index and use the referenced element as the dimension's index. Perform bounds checking on this final index. (gfc_conv_section_upper_bound): Return null for vector indexes. (gfc_conv_section_startstride): Give vector indexes a start value of 0 and a stride of 1. (gfc_conv_ss_startstride): Adjust for new GFC_SS_VECTOR representation. (gfc_conv_expr_descriptor): Expand comments. Generalize the handling of the !want_pointer && !direct_byref case. Use gfc_ref_needs_temporary_p to decide whether the variable case needs a temporary. (gfc_walk_variable_expr): Handle DIMEN_VECTOR by creating a GFC_SS_VECTOR index. * trans-expr.c: Include dependency.h. (gfc_trans_arrayfunc_assign): Fail if the target needs a temporary. 2005-09-09 Richard Sandiford <richard@codesourcery.com> PR fortran/21104 * trans.h (gfc_interface_sym_mapping, gfc_interface_mapping): Moved from trans-expr.c. (gfc_init_interface_mapping, gfc_free_interface_mapping) (gfc_add_interface_mapping, gfc_finish_interface_mapping) (gfc_apply_interface_mapping): Declare. * trans-array.h (gfc_set_loop_bounds_from_array_spec): Declare. (gfc_trans_allocate_temp_array): Add pre and post block arguments. * trans-array.c (gfc_set_loop_bounds_from_array_spec): New function. (gfc_trans_allocate_array_storage): Replace loop argument with separate pre and post blocks. (gfc_trans_allocate_temp_array): Add pre and post block arguments. Update call to gfc_trans_allocate_array_storage. (gfc_trans_array_constructor, gfc_conv_loop_setup): Adjust for new interface to gfc_trans_allocate_temp_array. * trans-expr.c (gfc_interface_sym_mapping, gfc_interface_mapping): Moved to trans.h. (gfc_init_interface_mapping, gfc_free_interface_mapping) (gfc_add_interface_mapping, gfc_finish_interface_mapping) (gfc_apply_interface_mapping): Make extern. (gfc_conv_function_call): Build an interface mapping for array return values too. Call gfc_set_loop_bounds_from_array_spec. Adjust call to gfc_trans_allocate_temp_array so that code is added to SE rather than LOOP. From-SVN: r104077
Diffstat (limited to 'gcc/fortran/dependency.c')
-rw-r--r--gcc/fortran/dependency.c68
1 files changed, 41 insertions, 27 deletions
diff --git a/gcc/fortran/dependency.c b/gcc/fortran/dependency.c
index 5b0045e..9c6b4f6 100644
--- a/gcc/fortran/dependency.c
+++ b/gcc/fortran/dependency.c
@@ -175,6 +175,45 @@ gfc_is_same_range (gfc_array_ref * ar1, gfc_array_ref * ar2, int n, int def)
}
+/* Return true if the result of reference REF can only be constructed
+ using a temporary array. */
+
+bool
+gfc_ref_needs_temporary_p (gfc_ref *ref)
+{
+ int n;
+ bool subarray_p;
+
+ subarray_p = false;
+ for (; ref; ref = ref->next)
+ switch (ref->type)
+ {
+ case REF_ARRAY:
+ /* Vector dimensions are generally not monotonic and must be
+ handled using a temporary. */
+ if (ref->u.ar.type == AR_SECTION)
+ for (n = 0; n < ref->u.ar.dimen; n++)
+ if (ref->u.ar.dimen_type[n] == DIMEN_VECTOR)
+ return true;
+
+ subarray_p = true;
+ break;
+
+ case REF_SUBSTRING:
+ /* Within an array reference, character substrings generally
+ need a temporary. Character array strides are expressed as
+ multiples of the element size (consistent with other array
+ types), not in characters. */
+ return subarray_p;
+
+ case REF_COMPONENT:
+ break;
+ }
+
+ return false;
+}
+
+
/* Dependency checking for direct function return by reference.
Returns true if the arguments of the function depend on the
destination. This is considerably less conservative than other
@@ -185,9 +224,7 @@ int
gfc_check_fncall_dependency (gfc_expr * dest, gfc_expr * fncall)
{
gfc_actual_arglist *actual;
- gfc_ref *ref;
gfc_expr *expr;
- int n;
gcc_assert (dest->expr_type == EXPR_VARIABLE
&& fncall->expr_type == EXPR_FUNCTION);
@@ -205,31 +242,8 @@ gfc_check_fncall_dependency (gfc_expr * dest, gfc_expr * fncall)
switch (expr->expr_type)
{
case EXPR_VARIABLE:
- if (expr->rank > 1)
- {
- /* This is an array section. */
- for (ref = expr->ref; ref; ref = ref->next)
- {
- if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
- break;
- }
- gcc_assert (ref);
- /* AR_FULL can't contain vector subscripts. */
- if (ref->u.ar.type == AR_SECTION)
- {
- for (n = 0; n < ref->u.ar.dimen; n++)
- {
- if (ref->u.ar.dimen_type[n] == DIMEN_VECTOR)
- break;
- }
- /* Vector subscript array sections will be copied to a
- temporary. */
- if (n != ref->u.ar.dimen)
- continue;
- }
- }
-
- if (gfc_check_dependency (dest, actual->expr, NULL, 0))
+ if (!gfc_ref_needs_temporary_p (expr->ref)
+ && gfc_check_dependency (dest, expr, NULL, 0))
return 1;
break;