Fortran: ALLOCATE statement, SOURCE/MOLD expressions with subrefs [PR114024]

PR fortran/114024

gcc/fortran/ChangeLog:

	* trans-stmt.cc (gfc_trans_allocate): When a source expression has
	substring references, part-refs, or %re/%im inquiries, wrap the
	entity in parentheses to force evaluation of the expression.

gcc/testsuite/ChangeLog:

	* gfortran.dg/allocate_with_source_27.f90: New test.
	* gfortran.dg/allocate_with_source_28.f90: New test.

Co-Authored-By: Harald Anlauf <anlauf@gmx.de>
This commit is contained in:
Steve Kargl 2024-02-23 22:05:04 +01:00 committed by Harald Anlauf
parent 85c12ae8b8
commit 80d126ba99
3 changed files with 118 additions and 2 deletions

View file

@ -6355,8 +6355,14 @@ gfc_trans_allocate (gfc_code * code, gfc_omp_namelist *omp_allocate)
vtab_needed = (al->expr->ts.type == BT_CLASS);
gfc_init_se (&se, NULL);
/* When expr3 is a variable, i.e., a very simple expression,
then convert it once here. */
/* When expr3 is a variable, i.e., a very simple expression, then
convert it once here. If one has a source expression that has
substring references, part-refs, or %re/%im inquiries, wrap the
entity in parentheses to force evaluation of the expression. */
if (code->expr3->expr_type == EXPR_VARIABLE
&& is_subref_array (code->expr3))
code->expr3 = gfc_get_parentheses (code->expr3);
if (code->expr3->expr_type == EXPR_VARIABLE
|| code->expr3->expr_type == EXPR_ARRAY
|| code->expr3->expr_type == EXPR_CONSTANT)

View file

@ -0,0 +1,20 @@
!
! { dg-do run }
!
! fortran/PR114024
! https://github.com/fujitsu/compiler-test-suite
! Modified from Fortran/0093/0093_0130.f90
!
program foo
implicit none
complex :: cmp(3)
real, allocatable :: xx(:), yy(:), zz(:)
cmp = (3., 6.78)
allocate(xx, source = cmp%re) ! This caused an ICE.
allocate(yy, source = cmp(1:3)%re) ! This caused an ICE.
allocate(zz, source = (cmp%re))
if (any(xx /= [3., 3., 3.])) stop 1
if (any(yy /= [3., 3., 3.])) stop 2
if (any(zz /= [3., 3., 3.])) stop 3
end program foo

View file

@ -0,0 +1,90 @@
! { dg-do run }
!
! PR fortran/114024
program foo
implicit none
complex :: cmp(3) = (3.,4.)
type ci ! pseudo "complex integer" type
integer :: re
integer :: im
end type ci
type cr ! pseudo "complex" type
real :: re
real :: im
end type cr
type u
type(ci) :: ii(3)
type(cr) :: rr(3)
end type u
type(u) :: cc
cc% ii% re = nint (cmp% re)
cc% ii% im = nint (cmp% im)
cc% rr% re = cmp% re
cc% rr% im = cmp% im
call test_substring ()
call test_int_real ()
call test_poly ()
contains
subroutine test_substring ()
character(4) :: str(3) = ["abcd","efgh","ijkl"]
character(:), allocatable :: ac(:)
allocate (ac, source=str(1::2)(2:4))
if (size (ac) /= 2 .or. len (ac) /= 3) stop 11
if (ac(2) /= "jkl") stop 12
deallocate (ac)
allocate (ac, mold=str(1::2)(2:4))
if (size (ac) /= 2 .or. len (ac) /= 3) stop 13
deallocate (ac)
end
subroutine test_int_real ()
integer, allocatable :: aa(:)
real, pointer :: pp(:)
allocate (aa, source = cc% ii% im)
if (size (aa) /= 3) stop 21
if (any (aa /= cmp% im)) stop 22
allocate (pp, source = cc% rr% re)
if (size (pp) /= 3) stop 23
if (any (pp /= cmp% re)) stop 24
deallocate (aa, pp)
end
subroutine test_poly ()
class(*), allocatable :: uu(:), vv(:)
allocate (uu, source = cc% ii% im)
allocate (vv, source = cc% rr% re)
if (size (uu) /= 3) stop 31
if (size (vv) /= 3) stop 32
call check (uu)
call check (vv)
deallocate (uu, vv)
allocate (uu, mold = cc% ii% im)
allocate (vv, mold = cc% rr% re)
if (size (uu) /= 3) stop 33
if (size (vv) /= 3) stop 34
deallocate (uu, vv)
end
subroutine check (x)
class(*), intent(in) :: x(:)
select type (x)
type is (integer)
if (any (x /= cmp% im)) then
print *, "'integer':", x
stop 41
end if
type is (real)
if (any (x /= cmp% re)) then
print *, "'real':", x
stop 42
end if
type is (character(*))
print *, "'character':", x
end select
end
end