https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93524
Bug ID: 93524 Summary: [ISO C Binding][F2018] CFI_allocate – elem_size mishandled + sm wrongly set? Product: gcc Version: unknown Status: UNCONFIRMED Keywords: wrong-code Severity: normal Priority: P3 Component: fortran Assignee: unassigned at gcc dot gnu.org Reporter: burnus at gcc dot gnu.org Target Milestone: --- CFI_cdesc_t structure type has: size_t elem_len; If the object is scalar, the value is the storage size in bytes of the object; otherwise, the value20is the storage size in bytes of an element of the object. CFI_establish has: elem_len If type is equal to CFI_type_struct, CFI_type_other, or a Fortran character type code, elem_len shall be greater than zero and equal to the storage size in bytes of an element of the object. Otherwise, elem_len will be ignored. (Similarly: CFI_allocate and CFI_select_part, although they only have character and not other/struct.) EXPECTED: 1. For establish/allocate/select_part, the elem_len is handled properly. (Check all three, the testcase only uses the first two.) 2. The CFI_allocate + CFI_contiguous work nice together. Regarding 1: Is seems as if establish handles it correctly but allocate fails if it's argument is elem_len = 0 – even if the descriptor has the proper elem_len = 4. Regaring 2: Currently, is_contiguous is 0 because: {base_addr = 0x408910, elem_len = 4, version = 1, rank = 3, attribute = 1, type = 1027, dim = {{lower_bound = -10, extent = 21, sm = 4}, {lower_bound = 0, extent = 6, sm = 84}, {lower_bound = 3, extent = 8, sm = 24}}} Here, the contiguous check works fine for dim=0 as sm=4 == elem_len. It also works for dim=1 as sm[1]=84 == sm[0]=4 * extent[0]=21 => 84 == 84 But for dim=2, sm[2]=24 != sm[1]=84 * extent[1]=6 => 24 != 504 That looks like a bug in allocate – but I might have also misunderstood something in is_contiguous. Test case; note the bounds of the second Fortran function are wrong because PR 92189 ==> hello_world.c <== #include <stdlib.h> // For size_t #include <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; } ==> hello_world.f90 <== subroutine my_fortran_sub_1 (A) bind(C) real :: A(:, :, :) print *, 'Lower bounds: ', lbound(A) ! Lower bounds: 1 1 1 print *, 'Upper bounds: ', ubound(A) ! Upper bounds: 21 6 8 end subroutine my_fortran_sub_2 (A) bind(C) real, ALLOCATABLE :: A(:, :, :) print *, 'Lower bounds: ', lbound(A) print *, 'Upper bounds: ', ubound(A) end subroutine my_fortran_sub_2