From 773b2aae412145d61638a0423c5891c4dfd0f945 Mon Sep 17 00:00:00 2001
From: Harald Anlauf <anlauf@gmx.de>
Date: Mon, 12 Jun 2023 23:08:48 +0200
Subject: [PATCH] Fortran: fix passing of zero-sized array arguments to
procedures [PR86277]
gcc/fortran/ChangeLog:
PR fortran/86277
* trans-array.cc (gfc_trans_allocate_array_storage): When passing a
zero-sized array with fixed (= non-dynamic) size, allocate temporary
by the caller, not by the callee.
gcc/testsuite/ChangeLog:
PR fortran/86277
* gfortran.dg/zero_sized_14.f90: New test.
* gfortran.dg/zero_sized_15.f90: New test.
Co-authored-by: Mikael Morin <mikael@gcc.gnu.org>
---
gcc/fortran/trans-array.cc | 2 +-
gcc/testsuite/gfortran.dg/zero_sized_14.f90 | 181 ++++++++++++++++++++
gcc/testsuite/gfortran.dg/zero_sized_15.f90 | 114 ++++++++++++
3 files changed, 296 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gfortran.dg/zero_sized_14.f90
create mode 100644 gcc/testsuite/gfortran.dg/zero_sized_15.f90
@@ -1117,7 +1117,7 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
desc = info->descriptor;
info->offset = gfc_index_zero_node;
- if (size == NULL_TREE || integer_zerop (size))
+ if (size == NULL_TREE || (dynamic && integer_zerop (size)))
{
/* A callee allocated array. */
gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
new file mode 100644
@@ -0,0 +1,181 @@
+! { dg-do run }
+! PR fortran/86277
+!
+! Check proper detection of presence of optional array dummy arguments
+! for zero-sized actual array arguments or array constructors:
+! tests for REAL (as non-character intrinsic type) and empty derived type
+
+program test
+ implicit none
+ real, parameter :: m(0) = 42.
+ real, parameter :: n(1) = 23.
+ real :: x(0) = 1.
+ real :: z(1) = 2.
+ real :: w(0)
+ real, pointer :: p(:)
+ real, allocatable :: y(:)
+ integer :: k = 0, l = 0 ! Test/failure counter
+ type dt
+ ! Empty type
+ end type dt
+ type(dt), parameter :: t0(0) = dt()
+ type(dt), parameter :: t1(1) = dt()
+ type(dt) :: t2(0) = dt()
+ type(dt) :: t3(1) = dt()
+ type(dt) :: t4(0)
+ type(dt), allocatable :: tt(:)
+ !
+ allocate (p(0))
+ allocate (y(0))
+ allocate (tt(0))
+ call a0 ()
+ call a1 ()
+ call a2 ()
+ call a3 ()
+ call all_missing ()
+ print *, "Total tests:", k, " failed:", l
+contains
+ subroutine a0 ()
+ print *, "Variables as actual argument"
+ call i (m)
+ call i (n)
+ call i (x)
+ call i (w)
+ call i (y)
+ call i (p)
+ call j (t0)
+ call j (t1)
+ call j (t2)
+ call j (t3)
+ call j (t4)
+ call j (tt)
+ print *, "Array section as actual argument"
+ call i (m(1:0))
+ call i (n(1:0))
+ call i (x(1:0))
+ call i (w(1:0))
+ call i (z(1:0))
+ call i (p(1:0))
+ call j (t0(1:0))
+ call j (t1(1:0))
+ call j (t2(1:0))
+ call j (t3(1:0))
+ call j (t4(1:0))
+ call j (tt(1:0))
+ end subroutine a0
+ !
+ subroutine a1 ()
+ print *, "Explicit temporary as actual argument"
+ call i ((m))
+ call i ((n))
+ call i ((n(1:0)))
+ call i ((x))
+ call i ((w))
+ call i ((z(1:0)))
+ call i ((y))
+ call i ((p))
+ call i ((p(1:0)))
+ call j ((t0))
+ call j ((t1))
+ call j ((tt))
+ call j ((t1(1:0)))
+ call j ((tt(1:0)))
+ end subroutine a1
+ !
+ subroutine a2 ()
+ print *, "Array constructor as actual argument"
+ call i ([m])
+ call i ([n])
+ call i ([x])
+ call i ([w])
+ call i ([z])
+ call i ([m(1:0)])
+ call i ([n(1:0)])
+ call i ([m,n(1:0)])
+ call i ([x(1:0)])
+ call i ([w(1:0)])
+ call i ([z(1:0)])
+ call i ([y])
+ call i ([p])
+ call i ([y,y])
+ call i ([p,p])
+ call i ([y(1:0)])
+ call i ([p(1:0)])
+ call j ([t0])
+ call j ([t0,t0])
+ call j ([t1])
+ call j ([tt])
+ call j ([tt,tt])
+ call j ([t1(1:0)])
+ call j ([tt(1:0)])
+ end subroutine a2
+ !
+ subroutine a3 ()
+ print *, "Array constructor with type-spec as actual argument"
+ call i ([real:: ])
+ call i ([real:: 7])
+ call i ([real:: m])
+ call i ([real:: n])
+ call i ([real:: x])
+ call i ([real:: w])
+ call i ([real:: m(1:0)])
+ call i ([real:: n(1:0)])
+ call i ([real:: m,n(1:0)])
+ call i ([real:: x(1:0)])
+ call i ([real:: w(1:0)])
+ call i ([real:: z(1:0)])
+ call i ([real:: y])
+ call i ([real:: p])
+ call i ([real:: y,y])
+ call i ([real:: p,p])
+ call i ([real:: y(1:0)])
+ call i ([real:: p(1:0)])
+ call j ([ dt :: ])
+ call j ([ dt :: t0])
+ call j ([ dt :: t0,t0])
+ call j ([ dt :: t1])
+ call j ([ dt :: tt])
+ call j ([ dt :: tt,tt])
+ call j ([ dt :: t1(1:0)])
+ call j ([ dt :: tt(1:0)])
+ end subroutine a3
+ !
+ subroutine i (arg)
+ real, optional, intent(in) :: arg(:)
+ logical :: t
+ t = present (arg)
+ k = k + 1
+ print *, 'test', k, merge (" ok", "FAIL", t)
+ if (.not. t) l = l + 1
+ if (.not. t) stop k
+ end subroutine i
+ !
+ subroutine j (arg)
+ type(dt), optional, intent(in) :: arg(:)
+ logical :: t
+ t = present (arg)
+ k = k + 1
+ print *, 'test', k, merge (" ok", "FAIL", t)
+ if (.not. t) l = l + 1
+ if (.not. t) stop k
+ end subroutine j
+ !
+ subroutine all_missing (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
+ real, optional, intent(in) :: arg1(:)
+ real, optional, allocatable :: arg2(:)
+ real, optional, pointer :: arg3(:)
+ character(*), optional, intent(in) :: arg4(:)
+ character(*), optional, allocatable :: arg5(:)
+ character(*), optional, pointer :: arg6(:)
+ character(:), optional, pointer :: arg7(:)
+ character(:), optional, allocatable :: arg8(:)
+ if (present (arg1)) stop 101
+ if (present (arg2)) stop 102
+ if (present (arg3)) stop 103
+ if (present (arg4)) stop 104
+ if (present (arg5)) stop 105
+ if (present (arg6)) stop 106
+ if (present (arg7)) stop 107
+ if (present (arg8)) stop 108
+ end subroutine all_missing
+end program
new file mode 100644
@@ -0,0 +1,114 @@
+! { dg-do run }
+! PR fortran/86277
+!
+! Check proper detection of presence of optional array dummy arguments
+! for zero-sized actual array arguments or array constructors:
+! tests for CHARACTER
+
+program test
+ implicit none
+ character(0), parameter :: c0(0) = ""
+ character(0), parameter :: c1(1) = ""
+ character(1), parameter :: d0(0) = ""
+ character(1), parameter :: d1(1) = ""
+ character(0) :: w0(0)
+ character(0) :: w1(1)
+ character(:), allocatable :: cc(:)
+ integer :: k = 0, l = 0 ! Test/failure counter
+ !
+ allocate (character(0) :: cc(0))
+ call a0 ()
+ call a1 ()
+ call a2 ()
+ call a3 ()
+ print *, "Total tests:", k, " failed:", l
+contains
+ subroutine a0 ()
+ print *, "Variables as actual argument"
+ call i (c0)
+ call i (c1)
+ call i (d0)
+ call i (d1)
+ call i (w0)
+ call i (w1)
+ call i (cc)
+ print *, "Array section as actual argument"
+ call i (c1(1:0))
+ call i (c1(1:0)(1:0))
+ call i (w1(1:0))
+ call i (w1(1:0)(1:0))
+ call i (cc(1:0))
+ call i (cc(1:0)(1:0))
+ end subroutine a0
+ !
+ subroutine a1 ()
+ print *, "Explicit temporary as actual argument"
+ call i ((c0))
+ call i ((c1))
+ call i ((d0))
+ call i ((d1))
+ call i ((w0))
+ call i ((w1))
+ call i ((cc))
+ call i ((c1(1:0)))
+ call i ((c1(1:0)(1:0)))
+ call i ((w1(1:0)))
+ call i ((w1(1:0)(1:0)))
+ call i ((cc(1:0)))
+ call i ((cc(1:0)(1:0)))
+ end subroutine a1
+ !
+ subroutine a2 ()
+ print *, "Array constructor as actual argument"
+ call i ([c0])
+ call i ([c1])
+ call i ([d0])
+ call i ([d1])
+ call i ([w0])
+ call i ([w1])
+ call i ([cc])
+ call i ([c0,c0])
+ call i ([c1,c1])
+ call i ([d0,d0])
+ call i ([cc,cc])
+ call i ([c1(1:0)])
+ call i ([c1(1:0)(1:0)])
+ call i ([w1(1:0)])
+ call i ([w1(1:0)(1:0)])
+ call i ([cc(1:0)])
+ call i ([cc(1:0)(1:0)])
+ end subroutine a2
+ !
+ subroutine a3 ()
+ print *, "Array constructor with type-spec as actual argument"
+ call i ([character(0) :: ])
+ call i ([character(0) :: ""])
+ call i ([character(0) :: c0])
+ call i ([character(0) :: c1])
+ call i ([character(0) :: d0])
+ call i ([character(0) :: d1])
+ call i ([character(0) :: w0])
+ call i ([character(0) :: w1])
+ call i ([character(0) :: cc])
+ call i ([character(0) :: c0,c0])
+ call i ([character(0) :: c1,c1])
+ call i ([character(0) :: d0,d0])
+ call i ([character(0) :: cc,cc])
+ call i ([character(0) :: c1(1:0)])
+ call i ([character(0) :: c1(1:0)(1:0)])
+ call i ([character(0) :: w1(1:0)])
+ call i ([character(0) :: w1(1:0)(1:0)])
+ call i ([character(0) :: cc(1:0)])
+ call i ([character(0) :: cc(1:0)(1:0)])
+ end subroutine a3
+ !
+ subroutine i(arg)
+ character(*), optional, intent(in) :: arg(:)
+ logical :: t
+ t = present (arg)
+ k = k + 1
+ print *, 'test', k, merge (" ok", "FAIL", t)
+ if (.not. t) l = l + 1
+ if (.not. t) stop k
+ end subroutine i
+end program
--
2.35.3