From 8e5fa4828678a1388e75795de2a1f253d9f0ec95 Mon Sep 17 00:00:00 2001 From: Paul-Antoine Arras Date: Fri, 20 Oct 2023 12:42:49 +0200 Subject: [PATCH] Fortran: Fix incompatible types between INTEGER(8) and TYPE(c_ptr) In the context of an OpenMP declare variant directive, arguments of type C_PTR are sometimes recognised as C_PTR in the base function and as INTEGER(8) in the variant - or the other way around, depending on the parsing order. This patch prevents such situation from turning into a compile error. 2023-10-20 Paul-Antoine Arras Tobias Burnus gcc/fortran/ChangeLog: * interface.cc (gfc_compare_types): Return true in this situation. gcc/testsuite/ChangeLog: * gfortran.dg/c_ptr_tests_20.f90: New test. --- gcc/fortran/ChangeLog.omp | 5 ++ gcc/fortran/interface.cc | 17 +++--- gcc/testsuite/ChangeLog.omp | 4 ++ gcc/testsuite/gfortran.dg/c_ptr_tests_20.f90 | 56 ++++++++++++++++++++ 4 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/c_ptr_tests_20.f90 diff --git a/gcc/fortran/ChangeLog.omp b/gcc/fortran/ChangeLog.omp index 62a33475ee5..299223ceaa7 100644 --- a/gcc/fortran/ChangeLog.omp +++ b/gcc/fortran/ChangeLog.omp @@ -1,3 +1,8 @@ +2023-10-20 Paul-Antoine Arras + Tobias Burnus + + * interface.cc (gfc_compare_types): Return true in this situation. + 2023-09-19 Tobias Burnus Backported from master: diff --git a/gcc/fortran/interface.cc b/gcc/fortran/interface.cc index e9843e9549c..8bd35fd6d22 100644 --- a/gcc/fortran/interface.cc +++ b/gcc/fortran/interface.cc @@ -705,12 +705,17 @@ gfc_compare_types (gfc_typespec *ts1, gfc_typespec *ts2) /* Special case for our C interop types. FIXME: There should be a better way of doing this. When ISO C binding is cleared up, - this can probably be removed. See PR 57048. */ - - if (((ts1->type == BT_INTEGER && ts2->type == BT_DERIVED) - || (ts1->type == BT_DERIVED && ts2->type == BT_INTEGER)) - && ts1->u.derived && ts2->u.derived - && ts1->u.derived == ts2->u.derived) + this can probably be removed. See PR 57048. + Note that this does not distinguish between c_ptr and c_funptr. */ + + if ((ts1->type == BT_INTEGER && ts2->type == BT_DERIVED + && ts1->f90_type == BT_VOID + && ts2->u.derived->ts.is_iso_c + && ts2->u.derived->ts.u.derived->ts.f90_type == BT_VOID) + || (ts2->type == BT_INTEGER && ts1->type == BT_DERIVED + && ts2->f90_type == BT_VOID + && ts1->u.derived->ts.is_iso_c + && ts1->u.derived->ts.u.derived->ts.f90_type == BT_VOID)) return true; /* The _data component is not always present, therefore check for its diff --git a/gcc/testsuite/ChangeLog.omp b/gcc/testsuite/ChangeLog.omp index e9f4d1c63e6..1fc9b0606dc 100644 --- a/gcc/testsuite/ChangeLog.omp +++ b/gcc/testsuite/ChangeLog.omp @@ -1,3 +1,7 @@ +2023-10-20 Paul-Antoine Arras + + * gfortran.dg/c_ptr_tests_20.f90: New test. + 2023-09-20 Tobias Burnus Backported from master: diff --git a/gcc/testsuite/gfortran.dg/c_ptr_tests_20.f90 b/gcc/testsuite/gfortran.dg/c_ptr_tests_20.f90 new file mode 100644 index 00000000000..777181cece0 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c_ptr_tests_20.f90 @@ -0,0 +1,56 @@ +! { dg-do compile } +! +! This failed to compile the declare variant directive due to the C_PTR +! arguments to foo being recognised as INTEGER(8) + +program adjust_args + use iso_c_binding, only: c_loc + implicit none + + integer, parameter :: N = 1024 + real, allocatable, target :: av(:), bv(:), cv(:) + + call foo(c_loc(bv), c_loc(av), N) + + !$omp target data map(to: av(:N)) map(from: cv(:N)) + !$omp parallel + call foo(c_loc(cv), c_loc(av), N) + !$omp end parallel + !$omp end target data + +contains + subroutine foo_variant(c_d_bv, c_d_av, n) + use iso_c_binding, only: c_ptr, c_f_pointer + type(c_ptr), intent(in) :: c_d_bv, c_d_av + integer, intent(in) :: n + real, pointer :: f_d_bv(:) + real, pointer :: f_d_av(:) + integer :: i + + call c_f_pointer(c_d_bv, f_d_bv, [n]) + call c_f_pointer(c_d_av, f_d_av, [n]) + !$omp target teams loop is_device_ptr(f_d_bv, f_d_av) + do i = 1, n + f_d_bv(i) = f_d_av(i) * i + end do + end subroutine + + + subroutine foo(c_bv, c_av, n) + use iso_c_binding, only: c_ptr, c_f_pointer + type(c_ptr), intent(in) :: c_bv, c_av + integer, intent(in) :: n + real, pointer :: f_bv(:) + real, pointer :: f_av(:) + integer :: i + !$omp declare variant(foo_variant) & + !$omp match(construct={parallel}) + + call c_f_pointer(c_bv, f_bv, [n]) + call c_f_pointer(c_av, f_av, [n]) + !$omp parallel loop + do i = 1, n + f_bv(i) = f_av(i) * i + end do + end subroutine +end program -- 2.42.0