aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/trans-expr.c
diff options
context:
space:
mode:
authorTobias Burnus <tobias@codesourcery.com>2021-09-27 14:04:54 +0200
committerTobias Burnus <tobias@codesourcery.com>2021-09-27 14:04:54 +0200
commit00f6de9c69119594f7dad3bd525937c94c8200d0 (patch)
tree5133e52eac80818ae2e4b4180af6e462af8b3571 /gcc/fortran/trans-expr.c
parent76773d3fea4daaaf5b0f6d79d9f48ffe6b3c97fd (diff)
downloadgcc-00f6de9c69119594f7dad3bd525937c94c8200d0.zip
gcc-00f6de9c69119594f7dad3bd525937c94c8200d0.tar.gz
gcc-00f6de9c69119594f7dad3bd525937c94c8200d0.tar.bz2
Fortran: Fix assumed-size to assumed-rank passing [PR94070]
This code inlines the size0 and size1 libgfortran calls, the former is still used by libgfortan itself (and by old code). Besides permitting more optimizations, it also permits to handle assumed-rank dummies better: If the dummy argument is a nonpointer/nonallocatable, an assumed-size actual arg is repesented by having ubound == -1 for the last dimension. However, for allocatable/pointers, this value can also exist. Hence, the dummy arg attr has to be honored. For that reason, when calling an assumed-rank procedure with nonpointer, nonallocatable dummy arguments, the bounds have to be updated to avoid the case ubound == -1 for the last dimension. PR fortran/94070 gcc/fortran/ChangeLog: * trans-array.c (gfc_tree_array_size): New function to find size inline (whole array or one dimension). (array_parameter_size): Use it, take stmt_block as arg. (gfc_conv_array_parameter): Update call. * trans-array.h (gfc_tree_array_size): Add prototype. * trans-decl.c (gfor_fndecl_size0, gfor_fndecl_size1): Remove these global vars. (gfc_build_intrinsic_function_decls): Remove their initialization. * trans-expr.c (gfc_conv_procedure_call): Update bounds of pointer/allocatable actual args to nonallocatable/nonpointer dummies to be one based. * trans-intrinsic.c (gfc_conv_intrinsic_shape): Fix case for assumed rank with allocatable/pointer dummy. (gfc_conv_intrinsic_size): Update to use inline function. * trans.h (gfor_fndecl_size0, gfor_fndecl_size1): Remove var decl. libgfortran/ChangeLog: * intrinsics/size.c (size0, size1): Comment that now not used by newer compiler code. libgomp/ChangeLog: * testsuite/libgomp.oacc-fortran/privatized-ref-2.f90: Update expected dg-note output. gcc/testsuite/ChangeLog: * gfortran.dg/c-interop/cf-out-descriptor-6.f90: Remove xfail. * gfortran.dg/c-interop/size.f90: Remove xfail. * gfortran.dg/intrinsic_size_3.f90: Update scan-tree-dump-times. * gfortran.dg/transpose_optimization_2.f90: Likewise. * gfortran.dg/size_optional_dim_1.f90: Add scan-tree-dump-not. * gfortran.dg/assumed_rank_22.f90: New test. * gfortran.dg/assumed_rank_22_aux.c: New test.
Diffstat (limited to 'gcc/fortran/trans-expr.c')
-rw-r--r--gcc/fortran/trans-expr.c43
1 files changed, 38 insertions, 5 deletions
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 41d5452..1c24556 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -6450,6 +6450,29 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
parmse.force_tmp = 1;
}
+ /* Special case for assumed-rank arrays: when passing an
+ argument to a nonallocatable/nonpointer dummy, the bounds have
+ to be reset as otherwise a last-dim ubound of -1 is
+ indistinguishable from an assumed-size array in the callee. */
+ if (!sym->attr.is_bind_c && e && fsym && fsym->as
+ && fsym->as->type == AS_ASSUMED_RANK
+ && e->rank != -1
+ && e->expr_type == EXPR_VARIABLE
+ && ((fsym->ts.type == BT_CLASS
+ && !CLASS_DATA (fsym)->attr.class_pointer
+ && !CLASS_DATA (fsym)->attr.allocatable)
+ || (fsym->ts.type != BT_CLASS
+ && !fsym->attr.pointer && !fsym->attr.allocatable)))
+ {
+ /* Change AR_FULL to a (:,:,:) ref to force bounds update. */
+ gfc_ref *ref;
+ for (ref = e->ref; ref->next; ref = ref->next)
+ ;
+ if (ref->u.ar.type == AR_FULL
+ && ref->u.ar.as->type != AS_ASSUMED_SIZE)
+ ref->u.ar.type = AR_SECTION;
+ }
+
if (sym->attr.is_bind_c && e
&& (is_CFI_desc (fsym, NULL) || assumed_length_string))
/* Implement F2018, 18.3.6, list item (5), bullet point 2. */
@@ -6510,16 +6533,26 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
gfc_conv_array_parameter (&parmse, e, nodesc_arg, fsym,
sym->name, NULL);
- /* Unallocated allocatable arrays and unassociated pointer arrays
- need their dtype setting if they are argument associated with
- assumed rank dummies, unless already assumed rank. */
+ /* Special case for assumed-rank arrays. */
if (!sym->attr.is_bind_c && e && fsym && fsym->as
&& fsym->as->type == AS_ASSUMED_RANK
&& e->rank != -1)
{
- if (gfc_expr_attr (e).pointer
+ if ((gfc_expr_attr (e).pointer
|| gfc_expr_attr (e).allocatable)
- set_dtype_for_unallocated (&parmse, e);
+ && ((fsym->ts.type == BT_CLASS
+ && (CLASS_DATA (fsym)->attr.class_pointer
+ || CLASS_DATA (fsym)->attr.allocatable))
+ || (fsym->ts.type != BT_CLASS
+ && (fsym->attr.pointer || fsym->attr.allocatable))))
+ {
+ /* Unallocated allocatable arrays and unassociated pointer
+ arrays need their dtype setting if they are argument
+ associated with assumed rank dummies. However, if the
+ dummy is nonallocate/nonpointer, the user may not
+ pass those. Hence, it can be skipped. */
+ set_dtype_for_unallocated (&parmse, e);
+ }
else if (e->expr_type == EXPR_VARIABLE
&& e->ref
&& e->ref->u.ar.type == AR_FULL