diff mbox series

Fortran: character array constructor with >= 4 constant elements [PR103115]

Message ID trinity-8b181888-d8ea-4fd7-ad50-31c047e8bc72-1721330833565@3c-app-gmx-bs03
State New
Headers show
Series Fortran: character array constructor with >= 4 constant elements [PR103115] | expand

Commit Message

Harald Anlauf July 18, 2024, 7:27 p.m. UTC
Dear all,

here's a quite obvious fix for an ICE when processing an array constructor
where the first element is of deferred length, and at least four constant
elements followed, or an iterator with at least four elements.  There
is a code path that then tries to combine these constant elements and
take the element size of the first (variable length) element in the
constructor.

(For gcc with checking=release, no ICE occured; wrong code was generated
instead.)

Obvious fix: if we see that the element size is not constant, falls back
to the case handling the constructor element-wise.

Regtested on x86_64-pc-linux-gnu.  OK for mainline / backports?

Thanks,
Harald

Comments

Andre Vehreschild July 19, 2024, 11:33 a.m. UTC | #1
Hi Harald,

you right, that solution looks pretty obvious to me. Ok by me. Thanks for the
patch and the opportunity to give back a review.

Keep up the good work!

Regards,
	Andre

On Thu, 18 Jul 2024 21:27:13 +0200
Harald Anlauf <anlauf@gmx.de> wrote:

> Dear all,
>
> here's a quite obvious fix for an ICE when processing an array constructor
> where the first element is of deferred length, and at least four constant
> elements followed, or an iterator with at least four elements.  There
> is a code path that then tries to combine these constant elements and
> take the element size of the first (variable length) element in the
> constructor.
>
> (For gcc with checking=release, no ICE occured; wrong code was generated
> instead.)
>
> Obvious fix: if we see that the element size is not constant, falls back
> to the case handling the constructor element-wise.
>
> Regtested on x86_64-pc-linux-gnu.  OK for mainline / backports?
>
> Thanks,
> Harald
>


--
Andre Vehreschild * Email: vehre ad gmx dot de
diff mbox series

Patch

From 5b264e77b54e211c7781d2c2e5dc324846a774a1 Mon Sep 17 00:00:00 2001
From: Harald Anlauf <anlauf@gmx.de>
Date: Thu, 18 Jul 2024 21:15:48 +0200
Subject: [PATCH] Fortran: character array constructor with >= 4 constant
 elements [PR103115]

gcc/fortran/ChangeLog:

	PR fortran/103115
	* trans-array.cc (gfc_trans_array_constructor_value): If the first
	element of an array constructor is deferred-length character and
	therefore does not have an element size known at compile time, do
	not try to collect subsequent constant elements into a constructor
	for optimization.

gcc/testsuite/ChangeLog:

	PR fortran/103115
	* gfortran.dg/string_array_constructor_4.f90: New test.
---
 gcc/fortran/trans-array.cc                    |  4 +-
 .../string_array_constructor_4.f90            | 59 +++++++++++++++++++
 2 files changed, 62 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gfortran.dg/string_array_constructor_4.f90

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index dc3de6c3b14..c93a5f1e754 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -2147,7 +2147,9 @@  gfc_trans_array_constructor_value (stmtblock_t * pblock,
 	      p = gfc_constructor_next (p);
 	      n++;
 	    }
-	  if (n < 4)
+	  /* Constructor with few constant elements, or element size not
+	     known at compile time (e.g. deferred-length character).  */
+	  if (n < 4 || !INTEGER_CST_P (TYPE_SIZE_UNIT (type)))
 	    {
 	      /* Scalar values.  */
 	      gfc_init_se (&se, NULL);
diff --git a/gcc/testsuite/gfortran.dg/string_array_constructor_4.f90 b/gcc/testsuite/gfortran.dg/string_array_constructor_4.f90
new file mode 100644
index 00000000000..b5b81f07395
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/string_array_constructor_4.f90
@@ -0,0 +1,59 @@ 
+! { dg-do run }
+! PR fortran/103115 - character array constructor with >= 4 constant elements
+!
+! This used to ICE when the first element is deferred-length character
+! or could lead to wrong results.
+
+program pr103115
+  implicit none
+  integer :: i
+  character(*), parameter :: expect(*) = [ "1","2","3","4","5" ]
+  character(5)            :: abc = "12345"
+  character(5), parameter :: def = "12345"
+  character(:), dimension(:), allocatable :: list
+  character(:), dimension(:), allocatable :: titles
+  titles = ["1"]
+  titles = [ titles&
+            ,"2"&
+            ,"3"&
+            ,"4"&
+            ,"5"&  ! used to ICE
+            ]
+  if (len (titles) /= 1 .or. size (titles) /= 5) stop 1
+  if (any (titles  /= expect))                   stop 2
+  titles = ["1"]
+  titles = [ titles, (char(48+i),i=2,5) ]
+  if (len (titles) /= 1 .or. size (titles) /= 5) stop 3
+  if (any (titles  /= expect))                   stop 4
+  titles = ["1"]
+  titles = [ titles, ("2345"(i:i),i=1,4) ]
+  if (len (titles) /= 1 .or. size (titles) /= 5) stop 5
+  if (any (titles  /= expect))                   stop 6
+  titles = ["1"]
+  titles = [ titles, (def(i:i),i=2,5) ]
+  if (len (titles) /= 1 .or. size (titles) /= 5) stop 7
+  if (any (titles  /= expect))                   stop 8
+  list = [ (char(48+i),i=1,5) ]
+  titles = [ list(1), (char(48+i),i=2,5) ]
+  if (len (titles) /= 1 .or. size (titles) /= 5) stop 9
+  if (any (titles  /= expect))                   stop 10
+  titles = ["1"]
+  titles = [ titles, (abc(i:i),i=2,5) ]
+  if (len (titles) /= 1 .or. size (titles) /= 5) stop 11
+  if (any (titles  /= expect))                   stop 12
+
+  ! with typespec:
+  list = [ (char(48+i),i=1,5) ]
+  titles = [ character(2) :: list(1), (char(48+i),i=2,5) ]
+  if (len (titles) /= 2 .or. size (titles) /= 5) stop 13
+  if (any (titles  /= expect))                   stop 14
+  titles = ["1"]
+  titles = [ character(2) :: titles, (char(48+i),i=2,5) ]
+  if (len (titles) /= 2 .or. size (titles) /= 5) stop 15
+  if (any (titles  /= expect))                   stop 16
+  titles = ["1"]
+  titles = [ character(2) :: titles, (def(i:i),i=2,5) ]
+  if (len (titles) /= 2 .or. size (titles) /= 5) stop 17
+  if (any (titles  /= expect))                   stop 18
+  deallocate (titles, list)
+end
--
2.35.3