https://gcc.gnu.org/g:c93be1606ecf8e0f65b96b67aa023fb456ceb3a3

commit r15-2156-gc93be1606ecf8e0f65b96b67aa023fb456ceb3a3
Author: Harald Anlauf <anl...@gmx.de>
Date:   Thu Jul 18 21:15:48 2024 +0200

    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.

Diff:
---
 gcc/fortran/trans-array.cc                         |  4 +-
 .../gfortran.dg/string_array_constructor_4.f90     | 59 ++++++++++++++++++++++
 2 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index dc3de6c3b149..c93a5f1e7543 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 000000000000..b5b81f07395a
--- /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

Reply via email to