Nvfortran bug in the Fortran-C interop features?

I believe this is a bug in the Fortran-C interop features of nvfortran. Take the following program as an example (program.F90):

PROGRAM main
    USE, INTRINSIC :: ISO_C_BINDING, ONLY: c_float
    IMPLICIT NONE

    INTERFACE
        SUBROUTINE check_array(res) BIND(C)
            IMPORT :: c_float
            REAL(c_float), INTENT(inout), ALLOCATABLE :: res(:, :, :)
        END SUBROUTINE check_array
    END INTERFACE

    REAL, ALLOCATABLE :: my_array(:, :, :)

    ! Everything works when the array is allocated - when the array is not
    ! allocated it fails
    ! ALLOCATE(my_array(3, 3, 3))

    CALL wrapper(my_array)

CONTAINS
    ! When check_array is called through this wrapper it does not work as
    ! expected
    SUBROUTINE wrapper(vertices)
        REAL, ALLOCATABLE, INTENT(inout) :: vertices(:, :, :)
        CALL check_array(vertices)
    END SUBROUTINE wrapper
END PROGRAM main

with the accompanying C++ code (check_array.cpp):

#include <ISO_Fortran_binding.h>

#include <iostream>
#include <cassert>

extern "C" {
    void check_array(CFI_cdesc_t* data) {
        std::cout << "Data rank: " << static_cast<int>(data->rank) << std::endl;
        std::cout << "Data type: " << static_cast<int>(data->type) << std::endl;

        assert (data->rank == 3);
        assert (data->type == CFI_type_float || data->type == CFI_type_double);
    }
}

Compiling this with nvc++ and nvfortran:

nvc++ -c check_array.cpp
nvfortran program.F90 check_array.o -lstdc++ -o test_cfi

and running it gives the following:

$ ./test_cfi 
Data rank: 0
Data type: -1
test_cfi: check_array.cpp:11: void check_array(CFI_cdesc_t *): Assertion `data->rank == 3' failed.
Aborted (core dumped)

In the example program, everything works when the call to check_array is performed directly in the same scope as the array declaration (i.e. replace wrapper with check_array). When the intermediate subroutine wrapper is used it does not work.

It also works if I first call check_array and then afterwards call wrapper from the main program.

The example works in all other “major” compilers (GNU, Intel, NAG Fortran). I am using the following nvfortran version:

$ nvfortran --version

nvfortran 24.3-0 64-bit target on x86-64 Linux -tp alderlake 
NVIDIA Compilers and Tools
Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES.  All rights reserved.

Any comments?

Hi hakostra -

So, if I run the code as you have it written, I do indeed get the result you claim. However - note that you’ve commented out the allocate line! So you’re not actually allocating the my_array array - so the behavior, in this case, is correct I believe. I highlight the pertinent line below.

! ALLOCATE(my_array(3, 3, 3))

If I remove the “!” from that line and actually allocate my_array, then using NVHPC 24.3 or NVHPC 24.5, the code appears to run correctly. Assuming your testing with other compilers worked - I imagine you may have tested the correct version of the code against other compilers and then mistakenly commented out the allocate line when testing NVHPC compilers.

Please let me know if this resolve your issue!

The ALLOCATE is deliberately left out. I believe that the CFI_cdesc_t in that case should hold the rank ( data->rank) and type of the allocatable (data->type). And it actually does, when check_array is called directly from the scoping unit of the allocatable itself. When the call goes through an intermediate wrapper this information disappear.

My use case is to pass an un-allocated Fortran allocatable to a C++ routine (just as in this example). The C++ routine will determine the necessary size of the array and then call CFI_Allocate to allocate the array before populating it with data. This works with Intel, GNU and NAG Fortran compilers.

Ah! I apologize! I didn’t read your post closely enough this morning. I will blame it on my morning coffee not having finished brewing. Obviously - you explained it very thoroughly that it worked if allocate was included. Having taken the time to more closely read the issue now - I have verified the issue that you’re experiencing with it working properly if you call the C++ subroutine directly - but getting incorrect behavior when passed through a fortran wrapping subroutine, as well as it working with other compilers but not ours.

I’ve opened a new bug report on it - #35723. As engineering works through the issue - I will reach out to you to notify you of the status! Thanks for making us aware of the issue.

Thanks! I have another Fortran-C interop bug ready soon - I believe it is unrelated to this one so I’ll make a new post on it tomorrow.

1 Like

Hakostra - I was just notified that a compiler engineer has put in a fix for this issue into our dev compiler. This likely means that a fix will propagate into the released compiler for 24.7. Of course, until it does propagate into the release compiler, I can’t make any promises. But I suspect that the issue here will be resolved in the next release.

Awesome, great!!! Thank you so much.

@hakostra - the 24.7 release appears to solve this issue! Thanks for bringing it to our attention. Please let us know if you run into any other issues.

I have now installed 24.7 and this works. Thanks!