Bug 97046 - Bad interaction between lbound/ubound, allocatable arrays and bind(C) subroutine with dimension(..) parameter
Summary: Bad interaction between lbound/ubound, allocatable arrays and bind(C) subrout...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 10.2.0
: P3 normal
Target Milestone: ---
Assignee: José Rui Faustino de Sousa
URL:
Keywords: patch
Depends on:
Blocks:
 
Reported: 2020-09-14 15:42 UTC by Igor Gayday
Modified: 2021-10-19 10:25 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-05-30 00:00:00


Attachments
Updated patch. (5.64 KB, patch)
2021-06-14 23:24 UTC, José Rui Faustino de Sousa
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Igor Gayday 2020-09-14 15:42:07 UTC
Consider the following code:

MODULE FOO
INTERFACE
SUBROUTINE dummyc(x0) BIND(C, name="sync")
type(*), dimension(..) :: x0
END SUBROUTINE
END INTERFACE
contains
SUBROUTINE dummy(x0)
type(*), dimension(..) :: x0
call dummyc(x0)
END SUBROUTINE
END MODULE

PROGRAM main
    USE FOO
    IMPLICIT NONE
    integer :: before(2), after(2)

    INTEGER, parameter :: n = 1

    DOUBLE PRECISION, ALLOCATABLE :: buf(:)
    DOUBLE PRECISION :: buf2(n)

    ALLOCATE(buf(n))
    before(1) = LBOUND(buf,1)
    before(2) = UBOUND(buf,1)
    CALL dummy (buf)
    after(1) = LBOUND(buf,1)
    after(2) = UBOUND(buf,1)

    if (before(1) .NE. after(1)) stop 1
    if (before(2) .NE. after(2)) stop 2

    before(1) = LBOUND(buf2,1)
    before(2) = UBOUND(buf2,1)
    CALL dummy (buf2)
    after(1) = LBOUND(buf2,1)
    after(2) = LBOUND(buf2,1)

    if (before(1) .NE. after(1)) stop 3
    if (before(2) .NE. after(2)) stop 4

END PROGRAM

lbound() and ubound() of an allocatable array return different values 
before and after a Fortran subroutine with dimension(..) parameter (that 
in turns invokes a bind(C) subroutine) is invoked.

Note that if the main program directly CALL dummyc(buf) (instead of 
dummy(buf)), then the error does not occur.

gcc versions 9.2.0, 10.2.0 and the latest master branch are all affected.

In particular, this causes issues with mpi_f08 module, see:
https://stackoverflow.com/questions/63824065/lbound-of-an-array-changes-after-call-to-mpi-gatherv-when-using-mpi-f08-module

This might be a duplicate of Bug #94070.
Comment 1 kargls 2020-09-14 17:09:38 UTC
(In reply to Igor Gayday from comment #0)
> Consider the following code:
> 
> MODULE FOO
> INTERFACE
> SUBROUTINE dummyc(x0) BIND(C, name="sync")
> type(*), dimension(..) :: x0
> END SUBROUTINE
> END INTERFACE

What are the implementation details for sync?
Comment 2 Gilles Gouaillardet 2020-09-14 23:56:18 UTC
This is the libc subroutine

void sync(void);


The point here is any subroutine (that will not cause a crash) can be used to evidence the issue.
Comment 3 Steve Kargl 2020-09-15 00:25:28 UTC
On Mon, Sep 14, 2020 at 11:56:18PM +0000, gilles.gouaillardet at gmail dot com wrote:
> This is the libc subroutine
> 
> void sync(void);
> 
> The point here is any subroutine (that will not cause a crash) can be used to
> evidence the issue.
> 

Isn't there a mismatch in the number of
arguments provided by your Fortran code
and the parameters expected in sync(2)?

dummy (struct array15_unknown & restrict x0)
{
  {
    void * cfi.0;

    x0->span = (integer(kind=4)) x0->dtype.elem_len;
    x0->dtype.attribute = 2;
    cfi.0 = 0B;
    _gfortran_gfc_desc_to_cfi_desc (&cfi.0, (struct array15_unknown *) x0);
    x0->dtype.attribute = 2;
    dummyc (cfi.0);
    _gfortran_cfi_desc_to_gfc_desc ((struct array15_unknown *) x0, &cfi.0);
    __builtin_free (cfi.0);
  }
}

dummyc(cfi.0) becomes sync(cfi.0).
Is this standard conform?
Comment 4 Gilles Gouaillardet 2020-09-15 01:13:21 UTC
I crafted the reproducer based on a previous one that has already been merged,
and using a libc subroutine was not an issue back then.

https://gcc.gnu.org/git?p=gcc.git;a=blob;f=gcc/testsuite/gfortran.dg/ISO_Fortran_binding_14.f90;h=388c5438252d49342f6bd357850062697fafb7b4;hb=980f185ce3ba6d532530ce0f23bfb6e30320fd8a


But I get your point, and you can

SUBROUTINE dummyc(x0) BIND(C, name="dummyc")

and then in dummyc.c

#include "ISO_Fortran_binding.h"

void dummyc (CFI_cdesc_t * x){
}



This does not change the fact that the test fails with GNU compilers though.
Comment 5 Igor Gayday 2020-09-15 05:56:09 UTC
I'd like to add that Gilles Gouaillardet is the author of the reproducer in my original post.
Comment 6 José Rui Faustino de Sousa 2021-05-19 18:09:41 UTC
Patch posted:

https://gcc.gnu.org/pipermail/fortran/2021-May/056054.html
Comment 7 Dominique d'Humieres 2021-05-30 20:08:44 UTC
> Patch posted:
>
> https://gcc.gnu.org/pipermail/fortran/2021-May/056054.html


The patch fixes this PR, see also pr94331.
Comment 8 José Rui Faustino de Sousa 2021-06-14 23:23:53 UTC
Updated patch:

https://gcc.gnu.org/pipermail/fortran/2021-June/056163.html
Comment 9 José Rui Faustino de Sousa 2021-06-14 23:24:20 UTC
Created attachment 51018 [details]
Updated patch.
Comment 10 GCC Commits 2021-07-26 12:33:30 UTC
The master branch has been updated by Tobias Burnus <burnus@gcc.gnu.org>:

https://gcc.gnu.org/g:0cbf03689e3e7d9d6002b8e5d159ef3716d0404c

commit r12-2511-g0cbf03689e3e7d9d6002b8e5d159ef3716d0404c
Author: Tobias Burnus <tobias@codesourcery.com>
Date:   Mon Jul 26 14:20:46 2021 +0200

    PR fortran/93308/93963/94327/94331/97046 problems raised by descriptor handling
    
    Fortran: Fix attributes and bounds in ISO_Fortran_binding.
    
    2021-07-26  José Rui Faustino de Sousa  <jrfsousa@gmail.com>
                Tobias Burnus  <tobias@codesourcery.com>
    
            PR fortran/93308
            PR fortran/93963
            PR fortran/94327
            PR fortran/94331
            PR fortran/97046
    
    gcc/fortran/ChangeLog:
    
            * trans-decl.c (convert_CFI_desc): Only copy out the descriptor
            if necessary.
            * trans-expr.c (gfc_conv_gfc_desc_to_cfi_desc): Updated attribute
            handling which reflect a previous intermediate version of the
            standard. Only copy out the descriptor if necessary.
    
    libgfortran/ChangeLog:
    
            * runtime/ISO_Fortran_binding.c (cfi_desc_to_gfc_desc): Add code
            to verify the descriptor. Correct bounds calculation.
            (gfc_desc_to_cfi_desc): Add code to verify the descriptor.
    
    gcc/testsuite/ChangeLog:
    
            * gfortran.dg/ISO_Fortran_binding_1.f90: Add pointer attribute,
            this test is still erroneous but now it compiles.
            * gfortran.dg/bind_c_array_params_2.f90: Update regex to match
            code changes.
            * gfortran.dg/PR93308.f90: New test.
            * gfortran.dg/PR93963.f90: New test.
            * gfortran.dg/PR94327.c: New test.
            * gfortran.dg/PR94327.f90: New test.
            * gfortran.dg/PR94331.c: New test.
            * gfortran.dg/PR94331.f90: New test.
            * gfortran.dg/PR97046.f90: New test.
Comment 11 Tobias Burnus 2021-10-19 10:25:35 UTC
FIXED (in GCC 12).

Thanks Igor for the testcase!