Skip to content

Commit 9f204cc

Browse files
author
Paul Thomas
committed
Fortran: Fix a gimplifier ICE/wrong result with finalization [PR36337]
2024-03-29 Paul Thomas <pault@gcc.gnu.org> gcc/fortran PR fortran/36337 PR fortran/110987 PR fortran/113885 * trans-expr.cc (gfc_trans_assignment_1): Place finalization block before rhs post block for elemental rhs. * trans.cc (gfc_finalize_tree_expr): Check directly if a type has no components, rather than the zero components attribute. Treat elemental zero component expressions in the same way as scalars. gcc/testsuite/ PR fortran/113885 * gfortran.dg/finalize_54.f90: New test. * gfortran.dg/finalize_55.f90: New test. gcc/testsuite/ PR fortran/110987 * gfortran.dg/finalize_56.f90: New test. (cherry picked from commit 3c793f0)
1 parent 094f8a3 commit 9f204cc

File tree

5 files changed

+313
-6
lines changed

5 files changed

+313
-6
lines changed

gcc/fortran/trans-expr.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12182,11 +12182,14 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
1218212182
gfc_add_block_to_block (&body, &lse.pre);
1218312183
gfc_add_expr_to_block (&body, tmp);
1218412184

12185-
/* Add the post blocks to the body. */
12186-
if (!l_is_temp)
12185+
/* Add the post blocks to the body. Scalar finalization must appear before
12186+
the post block in case any dellocations are done. */
12187+
if (rse.finalblock.head
12188+
&& (!l_is_temp || (expr2->expr_type == EXPR_FUNCTION
12189+
&& gfc_expr_attr (expr2).elemental)))
1218712190
{
12188-
gfc_add_block_to_block (&rse.finalblock, &rse.post);
1218912191
gfc_add_block_to_block (&body, &rse.finalblock);
12192+
gfc_add_block_to_block (&body, &rse.post);
1219012193
}
1219112194
else
1219212195
gfc_add_block_to_block (&body, &rse.post);

gcc/fortran/trans.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,7 +1527,7 @@ gfc_finalize_tree_expr (gfc_se *se, gfc_symbol *derived,
15271527
}
15281528
else if (derived && gfc_is_finalizable (derived, NULL))
15291529
{
1530-
if (derived->attr.zero_comp && !rank)
1530+
if (!derived->components && (!rank || attr.elemental))
15311531
{
15321532
/* Any attempt to assign zero length entities, causes the gimplifier
15331533
all manner of problems. Instead, a variable is created to act as
@@ -1578,7 +1578,7 @@ gfc_finalize_tree_expr (gfc_se *se, gfc_symbol *derived,
15781578
final_fndecl);
15791579
if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
15801580
{
1581-
if (is_class)
1581+
if (is_class || attr.elemental)
15821582
desc = gfc_conv_scalar_to_descriptor (se, desc, attr);
15831583
else
15841584
{
@@ -1588,7 +1588,7 @@ gfc_finalize_tree_expr (gfc_se *se, gfc_symbol *derived,
15881588
}
15891589
}
15901590

1591-
if (derived && derived->attr.zero_comp)
1591+
if (derived && !derived->components)
15921592
{
15931593
/* All the conditions below break down for zero length derived types. */
15941594
tmp = build_call_expr_loc (input_location, final_fndecl, 3,
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
! { dg-do compile }
2+
! Test the fix for PR113885, where not only was there a gimplifier ICE
3+
! for a derived type 't' with no components but, with a component, gfortran
4+
! gave wrong results.
5+
! Contributed by David Binderman <dcb314@hotmail.com>
6+
!
7+
module types
8+
type t
9+
contains
10+
final :: finalize
11+
end type t
12+
contains
13+
pure subroutine finalize(x)
14+
type(t), intent(inout) :: x
15+
end subroutine finalize
16+
end module types
17+
18+
subroutine test1(x)
19+
use types
20+
interface
21+
elemental function elem(x)
22+
use types
23+
type(t), intent(in) :: x
24+
type(t) :: elem
25+
end function elem
26+
end interface
27+
type(t) :: x(:)
28+
x = elem(x)
29+
end subroutine test1
30+
31+
subroutine test2(x)
32+
use types
33+
interface
34+
elemental function elem(x)
35+
use types
36+
type(t), intent(in) :: x
37+
type(t) :: elem
38+
end function elem
39+
elemental function elem2(x, y)
40+
use types
41+
type(t), intent(in) :: x, y
42+
type(t) :: elem2
43+
end function elem2
44+
end interface
45+
type(t) :: x(:)
46+
x = elem2(elem(x), elem(x))
47+
end subroutine test2
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
! { dg-do run }
2+
! Test the fix for PR113885, where not only was there a gimplifier ICE
3+
! for a derived type 't' with no components but this version gave wrong
4+
! results.
5+
! Contributed by David Binderman <dcb314@hotmail.com>
6+
!
7+
module types
8+
type t
9+
integer :: i
10+
contains
11+
final :: finalize
12+
end type t
13+
integer :: ctr = 0
14+
contains
15+
impure elemental subroutine finalize(x)
16+
type(t), intent(inout) :: x
17+
ctr = ctr + 1
18+
end subroutine finalize
19+
end module types
20+
21+
impure elemental function elem(x)
22+
use types
23+
type(t), intent(in) :: x
24+
type(t) :: elem
25+
elem%i = x%i + 1
26+
end function elem
27+
28+
impure elemental function elem2(x, y)
29+
use types
30+
type(t), intent(in) :: x, y
31+
type(t) :: elem2
32+
elem2%i = x%i + y%i
33+
end function elem2
34+
35+
subroutine test1(x)
36+
use types
37+
interface
38+
impure elemental function elem(x)
39+
use types
40+
type(t), intent(in) :: x
41+
type(t) :: elem
42+
end function elem
43+
end interface
44+
type(t) :: x(:)
45+
type(t), allocatable :: y(:)
46+
y = x
47+
x = elem(y)
48+
end subroutine test1
49+
50+
subroutine test2(x)
51+
use types
52+
interface
53+
impure elemental function elem(x)
54+
use types
55+
type(t), intent(in) :: x
56+
type(t) :: elem
57+
end function elem
58+
impure elemental function elem2(x, y)
59+
use types
60+
type(t), intent(in) :: x, y
61+
type(t) :: elem2
62+
end function elem2
63+
end interface
64+
type(t) :: x(:)
65+
type(t), allocatable :: y(:)
66+
y = x
67+
x = elem2(elem(y), elem(y))
68+
end subroutine test2
69+
70+
program test113885
71+
use types
72+
interface
73+
subroutine test1(x)
74+
use types
75+
type(t) :: x(:)
76+
end subroutine
77+
subroutine test2(x)
78+
use types
79+
type(t) :: x(:)
80+
end subroutine
81+
end interface
82+
type(t) :: x(2) = [t(1),t(2)]
83+
call test1 (x)
84+
if (any (x%i .ne. [2,3])) stop 1
85+
if (ctr .ne. 6) stop 2
86+
call test2 (x)
87+
if (any (x%i .ne. [6,8])) stop 3
88+
if (ctr .ne. 16) stop 4
89+
end
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
! { dg-do run }
2+
! Test the fix for PR110987
3+
! Segfaulted in runtime, as shown below.
4+
! Contributed by Kirill Chankin <chilikin.k@gmail.com>
5+
! and John Haiducek <jhaiduce@gmail.com> (comment 5)
6+
!
7+
MODULE original_mod
8+
IMPLICIT NONE
9+
10+
TYPE T1_POINTER
11+
CLASS(T1), POINTER :: T1
12+
END TYPE
13+
14+
TYPE T1
15+
INTEGER N_NEXT
16+
CLASS(T1_POINTER), ALLOCATABLE :: NEXT(:)
17+
CONTAINS
18+
FINAL :: T1_DESTRUCTOR
19+
PROCEDURE :: SET_N_NEXT => T1_SET_N_NEXT
20+
PROCEDURE :: GET_NEXT => T1_GET_NEXT
21+
END TYPE
22+
23+
INTERFACE T1
24+
PROCEDURE T1_CONSTRUCTOR
25+
END INTERFACE
26+
27+
TYPE, EXTENDS(T1) :: T2
28+
REAL X
29+
CONTAINS
30+
END TYPE
31+
32+
INTERFACE T2
33+
PROCEDURE T2_CONSTRUCTOR
34+
END INTERFACE
35+
36+
TYPE, EXTENDS(T1) :: T3
37+
CONTAINS
38+
FINAL :: T3_DESTRUCTOR
39+
END TYPE
40+
41+
INTERFACE T3
42+
PROCEDURE T3_CONSTRUCTOR
43+
END INTERFACE
44+
45+
INTEGER :: COUNTS = 0
46+
47+
CONTAINS
48+
49+
TYPE(T1) FUNCTION T1_CONSTRUCTOR() RESULT(L)
50+
IMPLICIT NONE
51+
L%N_NEXT = 0
52+
END FUNCTION
53+
54+
SUBROUTINE T1_DESTRUCTOR(SELF)
55+
IMPLICIT NONE
56+
TYPE(T1), INTENT(INOUT) :: SELF
57+
IF (ALLOCATED(SELF%NEXT)) THEN
58+
DEALLOCATE(SELF%NEXT)
59+
ENDIF
60+
END SUBROUTINE
61+
62+
SUBROUTINE T3_DESTRUCTOR(SELF)
63+
IMPLICIT NONE
64+
TYPE(T3), INTENT(IN) :: SELF
65+
if (.NOT.ALLOCATED (SELF%NEXT)) COUNTS = COUNTS + 1
66+
END SUBROUTINE
67+
68+
SUBROUTINE T1_SET_N_NEXT(SELF, N_NEXT)
69+
IMPLICIT NONE
70+
CLASS(T1), INTENT(INOUT) :: SELF
71+
INTEGER, INTENT(IN) :: N_NEXT
72+
INTEGER I
73+
SELF%N_NEXT = N_NEXT
74+
ALLOCATE(SELF%NEXT(N_NEXT))
75+
DO I = 1, N_NEXT
76+
NULLIFY(SELF%NEXT(I)%T1)
77+
ENDDO
78+
END SUBROUTINE
79+
80+
FUNCTION T1_GET_NEXT(SELF) RESULT(NEXT)
81+
IMPLICIT NONE
82+
CLASS(T1), TARGET, INTENT(IN) :: SELF
83+
CLASS(T1), POINTER :: NEXT
84+
CLASS(T1), POINTER :: L
85+
INTEGER I
86+
IF (SELF%N_NEXT .GE. 1) THEN
87+
NEXT => SELF%NEXT(1)%T1
88+
RETURN
89+
ENDIF
90+
NULLIFY(NEXT)
91+
END FUNCTION
92+
93+
TYPE(T2) FUNCTION T2_CONSTRUCTOR() RESULT(L)
94+
IMPLICIT NONE
95+
L%T1 = T1()
96+
CALL L%T1%SET_N_NEXT(1)
97+
END FUNCTION
98+
99+
TYPE(T3) FUNCTION T3_CONSTRUCTOR() RESULT(L)
100+
IMPLICIT NONE
101+
L%T1 = T1()
102+
END FUNCTION
103+
104+
END MODULE original_mod
105+
106+
module comment5_mod
107+
type::parent
108+
character(:), allocatable::name
109+
end type parent
110+
type, extends(parent)::child
111+
contains
112+
final::child_finalize
113+
end type child
114+
interface child
115+
module procedure new_child
116+
end interface child
117+
integer :: counts = 0
118+
119+
contains
120+
121+
type(child) function new_child(name)
122+
character(*)::name
123+
new_child%name=name
124+
end function new_child
125+
126+
subroutine child_finalize(this)
127+
type(child), intent(in)::this
128+
counts = counts + 1
129+
end subroutine child_finalize
130+
end module comment5_mod
131+
132+
PROGRAM TEST_PROGRAM
133+
call original
134+
call comment5
135+
contains
136+
subroutine original
137+
USE original_mod
138+
IMPLICIT NONE
139+
TYPE(T1), TARGET :: X1
140+
TYPE(T2), TARGET :: X2
141+
TYPE(T3), TARGET :: X3
142+
CLASS(T1), POINTER :: L
143+
X1 = T1()
144+
X2 = T2()
145+
X2%NEXT(1)%T1 => X1
146+
X3 = T3()
147+
CALL X3%SET_N_NEXT(1)
148+
X3%NEXT(1)%T1 => X2
149+
L => X3
150+
DO WHILE (.TRUE.)
151+
L => L%GET_NEXT() ! Used to segfault here in runtime
152+
IF (.NOT. ASSOCIATED(L)) EXIT
153+
COUNTS = COUNTS + 1
154+
ENDDO
155+
! Two for T3 finalization and two for associated 'L's
156+
IF (COUNTS .NE. 4) STOP 1
157+
end subroutine original
158+
159+
subroutine comment5
160+
use comment5_mod, only: child, counts
161+
implicit none
162+
type(child)::kid
163+
kid = child("Name")
164+
if (.not.allocated (kid%name)) stop 2
165+
if (kid%name .ne. "Name") stop 3
166+
if (counts .ne. 2) stop 4
167+
end subroutine comment5
168+
END PROGRAM

0 commit comments

Comments
 (0)