From f61e5d4d8b6d4cfa96863187fa61b8c6b057a491 Mon Sep 17 00:00:00 2001 From: Sandra Loosemore Date: Tue, 22 Jun 2021 12:42:17 -0700 Subject: Fortran: fix sm computation in CFI_allocate [PR93524] This patch fixes a bug in setting the step multiplier field in the C descriptor for array dimensions > 2. 2021-06-21 Sandra Loosemore Tobias Burnus libgfortran/ PR fortran/93524 * runtime/ISO_Fortran_binding.c (CFI_allocate): Fix sm computation. gcc/testsuite/ PR fortran/93524 * gfortran.dg/pr93524.c: New. * gfortran.dg/pr93524.f90: New. --- gcc/testsuite/gfortran.dg/pr93524.c | 33 +++++++++++++++++++++++++++++++ gcc/testsuite/gfortran.dg/pr93524.f90 | 17 ++++++++++++++++ libgfortran/runtime/ISO_Fortran_binding.c | 5 +---- 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/pr93524.c create mode 100644 gcc/testsuite/gfortran.dg/pr93524.f90 diff --git a/gcc/testsuite/gfortran.dg/pr93524.c b/gcc/testsuite/gfortran.dg/pr93524.c new file mode 100644 index 00000000000..24e5e094631 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr93524.c @@ -0,0 +1,33 @@ +/* Test the fix for PR93524, in which CFI_allocate was computing + sm incorrectly for dimensions > 2. */ + +#include // For size_t +#include "../../../libgfortran/ISO_Fortran_binding.h" + +void my_fortran_sub_1 (CFI_cdesc_t *dv); +void my_fortran_sub_2 (CFI_cdesc_t *dv); + +int main () +{ + CFI_CDESC_T (3) a; + CFI_cdesc_t *dv = (CFI_cdesc_t *) &a; + // dv, base_addr, attribute, type, elem_len, rank, extents + CFI_establish (dv, NULL, CFI_attribute_allocatable, CFI_type_float, 0, 3, NULL); + + if (dv->base_addr != NULL) + return 1; // shall not be allocated + + CFI_index_t lower_bounds[] = {-10, 0, 3}; + CFI_index_t upper_bounds[] = {10, 5, 10}; + size_t elem_len = 0; // only needed for strings + if (CFI_SUCCESS != CFI_allocate (dv, lower_bounds, upper_bounds, elem_len)) + return 2; + + if (!CFI_is_contiguous (dv)) + return 2; // allocatables shall be contiguous,unless a strided section is used + + my_fortran_sub_1 (dv); + my_fortran_sub_2 (dv); + CFI_deallocate (dv); + return 0; +} diff --git a/gcc/testsuite/gfortran.dg/pr93524.f90 b/gcc/testsuite/gfortran.dg/pr93524.f90 new file mode 100644 index 00000000000..0cebc8f24a8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr93524.f90 @@ -0,0 +1,17 @@ +! { dg-additional-sources pr93524.c } +! { dg-do run } +! +! Test the fix for PR93524. The main program is in pr93524.c. + +subroutine my_fortran_sub_1 (A) bind(C) + real :: A(:, :, :) + if (any (lbound(A) /= 1)) stop 1 + if (any (ubound(A) /= [21,6,8])) stop 2 + if (.not. is_contiguous (A)) stop 3 +end +subroutine my_fortran_sub_2 (A) bind(C) + real, ALLOCATABLE :: A(:, :, :) + if (any (lbound(A) /= [-10,0,3])) stop 1 + if (any (ubound(A) /= [10,5,10])) stop 2 + if (.not. is_contiguous (A)) stop 3 +end subroutine my_fortran_sub_2 diff --git a/libgfortran/runtime/ISO_Fortran_binding.c b/libgfortran/runtime/ISO_Fortran_binding.c index 20833ad2025..09788321c9e 100644 --- a/libgfortran/runtime/ISO_Fortran_binding.c +++ b/libgfortran/runtime/ISO_Fortran_binding.c @@ -254,10 +254,7 @@ CFI_allocate (CFI_cdesc_t *dv, const CFI_index_t lower_bounds[], { dv->dim[i].lower_bound = lower_bounds[i]; dv->dim[i].extent = upper_bounds[i] - dv->dim[i].lower_bound + 1; - if (i == 0) - dv->dim[i].sm = dv->elem_len; - else - dv->dim[i].sm = dv->elem_len * dv->dim[i - 1].extent; + dv->dim[i].sm = dv->elem_len * arr_len; arr_len *= dv->dim[i].extent; } } -- cgit v1.2.3