[gcc r12-10631] Fortran: character array constructor with >= 4 constant elements [PR103115]

2024-07-21 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:ecc80e18f05b77a773c6d894871572029d4fc579

commit r12-10631-gecc80e18f05b77a773c6d894871572029d4fc579
Author: Harald Anlauf 
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.

(cherry picked from commit c93be1606ecf8e0f65b96b67aa023fb456ceb3a3)

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 c82b1fa47e59..85c641b55c52 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -2114,7 +2114,9 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, 
tree type,
  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 (, 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 ..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


[gcc r13-8930] Fortran: character array constructor with >= 4 constant elements [PR103115]

2024-07-21 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:ae6d5dc35735168c13f4599e7cf3f32fbb3c06c9

commit r13-8930-gae6d5dc35735168c13f4599e7cf3f32fbb3c06c9
Author: Harald Anlauf 
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.

(cherry picked from commit c93be1606ecf8e0f65b96b67aa023fb456ceb3a3)

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 9557cd14b5e0..4d42cf1131aa 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -2119,7 +2119,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 (, 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 ..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


[gcc r14-10475] Fortran: character array constructor with >= 4 constant elements [PR103115]

2024-07-19 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:ca0fa18adda03faae3464d8f44c215672b71baa5

commit r14-10475-gca0fa18adda03faae3464d8f44c215672b71baa5
Author: Harald Anlauf 
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.

(cherry picked from commit c93be1606ecf8e0f65b96b67aa023fb456ceb3a3)

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 d4b16772de21..16041b629c21 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -2137,7 +2137,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 (, 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 ..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


[gcc r15-2156] Fortran: character array constructor with >= 4 constant elements [PR103115]

2024-07-19 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:c93be1606ecf8e0f65b96b67aa023fb456ceb3a3

commit r15-2156-gc93be1606ecf8e0f65b96b67aa023fb456ceb3a3
Author: Harald Anlauf 
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 (, 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 ..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


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

2024-07-18 Thread Harald Anlauf
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

From 5b264e77b54e211c7781d2c2e5dc324846a774a1 Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
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 (, 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 000..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



Re: [Patch, fortran] PR84868 - [11/12/13/14/15 Regression] ICE in gfc_conv_descriptor_offset, at fortran/trans-array.c:208

2024-07-16 Thread Harald Anlauf

Hi Paul,

Am 16.07.24 um 18:35 schrieb Paul Richard Thomas:

In answer to some of your latest points:




Can we prevent the export of this artificial symbol?




The export of this symbol is needed for interface mapping. Without it, the
original bug would reappear. If such len_trim calls are made outside of
specification expressions, the symbols are not exported as you verify with
either the parse tree dump or direct inspection of the module files from
the testcases.


I was under the impression that an interface that is not visible
at the top level of the module does not need to be exported.
And a contained procedure would satisfy that, or doesn't it?

The ICE I saw is actually a pre-existing issue reported by Gerhard:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100273

Cheers,
Harald



Re: [Patch, fortran] PR84868 - [11/12/13/14/15 Regression] ICE in gfc_conv_descriptor_offset, at fortran/trans-array.c:208

2024-07-15 Thread Harald Anlauf

Am 15.07.24 um 20:27 schrieb Harald Anlauf:

Replying to myself:

Am 15.07.24 um 19:35 schrieb Harald Anlauf:

For '_len_trim_c_k':

Breakpoint 1, gfc_create_module_variable (sym=0x32af2f0)
 at ../../gcc-trunk/gcc/fortran/trans-decl.cc:5515
5515  gcc_assert (sym->ns->proc_name->attr.flavor == FL_MODULE
(gdb) p sym->ns->proc_name->attr.flavor
$9 = FL_PROCEDURE
(gdb) p sym->ns->parent->proc_name->attr.flavor
$10 = FL_PROCEDURE

This is not good.

Can we prevent the export of this artificial symbol?


Like this here (to give an idea, but otherwise untested):

diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index 54ab60b4935..cc6ac7f192e 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -5455,6 +5468,13 @@ gfc_create_module_variable (gfc_symbol * sym)
  && !(sym->attr.flavor == FL_PROCEDURE && sym->attr.proc_pointer))
  return;

+  /* Do not output artificially created parameters.  */
+  if (sym->attr.flavor == FL_PARAMETER
+  && sym->name[0] == '_'
+  && sym->ns->proc_name->attr.flavor == FL_PROCEDURE
+  && sym->ns->parent->proc_name->attr.flavor == FL_PROCEDURE)
+    return;
+
    if ((sym->attr.in_common || sym->attr.in_equivalence) &&
sym->backend_decl)
  {
    decl = sym->backend_decl;

Maybe one might mark the symbol already at creation time and
detect this mark here, too.


JFTR: this regtests cleanly here.

While looking over the last version of the patch again,
the following should be corrected:

@@ -4637,6 +4637,75 @@ gfc_simplify_len_trim (gfc_expr *e, gfc_expr *kind)
   if (k == -1)
 return _bad_expr;

+  if (e->expr_type == EXPR_VARIABLE
+  && e->ts.type == BT_CHARACTER
+  && e->symtree->n.sym->attr.flavor == FL_PARAMETER
+  && e->ref && e->ref->type == REF_ARRAY
+  && e->ref->u.ar.dimen_type[0] == DIMEN_ELEMENT
+  && e->symtree->n.sym->value)
+{
+  char name[2*GFC_MAX_SYMBOL_LEN + 10];
^^ this has to be 12 now

+  gfc_namespace *ns = e->symtree->n.sym->ns;
+  gfc_symtree *st;
+  gfc_expr *expr;
+  gfc_expr *p;
+  gfc_constructor *c;
+  int cnt = 0;
+
+  sprintf (name, "_len_trim_%s_%s", e->symtree->n.sym->name,
ns->proc_name->name);

Cheers,
Harald



[gcc r14-10423] Fortran: improve attribute conflict checking [PR93635]

2024-07-15 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:71ec9ed7a7353f66d55b034a45336bf43a026b1d

commit r14-10423-g71ec9ed7a7353f66d55b034a45336bf43a026b1d
Author: Harald Anlauf 
Date:   Thu May 23 21:13:00 2024 +0200

Fortran: improve attribute conflict checking [PR93635]

gcc/fortran/ChangeLog:

PR fortran/93635
* symbol.cc (conflict_std): Helper function for reporting attribute
conflicts depending on the Fortran standard version.
(conf_std): Helper macro for checking standard-dependent conflicts.
(gfc_check_conflict): Use it.

gcc/testsuite/ChangeLog:

PR fortran/93635
* gfortran.dg/c-interop/c1255-2.f90: Adjust pattern.
* gfortran.dg/pr87907.f90: Likewise.
* gfortran.dg/pr93635.f90: New test.

Co-authored-by: Steven G. Kargl 
(cherry picked from commit 9561cf550a66a89e7c8d31202a03c4fddf82a3f2)

Diff:
---
 gcc/fortran/symbol.cc   | 63 +++--
 gcc/testsuite/gfortran.dg/c-interop/c1255-2.f90 |  4 +-
 gcc/testsuite/gfortran.dg/pr87907.f90   |  8 ++--
 gcc/testsuite/gfortran.dg/pr93635.f90   | 19 
 4 files changed, 54 insertions(+), 40 deletions(-)

diff --git a/gcc/fortran/symbol.cc b/gcc/fortran/symbol.cc
index 0a1646def678..5db3c887127b 100644
--- a/gcc/fortran/symbol.cc
+++ b/gcc/fortran/symbol.cc
@@ -407,18 +407,36 @@ gfc_check_function_type (gfc_namespace *ns)
 
 / Symbol attribute stuff */
 
+/* Older standards produced conflicts for some attributes that are allowed
+   in newer standards.  Check for the conflict and issue an error depending
+   on the standard in play.  */
+
+static bool
+conflict_std (int standard, const char *a1, const char *a2, const char *name,
+ locus *where)
+{
+  if (name == NULL)
+{
+  return gfc_notify_std (standard, "%s attribute conflicts "
+"with %s attribute at %L", a1, a2,
+where);
+}
+  else
+{
+  return gfc_notify_std (standard, "%s attribute conflicts "
+"with %s attribute in %qs at %L",
+a1, a2, name, where);
+}
+}
+
 /* This is a generic conflict-checker.  We do this to avoid having a
single conflict in two places.  */
 
 #define conf(a, b) if (attr->a && attr->b) { a1 = a; a2 = b; goto conflict; }
 #define conf2(a) if (attr->a) { a2 = a; goto conflict; }
-#define conf_std(a, b, std) if (attr->a && attr->b)\
-  {\
-a1 = a;\
-a2 = b;\
-standard = std;\
-goto conflict_std;\
-  }
+#define conf_std(a, b, std) if (attr->a && attr->b \
+   && !conflict_std (std, a, b, name, where)) \
+   return false;
 
 bool
 gfc_check_conflict (symbol_attribute *attr, const char *name, locus *where)
@@ -451,7 +469,6 @@ gfc_check_conflict (symbol_attribute *attr, const char 
*name, locus *where)
"OACC DECLARE DEVICE_RESIDENT";
 
   const char *a1, *a2;
-  int standard;
 
   if (attr->artificial)
 return true;
@@ -460,20 +477,10 @@ gfc_check_conflict (symbol_attribute *attr, const char 
*name, locus *where)
 where = _current_locus;
 
   if (attr->pointer && attr->intent != INTENT_UNKNOWN)
-{
-  a1 = pointer;
-  a2 = intent;
-  standard = GFC_STD_F2003;
-  goto conflict_std;
-}
+conf_std (pointer, intent, GFC_STD_F2003);
 
-  if (attr->in_namelist && (attr->allocatable || attr->pointer))
-{
-  a1 = in_namelist;
-  a2 = attr->allocatable ? allocatable : pointer;
-  standard = GFC_STD_F2003;
-  goto conflict_std;
-}
+  conf_std (in_namelist, allocatable, GFC_STD_F2003);
+  conf_std (in_namelist, pointer, GFC_STD_F2003);
 
   /* Check for attributes not allowed in a BLOCK DATA.  */
   if (gfc_current_state () == COMP_BLOCK_DATA)
@@ -922,20 +929,6 @@ conflict:
   a1, a2, name, where);
 
   return false;
-
-conflict_std:
-  if (name == NULL)
-{
-  return gfc_notify_std (standard, "%s attribute conflicts "
- "with %s attribute at %L", a1, a2,
- where);
-}
-  else
-{
-  return gfc_notify_std (standard, "%s attribute conflicts "
-"with %s attribute in %qs at %L",
- a1, a2, name, where);
-}
 }
 
 #undef conf
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c1255-2.f90 
b/gcc/testsuite/gfortran.dg/c-interop/c1255-2.f90
index 0e5505a01835..feed2e7645fd 100644

Re: Lower zeroing array assignment to memset for allocatable arrays

2024-07-15 Thread Harald Anlauf

Hi Prathamesh!

Am 15.07.24 um 15:07 schrieb Prathamesh Kulkarni:

-Original Message-
From: Harald Anlauf 
I agree that it is reasonable to defer the handling of arrays as
components of derived types, and recommend to do the following:

- replace "&& gfc_is_simply_contiguous (expr, true, false))" in your
last patch by "&& gfc_is_simply_contiguous (expr, false, false))",
as that would also allow to treat

z(:,::1,:) = 0

as contiguous if z is allocatable or a contiguous pointer.

- open a PR in bugzilla to track the missed-optimization for
the cases we discussed here, and link the discussion in the ML.

Done: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115935


Your patch then will be OK for mainline.

Thanks, does the attached version look OK ?
Bootstrapped+tested on aarch64-linux-gnu, x86_64-linux-gnu.


This is now OK.

Thanks for the patch!

Harald


Thanks,
Prathamesh





Re: [Patch, fortran] PR84868 - [11/12/13/14/15 Regression] ICE in gfc_conv_descriptor_offset, at fortran/trans-array.c:208

2024-07-15 Thread Harald Anlauf

Replying to myself:

Am 15.07.24 um 19:35 schrieb Harald Anlauf:

For '_len_trim_c_k':

Breakpoint 1, gfc_create_module_variable (sym=0x32af2f0)
     at ../../gcc-trunk/gcc/fortran/trans-decl.cc:5515
5515  gcc_assert (sym->ns->proc_name->attr.flavor == FL_MODULE
(gdb) p sym->ns->proc_name->attr.flavor
$9 = FL_PROCEDURE
(gdb) p sym->ns->parent->proc_name->attr.flavor
$10 = FL_PROCEDURE

This is not good.

Can we prevent the export of this artificial symbol?


Like this here (to give an idea, but otherwise untested):

diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index 54ab60b4935..cc6ac7f192e 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -5455,6 +5468,13 @@ gfc_create_module_variable (gfc_symbol * sym)
&& !(sym->attr.flavor == FL_PROCEDURE && sym->attr.proc_pointer))
 return;

+  /* Do not output artificially created parameters.  */
+  if (sym->attr.flavor == FL_PARAMETER
+  && sym->name[0] == '_'
+  && sym->ns->proc_name->attr.flavor == FL_PROCEDURE
+  && sym->ns->parent->proc_name->attr.flavor == FL_PROCEDURE)
+return;
+
   if ((sym->attr.in_common || sym->attr.in_equivalence) && 
sym->backend_decl)

 {
   decl = sym->backend_decl;

Maybe one might mark the symbol already at creation time and
detect this mark here, too.

Harald




Re: [Patch, fortran] PR84868 - [11/12/13/14/15 Regression] ICE in gfc_conv_descriptor_offset, at fortran/trans-array.c:208

2024-07-15 Thread Harald Anlauf

Hi Paul, Andre,

at the risk of getting stoned to death, here's an example:

module m
  implicit none
  integer :: c
contains
  function f(n) result(z)
integer,  intent(in) :: n
character, parameter :: c(3) = ['x', 'y', 'z']
character(len_trim(c(n)))  :: z
z = c(n)
  end
  function h(n) result(z)
integer,  intent(in) :: n
character, parameter :: c(3,3) = 'x'
character(len_trim(c(n,n)))  :: z
z = c(n,n)
  contains
function k(n) result(z)
  integer,  intent(in) :: n
  character, parameter :: c(3) = ['*', '+', '-']
  character(len_trim(c(n)))  :: z
  z = c(n)
end
  end
end
program p
  use m
  implicit none
  print *, f(2)
  print *, h(1)
end

% gfc-15 pr84868-z0.f90 -fdump-fortran-original

Namespace: A-Z: (UNKNOWN 0)
procedure name = m
  symtree: '@0'  || symbol: '_len_trim_c_h' from namespace 'h'
  symtree: '@1'  || symbol: '_len_trim_c_k' from namespace 'k'
  symtree: '@2'  || symbol: '_len_trim_c_f' from namespace 'f'
  symtree: 'c'   || symbol: 'c'
[...]
f951: internal compiler error: in gfc_create_module_variable, at
fortran/trans-decl.cc:5515
0x2438776 internal_error(char const*, ...)
../../gcc-trunk/gcc/diagnostic-global-context.cc:491
0x96df24 fancy_abort(char const*, int, char const*)
../../gcc-trunk/gcc/diagnostic.cc:1725
0x752d8a gfc_create_module_variable
../../gcc-trunk/gcc/fortran/trans-decl.cc:5515
0x752d8a gfc_create_module_variable
../../gcc-trunk/gcc/fortran/trans-decl.cc:5428
[...]

So you are very close!

My example is likely very artificial, but nevertheless legal.

We hit the following assert:

  gcc_assert (sym->ns->proc_name->attr.flavor == FL_MODULE
  || (sym->ns->parent->proc_name->attr.flavor == FL_MODULE
  && sym->fn_result_spec));

For '_len_trim_c_k':

Breakpoint 1, gfc_create_module_variable (sym=0x32af2f0)
at ../../gcc-trunk/gcc/fortran/trans-decl.cc:5515
5515  gcc_assert (sym->ns->proc_name->attr.flavor == FL_MODULE
(gdb) p sym->ns->proc_name->attr.flavor
$9 = FL_PROCEDURE
(gdb) p sym->ns->parent->proc_name->attr.flavor
$10 = FL_PROCEDURE

This is not good.

Can we prevent the export of this artificial symbol?

Otherwise the patch is fine.

Thanks,
Harald


Am 15.07.24 um 12:23 schrieb Andre Vehreschild:

Hi Paul,

I tried to "break" your patch, but I failed. (I tried having same function in
both modules with identical signature; but I do not get a symbol collision). So
to me the patch looks fine now. But you may want to give Harald some time for a
look.

Thanks for the patch,
Andre

On Mon, 15 Jul 2024 10:41:45 +0100
Paul Richard Thomas  wrote:


I've done it again! Patch duly added.

Paul

On Mon, 15 Jul 2024 at 09:21, Paul Richard Thomas <
paul.richard.tho...@gmail.com> wrote:


Hi Harald,

Thank you for the review and for the testing to destruction. Both issues
are fixed in the attached patch. Note the new function 'h', which both
tests that the namespace confusion is fixed and that the elemental-ness of
LEN_TRIM is respected.

The patch continues to regtest OK. If I don't receive anymore
comments/corrections, I will commit tomorrow morning.

Regards

Paul


On Sun, 14 Jul 2024 at 19:50, Harald Anlauf  wrote:


Hi Paul,

at first sight the patch seems to be the right approach, but
it breaks for the following two variations:

(1) LEN_TRIM is elemental, but the following is erroneously rejected:

function g(n) result(z)
  integer,  intent(in) :: n
  character, parameter :: d(3,3) = 'x'
  character(len_trim(d(n,n))) :: z
  z = d(n,n)
end

This is fixed here by commenting/removing the line

expr->rank = 1;

as the result shall have the same shape as the argument.
Can you check?

(2) The handling of namespaces is problematic: using the same name
for a parameter within procedures in the same scope generates another
ICE.  The following testcase demonstrates this:

module m
implicit none
integer :: c
contains
function f(n) result(z)
  integer,  intent(in) :: n
  character, parameter :: c(3) = ['x', 'y', 'z']
  character(len_trim(c(n)))  :: z
  z = c(n)
end
function h(n) result(z)
  integer,  intent(in) :: n
  character, parameter :: c(3,3) = 'x'
  character(len_trim(c(n,n)))  :: z
  z = c(n,n)
end
end
program p
use m
implicit none
print *, f(2)
print *, h(1)
end

I get:

pr84868-z0.f90:22:15:

 22 |   print *, h(1)
|   1
internal compiler error: in gfc_conv_descriptor_stride_get, at
fortran/trans-array.cc:483
0x243e156 internal_error(char const*, ...)
  ../../gcc-trunk/gcc/diagnostic-global-context.cc:491
0x96dd70 fancy_abort(char const*, int, char const*)
  ../../gcc-trunk/gcc/diagnostic.cc:1725
0x749d68 gfc_conv_descriptor_stride_get(tree_node*, tree_node*)
  ../../gcc-trunk/gcc/fortran

Re: [Patch, fortran] PR84868 - [11/12/13/14/15 Regression] ICE in gfc_conv_descriptor_offset, at fortran/trans-array.c:208

2024-07-14 Thread Harald Anlauf

Hi Paul,

at first sight the patch seems to be the right approach, but
it breaks for the following two variations:

(1) LEN_TRIM is elemental, but the following is erroneously rejected:

  function g(n) result(z)
integer,  intent(in) :: n
character, parameter :: d(3,3) = 'x'
character(len_trim(d(n,n))) :: z
z = d(n,n)
  end

This is fixed here by commenting/removing the line

  expr->rank = 1;

as the result shall have the same shape as the argument.
Can you check?

(2) The handling of namespaces is problematic: using the same name
for a parameter within procedures in the same scope generates another
ICE.  The following testcase demonstrates this:

module m
  implicit none
  integer :: c
contains
  function f(n) result(z)
integer,  intent(in) :: n
character, parameter :: c(3) = ['x', 'y', 'z']
character(len_trim(c(n)))  :: z
z = c(n)
  end
  function h(n) result(z)
integer,  intent(in) :: n
character, parameter :: c(3,3) = 'x'
character(len_trim(c(n,n)))  :: z
z = c(n,n)
  end
end
program p
  use m
  implicit none
  print *, f(2)
  print *, h(1)
end

I get:

pr84868-z0.f90:22:15:

   22 |   print *, h(1)
  |   1
internal compiler error: in gfc_conv_descriptor_stride_get, at
fortran/trans-array.cc:483
0x243e156 internal_error(char const*, ...)
../../gcc-trunk/gcc/diagnostic-global-context.cc:491
0x96dd70 fancy_abort(char const*, int, char const*)
../../gcc-trunk/gcc/diagnostic.cc:1725
0x749d68 gfc_conv_descriptor_stride_get(tree_node*, tree_node*)
../../gcc-trunk/gcc/fortran/trans-array.cc:483
[rest of traceback elided]

Renaming the parameter array in h solves the problem.

Am 13.07.24 um 17:57 schrieb Paul Richard Thomas:

Hi All,

Harald has pointed out that I attached the ChangeLog twice and the patch
not at all :-(

Please find the patch duly attached.

Paul


On Sat, 13 Jul 2024 at 10:58, Paul Richard Thomas <
paul.richard.tho...@gmail.com> wrote:


Hi All,

After messing around with argument mapping, where I found and fixed
another bug, I realised that the problem lay with simplification of
len_trim with an argument that is the element of a parameter array. The fix
was then a straightforward lift of existing code in expr.cc. The mapping
bug is also fixed by supplying the se string length when building character
typespecs.

Regtests just fine. OK for mainline? I believe that this is safe for
backporting to 14-branch before the 14.2 release - thoughts?


If you manage to correct/fix the above issues, I am fine with
backporting, as this appears a very reasonable fix.

Thanks,
Harald


Regards

Paul







Re: Lower zeroing array assignment to memset for allocatable arrays

2024-07-12 Thread Harald Anlauf

Hi Prathamesh,

Am 12.07.24 um 15:31 schrieb Prathamesh Kulkarni:

It seems that component references are not currently handled even for static 
size arrays ?
For eg:
subroutine test_dt (dt, y)
implicit none
real :: y (10, 20, 30)
type t
   real :: x(10, 20, 30)
end type t
type(t) :: dt
y = 0
dt% x = 0
end subroutine

With trunk, it generates memset for 'y' but not for dt%x.
That happens because copyable_array_p returns false for dt%x,
because expr->ref->next is non NULL:

   /* First check it's an array.  */
   if (expr->rank < 1 || !expr->ref || expr->ref->next)
 return false;

and gfc_full_array_ref_p(expr) bails out if expr->ref->type != REF_ARRAY.


Indeed that check (as is) prevents the use of component refs.
(I just tried to modify the this part to cycle thru the refs,
but then I get regressions in the testsuite for some of the
coarray tests.  Furthermore, gfc_trans_zero_assign would
need further changes to handle even the constant shapes
from above.)


Looking thru git history, it seems both the checks were added in 18eaa2c0cd20 
to fix PR33370.
(Even after removing these checks, the previous patch bails out from 
gfc_trans_zero_assign because
GFC_DESCRIPTOR_TYPE_P (type) returns false for component ref and ends up 
returning NULL_TREE)
I am working on extending the patch to handle component refs for statically 
sized as well as allocatable arrays.

Since it looks like a bigger change and an extension to current functionality, 
will it be OK to commit the previous patch as-is (if it looks correct)
and address component refs in follow up one ?


I agree that it is reasonable to defer the handling of arrays as
components of derived types, and recommend to do the following:

- replace "&& gfc_is_simply_contiguous (expr, true, false))" in your
  last patch by "&& gfc_is_simply_contiguous (expr, false, false))",
  as that would also allow to treat

  z(:,::1,:) = 0

  as contiguous if z is allocatable or a contiguous pointer.

- open a PR in bugzilla to track the missed-optimization for
  the cases we discussed here, and link the discussion in the ML.

Your patch then will be OK for mainline.

Thanks,
Harald


Thanks,
Prathamesh


Thanks,
Harald


Bootstrapped+tested on aarch64-linux-gnu.
Does the attached patch look OK ?

Signed-off-by: Prathamesh Kulkarni 

Thanks,
Prathamesh


Thanks,
Harald



Signed-off-by: Prathamesh Kulkarni 

Thanks,
Prathamesh








Re: [PATCH] fortran: Factor the evaluation of MINLOCK/MAXLOC's BACK argument

2024-07-11 Thread Harald Anlauf

Hi Mikael,

Am 11.07.24 um 21:55 schrieb Mikael Morin:

From: Mikael Morin 

Hello,

I discovered this while testing the inline MINLOC/MAXLOC (aka PR90608) patches.
Regression tested on x86_64-linux.
OK for master?


this is a nice finding!  (NAG seems to fail on the cases with
array size 0, while Intel gets it right.)

The commit message promises to cover all variations ("with/out NANs"?)
but I fail to see these.  Were these removed in the submission?

Otherwise the patch looks pretty simple and is OK for mainline.
But do not forget to s/MINLOCK/MINLOC/ in the summary.

Thanks for the patch!

Harald


-- 8< --

Move the evaluation of the BACK argument out of the loop in the inline code
generated for MINLOC or MAXLOC.  For that, add a new (scalar) element
associated with BACK to the scalarization loop chain, evaluate the argument
with the context of that element, and let the scalarizer do its job.

The problem was not only a missed optimisation, but also a wrong code
one in the cases where the expression associated with BACK is not free of
side-effects, making multiple evaluations observable.

The new tests check the evaluation count of the BACK argument, and try to
cover all the variations (with/out NANs, constant or unknown shape, absent
or scalar or array MASK) supported by the inline implementation of the
functions.  Care has been taken to not check the case of a constant .FALSE.
MASK, for which the evaluation of BACK can be elided.

gcc/fortran/ChangeLog:

* trans-intrinsic.cc (gfc_conv_intrinsic_minmaxloc): Create a new
scalar scalarization chain element if BACK is present.  Add it to
the loop.  Set the scalarization chain before evaluating the
argument.

gcc/testsuite/ChangeLog:

* gfortran.dg/maxloc_5.f90: New test.
* gfortran.dg/minloc_5.f90: New test.
---
  gcc/fortran/trans-intrinsic.cc |  10 +
  gcc/testsuite/gfortran.dg/maxloc_5.f90 | 257 +
  gcc/testsuite/gfortran.dg/minloc_5.f90 | 257 +
  3 files changed, 524 insertions(+)
  create mode 100644 gcc/testsuite/gfortran.dg/maxloc_5.f90
  create mode 100644 gcc/testsuite/gfortran.dg/minloc_5.f90

diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 5ea10e84060..cadbd177452 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -5325,6 +5325,7 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * 
expr, enum tree_code op)
gfc_actual_arglist *actual;
gfc_ss *arrayss;
gfc_ss *maskss;
+  gfc_ss *backss;
gfc_se arrayse;
gfc_se maskse;
gfc_expr *arrayexpr;
@@ -5390,6 +5391,11 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * 
expr, enum tree_code op)
  && maskexpr->symtree->n.sym->attr.dummy
  && maskexpr->symtree->n.sym->attr.optional;
backexpr = actual->next->next->expr;
+  if (backexpr)
+backss = gfc_get_scalar_ss (gfc_ss_terminator, backexpr);
+  else
+backss = nullptr;
+
nonempty = NULL;
if (maskexpr && maskexpr->rank != 0)
  {
@@ -5449,6 +5455,9 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * 
expr, enum tree_code op)
if (maskss)
  gfc_add_ss_to_loop (, maskss);

+  if (backss)
+gfc_add_ss_to_loop (, backss);
+
gfc_add_ss_to_loop (, arrayss);

/* Initialize the loop.  */
@@ -5535,6 +5544,7 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * 
expr, enum tree_code op)
gfc_add_block_to_block (, );

gfc_init_se (, NULL);
+  backse.ss = backss;
gfc_conv_expr_val (, backexpr);
gfc_add_block_to_block (, );

diff --git a/gcc/testsuite/gfortran.dg/maxloc_5.f90 
b/gcc/testsuite/gfortran.dg/maxloc_5.f90
new file mode 100644
index 000..5d722450c8f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/maxloc_5.f90
@@ -0,0 +1,257 @@
+! { dg-do run }
+!
+! Check that the evaluation of MAXLOC's BACK argument is made only once
+! before the scalarisation loops.
+
+program p
+  implicit none
+  integer, parameter :: data10(*) = (/ 7, 4, 7, 6, 6, 4, 6, 3, 9, 8 /)
+  logical, parameter :: mask10(*) = (/ .false., .true., .false., &
+   .false., .true., .true.,  &
+   .true. , .true., .false., &
+   .false. /)
+  integer :: calls_count = 0
+  call check_int_const_shape
+  call check_int_const_shape_scalar_mask
+  call check_int_const_shape_array_mask
+  call check_int_const_shape_optional_mask_present
+  call check_int_const_shape_optional_mask_absent
+  call check_int_const_shape_empty
+  call check_int_alloc
+  call check_int_alloc_scalar_mask
+  call check_int_alloc_array_mask
+  call check_int_alloc_empty
+  call check_real_const_shape
+  call check_real_const_shape_scalar_mask
+  call check_real_const_shape_array_mask
+  call check_real_const_shape_optional_mask_present
+  call check_real_const_shape_optional_mask_absent
+  call check_real_const_shape_empty
+  call check_real_alloc

Re: Lower zeroing array assignment to memset for allocatable arrays

2024-07-11 Thread Harald Anlauf

Hi Prathamesh!

Am 11.07.24 um 12:16 schrieb Prathamesh Kulkarni:




-Original Message-
From: Harald Anlauf 
Sent: Thursday, July 11, 2024 12:53 AM
To: Prathamesh Kulkarni ; gcc-
patc...@gcc.gnu.org; fort...@gcc.gnu.org
Subject: Re: Lower zeroing array assignment to memset for allocatable
arrays

External email: Use caution opening links or attachments


Hi Prathamesh,

Am 10.07.24 um 13:22 schrieb Prathamesh Kulkarni:

Hi,
The attached patch lowers zeroing array assignment to memset for

allocatable arrays.


For example:
subroutine test(z, n)
  implicit none
  integer :: n
  real(4), allocatable :: z(:,:,:)

  allocate(z(n, 8192, 2048))
  z = 0
end subroutine

results in following call to memset instead of 3 nested loops for z

= 0:

  (void) __builtin_memset ((void *) z->data, 0, (unsigned long)
MAX_EXPR dim[0].ubound - z->dim[0].lbound, -1> + 1) *
(MAX_EXPR dim[1].ubound - z->dim[1].lbound, -1> + 1)) *

(MAX_EXPR

dim[2].ubound - z->dim[2].lbound, -1> + 1)) * 4));

The patch significantly improves speedup for an internal Fortran

application on AArch64 -mcpu=grace (and potentially on other AArch64
cores too).

Bootstrapped+tested on aarch64-linux-gnu.
Does the patch look OK to commit ?


no, it is NOT ok.

Consider:

subroutine test0 (n, z)
implicit none
integer :: n
real, pointer :: z(:,:,:) ! need not be contiguous!
z = 0
end subroutine

After your patch this also generates a memset, but this cannot be true
in general.  One would need to have a test on contiguity of the array
before memset can be used.

In principle this is a nice idea, and IIRC there exists a very old PR
on this (by Thomas König?).  So it might be worth pursuing.

Hi Harald,
Thanks for the suggestions!
The attached patch checks gfc_is_simply_contiguous(expr, true, false) before 
lowering to memset,
which avoids generating memset for your example above.


This is much better, as it avoids generating false memsets where
it should not.  However, you now miss cases where the array is a
component reference, as in:

subroutine test_dt (dt)
  implicit none
  type t
 real, allocatable :: x(:,:,:) ! contiguous!
 real, pointer, contiguous :: y(:,:,:) ! contiguous!
 real, pointer :: z(:,:,:) ! need not be contiguous!
  end type t
  type(t) :: dt
  dt% x = 0  ! memset possible!
  dt% y = 0  ! memset possible!
  dt% z = 0  ! memset NOT possible!
end subroutine

You'll need to cycle through the component references and
apply the check for contiguity to the ultimate component,
not the top level.

Can you have another look?

Thanks,
Harald


Bootstrapped+tested on aarch64-linux-gnu.
Does the attached patch look OK ?

Signed-off-by: Prathamesh Kulkarni 

Thanks,
Prathamesh


Thanks,
Harald



Signed-off-by: Prathamesh Kulkarni 

Thanks,
Prathamesh







Re: Lower zeroing array assignment to memset for allocatable arrays

2024-07-10 Thread Harald Anlauf

Hi Prathamesh,

Am 10.07.24 um 13:22 schrieb Prathamesh Kulkarni:

Hi,
The attached patch lowers zeroing array assignment to memset for allocatable 
arrays.

For example:
subroutine test(z, n)
 implicit none
 integer :: n
 real(4), allocatable :: z(:,:,:)

 allocate(z(n, 8192, 2048))
 z = 0
end subroutine

results in following call to memset instead of 3 nested loops for z = 0:
 (void) __builtin_memset ((void *) z->data, 0, (unsigned long) MAX_EXPR dim[0].ubound - 
z->dim[0].lbound, -1> + 1) * (MAX_EXPR dim[1].ubound - z->dim[1].lbound, -1> + 1)) * (MAX_EXPR 
dim[2].ubound - z->dim[2].lbound, -1> + 1)) * 4));

The patch significantly improves speedup for an internal Fortran application on 
AArch64 -mcpu=grace (and potentially on other AArch64 cores too).
Bootstrapped+tested on aarch64-linux-gnu.
Does the patch look OK to commit ?


no, it is NOT ok.

Consider:

subroutine test0 (n, z)
  implicit none
  integer :: n
  real, pointer :: z(:,:,:) ! need not be contiguous!
  z = 0
end subroutine

After your patch this also generates a memset, but this cannot be true
in general.  One would need to have a test on contiguity of the array
before memset can be used.

In principle this is a nice idea, and IIRC there exists a very
old PR on this (by Thomas König?).  So it might be worth
pursuing.

Thanks,
Harald



Signed-off-by: Prathamesh Kulkarni 

Thanks,
Prathamesh




Re: [Fortran, Patch, PR 96992, V4] Fix Class arrays of different ranks are rejected as storage association argument

2024-07-10 Thread Harald Anlauf

Hi Andre,

Am 10.07.24 um 10:45 schrieb Andre Vehreschild:

Hi Harald,

thanks for the review. I totally agree, that this patch has gotten bigger than
I expected (and wanted). But things are as they are.

About the coding style: I have worked in so many projects, that I consider a
consistent coding style luxury. I esp. do not have my own one anymore. The
formating you are seeing in my patches is the result of clang-format with the
provided parameter file in contrib/clang-format. I was happy to have a tool
to do the formatting, that I could integrate into my IDE, because previously it
was hard to mimic the GNU style. I try to get to the GNU style as good as
possible, where I consider clang-format doing garbage.

I see that clang-format has a "very specific opinion" on how to format the
lines you mentioned, but it will "correct" them any time I change them and
touch them later. I now have forbidden clang-format to touch the code lines,
but this means to add formatter specific comments. Is this ok?


yes, this is much better now!  Thanks.

(I entirely rely on Emacs' formatting when working with C.  Sometimes
the indentation at first may appear unexpected, but in most of these
cases I find that it helps to just use explicit parentheses to convince
Emacs.  This is documented.)


About the assumed size arrays, that was a small change and is added now.


Great!


Note, the runtime part of the patch (pr96992_3p1.patch) did not change and is
therefore not updated.

Regtests ok on x86_64-pc-linux-gnu/Fedora 39. Ok for mainline?


Yes, this is OK now.

Thanks for the patch and your patience ;-)

Harald



Regards,
Andre

On Fri, 5 Jul 2024 22:10:16 +0200
Harald Anlauf  wrote:


Hi Andre,

Am 03.07.24 um 12:58 schrieb Andre Vehreschild:

Hi Harald,

I am sorry for the long delay, but fixing the negative stride lead from one
issue to the next. I finally got a version that does not regress. Please
have a look.

This patch has two parts:
1. The runtime library part in pr96992_3p1.patch and
2. the compiler changes in pr96992_3p2.patch.

In my branch also the two patches from Paul for pr59104 and pr102689 are
living, which might lead to small shifts during application of the patches.

NOTE, this patch adds internal packing and unpacking of class arrays
similar to the regular pack and unpack. I think this is necessary, because
the regular un-/pack does not use the vptr's _copy routine for moving data
and therefore may produce bugs.

The un-/pack_class routines are yet only used for converting a derived type
array to a class array. Extending their use when a UN-/PACK() is applied on
a class array is still to be done (as part of another PR).

Regtests fine on x86_64-pc-linux-gnu/ Fedora 39.


this is a really huge patch to review, and I am not sure that I can do
this without help from others.  Paul?  Anybody else?

As far as I can tell for now:

- pr96992_3p1.patch (the libgfortran part) looks good to me.

- git had some whitespace issues with pr96992_3p2.patch as attached,
but I could fix that locally and do some testing parallel to reading.

A few advance comments on the latter patch:

- my understanding is that the PR at the end of a summary line should be
like in:

Fortran: Fix rejecting class arrays of different ranks as storage
association argument [PR96992]

I was told that this helps people explicitly scanning for the PR
number in that place.

- some rewrites of logical conditions change the coding style from
what it recommended GNU coding style, and I find the more compact
way used in some places harder to grok (but that may be just me).
Example:

@@ -8850,20 +8857,24 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr
* expr, bool g77,
 /* There is no need to pack and unpack the array, if it is contiguous
and not a deferred- or assumed-shape array, or if it is simply
contiguous.  */
-  no_pack = ((sym && sym->as
- && !sym->attr.pointer
- && sym->as->type != AS_DEFERRED
- && sym->as->type != AS_ASSUMED_RANK
- && sym->as->type != AS_ASSUMED_SHAPE)
- ||
-(ref && ref->u.ar.as
- && ref->u.ar.as->type != AS_DEFERRED
+  no_pack = false;
+  gfc_array_spec *as;
+  if (sym)
+{
+  symbol_attribute *attr
+   = &(IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->attr : sym->attr);
+  as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
+  no_pack
+   = (as && !attr->pointer && as->type != AS_DEFERRED
+  && as->type != AS_ASSUMED_RANK && as->type != AS_ASSUMED_SHAPE);
+}
+  if (ref && ref->u.ar.as)
+no_pack = no_pack
+ || (ref->u.ar.as->type != AS_DEFERRED
  && ref->u.ar.as->type !

[gcc r14-10387] Fortran: fix associate with assumed-length character array [PR115700]

2024-07-07 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:36ca07f0a95c00cc985fc06e46df4028e6f2b77e

commit r14-10387-g36ca07f0a95c00cc985fc06e46df4028e6f2b77e
Author: Harald Anlauf 
Date:   Tue Jul 2 21:26:05 2024 +0200

Fortran: fix associate with assumed-length character array [PR115700]

gcc/fortran/ChangeLog:

PR fortran/115700
* trans-stmt.cc (trans_associate_var): When the associate target
is an array-valued character variable, the length is known at entry
of the associate block.  Move setting of string length of the
selector to the initialization part of the block.

gcc/testsuite/ChangeLog:

PR fortran/115700
* gfortran.dg/associate_69.f90: New test.

(cherry picked from commit 7b7f203472d07a05d959a29638c7c95d98bf0c1c)

Diff:
---
 gcc/fortran/trans-stmt.cc  | 18 
 gcc/testsuite/gfortran.dg/associate_69.f90 | 33 ++
 2 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 1fd75c6a37c..59237b8cdfb 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -1911,6 +1911,8 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block 
*block)
   gfc_se se;
   tree desc;
   bool cst_array_ctor;
+  stmtblock_t init;
+  gfc_init_block ();
 
   desc = sym->backend_decl;
   cst_array_ctor = e->expr_type == EXPR_ARRAY
@@ -1935,10 +1937,17 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block 
*block)
  && !sym->attr.select_type_temporary
  && sym->ts.u.cl->backend_decl
  && VAR_P (sym->ts.u.cl->backend_decl)
+ && se.string_length
  && se.string_length != sym->ts.u.cl->backend_decl)
-   gfc_add_modify (, sym->ts.u.cl->backend_decl,
- fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl),
-   se.string_length));
+   {
+ /* When the target is a variable, its length is already known.  */
+ tree len = fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl),
+  se.string_length);
+ if (e->expr_type == EXPR_VARIABLE)
+   gfc_add_modify (, sym->ts.u.cl->backend_decl, len);
+ else
+   gfc_add_modify (, sym->ts.u.cl->backend_decl, len);
+   }
 
   /* If we didn't already do the pointer assignment, set associate-name
 descriptor to the one generated for the temporary.  */
@@ -1978,7 +1987,8 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block 
*block)
}
 
   /* Done, register stuff as init / cleanup code.  */
-  gfc_add_init_cleanup (block, gfc_finish_block (),
+  gfc_add_block_to_block (, );
+  gfc_add_init_cleanup (block, gfc_finish_block (),
gfc_finish_block ());
 }
 
diff --git a/gcc/testsuite/gfortran.dg/associate_69.f90 
b/gcc/testsuite/gfortran.dg/associate_69.f90
new file mode 100644
index 000..28f488bb274
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/associate_69.f90
@@ -0,0 +1,33 @@
+! { dg-do compile }
+! { dg-options "-Og -Wuninitialized -Wmaybe-uninitialized 
-fdump-tree-optimized" }
+!
+! PR fortran/115700 - Bogus warning for associate with assumed-length 
character array
+!
+subroutine mvce(x)
+  implicit none
+  character(len=*), dimension(:), intent(in)  :: x
+
+  associate (tmp1 => x)
+if (len (tmp1) /= len (x)) stop 1
+  end associate
+
+  associate (tmp2 => x(1:))
+if (len (tmp2) /= len (x)) stop 2
+  end associate
+
+  associate (tmp3 => x(1:)(:))
+if (len (tmp3) /= len (x)) stop 3
+  end associate
+
+! The following associate blocks still produce bogus warnings:
+
+! associate (tmp4 => x(:)(1:))
+!   if (len (tmp4) /= len (x)) stop 4
+! end associate
+!
+! associate (tmp5 => x(1:)(1:))
+!   if (len (tmp5) /= len (x)) stop 5
+! end associate
+end
+
+! { dg-final { scan-tree-dump-not " \\.tmp" "optimized" } }


Re: [Fortran, Patch, PR 96992, V3] Fix Class arrays of different ranks are rejected as storage association argument

2024-07-05 Thread Harald Anlauf

Hi Andre,

Am 03.07.24 um 12:58 schrieb Andre Vehreschild:

Hi Harald,

I am sorry for the long delay, but fixing the negative stride lead from one
issue to the next. I finally got a version that does not regress. Please have a
look.

This patch has two parts:
1. The runtime library part in pr96992_3p1.patch and
2. the compiler changes in pr96992_3p2.patch.

In my branch also the two patches from Paul for pr59104 and pr102689 are
living, which might lead to small shifts during application of the patches.

NOTE, this patch adds internal packing and unpacking of class arrays similar to
the regular pack and unpack. I think this is necessary, because the regular
un-/pack does not use the vptr's _copy routine for moving data and therefore
may produce bugs.

The un-/pack_class routines are yet only used for converting a derived type
array to a class array. Extending their use when a UN-/PACK() is applied on a
class array is still to be done (as part of another PR).

Regtests fine on x86_64-pc-linux-gnu/ Fedora 39.


this is a really huge patch to review, and I am not sure that I can do
this without help from others.  Paul?  Anybody else?

As far as I can tell for now:

- pr96992_3p1.patch (the libgfortran part) looks good to me.

- git had some whitespace issues with pr96992_3p2.patch as attached,
  but I could fix that locally and do some testing parallel to reading.

A few advance comments on the latter patch:

- my understanding is that the PR at the end of a summary line should be
  like in:

Fortran: Fix rejecting class arrays of different ranks as storage
association argument [PR96992]

  I was told that this helps people explicitly scanning for the PR
  number in that place.

- some rewrites of logical conditions change the coding style from
  what it recommended GNU coding style, and I find the more compact
  way used in some places harder to grok (but that may be just me).
  Example:

@@ -8850,20 +8857,24 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr
* expr, bool g77,
   /* There is no need to pack and unpack the array, if it is contiguous
  and not a deferred- or assumed-shape array, or if it is simply
  contiguous.  */
-  no_pack = ((sym && sym->as
- && !sym->attr.pointer
- && sym->as->type != AS_DEFERRED
- && sym->as->type != AS_ASSUMED_RANK
- && sym->as->type != AS_ASSUMED_SHAPE)
- ||
-(ref && ref->u.ar.as
- && ref->u.ar.as->type != AS_DEFERRED
+  no_pack = false;
+  gfc_array_spec *as;
+  if (sym)
+{
+  symbol_attribute *attr
+   = &(IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->attr : sym->attr);
+  as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
+  no_pack
+   = (as && !attr->pointer && as->type != AS_DEFERRED
+  && as->type != AS_ASSUMED_RANK && as->type != AS_ASSUMED_SHAPE);
+}
+  if (ref && ref->u.ar.as)
+no_pack = no_pack
+ || (ref->u.ar.as->type != AS_DEFERRED
  && ref->u.ar.as->type != AS_ASSUMED_RANK
- && ref->u.ar.as->type != AS_ASSUMED_SHAPE)
- ||
-gfc_is_simply_contiguous (expr, false, true));
-
-  no_pack = contiguous && no_pack;
+ && ref->u.ar.as->type != AS_ASSUMED_SHAPE);
+  no_pack
+= contiguous && (no_pack || gfc_is_simply_contiguous (expr, false,
true));

   /* If we have an EXPR_OP or a function returning an explicit-shaped
  or allocatable array, an array temporary will be generated which


I understand that this may be your personal coding style, but you
might keep in mind that reviewers have to understand the code, too...

I have not fully understood your logic when packing is now invoked.
We not only need to do it for explicit-size arrays, but also for
assumed-size.  This still fails for my slightly extended testcase
(see attached) where I pass the class array via:

  subroutine d4(x,n)
integer, intent(in) :: n
!   class (foo), intent(inout) :: x(n)  ! OK
class (foo), intent(inout) :: x(*)  ! not OK
call d3(x,n)! Simply pass assumed-size array
  end subroutine d4

I am unable to point to the places in your patch where you need to
handle that in addition.

Otherwise I was unable to see any obvious, major problem with the
patch, but then I am not fluent enough in class handling in the
gfortran FE.  So if e.g. Paul jumps in here within the next 72 hours,
it would be great.

So here comes the issue with the attached code variant.
After your patch, this prints as last 4 relevant lines:

 full: -43  44  45 -46  47
48 -49  50
 d3_1: -43  44  45
 d3_2:  43 -44 -45
 full:  43 -44 -45 -46  47
48 -49  50

while when switching the declaration of the dummy argument of d4:

 full: -43  44  45 

[gcc r15-1826] Fortran: fix associate with assumed-length character array [PR115700]

2024-07-03 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:7b7f203472d07a05d959a29638c7c95d98bf0c1c

commit r15-1826-g7b7f203472d07a05d959a29638c7c95d98bf0c1c
Author: Harald Anlauf 
Date:   Tue Jul 2 21:26:05 2024 +0200

Fortran: fix associate with assumed-length character array [PR115700]

gcc/fortran/ChangeLog:

PR fortran/115700
* trans-stmt.cc (trans_associate_var): When the associate target
is an array-valued character variable, the length is known at entry
of the associate block.  Move setting of string length of the
selector to the initialization part of the block.

gcc/testsuite/ChangeLog:

PR fortran/115700
* gfortran.dg/associate_69.f90: New test.

Diff:
---
 gcc/fortran/trans-stmt.cc  | 18 
 gcc/testsuite/gfortran.dg/associate_69.f90 | 33 ++
 2 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 60275e18867..703a705e7ca 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -1911,6 +1911,8 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block 
*block)
   gfc_se se;
   tree desc;
   bool cst_array_ctor;
+  stmtblock_t init;
+  gfc_init_block ();
 
   desc = sym->backend_decl;
   cst_array_ctor = e->expr_type == EXPR_ARRAY
@@ -1935,10 +1937,17 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block 
*block)
  && !sym->attr.select_type_temporary
  && sym->ts.u.cl->backend_decl
  && VAR_P (sym->ts.u.cl->backend_decl)
+ && se.string_length
  && se.string_length != sym->ts.u.cl->backend_decl)
-   gfc_add_modify (, sym->ts.u.cl->backend_decl,
- fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl),
-   se.string_length));
+   {
+ /* When the target is a variable, its length is already known.  */
+ tree len = fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl),
+  se.string_length);
+ if (e->expr_type == EXPR_VARIABLE)
+   gfc_add_modify (, sym->ts.u.cl->backend_decl, len);
+ else
+   gfc_add_modify (, sym->ts.u.cl->backend_decl, len);
+   }
 
   /* If we didn't already do the pointer assignment, set associate-name
 descriptor to the one generated for the temporary.  */
@@ -1978,7 +1987,8 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block 
*block)
}
 
   /* Done, register stuff as init / cleanup code.  */
-  gfc_add_init_cleanup (block, gfc_finish_block (),
+  gfc_add_block_to_block (, );
+  gfc_add_init_cleanup (block, gfc_finish_block (),
gfc_finish_block ());
 }
 
diff --git a/gcc/testsuite/gfortran.dg/associate_69.f90 
b/gcc/testsuite/gfortran.dg/associate_69.f90
new file mode 100644
index 000..28f488bb274
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/associate_69.f90
@@ -0,0 +1,33 @@
+! { dg-do compile }
+! { dg-options "-Og -Wuninitialized -Wmaybe-uninitialized 
-fdump-tree-optimized" }
+!
+! PR fortran/115700 - Bogus warning for associate with assumed-length 
character array
+!
+subroutine mvce(x)
+  implicit none
+  character(len=*), dimension(:), intent(in)  :: x
+
+  associate (tmp1 => x)
+if (len (tmp1) /= len (x)) stop 1
+  end associate
+
+  associate (tmp2 => x(1:))
+if (len (tmp2) /= len (x)) stop 2
+  end associate
+
+  associate (tmp3 => x(1:)(:))
+if (len (tmp3) /= len (x)) stop 3
+  end associate
+
+! The following associate blocks still produce bogus warnings:
+
+! associate (tmp4 => x(:)(1:))
+!   if (len (tmp4) /= len (x)) stop 4
+! end associate
+!
+! associate (tmp5 => x(1:)(1:))
+!   if (len (tmp5) /= len (x)) stop 5
+! end associate
+end
+
+! { dg-final { scan-tree-dump-not " \\.tmp" "optimized" } }


[PATCH] Fortran: fix associate with assumed-length character array [PR115700]

2024-07-02 Thread Harald Anlauf
Dear all,

the attached patch addresses an effectively bogus warning about
uninitialized temporary string lengths of associate selectors.
The primary reason is that the array descriptor for a character
array is created before the corresponding string length is set.
Moving the setting of the string length temporary to the beginning
of the block solves the issue.

The patch does not solve the case for the target containing
substring references.  This needs to be addressed separately.
(So far I could not find a solution that does not regress.)

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

As the PR is marked as a regression, is it also OK for backporting?

Thanks,
Harald

From 930a1be8c623cf03f9b2e6dbddb45d0b69e152dd Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Tue, 2 Jul 2024 21:26:05 +0200
Subject: [PATCH] Fortran: fix associate with assumed-length character array
 [PR115700]

gcc/fortran/ChangeLog:

	PR fortran/115700
	* trans-stmt.cc (trans_associate_var): When the associate target
	is an array-valued character variable, the length is known at entry
	of the associate block.  Move setting of string length of the
	selector to the initialization part of the block.

gcc/testsuite/ChangeLog:

	PR fortran/115700
	* gfortran.dg/associate_69.f90: New test.
---
 gcc/fortran/trans-stmt.cc  | 18 +---
 gcc/testsuite/gfortran.dg/associate_69.f90 | 33 ++
 2 files changed, 47 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/associate_69.f90

diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 60275e18867..703a705e7ca 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -1911,6 +1911,8 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
   gfc_se se;
   tree desc;
   bool cst_array_ctor;
+  stmtblock_t init;
+  gfc_init_block ();

   desc = sym->backend_decl;
   cst_array_ctor = e->expr_type == EXPR_ARRAY
@@ -1935,10 +1937,17 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
 	  && !sym->attr.select_type_temporary
 	  && sym->ts.u.cl->backend_decl
 	  && VAR_P (sym->ts.u.cl->backend_decl)
+	  && se.string_length
 	  && se.string_length != sym->ts.u.cl->backend_decl)
-	gfc_add_modify (, sym->ts.u.cl->backend_decl,
-			  fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl),
-	se.string_length));
+	{
+	  /* When the target is a variable, its length is already known.  */
+	  tree len = fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl),
+   se.string_length);
+	  if (e->expr_type == EXPR_VARIABLE)
+	gfc_add_modify (, sym->ts.u.cl->backend_decl, len);
+	  else
+	gfc_add_modify (, sym->ts.u.cl->backend_decl, len);
+	}

   /* If we didn't already do the pointer assignment, set associate-name
 	 descriptor to the one generated for the temporary.  */
@@ -1978,7 +1987,8 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
 	}

   /* Done, register stuff as init / cleanup code.  */
-  gfc_add_init_cleanup (block, gfc_finish_block (),
+  gfc_add_block_to_block (, );
+  gfc_add_init_cleanup (block, gfc_finish_block (),
 			gfc_finish_block ());
 }

diff --git a/gcc/testsuite/gfortran.dg/associate_69.f90 b/gcc/testsuite/gfortran.dg/associate_69.f90
new file mode 100644
index 000..28f488bb274
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/associate_69.f90
@@ -0,0 +1,33 @@
+! { dg-do compile }
+! { dg-options "-Og -Wuninitialized -Wmaybe-uninitialized -fdump-tree-optimized" }
+!
+! PR fortran/115700 - Bogus warning for associate with assumed-length character array
+!
+subroutine mvce(x)
+  implicit none
+  character(len=*), dimension(:), intent(in)  :: x
+
+  associate (tmp1 => x)
+if (len (tmp1) /= len (x)) stop 1
+  end associate
+
+  associate (tmp2 => x(1:))
+if (len (tmp2) /= len (x)) stop 2
+  end associate
+
+  associate (tmp3 => x(1:)(:))
+if (len (tmp3) /= len (x)) stop 3
+  end associate
+
+! The following associate blocks still produce bogus warnings:
+
+! associate (tmp4 => x(:)(1:))
+!   if (len (tmp4) /= len (x)) stop 4
+! end associate
+!
+! associate (tmp5 => x(1:)(1:))
+!   if (len (tmp5) /= len (x)) stop 5
+! end associate
+end
+
+! { dg-final { scan-tree-dump-not " \\.tmp" "optimized" } }
--
2.35.3



[gcc r14-10364] Fortran: fix ALLOCATE with SOURCE of deferred character length [PR114019]

2024-06-30 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:603b344c07aa55f8292446e8fd28f5da9a983a21

commit r14-10364-g603b344c07aa55f8292446e8fd28f5da9a983a21
Author: Harald Anlauf 
Date:   Fri Jun 28 21:44:06 2024 +0200

Fortran: fix ALLOCATE with SOURCE of deferred character length [PR114019]

gcc/fortran/ChangeLog:

PR fortran/114019
* trans-stmt.cc (gfc_trans_allocate): Fix handling of case of
scalar character expression being used for SOURCE.

gcc/testsuite/ChangeLog:

PR fortran/114019
* gfortran.dg/allocate_with_source_33.f90: New test.

(cherry picked from commit 7682d115402743090f20aca63a3b5e6c205dedff)

Diff:
---
 gcc/fortran/trans-stmt.cc  |  5 +-
 .../gfortran.dg/allocate_with_source_33.f90| 69 ++
 2 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 87dd833872a..1fd75c6a37c 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -6464,7 +6464,10 @@ gfc_trans_allocate (gfc_code * code, gfc_omp_namelist 
*omp_allocate)
   else if (se.expr != NULL_TREE && temp_var_needed)
{
  tree var, desc;
- tmp = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)) || is_coarray ?
+ tmp = (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
+|| is_coarray
+|| (code->expr3->ts.type == BT_CHARACTER
+&& code->expr3->rank == 0)) ?
se.expr
  : build_fold_indirect_ref_loc (input_location, se.expr);
 
diff --git a/gcc/testsuite/gfortran.dg/allocate_with_source_33.f90 
b/gcc/testsuite/gfortran.dg/allocate_with_source_33.f90
new file mode 100644
index 000..43a03625950
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/allocate_with_source_33.f90
@@ -0,0 +1,69 @@
+! { dg-do compile }
+! { dg-options "-O0" }
+!
+! PR fortran/114019 - allocation with source of deferred character length
+
+subroutine s
+  implicit none
+  character(1)  :: w   = "4"
+  character(*), parameter   :: str = "123"
+  character(5), pointer :: chr_pointer1
+  character(:), pointer :: chr_pointer2
+  character(:), pointer :: chr_ptr_arr(:)
+  character(5), allocatable :: chr_alloc1
+  character(:), allocatable :: chr_alloc2
+  character(:), allocatable :: chr_all_arr(:)
+  allocate (chr_pointer1, source=w// str//w)
+  allocate (chr_pointer2, source=w// str//w)
+  allocate (chr_ptr_arr,  source=w//[str//w])
+  allocate (chr_alloc1,   source=w// str//w)
+  allocate (chr_alloc2,   source=w// str//w)
+  allocate (chr_all_arr,  source=w//[str//w])
+  allocate (chr_pointer2, source=str)
+  allocate (chr_pointer2, source=w)
+  allocate (chr_alloc2,   source=str)
+  allocate (chr_alloc2,   source=w)
+  allocate (chr_pointer1, mold  =w// str//w)
+  allocate (chr_pointer2, mold  =w// str//w)
+  allocate (chr_ptr_arr,  mold  =w//[str//w])
+  allocate (chr_alloc1,   mold  =w// str//w)
+  allocate (chr_alloc2,   mold  =w// str//w)
+  allocate (chr_all_arr,  mold  =w//[str//w])
+  allocate (chr_pointer2, mold  =str)
+  allocate (chr_pointer2, mold  =w)
+  allocate (chr_alloc2,   mold  =str)
+  allocate (chr_alloc2,   mold  =w)
+end
+
+subroutine s2
+  implicit none
+  integer, parameter :: ck=4
+  character(kind=ck,len=1)  :: w   = ck_"4"
+  character(kind=ck,len=*), parameter   :: str = ck_"123"
+  character(kind=ck,len=5), pointer :: chr_pointer1
+  character(kind=ck,len=:), pointer :: chr_pointer2
+  character(kind=ck,len=:), pointer :: chr_ptr_arr(:)
+  character(kind=ck,len=5), allocatable :: chr_alloc1
+  character(kind=ck,len=:), allocatable :: chr_alloc2
+  character(kind=ck,len=:), allocatable :: chr_all_arr(:)
+  allocate (chr_pointer1, source=w// str//w)
+  allocate (chr_pointer2, source=w// str//w)
+  allocate (chr_ptr_arr,  source=w//[str//w])
+  allocate (chr_alloc1,   source=w// str//w)
+  allocate (chr_alloc2,   source=w// str//w)
+  allocate (chr_all_arr,  source=w//[str//w])
+  allocate (chr_pointer2, source=str)
+  allocate (chr_pointer2, source=w)
+  allocate (chr_alloc2,   source=str)
+  allocate (chr_alloc2,   source=w)
+  allocate (chr_pointer1, mold  =w// str//w)
+  allocate (chr_pointer2, mold  =w// str//w)
+  allocate (chr_ptr_arr,  mold  =w//[str//w])
+  allocate (chr_alloc1,   mold  =w// str//w)
+  allocate (chr_alloc2,   mold  =w// str//w)
+  allocate (chr_all_arr,  mold  =w//[str//w])
+  allocate (chr_pointer2, mold  =str)
+  allocate (chr_pointer2, mold  =w)
+  allocate (chr_alloc2,   mold  =str)
+  allocate (chr_alloc2,   mold  =w)
+end


[gcc r14-10363] Fortran: fix passing of optional dummy as actual to optional argument [PR55978]

2024-06-30 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:9f147487de660f026e2fb1281e1a1800f58b3bdd

commit r14-10363-g9f147487de660f026e2fb1281e1a1800f58b3bdd
Author: Harald Anlauf 
Date:   Sun Jun 23 22:36:43 2024 +0200

Fortran: fix passing of optional dummy as actual to optional argument 
[PR55978]

gcc/fortran/ChangeLog:

PR fortran/55978
* trans-array.cc (gfc_conv_array_parameter): Do not dereference
data component of a missing allocatable dummy array argument for
passing as actual to optional dummy.  Harden logic of presence
check for optional pointer dummy by using TRUTH_ANDIF_EXPR instead
of TRUTH_AND_EXPR.

gcc/testsuite/ChangeLog:

PR fortran/55978
* gfortran.dg/optional_absent_12.f90: New test.

(cherry picked from commit f02c70dafd384f0c44d7a0920f4a75a30e267045)

Diff:
---
 gcc/fortran/trans-array.cc   | 20 
 gcc/testsuite/gfortran.dg/optional_absent_12.f90 | 30 
 2 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index a15ff30e8f4..d4b16772de2 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -8673,6 +8673,10 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, 
bool g77,
&& (sym->backend_decl != parent))
 this_array_result = false;
 
+  /* Passing an optional dummy argument as actual to an optional dummy?  */
+  bool pass_optional;
+  pass_optional = fsym && fsym->attr.optional && sym && sym->attr.optional;
+
   /* Passing address of the array if it is not pointer or assumed-shape.  */
   if (full_array_var && g77 && !this_array_result
   && sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
@@ -8710,6 +8714,14 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, 
bool g77,
  if (size)
array_parameter_size (>pre, tmp, expr, size);
  se->expr = gfc_conv_array_data (tmp);
+ if (pass_optional)
+   {
+ tree cond = gfc_conv_expr_present (sym);
+ se->expr = build3_loc (input_location, COND_EXPR,
+TREE_TYPE (se->expr), cond, se->expr,
+fold_convert (TREE_TYPE (se->expr),
+  null_pointer_node));
+   }
   return;
 }
 }
@@ -8959,8 +8971,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, 
bool g77,
  tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
 fold_convert (TREE_TYPE (tmp), ptr), tmp);
 
- if (fsym && fsym->attr.optional && sym && sym->attr.optional)
-   tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+ if (pass_optional)
+   tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
   logical_type_node,
   gfc_conv_expr_present (sym), tmp);
 
@@ -8994,8 +9006,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, 
bool g77,
   tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
 fold_convert (TREE_TYPE (tmp), ptr), tmp);
 
-  if (fsym && fsym->attr.optional && sym && sym->attr.optional)
-   tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+  if (pass_optional)
+   tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
   logical_type_node,
   gfc_conv_expr_present (sym), tmp);
 
diff --git a/gcc/testsuite/gfortran.dg/optional_absent_12.f90 
b/gcc/testsuite/gfortran.dg/optional_absent_12.f90
new file mode 100644
index 000..1e61d91fb6d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/optional_absent_12.f90
@@ -0,0 +1,30 @@
+! { dg-do run }
+! { dg-additional-options "-fcheck=array-temps" }
+!
+! PR fortran/55978 - comment#19
+!
+! Test passing of (missing) optional dummy to optional array argument
+
+program test
+  implicit none
+  integer, pointer :: p(:) => null()
+  call one (p)
+  call one (null())
+  call one ()
+  call three ()
+contains
+  subroutine one (y)
+integer, pointer, optional, intent(in) :: y(:)
+call two (y)
+  end subroutine one
+
+  subroutine three (z)
+integer, allocatable, optional, intent(in) :: z(:)
+call two (z)
+  end subroutine three
+
+  subroutine two (x)
+integer, optional, intent(in) :: x(*)
+if (present (x)) stop 1
+  end subroutine two
+end


[gcc r14-10362] Fortran: fix for CHARACTER(len=*) dummies with bind(C) [PR115390]

2024-06-30 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:b31e1900fa0cffabb0702962d01ba3fe917fdf69

commit r14-10362-gb31e1900fa0cffabb0702962d01ba3fe917fdf69
Author: Harald Anlauf 
Date:   Tue Jun 18 21:57:19 2024 +0200

Fortran: fix for CHARACTER(len=*) dummies with bind(C) [PR115390]

gcc/fortran/ChangeLog:

PR fortran/115390
* trans-decl.cc (gfc_conv_cfi_to_gfc): Move derivation of type sizes
for character via gfc_trans_vla_type_sizes to after character length
has been set.

gcc/testsuite/ChangeLog:

PR fortran/115390
* gfortran.dg/bind_c_char_11.f90: New test.

(cherry picked from commit 954f9011c4923b72f42cc6ca8460333e7c7aad98)

Diff:
---
 gcc/fortran/trans-decl.cc|  4 +--
 gcc/testsuite/gfortran.dg/bind_c_char_11.f90 | 45 
 2 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index 301439baaf5..1a319b27449 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -7056,8 +7056,8 @@ gfc_conv_cfi_to_gfc (stmtblock_t *init, stmtblock_t 
*finally,
   if (sym->ts.type == BT_CHARACTER
   && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
 {
-  gfc_conv_string_length (sym->ts.u.cl, NULL, init);
-  gfc_trans_vla_type_sizes (sym, init);
+  gfc_conv_string_length (sym->ts.u.cl, NULL, );
+  gfc_trans_vla_type_sizes (sym, );
 }
 
   /* gfc->data = cfi->base_addr - or for scalars: gfc = cfi->base_addr.
diff --git a/gcc/testsuite/gfortran.dg/bind_c_char_11.f90 
b/gcc/testsuite/gfortran.dg/bind_c_char_11.f90
new file mode 100644
index 000..5ed8e82853b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind_c_char_11.f90
@@ -0,0 +1,45 @@
+! { dg-do compile }
+! { dg-additional-options "-Wuninitialized" }
+!
+! PR fortran/115390 - fixes for CHARACTER(len=*) dummies with bind(C)
+
+module test
+  implicit none
+contains
+  subroutine bar(s,t) bind(c)
+character(*), intent(in) :: s,t
+optional :: t
+call foo(s,t)
+  end
+  subroutine bar1(s,t) bind(c)
+character(*), intent(in) :: s(:),t(:)
+optional :: t
+call foo1(s,t)
+  end
+  subroutine bar4(s,t) bind(c)
+character(len=*,kind=4), intent(in) :: s,t
+optional:: t
+call foo4(s,t)
+  end
+  subroutine bar5(s,t) bind(c)
+character(len=*,kind=4), intent(in) :: s(:),t(:)
+optional:: t
+call foo5(s,t)
+  end
+  subroutine foo(s,t)
+character(*), intent(in) :: s,t
+optional :: t
+  end
+  subroutine foo1(s,t)
+character(*), intent(in) :: s(:),t(:)
+optional :: t
+  end
+  subroutine foo4(s,t)
+character(len=*,kind=4), intent(in) :: s,t
+optional:: t
+  end
+  subroutine foo5(s,t)
+character(len=*,kind=4), intent(in) :: s(:),t(:)
+optional:: t
+  end
+end


[gcc r15-1722] Fortran: fix ALLOCATE with SOURCE of deferred character length [PR114019]

2024-06-29 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:7682d115402743090f20aca63a3b5e6c205dedff

commit r15-1722-g7682d115402743090f20aca63a3b5e6c205dedff
Author: Harald Anlauf 
Date:   Fri Jun 28 21:44:06 2024 +0200

Fortran: fix ALLOCATE with SOURCE of deferred character length [PR114019]

gcc/fortran/ChangeLog:

PR fortran/114019
* trans-stmt.cc (gfc_trans_allocate): Fix handling of case of
scalar character expression being used for SOURCE.

gcc/testsuite/ChangeLog:

PR fortran/114019
* gfortran.dg/allocate_with_source_33.f90: New test.

Diff:
---
 gcc/fortran/trans-stmt.cc  |  5 +-
 .../gfortran.dg/allocate_with_source_33.f90| 69 ++
 2 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 93b633e212e..60275e18867 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -6464,7 +6464,10 @@ gfc_trans_allocate (gfc_code * code, gfc_omp_namelist 
*omp_allocate)
   else if (se.expr != NULL_TREE && temp_var_needed)
{
  tree var, desc;
- tmp = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)) || is_coarray ?
+ tmp = (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
+|| is_coarray
+|| (code->expr3->ts.type == BT_CHARACTER
+&& code->expr3->rank == 0)) ?
se.expr
  : build_fold_indirect_ref_loc (input_location, se.expr);
 
diff --git a/gcc/testsuite/gfortran.dg/allocate_with_source_33.f90 
b/gcc/testsuite/gfortran.dg/allocate_with_source_33.f90
new file mode 100644
index 000..43a03625950
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/allocate_with_source_33.f90
@@ -0,0 +1,69 @@
+! { dg-do compile }
+! { dg-options "-O0" }
+!
+! PR fortran/114019 - allocation with source of deferred character length
+
+subroutine s
+  implicit none
+  character(1)  :: w   = "4"
+  character(*), parameter   :: str = "123"
+  character(5), pointer :: chr_pointer1
+  character(:), pointer :: chr_pointer2
+  character(:), pointer :: chr_ptr_arr(:)
+  character(5), allocatable :: chr_alloc1
+  character(:), allocatable :: chr_alloc2
+  character(:), allocatable :: chr_all_arr(:)
+  allocate (chr_pointer1, source=w// str//w)
+  allocate (chr_pointer2, source=w// str//w)
+  allocate (chr_ptr_arr,  source=w//[str//w])
+  allocate (chr_alloc1,   source=w// str//w)
+  allocate (chr_alloc2,   source=w// str//w)
+  allocate (chr_all_arr,  source=w//[str//w])
+  allocate (chr_pointer2, source=str)
+  allocate (chr_pointer2, source=w)
+  allocate (chr_alloc2,   source=str)
+  allocate (chr_alloc2,   source=w)
+  allocate (chr_pointer1, mold  =w// str//w)
+  allocate (chr_pointer2, mold  =w// str//w)
+  allocate (chr_ptr_arr,  mold  =w//[str//w])
+  allocate (chr_alloc1,   mold  =w// str//w)
+  allocate (chr_alloc2,   mold  =w// str//w)
+  allocate (chr_all_arr,  mold  =w//[str//w])
+  allocate (chr_pointer2, mold  =str)
+  allocate (chr_pointer2, mold  =w)
+  allocate (chr_alloc2,   mold  =str)
+  allocate (chr_alloc2,   mold  =w)
+end
+
+subroutine s2
+  implicit none
+  integer, parameter :: ck=4
+  character(kind=ck,len=1)  :: w   = ck_"4"
+  character(kind=ck,len=*), parameter   :: str = ck_"123"
+  character(kind=ck,len=5), pointer :: chr_pointer1
+  character(kind=ck,len=:), pointer :: chr_pointer2
+  character(kind=ck,len=:), pointer :: chr_ptr_arr(:)
+  character(kind=ck,len=5), allocatable :: chr_alloc1
+  character(kind=ck,len=:), allocatable :: chr_alloc2
+  character(kind=ck,len=:), allocatable :: chr_all_arr(:)
+  allocate (chr_pointer1, source=w// str//w)
+  allocate (chr_pointer2, source=w// str//w)
+  allocate (chr_ptr_arr,  source=w//[str//w])
+  allocate (chr_alloc1,   source=w// str//w)
+  allocate (chr_alloc2,   source=w// str//w)
+  allocate (chr_all_arr,  source=w//[str//w])
+  allocate (chr_pointer2, source=str)
+  allocate (chr_pointer2, source=w)
+  allocate (chr_alloc2,   source=str)
+  allocate (chr_alloc2,   source=w)
+  allocate (chr_pointer1, mold  =w// str//w)
+  allocate (chr_pointer2, mold  =w// str//w)
+  allocate (chr_ptr_arr,  mold  =w//[str//w])
+  allocate (chr_alloc1,   mold  =w// str//w)
+  allocate (chr_alloc2,   mold  =w// str//w)
+  allocate (chr_all_arr,  mold  =w//[str//w])
+  allocate (chr_pointer2, mold  =str)
+  allocate (chr_pointer2, mold  =w)
+  allocate (chr_alloc2,   mold  =str)
+  allocate (chr_alloc2,   mold  =w)
+end


[PATCH] Fortran: fix ALLOCATE with SOURCE of deferred character length [PR114019]

2024-06-28 Thread Harald Anlauf
Dear all,

the attached patch fixes an ICE occuring for ALLOCATE with SOURCE
(or MOLD) of deferred character length in the scalar case, which
looked obscure because the ICE disappears at -O1 and higher.

The dump tree suggests that it is a wrong decl for the temporary
source that was e.g.

character(kind=1) source.2[1:];

whereas I had expected

character(kind=1)[1:] * source.2;

and which we now get after the patch.  Or am I missing something?

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

Thanks,
Harald

From 4d12f6d0cf63ea6a2deb5398e6478dde114e76b8 Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Fri, 28 Jun 2024 21:44:06 +0200
Subject: [PATCH] Fortran: fix ALLOCATE with SOURCE of deferred character
 length [PR114019]

gcc/fortran/ChangeLog:

	PR fortran/114019
	* trans-stmt.cc (gfc_trans_allocate): Fix handling of case of
	scalar character expression being used for SOURCE.

gcc/testsuite/ChangeLog:

	PR fortran/114019
	* gfortran.dg/allocate_with_source_33.f90: New test.
---
 gcc/fortran/trans-stmt.cc |  5 +-
 .../gfortran.dg/allocate_with_source_33.f90   | 53 +++
 2 files changed, 57 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gfortran.dg/allocate_with_source_33.f90

diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 93b633e212e..60275e18867 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -6464,7 +6464,10 @@ gfc_trans_allocate (gfc_code * code, gfc_omp_namelist *omp_allocate)
   else if (se.expr != NULL_TREE && temp_var_needed)
 	{
 	  tree var, desc;
-	  tmp = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)) || is_coarray ?
+	  tmp = (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
+		 || is_coarray
+		 || (code->expr3->ts.type == BT_CHARACTER
+		 && code->expr3->rank == 0)) ?
 		se.expr
 	  : build_fold_indirect_ref_loc (input_location, se.expr);

diff --git a/gcc/testsuite/gfortran.dg/allocate_with_source_33.f90 b/gcc/testsuite/gfortran.dg/allocate_with_source_33.f90
new file mode 100644
index 000..7b1a26c464c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/allocate_with_source_33.f90
@@ -0,0 +1,53 @@
+! { dg-do compile }
+! { dg-options "-O0" }
+!
+! PR fortran/114019 - allocation with source of deferred character length
+
+subroutine s
+  implicit none
+  character(1)  :: w   = "4"
+  character(*), parameter   :: str = "123"
+  character(5), pointer :: chr_pointer1
+  character(:), pointer :: chr_pointer2
+  character(:), pointer :: chr_ptr_arr(:)
+  character(5), allocatable :: chr_alloc1
+  character(:), allocatable :: chr_alloc2
+  character(:), allocatable :: chr_all_arr(:)
+  allocate (chr_pointer1, source=w// str//w)
+  allocate (chr_pointer2, source=w// str//w)
+  allocate (chr_ptr_arr,  source=w//[str//w])
+  allocate (chr_alloc1,   source=w// str//w)
+  allocate (chr_alloc2,   source=w// str//w)
+  allocate (chr_all_arr,  source=w//[str//w])
+  allocate (chr_pointer1, mold  =w// str//w)
+  allocate (chr_pointer2, mold  =w// str//w)
+  allocate (chr_ptr_arr,  mold  =w//[str//w])
+  allocate (chr_alloc1,   mold  =w// str//w)
+  allocate (chr_alloc2,   mold  =w// str//w)
+  allocate (chr_all_arr,  mold  =w//[str//w])
+end
+
+subroutine s2
+  implicit none
+  integer, parameter :: ck=4
+  character(kind=ck,len=1)  :: w   = ck_"4"
+  character(kind=ck,len=*), parameter   :: str = ck_"123"
+  character(kind=ck,len=5), pointer :: chr_pointer1
+  character(kind=ck,len=:), pointer :: chr_pointer2
+  character(kind=ck,len=:), pointer :: chr_ptr_arr(:)
+  character(kind=ck,len=5), allocatable :: chr_alloc1
+  character(kind=ck,len=:), allocatable :: chr_alloc2
+  character(kind=ck,len=:), allocatable :: chr_all_arr(:)
+  allocate (chr_pointer1, source=w// str//w)
+  allocate (chr_pointer2, source=w// str//w)
+  allocate (chr_ptr_arr,  source=w//[str//w])
+  allocate (chr_alloc1,   source=w// str//w)
+  allocate (chr_alloc2,   source=w// str//w)
+  allocate (chr_all_arr,  source=w//[str//w])
+  allocate (chr_pointer1, mold  =w// str//w)
+  allocate (chr_pointer2, mold  =w// str//w)
+  allocate (chr_ptr_arr,  mold  =w//[str//w])
+  allocate (chr_alloc1,   mold  =w// str//w)
+  allocate (chr_alloc2,   mold  =w// str//w)
+  allocate (chr_all_arr,  mold  =w//[str//w])
+end
--
2.35.3



[gcc r15-1585] Fortran: fix passing of optional dummy as actual to optional argument [PR55978]

2024-06-24 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:f02c70dafd384f0c44d7a0920f4a75a30e267045

commit r15-1585-gf02c70dafd384f0c44d7a0920f4a75a30e267045
Author: Harald Anlauf 
Date:   Sun Jun 23 22:36:43 2024 +0200

Fortran: fix passing of optional dummy as actual to optional argument 
[PR55978]

gcc/fortran/ChangeLog:

PR fortran/55978
* trans-array.cc (gfc_conv_array_parameter): Do not dereference
data component of a missing allocatable dummy array argument for
passing as actual to optional dummy.  Harden logic of presence
check for optional pointer dummy by using TRUTH_ANDIF_EXPR instead
of TRUTH_AND_EXPR.

gcc/testsuite/ChangeLog:

PR fortran/55978
* gfortran.dg/optional_absent_12.f90: New test.

Diff:
---
 gcc/fortran/trans-array.cc   | 20 
 gcc/testsuite/gfortran.dg/optional_absent_12.f90 | 30 
 2 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 19d69aec9c0..26237f43bec 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -8703,6 +8703,10 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, 
bool g77,
&& (sym->backend_decl != parent))
 this_array_result = false;
 
+  /* Passing an optional dummy argument as actual to an optional dummy?  */
+  bool pass_optional;
+  pass_optional = fsym && fsym->attr.optional && sym && sym->attr.optional;
+
   /* Passing address of the array if it is not pointer or assumed-shape.  */
   if (full_array_var && g77 && !this_array_result
   && sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
@@ -8740,6 +8744,14 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, 
bool g77,
  if (size)
array_parameter_size (>pre, tmp, expr, size);
  se->expr = gfc_conv_array_data (tmp);
+ if (pass_optional)
+   {
+ tree cond = gfc_conv_expr_present (sym);
+ se->expr = build3_loc (input_location, COND_EXPR,
+TREE_TYPE (se->expr), cond, se->expr,
+fold_convert (TREE_TYPE (se->expr),
+  null_pointer_node));
+   }
   return;
 }
 }
@@ -8989,8 +9001,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, 
bool g77,
  tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
 fold_convert (TREE_TYPE (tmp), ptr), tmp);
 
- if (fsym && fsym->attr.optional && sym && sym->attr.optional)
-   tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+ if (pass_optional)
+   tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
   logical_type_node,
   gfc_conv_expr_present (sym), tmp);
 
@@ -9024,8 +9036,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, 
bool g77,
   tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
 fold_convert (TREE_TYPE (tmp), ptr), tmp);
 
-  if (fsym && fsym->attr.optional && sym && sym->attr.optional)
-   tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+  if (pass_optional)
+   tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
   logical_type_node,
   gfc_conv_expr_present (sym), tmp);
 
diff --git a/gcc/testsuite/gfortran.dg/optional_absent_12.f90 
b/gcc/testsuite/gfortran.dg/optional_absent_12.f90
new file mode 100644
index 000..1e61d91fb6d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/optional_absent_12.f90
@@ -0,0 +1,30 @@
+! { dg-do run }
+! { dg-additional-options "-fcheck=array-temps" }
+!
+! PR fortran/55978 - comment#19
+!
+! Test passing of (missing) optional dummy to optional array argument
+
+program test
+  implicit none
+  integer, pointer :: p(:) => null()
+  call one (p)
+  call one (null())
+  call one ()
+  call three ()
+contains
+  subroutine one (y)
+integer, pointer, optional, intent(in) :: y(:)
+call two (y)
+  end subroutine one
+
+  subroutine three (z)
+integer, allocatable, optional, intent(in) :: z(:)
+call two (z)
+  end subroutine three
+
+  subroutine two (x)
+integer, optional, intent(in) :: x(*)
+if (present (x)) stop 1
+  end subroutine two
+end


[PATCH] Fortran: fix passing of optional dummy as actual to optional argument [PR55978]

2024-06-23 Thread Harald Anlauf
Dear all,

the attached patch fixes issues exhibited by the testcase in comment#19 of 
PR55978.

First, when passing an allocatable optional dummy array to an optional dummy,
we need to prevent accessing the data component of the array when the argument
is not present, and pass a null pointer instead.  This is straightforward.

Second, the case of a missing pointer optional dummy array should have worked,
but the presence check surprisingly did not work as expected at -O0 or -Og,
but at higher optimization levels.  Interestingly, the dump-tree looked right,
but running under gdb or investigating the assembler revealed that the order
of tests in a logical AND expression was opposed to what the tree-dump looked
like.  Replacing TRUTH_AND_EXPR by TRUTH_ANDIF_EXPR and checking the optimized
dump confirmed that this does fix the issue.

Note that the tree-dump is not changed by this replacement.  Does this mean
thar AND and ANDIF currently are not differentiated at this level?

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

Would it be ok to backport this to 14-branch, too?

Thanks,
Harald

From 94e4c66d8374a12be38637620f362acf1fba5343 Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Sun, 23 Jun 2024 22:36:43 +0200
Subject: [PATCH] Fortran: fix passing of optional dummy as actual to optional
 argument [PR55978]

gcc/fortran/ChangeLog:

	PR fortran/55978
	* trans-array.cc (gfc_conv_array_parameter): Do not dereference
	data component of a missing allocatable dummy array argument for
	passing as actual to optional dummy.  Harden logic of presence
	check for optional pointer dummy by using TRUTH_ANDIF_EXPR instead
	of TRUTH_AND_EXPR.

gcc/testsuite/ChangeLog:

	PR fortran/55978
	* gfortran.dg/optional_absent_12.f90: New test.
---
 gcc/fortran/trans-array.cc| 20 ++---
 .../gfortran.dg/optional_absent_12.f90| 30 +++
 2 files changed, 46 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/optional_absent_12.f90

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 19d69aec9c0..26237f43bec 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -8703,6 +8703,10 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
 	&& (sym->backend_decl != parent))
 this_array_result = false;

+  /* Passing an optional dummy argument as actual to an optional dummy?  */
+  bool pass_optional;
+  pass_optional = fsym && fsym->attr.optional && sym && sym->attr.optional;
+
   /* Passing address of the array if it is not pointer or assumed-shape.  */
   if (full_array_var && g77 && !this_array_result
   && sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
@@ -8740,6 +8744,14 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
 	  if (size)
 	array_parameter_size (>pre, tmp, expr, size);
 	  se->expr = gfc_conv_array_data (tmp);
+	  if (pass_optional)
+	{
+	  tree cond = gfc_conv_expr_present (sym);
+	  se->expr = build3_loc (input_location, COND_EXPR,
+ TREE_TYPE (se->expr), cond, se->expr,
+ fold_convert (TREE_TYPE (se->expr),
+		   null_pointer_node));
+	}
   return;
 }
 }
@@ -8989,8 +9001,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
 	  tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
  fold_convert (TREE_TYPE (tmp), ptr), tmp);

-	  if (fsym && fsym->attr.optional && sym && sym->attr.optional)
-	tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+	  if (pass_optional)
+	tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
    logical_type_node,
    gfc_conv_expr_present (sym), tmp);

@@ -9024,8 +9036,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
   tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
 			 fold_convert (TREE_TYPE (tmp), ptr), tmp);

-  if (fsym && fsym->attr.optional && sym && sym->attr.optional)
-	tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+  if (pass_optional)
+	tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
 			   logical_type_node,
 			   gfc_conv_expr_present (sym), tmp);

diff --git a/gcc/testsuite/gfortran.dg/optional_absent_12.f90 b/gcc/testsuite/gfortran.dg/optional_absent_12.f90
new file mode 100644
index 000..1e61d91fb6d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/optional_absent_12.f90
@@ -0,0 +1,30 @@
+! { dg-do run }
+! { dg-additional-options "-fcheck=array-temps" }
+!
+! PR fortran/55978 - comment#19
+!
+! Test passing of (missing) optional dummy to optional array argument
+
+program test
+  implicit none
+  integer, pointer :: p(:) => null()
+  call one (p)
+  call one (null())
+  call one ()
+  call three ()
+contains
+  subroutine one (y)

[gcc r13-8857] Fortran: fix ALLOCATE with SOURCE=, zero-length character [PR83865]

2024-06-19 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:0530884fbf49cc81119d66de7e4a48b47172ed4c

commit r13-8857-g0530884fbf49cc81119d66de7e4a48b47172ed4c
Author: Harald Anlauf 
Date:   Mon Jun 3 22:02:06 2024 +0200

Fortran: fix ALLOCATE with SOURCE=, zero-length character [PR83865]

gcc/fortran/ChangeLog:

PR fortran/83865
* trans-stmt.cc (gfc_trans_allocate): Restrict special case for
source-expression with zero-length character to rank 0, so that
the array shape is not discarded.

gcc/testsuite/ChangeLog:

PR fortran/83865
* gfortran.dg/allocate_with_source_32.f90: New test.

(cherry picked from commit 7f21aee0d4ef95eee7d9f7f42e9a056715836648)

Diff:
---
 gcc/fortran/trans-stmt.cc  |  3 +-
 .../gfortran.dg/allocate_with_source_32.f90| 33 ++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 35eb1880539b..caa7b59e9129 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -6398,8 +6398,9 @@ gfc_trans_allocate (gfc_code * code)
   else
gfc_add_block_to_block (, );
 
-  /* Special case when string in expr3 is zero.  */
+  /* Special case when string in expr3 is scalar and has length zero.  */
   if (code->expr3->ts.type == BT_CHARACTER
+ && code->expr3->rank == 0
  && integer_zerop (se.string_length))
{
  gfc_init_se (, NULL);
diff --git a/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90 
b/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90
new file mode 100644
index ..4a9bd46da4d5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90
@@ -0,0 +1,33 @@
+! { dg-do run }
+!
+! PR fortran/83865
+!
+! Test ALLOCATE with SOURCE= of deferred length character, where
+! the source-expression is an array of character with length 0.
+
+program p
+  implicit none
+  character(:), allocatable :: z(:)
+  character(1) :: cc(4) = ""
+  allocate (z, source=[''])
+  if (len (z) /= 0 .or. size (z) /= 1) stop 1
+  deallocate (z)
+  allocate (z, source=['',''])
+  if (len (z) /= 0 .or. size (z) /= 2) stop 2
+  deallocate (z)
+  allocate (z, source=[ character(0) :: 'a','b','c'])
+  if (len (z) /= 0 .or. size (z) /= 3) stop 3
+  deallocate (z)
+  allocate (z, source=[ character(0) :: cc ])
+  if (len (z) /= 0 .or. size (z) /= 4) stop 4
+  deallocate (z)
+  associate (x => f())
+if (len (x) /= 0 .or. size (x) /= 1) stop 5
+if (x(1) /= '') stop 6
+  end associate
+contains
+  function f() result(z)
+character(:), allocatable :: z(:)
+allocate (z, source=[''])
+  end function f
+end


Re: [Fortran, Patch, PR 96992] Fix Class arrays of different ranks are rejected as storage association argument

2024-06-19 Thread Harald Anlauf

Hi Andre,

Am 19.06.24 um 09:07 schrieb Andre Vehreschild:

Hi Harald,

thank you for the investigation and useful tips. I had to figure what went
wrong here, but I now figured, that the array needs repacking when a negative
stride is used (or at least a call to that routine, which then fixes "stuff").
I have added it, freeing the memory allocated potentially by pack, and also
updated the testcase to include the negative stride.


hmmm, the pack does not always get generated:

module foo_mod
  implicit none
  type foo
 integer :: i
  end type foo
contains
  subroutine d1(x,n)
integer, intent(in) :: n
integer :: i
class (foo), intent(out) :: x(n)
select type(x)
class is(foo)
   x(:)%i = (/ (42 + i, i = 1, n ) /)
class default
   stop 1
end select
  end subroutine d1
  subroutine d2(x,n)
integer, intent(in) :: n
integer :: i
class (foo), intent(in) :: x(n,n,n)
select type (x)
class is (foo)
   print *,"d2:  ", x%i
   if ( any( x%i /= reshape((/ (42 + i, i = 1, n ** 3 ) /), [n, n, 
n] ))) stop 2

class default
   stop 3
end select
  end subroutine d2

  subroutine d3(x,n)
integer, intent(in) :: n
integer :: i
class (foo), intent(inout) :: x(n)
select type (x)
class is (foo)
   print *,"d3_1:", x%i
   x%i = -x%i   ! Simply negate elements
   print *,"d3_2:", x%i
class default
   stop 33
end select
  end subroutine d3
end module foo_mod
program main
  use foo_mod
  implicit none
  type (foo), dimension(:), allocatable :: f
  integer :: n, k, m
  n = 2
  allocate (f(n*n*n))
  ! Original testcase:
  call d1(f,n*n*n)
  print *, "d1->:", f%i
  call d2(f,n)
  ! Ensure that array f is ok:
  print *, "d2->:", f%i

  ! The following shows that no appropriate internal pack is generated:
  call d1(f,n*n*n)
  print *, "d1->:", f%i
  m = n*n*n
  k = 3
  print *, "->d3:", f(1:m:k)%i
  call d3(f(1:m:k),1+(m-1)/k)
  print *, "d3->:", f(1:m:k)%i
  print *, "full:", f%i
  deallocate (f)
end program main


After the second version of your patch this prints:

 d1->:  43  44  45  46  47 
48  49  50
 d2:43  44  45  46  47 
48  49  50
 d2->:  43  44  45  46  47 
48  49  50
 d1->:  43  44  45  46  47 
48  49  50

 ->d3:  43  46  49
 d3_1:  43  44  45
 d3_2: -43 -44 -45
 d3->: -43  46  49
 full: -43 -44 -45  46  47 
48  49  50


While the print properly handles f(1:m:k)%i, passing it as
actual argument to subroutine d3 does not do pack/unpack.

Can you have another look?

Thanks,
Harald



Regtests fine on x86_64-pc-linux-gnu/Fedora 39. Ok for mainline?

Regards,
Andre

On Sun, 16 Jun 2024 23:27:46 +0200
Harald Anlauf  wrote:

<< snipped for brevity >>>
--
Andre Vehreschild * Email: vehre ad gmx dot de





[gcc r15-1449] Fortran: fix for CHARACTER(len=*) dummies with bind(C) [PR115390]

2024-06-19 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:954f9011c4923b72f42cc6ca8460333e7c7aad98

commit r15-1449-g954f9011c4923b72f42cc6ca8460333e7c7aad98
Author: Harald Anlauf 
Date:   Tue Jun 18 21:57:19 2024 +0200

Fortran: fix for CHARACTER(len=*) dummies with bind(C) [PR115390]

gcc/fortran/ChangeLog:

PR fortran/115390
* trans-decl.cc (gfc_conv_cfi_to_gfc): Move derivation of type sizes
for character via gfc_trans_vla_type_sizes to after character length
has been set.

gcc/testsuite/ChangeLog:

PR fortran/115390
* gfortran.dg/bind_c_char_11.f90: New test.

Diff:
---
 gcc/fortran/trans-decl.cc|  4 +--
 gcc/testsuite/gfortran.dg/bind_c_char_11.f90 | 45 
 2 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index 88538713a02b..f7fb6eec336a 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -7063,8 +7063,8 @@ gfc_conv_cfi_to_gfc (stmtblock_t *init, stmtblock_t 
*finally,
   if (sym->ts.type == BT_CHARACTER
   && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
 {
-  gfc_conv_string_length (sym->ts.u.cl, NULL, init);
-  gfc_trans_vla_type_sizes (sym, init);
+  gfc_conv_string_length (sym->ts.u.cl, NULL, );
+  gfc_trans_vla_type_sizes (sym, );
 }
 
   /* gfc->data = cfi->base_addr - or for scalars: gfc = cfi->base_addr.
diff --git a/gcc/testsuite/gfortran.dg/bind_c_char_11.f90 
b/gcc/testsuite/gfortran.dg/bind_c_char_11.f90
new file mode 100644
index ..5ed8e82853bf
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind_c_char_11.f90
@@ -0,0 +1,45 @@
+! { dg-do compile }
+! { dg-additional-options "-Wuninitialized" }
+!
+! PR fortran/115390 - fixes for CHARACTER(len=*) dummies with bind(C)
+
+module test
+  implicit none
+contains
+  subroutine bar(s,t) bind(c)
+character(*), intent(in) :: s,t
+optional :: t
+call foo(s,t)
+  end
+  subroutine bar1(s,t) bind(c)
+character(*), intent(in) :: s(:),t(:)
+optional :: t
+call foo1(s,t)
+  end
+  subroutine bar4(s,t) bind(c)
+character(len=*,kind=4), intent(in) :: s,t
+optional:: t
+call foo4(s,t)
+  end
+  subroutine bar5(s,t) bind(c)
+character(len=*,kind=4), intent(in) :: s(:),t(:)
+optional:: t
+call foo5(s,t)
+  end
+  subroutine foo(s,t)
+character(*), intent(in) :: s,t
+optional :: t
+  end
+  subroutine foo1(s,t)
+character(*), intent(in) :: s(:),t(:)
+optional :: t
+  end
+  subroutine foo4(s,t)
+character(len=*,kind=4), intent(in) :: s,t
+optional:: t
+  end
+  subroutine foo5(s,t)
+character(len=*,kind=4), intent(in) :: s(:),t(:)
+optional:: t
+  end
+end


[PATCH] Fortran: fix for CHARACTER(len=*) dummies with bind(C) [PR115390]

2024-06-18 Thread Harald Anlauf
Dear all,

the attached simple patch fixes warnings for use of uninitialized
temporaries for the string length before being defined.  The cause
is obvious: type sizes were being calculated before the temporaries
were set from the descriptor for the dummy passed to the BIND(C)
procedure.  Wrong code might have been possible as well.

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

Thanks,
Harald

From 95a3cefd5e84cf0d393c2606757894389c08ebba Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Tue, 18 Jun 2024 21:57:19 +0200
Subject: [PATCH] Fortran: fix for CHARACTER(len=*) dummies with bind(C)
 [PR115390]

gcc/fortran/ChangeLog:

	PR fortran/115390
	* trans-decl.cc (gfc_conv_cfi_to_gfc): Move derivation of type sizes
	for character via gfc_trans_vla_type_sizes to after character length
	has been set.

gcc/testsuite/ChangeLog:

	PR fortran/115390
	* gfortran.dg/bind_c_char_11.f90: New test.
---
 gcc/fortran/trans-decl.cc|  4 +-
 gcc/testsuite/gfortran.dg/bind_c_char_11.f90 | 45 
 2 files changed, 47 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/bind_c_char_11.f90

diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index dca7779528b..704f24be84a 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -7063,8 +7063,8 @@ gfc_conv_cfi_to_gfc (stmtblock_t *init, stmtblock_t *finally,
   if (sym->ts.type == BT_CHARACTER
   && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
 {
-  gfc_conv_string_length (sym->ts.u.cl, NULL, init);
-  gfc_trans_vla_type_sizes (sym, init);
+  gfc_conv_string_length (sym->ts.u.cl, NULL, );
+  gfc_trans_vla_type_sizes (sym, );
 }

   /* gfc->data = cfi->base_addr - or for scalars: gfc = cfi->base_addr.
diff --git a/gcc/testsuite/gfortran.dg/bind_c_char_11.f90 b/gcc/testsuite/gfortran.dg/bind_c_char_11.f90
new file mode 100644
index 000..5ed8e82853b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind_c_char_11.f90
@@ -0,0 +1,45 @@
+! { dg-do compile }
+! { dg-additional-options "-Wuninitialized" }
+!
+! PR fortran/115390 - fixes for CHARACTER(len=*) dummies with bind(C)
+
+module test
+  implicit none
+contains
+  subroutine bar(s,t) bind(c)
+character(*), intent(in) :: s,t
+optional :: t
+call foo(s,t)
+  end
+  subroutine bar1(s,t) bind(c)
+character(*), intent(in) :: s(:),t(:)
+optional :: t
+call foo1(s,t)
+  end
+  subroutine bar4(s,t) bind(c)
+character(len=*,kind=4), intent(in) :: s,t
+optional:: t
+call foo4(s,t)
+  end
+  subroutine bar5(s,t) bind(c)
+character(len=*,kind=4), intent(in) :: s(:),t(:)
+optional:: t
+call foo5(s,t)
+  end
+  subroutine foo(s,t)
+character(*), intent(in) :: s,t
+optional :: t
+  end
+  subroutine foo1(s,t)
+character(*), intent(in) :: s(:),t(:)
+optional :: t
+  end
+  subroutine foo4(s,t)
+character(len=*,kind=4), intent(in) :: s,t
+optional:: t
+  end
+  subroutine foo5(s,t)
+character(len=*,kind=4), intent(in) :: s(:),t(:)
+optional:: t
+  end
+end
--
2.35.3



Re: [Patch, Fortran, 96418] Fix Test coarray_alloc_comp_4.f08 ICEs

2024-06-17 Thread Harald Anlauf

Hi Andre,

Am 17.06.24 um 09:51 schrieb Andre Vehreschild:

Regarding your question on the coarray-tests that are not in the
coarray-directory: These test in most cases test only one method of
implementing coarrays. I.e., they are either testing just -fcoarray=single or
-fcoarray=lib -lcaf_single, which are two different approaches. The tests in
the coarray-directory test all available methods to implement coarrays.  Pushing


ah, that explains it.  I only looked at some of the test sources,
but did not think of looking at caf.exp ...


all coarray-tests into the coarray-directory will fail a lot of them, because
the behavior of -fcoarray=single and -fcoarray=lib -lcaf_single is different in
some corner cases. That's why the coarray-tests in the main gfortran-dir are
separate.

I do understand why it may be confusing, but I don't see an easy solution. Does
this answer your question?


Indeed it does!

Thanks,
Harald



Re: [Fortran, Patch, PR 96992] Fix Class arrays of different ranks are rejected as storage association argument

2024-06-16 Thread Harald Anlauf

Hi Andre,

Am 14.06.24 um 17:05 schrieb Andre Vehreschild:

Hi all,

I somehow got assigned to this PR so I fixed it. GFortran was ICEing because of
the ASSUME_RANK in a derived to class conversion. After fixing this, storage
association was producing segfaults. The "shape conversion" of the class array
as dummy argument was not initializing the dim 0 stride and with that grabbing
into the memory somewhere. This is now fixed and

regtests fine on x86_64 Fedora 39. Ok for mainline?


the patch fixes the testcase in your submission, but not the following
slight variation of the main program:

module foo_mod
  implicit none
  type foo
 integer :: i
  end type foo
contains
  subroutine d1(x,n)
integer, intent(in) :: n
integer :: i
class (foo), intent(out) :: x(n)
select type(x)
class is(foo)
   x(:)%i = (/ (42 + i, i = 1, n ) /)
class default
   stop 1
end select
  end subroutine d1
  subroutine d2(x,n)
integer, intent(in) :: n
integer :: i
class (foo), intent(in) :: x(n,n,n)
select type (x)
class is (foo)
   print *,x%i
   if ( any( x%i /= reshape((/ (42 + i, i = 1, n ** 3 ) /), [n, n, 
n] ))) stop 2

class default
   stop 3
end select
  end subroutine d2
end module foo_mod
program main
  use foo_mod
  implicit none
  type (foo), dimension(:), allocatable :: f
  integer :: n
  n = 2
  allocate (f(n*n*n))
  ! Original testcase:
  call d1(f,n*n*n)
  call d2(f,n)  ! OK
  call d1(f(1:n*n*n),n*n*n)
  print *, "After call d1(f(1:n*n*n:1),n*n*n):"
  print *, f%i
  call d2(f(1:n*n*n),n) ! OK
  ! Using stride -1:
  call d1(f(n*n*n:1:-1),n*n*n)
  print *, "After call d1(f(n*n*n:1:-1),n*n*n):"
  print *, f%i
  call d2(f(n*n*n:1:-1),n)  ! not OK
  deallocate (f)
end program main

While this runs fine with the latest Intel compiler, gfortran including
your patch prints:

  43  44  45  46  47 
48  49  50

 After call d1(f(1:n*n*n:1),n*n*n):
  43  44  45  46  47 
48  49  50
  43  44  45  46  47 
48  49  50

 After call d1(f(n*n*n:1:-1),n*n*n):
  50  49  48  47  46 
45  44  43
  43   0   0  49   0 
34244976   034238480

STOP 2

So while the negative stride (-1) in the call to d1 appears to
work as it should, it does not work properly for the call to d2.
The first array element is fine in d2, but anything else isn't.

Do you see what goes wrong here?

(This may be a more general, pre-existing issue in a different place.)

Thanks,
Harald

P.S.: regarding your commit message, I think the reference to the pr
in brackets should be moved to the end of the summary line, i.e. for

Fortran: [PR96992] Fix rejecting class arrays of different ranks as 
storage association argument.


the "[PR96992" should be moved.  Makes it also easier to read.


I assume this patch could be fixing some other PRs with class array's parameter
passing, too. If that sounds familiar, feel free to point me to them.

Regards,
Andre
--
Andre Vehreschild * Email: vehre ad gmx dot de





Re: [Patch, fortran] PR59104

2024-06-14 Thread Harald Anlauf

Hi Paul,

this looks good to me and is OK for mainline.  When it has survived a
week or two, backporting at least to 14-branch (ideally before 14.2
release) would be a good thing!

Regarding the following excerpt of the testcase:

+! Commented out lines give implicit type warnings with gfortran and nagfor
+!character(len = len (d)) :: line4 (len (line3))
+character(len = len (line3)) :: line4 (len (line3))
+!character(len = size(len4, 1)) :: line5

I guess the last commented line should have referred to size(line4, 1),
right?  The lexical distance of len4 and line4 can be small after
long coding...

The first commented line gives no warning here, but is simply
inconsistent with a test later on, since len (d) < len (line3).
What exactly was the issue?

***

A minor nit: while you were fixing whitespace issues in the source,
you missed an indent with spaces here:

@@ -857,12 +873,26 @@ gfc_defer_symbol_init (gfc_symbol * sym)
   /* Find the first dummy arg seen after us, or the first
non-dummy arg.
  This is a circular list, so don't go past the head.  */
   while (p != head
- && (!p->attr.dummy || p->dummy_order > sym->dummy_order))
+ && (!p->attr.dummy || decl_order (p, sym)))
 {

At least on my side there is no tab...
(It is fine in a similar code later on.)

***

Finally a big thanks for the patch!

Harald


Am 13.06.24 um 23:43 schrieb Paul Richard Thomas:

Hi Both,

Thanks for the highly constructive comments. I think that I have
incorporated them fully in the attached.

OK for mainline and ...?

Paul


On Mon, 10 Jun 2024 at 08:19, Andre Vehreschild  wrote:


Hi Paul,

while looking at your patch I see calls to gfc_add_init_cleanup (...,
back),
while the function signature is gfc_add_init_cleanup (..., bool front).
This
slightly confuses me. I would at least expect to see
gfc_add_init_cleanup(...,
!back) calls. Just to get the semantics right.

Then I wonder why not doing:

diff --git a/gcc/fortran/dependency.cc b/gcc/fortran/dependency.cc
index bafe8cbc5bc..97ace8c778e 100644
--- a/gcc/fortran/dependency.cc
+++ b/gcc/fortran/dependency.cc
@@ -2497,3 +2497,63 @@ gfc_omp_expr_prefix_same (gfc_expr *lexpr, gfc_expr
*rexpr)
return true;
  }
+
+
+/* gfc_function_dependency returns true for non-dummy symbols with
dependencies
+   on an old-fashioned function result (ie. proc_name =
proc_name->result).
+   This is used to ensure that initialization code appears after the
function
+   result is treated and that any mutual dependencies between these
symbols are
+   respected.  */
+
+static bool
+dependency_fcn (gfc_expr *e, gfc_symbol *sym,
+int *f ATTRIBUTE_UNUSED)
+{
+  return (e && e->expr_type == EXPR_VARIABLE
+  && e->symtree
+  && e->symtree->n.sym == sym);
+}

Instead of the multiple if-statements?

+
+bool
+gfc_function_dependency (gfc_symbol *sym, gfc_symbol *proc_name)
+{
+  bool front = false;
+
+  if (proc_name && proc_name->attr.function
+  && proc_name == proc_name->result
+  && !(sym->attr.dummy || sym->attr.result))
+{
+  if (sym->as && sym->as->type == AS_EXPLICIT)
+   {
+ for (int dim = 0; dim < sym->as->rank; dim++)
+   {
+ if (sym->as->lower[dim]
+ && sym->as->lower[dim]->expr_type != EXPR_CONSTANT)
+   front = gfc_traverse_expr (sym->as->lower[dim], proc_name,
+  dependency_fcn, 0);
+ if (front)
+   break;
+ if (sym->as->upper[dim]
+ && sym->as->upper[dim]->expr_type != EXPR_CONSTANT)
+   front = gfc_traverse_expr (sym->as->upper[dim], proc_name,
+  dependency_fcn, 0);
+ if (front)
+   break;
+   }
+   }
+
+  if (sym->ts.type == BT_CHARACTER
+ && sym->ts.u.cl && sym->ts.u.cl->length
+ && sym->ts.u.cl->length->expr_type != EXPR_CONSTANT)
+   front = gfc_traverse_expr (sym->ts.u.cl->length, proc_name,
+  dependency_fcn, 0);

This can overwrite a previous front == true, right? Is this intended?

+}
+  return front;
+ }

The rest - besides the front-back confusion - looks fine to me. Thanks for
the
patch.

Regards,
 Andre

On Sun, 9 Jun 2024 07:14:39 +0100
Paul Richard Thomas  wrote:


Hi All,

The attached fixes a problem that, judging by the comments, has been

looked

at periodically over the last ten years but just looked to be too
fiendishly complicated to fix. This is not in small part because of the
confusing ordering of dummies in the tlink chain and the unintuitive
placement of all deferred initializations to the front of the init chain

in

the wrapped block.

The result of the existing ordering is that the initialization code for
non-dummy variables that depends on the function result occurs before any
initialization code for the function result itself. The fix 

Re: [Patch, Fortran, 96418] Fix Test coarray_alloc_comp_4.f08 ICEs

2024-06-14 Thread Harald Anlauf

Hi Andre,

the patch looks fairly simple and obvious, so OK from my side.

***

Regarding the testsuite: since you renamed one of the testcases
gfortran.dg/coarray_alloc_comp_* and moved it to gfortran.dg/coarray/,
I checked and noticed that there are other similar runtime tests for
coarrays (while some are compile-time only tests).

Do we plan to "clean" this up and move more/all related runtime
tests to the coarray/ subdirectory?  What is the general opinion on
this?

***

Thanks for the patch!

Harald


Am 14.06.24 um 09:22 schrieb Andre Vehreschild:

Hi all,

I messed up renaming of the coarray_alloc_comp-test. This is fixed in the second
version of the patch. Sorry for the inconvenience.

Additionally I figured that this patch also fixed PR fortran/103112.

Regtests ok on x86_64 Fedora 39. Ok for mainline?

Regards,
Andre

On Tue, 11 Jun 2024 16:12:38 +0200
Andre Vehreschild  wrote:


Hi all,

attached patch has already been present in 2020, but lost my attention. It
fixes an ICE in the testsuite. The old mails description is:

attached patch fixes PR96418 where the code in the testsuite when compiled
with -fcoarray=single  lead to an ICE. The reason was that the coarray object
was derefed as an array, but it was no array. Introducing the test for the
descriptor removes the ICE.

Regtests ok on x86_64-linux/Fedora 39. Ok for mainline?

Regards,
Andre
--
Andre Vehreschild * Email: vehre ad gmx dot de



--
Andre Vehreschild * Email: vehre ad gmx dot de




Re: [Patch, fortran] PR59104

2024-06-09 Thread Harald Anlauf

Hi Paul,

your approach sounds entirely reasonable.

But as the following addition to the testcase shows, there seem to
be loopholes left.

When I add the following to function f:

 integer :: l1(size(y))
 integer :: l2(size(z))
 print *, size (l1), size (l2), size (z)

I get:

   0   0   3

Expected:

   2   3   3

Can you please check?

Thanks,
Harald


Am 09.06.24 um 17:57 schrieb Paul Richard Thomas:

Hi All,

I have extended the testcase - see below and have
s/dependent_decls_2/dependent_decls_2.f90/ in the ChnageLog.

Cheers

Paul

! { dg-do run }
!
! Fix for PR59104 in which the dependence on the old style function result
! was not taken into account in the ordering of auto array allocation and
! characters with dependent lengths.
!
! Contributed by Tobias Burnus  
!
module m
implicit none
integer, parameter :: dp = kind([double precision::])
contains
   function f(x)
  integer, intent(in) :: x
  real(dp) f(x/2)
  real(dp) g(x/2)
  integer y(size (f)+1) ! This was the original problem
  integer z(size (f) + size (y)) ! Found in development of the fix
  integer w(size (f) + size (y) + x) ! Check dummy is OK
  f = 10.0
  y = 1! Stop -Wall from complaining
  z = 1
  g = 1
  w = 1
  if (size (f) .ne. 1) stop 1
  if (size (g) .ne. 1) stop 2
  if (size (y) .ne. 2) stop 3
  if (size (z) .ne. 3) stop 4
  if (size (w) .ne. 5) stop 5
   end function f
   function e(x) result(f)
  integer, intent(in) :: x
  real(dp) f(x/2)
  real(dp) g(x/2)
  integer y(size (f)+1)
  integer z(size (f) + size (y)) ! As was this.
  integer w(size (f) + size (y) + x)
  f = 10.0
  y = 1
  z = 1
  g = 1
  w = 1
  if (size (f) .ne. 2) stop 6
  if (size (g) .ne. 2) stop 7
  if (size (y) .ne. 3) stop 8
  if (size (z) .ne. 5) stop 9
  if (size (w) .ne. 9) stop 10
   end function
   function d(x)  ! After fixes to arrays, what was needed was known!
 integer, intent(in) :: x
 character(len = x/2) :: d
 character(len = len (d)) :: line
 character(len = len (d) + len (line)) :: line2
 character(len = len (d) + len (line) + x) :: line3
 line = repeat ("a", len (d))
 line2 = repeat ("b", x)
 line3 = repeat ("c", len (line3))
 if (len (line2) .ne. x) stop 11
 if (line3 .ne. "") stop 12
 d = line
   end
end module m

program p
use m
implicit none
real(dp) y

y = sum (f (2))
if (int (y) .ne. 10) stop 13
y = sum (e (4))
if (int (y) .ne. 20) stop 14
if (d (4) .ne. "aa") stop 15
end program p



On Sun, 9 Jun 2024 at 07:14, Paul Richard Thomas <
paul.richard.tho...@gmail.com> wrote:


Hi All,

The attached fixes a problem that, judging by the comments, has been
looked at periodically over the last ten years but just looked to be too
fiendishly complicated to fix. This is not in small part because of the
confusing ordering of dummies in the tlink chain and the unintuitive
placement of all deferred initializations to the front of the init chain in
the wrapped block.

The result of the existing ordering is that the initialization code for
non-dummy variables that depends on the function result occurs before any
initialization code for the function result itself. The fix ensures that:
(i) These variables are placed correctly in the tlink chain, respecting
inter-dependencies; and (ii) The dependent initializations are placed at
the end of the wrapped block init chain.  The details appear in the
comments in the patch. It is entirely possible that a less clunky fix
exists but I failed to find it.

OK for mainline?

Regards

Paul











[gcc r14-10291] Fortran: fix ALLOCATE with SOURCE=, zero-length character [PR83865]

2024-06-08 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:c3e16edcf2c8429da2cb479d8941397f4300e0c4

commit r14-10291-gc3e16edcf2c8429da2cb479d8941397f4300e0c4
Author: Harald Anlauf 
Date:   Mon Jun 3 22:02:06 2024 +0200

Fortran: fix ALLOCATE with SOURCE=, zero-length character [PR83865]

gcc/fortran/ChangeLog:

PR fortran/83865
* trans-stmt.cc (gfc_trans_allocate): Restrict special case for
source-expression with zero-length character to rank 0, so that
the array shape is not discarded.

gcc/testsuite/ChangeLog:

PR fortran/83865
* gfortran.dg/allocate_with_source_32.f90: New test.

(cherry picked from commit 7f21aee0d4ef95eee7d9f7f42e9a056715836648)

Diff:
---
 gcc/fortran/trans-stmt.cc  |  3 +-
 .../gfortran.dg/allocate_with_source_32.f90| 33 ++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index d355009fa5e..87dd833872a 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -6449,8 +6449,9 @@ gfc_trans_allocate (gfc_code * code, gfc_omp_namelist 
*omp_allocate)
   else
gfc_add_block_to_block (, );
 
-  /* Special case when string in expr3 is zero.  */
+  /* Special case when string in expr3 is scalar and has length zero.  */
   if (code->expr3->ts.type == BT_CHARACTER
+ && code->expr3->rank == 0
  && integer_zerop (se.string_length))
{
  gfc_init_se (, NULL);
diff --git a/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90 
b/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90
new file mode 100644
index 000..4a9bd46da4d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90
@@ -0,0 +1,33 @@
+! { dg-do run }
+!
+! PR fortran/83865
+!
+! Test ALLOCATE with SOURCE= of deferred length character, where
+! the source-expression is an array of character with length 0.
+
+program p
+  implicit none
+  character(:), allocatable :: z(:)
+  character(1) :: cc(4) = ""
+  allocate (z, source=[''])
+  if (len (z) /= 0 .or. size (z) /= 1) stop 1
+  deallocate (z)
+  allocate (z, source=['',''])
+  if (len (z) /= 0 .or. size (z) /= 2) stop 2
+  deallocate (z)
+  allocate (z, source=[ character(0) :: 'a','b','c'])
+  if (len (z) /= 0 .or. size (z) /= 3) stop 3
+  deallocate (z)
+  allocate (z, source=[ character(0) :: cc ])
+  if (len (z) /= 0 .or. size (z) /= 4) stop 4
+  deallocate (z)
+  associate (x => f())
+if (len (x) /= 0 .or. size (x) /= 1) stop 5
+if (x(1) /= '') stop 6
+  end associate
+contains
+  function f() result(z)
+character(:), allocatable :: z(:)
+allocate (z, source=[''])
+  end function f
+end


[gcc r15-1018] Fortran: fix ALLOCATE with SOURCE=, zero-length character [PR83865]

2024-06-04 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:7f21aee0d4ef95eee7d9f7f42e9a056715836648

commit r15-1018-g7f21aee0d4ef95eee7d9f7f42e9a056715836648
Author: Harald Anlauf 
Date:   Mon Jun 3 22:02:06 2024 +0200

Fortran: fix ALLOCATE with SOURCE=, zero-length character [PR83865]

gcc/fortran/ChangeLog:

PR fortran/83865
* trans-stmt.cc (gfc_trans_allocate): Restrict special case for
source-expression with zero-length character to rank 0, so that
the array shape is not discarded.

gcc/testsuite/ChangeLog:

PR fortran/83865
* gfortran.dg/allocate_with_source_32.f90: New test.

Diff:
---
 gcc/fortran/trans-stmt.cc  |  3 +-
 .../gfortran.dg/allocate_with_source_32.f90| 33 ++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 9b497d6bdc6..93b633e212e 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -6449,8 +6449,9 @@ gfc_trans_allocate (gfc_code * code, gfc_omp_namelist 
*omp_allocate)
   else
gfc_add_block_to_block (, );
 
-  /* Special case when string in expr3 is zero.  */
+  /* Special case when string in expr3 is scalar and has length zero.  */
   if (code->expr3->ts.type == BT_CHARACTER
+ && code->expr3->rank == 0
  && integer_zerop (se.string_length))
{
  gfc_init_se (, NULL);
diff --git a/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90 
b/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90
new file mode 100644
index 000..4a9bd46da4d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90
@@ -0,0 +1,33 @@
+! { dg-do run }
+!
+! PR fortran/83865
+!
+! Test ALLOCATE with SOURCE= of deferred length character, where
+! the source-expression is an array of character with length 0.
+
+program p
+  implicit none
+  character(:), allocatable :: z(:)
+  character(1) :: cc(4) = ""
+  allocate (z, source=[''])
+  if (len (z) /= 0 .or. size (z) /= 1) stop 1
+  deallocate (z)
+  allocate (z, source=['',''])
+  if (len (z) /= 0 .or. size (z) /= 2) stop 2
+  deallocate (z)
+  allocate (z, source=[ character(0) :: 'a','b','c'])
+  if (len (z) /= 0 .or. size (z) /= 3) stop 3
+  deallocate (z)
+  allocate (z, source=[ character(0) :: cc ])
+  if (len (z) /= 0 .or. size (z) /= 4) stop 4
+  deallocate (z)
+  associate (x => f())
+if (len (x) /= 0 .or. size (x) /= 1) stop 5
+if (x(1) /= '') stop 6
+  end associate
+contains
+  function f() result(z)
+character(:), allocatable :: z(:)
+allocate (z, source=[''])
+  end function f
+end


[PATCH] Fortran: fix ALLOCATE with SOURCE=, zero-length character [PR83865]

2024-06-03 Thread Harald Anlauf
Dear all,

the attached simple patch fixes an ICE for ALLOCATE with SOURCE=
of a deferred-length character array with source-expression
being an array of character with length zero.  The reason was
that the array descriptor of the source-expression was discarded
in the special case of length 0.

Solution: restrict special case to rank 0.

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

The offending code was introduced during 7-development,
so it is technically a regression.  I would therefore
like to backport after waiting for a week or two.

Thanks,
Harald
From ae5e3654d30d17584cfcfc3bbcc48cf75cb7453c Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Mon, 3 Jun 2024 22:02:06 +0200
Subject: [PATCH] Fortran: fix ALLOCATE with SOURCE=, zero-length character
 [PR83865]

gcc/fortran/ChangeLog:

	PR fortran/83865
	* trans-stmt.cc (gfc_trans_allocate): Restrict special case for
	source-expression with zero-length character to rank 0, so that
	the array shape is not discarded.

gcc/testsuite/ChangeLog:

	PR fortran/83865
	* gfortran.dg/allocate_with_source_32.f90: New test.
---
 gcc/fortran/trans-stmt.cc |  3 +-
 .../gfortran.dg/allocate_with_source_32.f90   | 33 +++
 2 files changed, 35 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gfortran.dg/allocate_with_source_32.f90

diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 9b497d6bdc6..93b633e212e 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -6449,8 +6449,9 @@ gfc_trans_allocate (gfc_code * code, gfc_omp_namelist *omp_allocate)
   else
 	gfc_add_block_to_block (, );

-  /* Special case when string in expr3 is zero.  */
+  /* Special case when string in expr3 is scalar and has length zero.  */
   if (code->expr3->ts.type == BT_CHARACTER
+	  && code->expr3->rank == 0
 	  && integer_zerop (se.string_length))
 	{
 	  gfc_init_se (, NULL);
diff --git a/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90 b/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90
new file mode 100644
index 000..4a9bd46da4d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90
@@ -0,0 +1,33 @@
+! { dg-do run }
+!
+! PR fortran/83865
+!
+! Test ALLOCATE with SOURCE= of deferred length character, where
+! the source-expression is an array of character with length 0.
+
+program p
+  implicit none
+  character(:), allocatable :: z(:)
+  character(1) :: cc(4) = ""
+  allocate (z, source=[''])
+  if (len (z) /= 0 .or. size (z) /= 1) stop 1
+  deallocate (z)
+  allocate (z, source=['',''])
+  if (len (z) /= 0 .or. size (z) /= 2) stop 2
+  deallocate (z)
+  allocate (z, source=[ character(0) :: 'a','b','c'])
+  if (len (z) /= 0 .or. size (z) /= 3) stop 3
+  deallocate (z)
+  allocate (z, source=[ character(0) :: cc ])
+  if (len (z) /= 0 .or. size (z) /= 4) stop 4
+  deallocate (z)
+  associate (x => f())
+if (len (x) /= 0 .or. size (x) /= 1) stop 5
+if (x(1) /= '') stop 6
+  end associate
+contains
+  function f() result(z)
+character(:), allocatable :: z(:)
+allocate (z, source=[''])
+  end function f
+end
--
2.35.3



Re: [PATCH 03/52] fortran: Replace uses of {FLOAT, {, LONG_}DOUBLE}_TYPE_SIZE

2024-06-03 Thread Harald Anlauf

Hi,

Am 03.06.24 um 05:00 schrieb Kewen Lin:

Joseph pointed out "floating types should have their mode,
not a poorly defined precision value" in the discussion[1],
as he and Richi suggested, the existing macros
{FLOAT,{,LONG_}DOUBLE}_TYPE_SIZE will be replaced with a
hook mode_for_floating_type.  To be prepared for that, this
patch is to replace use of {FLOAT,{,LONG_}DOUBLE}_TYPE_SIZE
in fortran with TYPE_PRECISION of
{float,{,long_}double}_type_node.

[1] https://gcc.gnu.org/pipermail/gcc-patches/2024-May/651209.html

gcc/fortran/ChangeLog:

* trans-intrinsic.cc (build_round_expr): Use TYPE_PRECISION of
long_double_type_node to replace LONG_DOUBLE_TYPE_SIZE.
* trans-types.cc (gfc_build_real_type): Use TYPE_PRECISION of
{float,double,long_double}_type_node to replace
{FLOAT,DOUBLE,LONG_DOUBLE}_TYPE_SIZE.
---
  gcc/fortran/trans-intrinsic.cc |  3 ++-
  gcc/fortran/trans-types.cc | 10 ++
  2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 912c1000e18..96839705112 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -395,7 +395,8 @@ build_round_expr (tree arg, tree restype)
   don't have an appropriate function that converts directly to the integer
   type (such as kind == 16), just use ROUND, and then convert the result to
   an integer.  We might also need to convert the result afterwards.  */
-  if (resprec <= INT_TYPE_SIZE && argprec <= LONG_DOUBLE_TYPE_SIZE)
+  if (resprec <= INT_TYPE_SIZE
+  && argprec <= TYPE_PRECISION (long_double_type_node))
  fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
else if (resprec <= LONG_TYPE_SIZE)
  fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
diff --git a/gcc/fortran/trans-types.cc b/gcc/fortran/trans-types.cc
index 8466c595e06..0ef67723fcd 100644
--- a/gcc/fortran/trans-types.cc
+++ b/gcc/fortran/trans-types.cc
@@ -873,13 +873,15 @@ gfc_build_real_type (gfc_real_info *info)
int mode_precision = info->mode_precision;
tree new_type;

-  if (mode_precision == FLOAT_TYPE_SIZE)
+  if (mode_precision == TYPE_PRECISION (float_type_node))
  info->c_float = 1;
-  if (mode_precision == DOUBLE_TYPE_SIZE)
+  if (mode_precision == TYPE_PRECISION (double_type_node))
  info->c_double = 1;
-  if (mode_precision == LONG_DOUBLE_TYPE_SIZE && !info->c_float128)
+  if (mode_precision == TYPE_PRECISION (long_double_type_node)
+  && !info->c_float128)
  info->c_long_double = 1;
-  if (mode_precision != LONG_DOUBLE_TYPE_SIZE && mode_precision == 128)
+  if (mode_precision != TYPE_PRECISION (long_double_type_node)
+  && mode_precision == 128)
  {
/* TODO: see PR101835.  */
info->c_float128 = 1;


the Fortran part looks good to me.

Thanks,
Harald



Re: [Patch, PR Fortran/90069] Polymorphic Return Type Memory Leak Without Intermediate Variable

2024-05-28 Thread Harald Anlauf

Hi Andre,

On 5/28/24 14:10, Andre Vehreschild wrote:

Hi all,

the attached patch fixes a memory leak with unlimited polymorphic return types.
The leak occurred, because an expression with side-effects was evaluated twice.
I have substituted the check for non-variable expressions followed by creating a
SAVE_EXPR with checking for trees with side effects and creating temp. variable
and freeing the memory.


this looks good to me.  It also solves the runtime memory leak in
testcase pr114012.f90 .  Nice!


Btw, I do not get the SAVE_EXPR in the old code. Is there something missing to
manifest it or is a SAVE_EXPR not meant to be evaluated twice?


I was assuming that the comment in gcc/tree.h applies here:

/* save_expr (EXP) returns an expression equivalent to EXP
   but it can be used multiple times within context CTX
   and only evaluate EXP once.  */

I do not know what the practical difference between a SAVE_EXPR
and a temporary explicitly evaluated once (which you have now)
is, except that you can free the temporary cleanly.


Anyway, regtested ok on Linux-x86_64-Fedora_39. Ok for master?


Yes, this is fine from my side.  If you are inclined to backport
to e.g. 14-branch after a grace period, that would be great.


This work is funded by the Souvereign Tech Fund. Yes, the funding has been
granted and Nicolas, Mikael and me will be working on some Fortran topics in
the next 12-18 months.


This is really great news!


Regards,
Andre


Thanks for the patch!

Harald


--
Andre Vehreschild * Email: vehre ad gmx dot de




[gcc r14-10244] Fortran: fix bounds check for assignment, class component [PR86100]

2024-05-25 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:b0b21d5bdfbc7d417b70010a11354b44968bb184

commit r14-10244-gb0b21d5bdfbc7d417b70010a11354b44968bb184
Author: Harald Anlauf 
Date:   Mon May 13 22:06:33 2024 +0200

Fortran: fix bounds check for assignment, class component [PR86100]

gcc/fortran/ChangeLog:

PR fortran/86100
* trans-array.cc (gfc_conv_ss_startstride): Use abridged_ref_name
to generate a more user-friendly name for bounds-check messages.
* trans-expr.cc (gfc_copy_class_to_class): Fix bounds check for
rank>1 by looping over the dimensions.

gcc/testsuite/ChangeLog:

PR fortran/86100
* gfortran.dg/bounds_check_25.f90: New test.

(cherry picked from commit 93765736815a049e14d985b758a213cfe60c1e1c)

Diff:
---
 gcc/fortran/trans-array.cc|  7 -
 gcc/fortran/trans-expr.cc | 40 +++
 gcc/testsuite/gfortran.dg/bounds_check_25.f90 | 32 +
 3 files changed, 60 insertions(+), 19 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 7ec33fb1598..a15ff30e8f4 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -4911,6 +4911,7 @@ done:
  gfc_expr *expr;
  locus *expr_loc;
  const char *expr_name;
+ char *ref_name = NULL;
 
  ss_info = ss->info;
  if (ss_info->type != GFC_SS_SECTION)
@@ -4922,7 +4923,10 @@ done:
 
  expr = ss_info->expr;
  expr_loc = >where;
- expr_name = expr->symtree->name;
+ if (expr->ref)
+   expr_name = ref_name = abridged_ref_name (expr, NULL);
+ else
+   expr_name = expr->symtree->name;
 
  gfc_start_block ();
 
@@ -5134,6 +5138,7 @@ done:
 
  gfc_add_expr_to_block (, tmp);
 
+ free (ref_name);
}
 
   tmp = gfc_finish_block ();
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index bc8eb419cff..d5fd6e39996 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -1518,7 +1518,6 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, 
bool unlimited)
   stmtblock_t body;
   stmtblock_t ifbody;
   gfc_loopinfo loop;
-  tree orig_nelems = nelems; /* Needed for bounds check.  */
 
   gfc_init_block ();
   tmp = fold_build2_loc (input_location, MINUS_EXPR,
@@ -1550,27 +1549,32 @@ gfc_copy_class_to_class (tree from, tree to, tree 
nelems, bool unlimited)
   /* Add bounds check.  */
   if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) > 0 && is_from_desc)
{
- char *msg;
  const char *name = "<>";
- tree from_len;
+ int dim, rank;
 
  if (DECL_P (to))
-   name = (const char *)(DECL_NAME (to)->identifier.id.str);
-
- from_len = gfc_conv_descriptor_size (from_data, 1);
- from_len = fold_convert (TREE_TYPE (orig_nelems), from_len);
- tmp = fold_build2_loc (input_location, NE_EXPR,
- logical_type_node, from_len, orig_nelems);
- msg = xasprintf ("Array bound mismatch for dimension %d "
-  "of array '%s' (%%ld/%%ld)",
-  1, name);
-
- gfc_trans_runtime_check (true, false, tmp, ,
-  _current_locus, msg,
-fold_convert (long_integer_type_node, orig_nelems),
-  fold_convert (long_integer_type_node, from_len));
+   name = IDENTIFIER_POINTER (DECL_NAME (to));
 
- free (msg);
+ rank = GFC_TYPE_ARRAY_RANK (TREE_TYPE (from_data));
+ for (dim = 1; dim <= rank; dim++)
+   {
+ tree from_len, to_len, cond;
+ char *msg;
+
+ from_len = gfc_conv_descriptor_size (from_data, dim);
+ from_len = fold_convert (long_integer_type_node, from_len);
+ to_len = gfc_conv_descriptor_size (to_data, dim);
+ to_len = fold_convert (long_integer_type_node, to_len);
+ msg = xasprintf ("Array bound mismatch for dimension %d "
+  "of array '%s' (%%ld/%%ld)",
+  dim, name);
+ cond = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node, from_len, to_len);
+ gfc_trans_runtime_check (true, false, cond, ,
+  _current_locus, msg,
+  to_len, from_len);
+ free (msg);
+   }
}
 
   tmp = build_call_vec (fcn_type, fcn, args);
diff --git a/gcc/testsuite/gfortran.dg/bounds_check_25.f90 
b/gcc/testsuite/gfortran.dg/bounds_check_25.f90
new file mode 100644
index 000..cc2247597f9
--- /dev/nu

[gcc r15-828] Fortran: improve attribute conflict checking [PR93635]

2024-05-24 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:9561cf550a66a89e7c8d31202a03c4fddf82a3f2

commit r15-828-g9561cf550a66a89e7c8d31202a03c4fddf82a3f2
Author: Harald Anlauf 
Date:   Thu May 23 21:13:00 2024 +0200

Fortran: improve attribute conflict checking [PR93635]

gcc/fortran/ChangeLog:

PR fortran/93635
* symbol.cc (conflict_std): Helper function for reporting attribute
conflicts depending on the Fortran standard version.
(conf_std): Helper macro for checking standard-dependent conflicts.
(gfc_check_conflict): Use it.

gcc/testsuite/ChangeLog:

PR fortran/93635
* gfortran.dg/c-interop/c1255-2.f90: Adjust pattern.
* gfortran.dg/pr87907.f90: Likewise.
* gfortran.dg/pr93635.f90: New test.

Co-authored-by: Steven G. Kargl 

Diff:
---
 gcc/fortran/symbol.cc   | 63 +++--
 gcc/testsuite/gfortran.dg/c-interop/c1255-2.f90 |  4 +-
 gcc/testsuite/gfortran.dg/pr87907.f90   |  8 ++--
 gcc/testsuite/gfortran.dg/pr93635.f90   | 19 
 4 files changed, 54 insertions(+), 40 deletions(-)

diff --git a/gcc/fortran/symbol.cc b/gcc/fortran/symbol.cc
index 0a1646def67..5db3c887127 100644
--- a/gcc/fortran/symbol.cc
+++ b/gcc/fortran/symbol.cc
@@ -407,18 +407,36 @@ gfc_check_function_type (gfc_namespace *ns)
 
 / Symbol attribute stuff */
 
+/* Older standards produced conflicts for some attributes that are allowed
+   in newer standards.  Check for the conflict and issue an error depending
+   on the standard in play.  */
+
+static bool
+conflict_std (int standard, const char *a1, const char *a2, const char *name,
+ locus *where)
+{
+  if (name == NULL)
+{
+  return gfc_notify_std (standard, "%s attribute conflicts "
+"with %s attribute at %L", a1, a2,
+where);
+}
+  else
+{
+  return gfc_notify_std (standard, "%s attribute conflicts "
+"with %s attribute in %qs at %L",
+a1, a2, name, where);
+}
+}
+
 /* This is a generic conflict-checker.  We do this to avoid having a
single conflict in two places.  */
 
 #define conf(a, b) if (attr->a && attr->b) { a1 = a; a2 = b; goto conflict; }
 #define conf2(a) if (attr->a) { a2 = a; goto conflict; }
-#define conf_std(a, b, std) if (attr->a && attr->b)\
-  {\
-a1 = a;\
-a2 = b;\
-standard = std;\
-goto conflict_std;\
-  }
+#define conf_std(a, b, std) if (attr->a && attr->b \
+   && !conflict_std (std, a, b, name, where)) \
+   return false;
 
 bool
 gfc_check_conflict (symbol_attribute *attr, const char *name, locus *where)
@@ -451,7 +469,6 @@ gfc_check_conflict (symbol_attribute *attr, const char 
*name, locus *where)
"OACC DECLARE DEVICE_RESIDENT";
 
   const char *a1, *a2;
-  int standard;
 
   if (attr->artificial)
 return true;
@@ -460,20 +477,10 @@ gfc_check_conflict (symbol_attribute *attr, const char 
*name, locus *where)
 where = _current_locus;
 
   if (attr->pointer && attr->intent != INTENT_UNKNOWN)
-{
-  a1 = pointer;
-  a2 = intent;
-  standard = GFC_STD_F2003;
-  goto conflict_std;
-}
+conf_std (pointer, intent, GFC_STD_F2003);
 
-  if (attr->in_namelist && (attr->allocatable || attr->pointer))
-{
-  a1 = in_namelist;
-  a2 = attr->allocatable ? allocatable : pointer;
-  standard = GFC_STD_F2003;
-  goto conflict_std;
-}
+  conf_std (in_namelist, allocatable, GFC_STD_F2003);
+  conf_std (in_namelist, pointer, GFC_STD_F2003);
 
   /* Check for attributes not allowed in a BLOCK DATA.  */
   if (gfc_current_state () == COMP_BLOCK_DATA)
@@ -922,20 +929,6 @@ conflict:
   a1, a2, name, where);
 
   return false;
-
-conflict_std:
-  if (name == NULL)
-{
-  return gfc_notify_std (standard, "%s attribute conflicts "
- "with %s attribute at %L", a1, a2,
- where);
-}
-  else
-{
-  return gfc_notify_std (standard, "%s attribute conflicts "
-"with %s attribute in %qs at %L",
- a1, a2, name, where);
-}
 }
 
 #undef conf
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c1255-2.f90 
b/gcc/testsuite/gfortran.dg/c-interop/c1255-2.f90
index 0e5505a0183..feed2e7645f 100644
--- a/gcc/testsuite/gfortran.dg/c-interop/c1255-2.f90
+++ b/gcc/testsuite/gfortran.dg

[gcc r15-827] Fortran: fix bounds check for assignment, class component [PR86100]

2024-05-24 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:93765736815a049e14d985b758a213cfe60c1e1c

commit r15-827-g93765736815a049e14d985b758a213cfe60c1e1c
Author: Harald Anlauf 
Date:   Mon May 13 22:06:33 2024 +0200

Fortran: fix bounds check for assignment, class component [PR86100]

gcc/fortran/ChangeLog:

PR fortran/86100
* trans-array.cc (gfc_conv_ss_startstride): Use abridged_ref_name
to generate a more user-friendly name for bounds-check messages.
* trans-expr.cc (gfc_copy_class_to_class): Fix bounds check for
rank>1 by looping over the dimensions.

gcc/testsuite/ChangeLog:

PR fortran/86100
* gfortran.dg/bounds_check_25.f90: New test.

Diff:
---
 gcc/fortran/trans-array.cc|  7 -
 gcc/fortran/trans-expr.cc | 40 +++
 gcc/testsuite/gfortran.dg/bounds_check_25.f90 | 32 +
 3 files changed, 60 insertions(+), 19 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index c5b56f4e273..eec62c296ff 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -4911,6 +4911,7 @@ done:
  gfc_expr *expr;
  locus *expr_loc;
  const char *expr_name;
+ char *ref_name = NULL;
 
  ss_info = ss->info;
  if (ss_info->type != GFC_SS_SECTION)
@@ -4922,7 +4923,10 @@ done:
 
  expr = ss_info->expr;
  expr_loc = >where;
- expr_name = expr->symtree->name;
+ if (expr->ref)
+   expr_name = ref_name = abridged_ref_name (expr, NULL);
+ else
+   expr_name = expr->symtree->name;
 
  gfc_start_block ();
 
@@ -5134,6 +5138,7 @@ done:
 
  gfc_add_expr_to_block (, tmp);
 
+ free (ref_name);
}
 
   tmp = gfc_finish_block ();
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index e315e2d3370..dfc5b8e9b4a 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -1520,7 +1520,6 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, 
bool unlimited)
   stmtblock_t body;
   stmtblock_t ifbody;
   gfc_loopinfo loop;
-  tree orig_nelems = nelems; /* Needed for bounds check.  */
 
   gfc_init_block ();
   tmp = fold_build2_loc (input_location, MINUS_EXPR,
@@ -1552,27 +1551,32 @@ gfc_copy_class_to_class (tree from, tree to, tree 
nelems, bool unlimited)
   /* Add bounds check.  */
   if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) > 0 && is_from_desc)
{
- char *msg;
  const char *name = "<>";
- tree from_len;
+ int dim, rank;
 
  if (DECL_P (to))
-   name = (const char *)(DECL_NAME (to)->identifier.id.str);
-
- from_len = gfc_conv_descriptor_size (from_data, 1);
- from_len = fold_convert (TREE_TYPE (orig_nelems), from_len);
- tmp = fold_build2_loc (input_location, NE_EXPR,
- logical_type_node, from_len, orig_nelems);
- msg = xasprintf ("Array bound mismatch for dimension %d "
-  "of array '%s' (%%ld/%%ld)",
-  1, name);
-
- gfc_trans_runtime_check (true, false, tmp, ,
-  _current_locus, msg,
-fold_convert (long_integer_type_node, orig_nelems),
-  fold_convert (long_integer_type_node, from_len));
+   name = IDENTIFIER_POINTER (DECL_NAME (to));
 
- free (msg);
+ rank = GFC_TYPE_ARRAY_RANK (TREE_TYPE (from_data));
+ for (dim = 1; dim <= rank; dim++)
+   {
+ tree from_len, to_len, cond;
+ char *msg;
+
+ from_len = gfc_conv_descriptor_size (from_data, dim);
+ from_len = fold_convert (long_integer_type_node, from_len);
+ to_len = gfc_conv_descriptor_size (to_data, dim);
+ to_len = fold_convert (long_integer_type_node, to_len);
+ msg = xasprintf ("Array bound mismatch for dimension %d "
+  "of array '%s' (%%ld/%%ld)",
+  dim, name);
+ cond = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node, from_len, to_len);
+ gfc_trans_runtime_check (true, false, cond, ,
+  _current_locus, msg,
+  to_len, from_len);
+ free (msg);
+   }
}
 
   tmp = build_call_vec (fcn_type, fcn, args);
diff --git a/gcc/testsuite/gfortran.dg/bounds_check_25.f90 
b/gcc/testsuite/gfortran.dg/bounds_check_25.f90
new file mode 100644
index 000..cc2247597f9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bounds_check_25.f90
@@ -0,0 +1,32 @@
+! { dg-do run

Re: [PATCH, v2] Fortran: improve attribute conflict checking [PR93635]

2024-05-24 Thread Harald Anlauf

Hi Mikael,

On 5/24/24 20:17, Mikael Morin wrote:

Le 23/05/2024 à 21:15, Harald Anlauf a écrit :

Hi Mikael,

On 5/23/24 09:49, Mikael Morin wrote:

Le 13/05/2024 à 09:25, Mikael Morin a écrit :

Le 10/05/2024 à 21:56, Harald Anlauf a écrit :

Am 10.05.24 um 21:48 schrieb Harald Anlauf:

Hi Mikael,

Am 10.05.24 um 11:45 schrieb Mikael Morin:

Le 09/05/2024 à 22:30, Harald Anlauf a écrit :

I'll stop here...


Thanks. Go figure, I have no problem reproducing today.
It's PR99798 (and there is even a patch for it).


this patch has rotten a bit: the type of gfc_reluease_symbol
has changed to bool, this can be fixed.

Unfortunately, applying the patch does not remove the ICEs here...


Oops, I take that back!  There was an error on my side applying the
patch; and now it does fix the ICEs after correcting that hickup


Now the PR99798 patch is ready to be pushed, but I won't be available
for a few days.  We can finish our discussion on this topic afterwards.


Hello,

I'm coming back to this.
I think either one of Steve's patch or your variant in the PR is a
better fix for the ICE as a first step; they seem less fragile at least.
Then we can look at a possible reordering of conflict checks as with the
patch you originally submitted in this thread.


like the attached variant?


Yes.  The churn in the testsuite is actually not that bad.
OK for master, thanks for the patch.


thanks, will do.

I wouldn't push for backporting, but if you feel like doing it, it seems 
safe enough (depending on my own backport for PR99798 of course).


There's no pressing need.  I'll mark the patch as backportable
with dependency in my own list, in case the question comes up.

Regarding the conflict check reordering, I'm tempted to just drop it at 
this point, or do you think it remains worth it?


I don't really have a showcase where this would bring a benefit now,
so I'm dropping this idea.

There are issues where specifying a standard version changes
the error recovery path (or rather lead to an ICE), but as some
of these are due to emitting an error during parsing instead of
during resolution, my suggestion does not help there.

If you look for an example: this one is taken from pr101281

subroutine a3pr (xn) bind(C)
  character(len=n), pointer :: xn(..)
end

vs.

subroutine a3pr (xn) bind(C)
  character(len=n), pointer :: xn
  dimension :: xn(..)
end

The first one gives lots of invalid reads in valgrind with -std=f2008,
or ICEs, while the second does not.

Thanks,
Harald




[PATCH, v2] Fortran: improve attribute conflict checking [PR93635]

2024-05-23 Thread Harald Anlauf

Hi Mikael,

On 5/23/24 09:49, Mikael Morin wrote:

Le 13/05/2024 à 09:25, Mikael Morin a écrit :

Le 10/05/2024 à 21:56, Harald Anlauf a écrit :

Am 10.05.24 um 21:48 schrieb Harald Anlauf:

Hi Mikael,

Am 10.05.24 um 11:45 schrieb Mikael Morin:

Le 09/05/2024 à 22:30, Harald Anlauf a écrit :

I'll stop here...


Thanks. Go figure, I have no problem reproducing today.
It's PR99798 (and there is even a patch for it).


this patch has rotten a bit: the type of gfc_reluease_symbol
has changed to bool, this can be fixed.

Unfortunately, applying the patch does not remove the ICEs here...


Oops, I take that back!  There was an error on my side applying the
patch; and now it does fix the ICEs after correcting that hickup

Now the PR99798 patch is ready to be pushed, but I won't be available 
for a few days.  We can finish our discussion on this topic afterwards.



Hello,

I'm coming back to this.
I think either one of Steve's patch or your variant in the PR is a 
better fix for the ICE as a first step; they seem less fragile at least.
Then we can look at a possible reordering of conflict checks as with the 
patch you originally submitted in this thread.


like the attached variant?

Harald


Mikael

From 68d73e6e2efa692afff10ea16eafb88236cbe69c Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Thu, 23 May 2024 21:13:00 +0200
Subject: [PATCH] Fortran: improve attribute conflict checking [PR93635]

gcc/fortran/ChangeLog:

	PR fortran/93635
	* symbol.cc (conflict_std): Helper function for reporting attribute
	conflicts depending on the Fortran standard version.
	(conf_std): Helper macro for checking standard-dependent conflicts.
	(gfc_check_conflict): Use it.

gcc/testsuite/ChangeLog:

	PR fortran/93635
	* gfortran.dg/c-interop/c1255-2.f90: Adjust pattern.
	* gfortran.dg/pr87907.f90: Likewise.
	* gfortran.dg/pr93635.f90: New test.

Co-authored-by: Steven G. Kargl 
---
 gcc/fortran/symbol.cc | 63 +--
 .../gfortran.dg/c-interop/c1255-2.f90 |  4 +-
 gcc/testsuite/gfortran.dg/pr87907.f90 |  8 ++-
 gcc/testsuite/gfortran.dg/pr93635.f90 | 19 ++
 4 files changed, 54 insertions(+), 40 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/pr93635.f90

diff --git a/gcc/fortran/symbol.cc b/gcc/fortran/symbol.cc
index 0a1646def67..5db3c887127 100644
--- a/gcc/fortran/symbol.cc
+++ b/gcc/fortran/symbol.cc
@@ -407,18 +407,36 @@ gfc_check_function_type (gfc_namespace *ns)
 
 / Symbol attribute stuff */
 
+/* Older standards produced conflicts for some attributes that are allowed
+   in newer standards.  Check for the conflict and issue an error depending
+   on the standard in play.  */
+
+static bool
+conflict_std (int standard, const char *a1, const char *a2, const char *name,
+	  locus *where)
+{
+  if (name == NULL)
+{
+  return gfc_notify_std (standard, "%s attribute conflicts "
+			 "with %s attribute at %L", a1, a2,
+			 where);
+}
+  else
+{
+  return gfc_notify_std (standard, "%s attribute conflicts "
+			 "with %s attribute in %qs at %L",
+			 a1, a2, name, where);
+}
+}
+
 /* This is a generic conflict-checker.  We do this to avoid having a
single conflict in two places.  */
 
 #define conf(a, b) if (attr->a && attr->b) { a1 = a; a2 = b; goto conflict; }
 #define conf2(a) if (attr->a) { a2 = a; goto conflict; }
-#define conf_std(a, b, std) if (attr->a && attr->b)\
-  {\
-a1 = a;\
-a2 = b;\
-standard = std;\
-goto conflict_std;\
-  }
+#define conf_std(a, b, std) if (attr->a && attr->b \
+&& !conflict_std (std, a, b, name, where)) \
+return false;
 
 bool
 gfc_check_conflict (symbol_attribute *attr, const char *name, locus *where)
@@ -451,7 +469,6 @@ gfc_check_conflict (symbol_attribute *attr, const char *name, locus *where)
 		"OACC DECLARE DEVICE_RESIDENT";
 
   const char *a1, *a2;
-  int standard;
 
   if (attr->artificial)
 return true;
@@ -460,20 +477,10 @@ gfc_check_conflict (symbol_attribute *attr, const char *name, locus *where)
 where = _current_locus;
 
   if (attr->pointer && attr->intent != INTENT_UNKNOWN)
-{
-  a1 = pointer;
-  a2 = intent;
-  standard = GFC_STD_F2003;
-  goto conflict_std;
-}
+conf_std (pointer, intent, GFC_STD_F2003);
 
-  if (attr->in_namelist && (attr->allocatable || attr->pointer))
-{
-  a1 = in_namelist;
-  a2 = attr->allocatable ? allocatable : pointer;
-  standard = GFC_STD_F2003;
-  goto conflict_std;
-}
+  conf_std (in_namelist, allocatable, GFC_STD_F2003);
+  conf_std (in_namelist, pointer, GFC_STD_F2003);
 
   /* Check fo

[gcc r13-8794] Fortran: fix issues with class(*) assignment [PR114827]

2024-05-22 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:f0b88ec4ae829798cb533618f781ca467bab6b9b

commit r13-8794-gf0b88ec4ae829798cb533618f781ca467bab6b9b
Author: Harald Anlauf 
Date:   Mon Apr 29 19:52:52 2024 +0200

Fortran: fix issues with class(*) assignment [PR114827]

gcc/fortran/ChangeLog:

PR fortran/114827
* trans-array.cc (gfc_alloc_allocatable_for_assignment): Take into
account _len of unlimited polymorphic entities when calculating
the effective element size for allocation size and array span.
Set _len of lhs to _len of rhs.
* trans-expr.cc (trans_class_assignment): Take into account _len
of unlimited polymorphic entities for allocation size.

gcc/testsuite/ChangeLog:

PR fortran/114827
* gfortran.dg/asan/unlimited_polymorphic_34.f90: New test.

(cherry picked from commit 21e7aa5f3ea44ca2fef8deb8788edffc04901b5c)

Diff:
---
 gcc/fortran/trans-array.cc |  16 +++
 gcc/fortran/trans-expr.cc  |  13 ++
 .../gfortran.dg/asan/unlimited_polymorphic_34.f90  | 135 +
 3 files changed, 164 insertions(+)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 5eef4b4ec87..f38e872f5d9 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -11008,6 +11008,19 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo 
*loop,
gfc_add_modify (, linfo->delta[dim], tmp);
 }
 
+  /* Take into account _len of unlimited polymorphic entities, so that span
+ for array descriptors and allocation sizes are computed correctly.  */
+  if (UNLIMITED_POLY (expr2))
+{
+  tree len = gfc_class_len_get (TREE_OPERAND (desc2, 0));
+  len = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
+fold_convert (size_type_node, len),
+size_one_node);
+  elemsize2 = fold_build2_loc (input_location, MULT_EXPR,
+  gfc_array_index_type, elemsize2,
+  fold_convert (gfc_array_index_type, len));
+}
+
   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
 gfc_conv_descriptor_span_set (, desc, elemsize2);
 
@@ -11054,6 +11067,9 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo 
*loop,
gfc_add_modify (, tmp,
fold_convert (TREE_TYPE (tmp),
  TYPE_SIZE_UNIT (type)));
+ else if (UNLIMITED_POLY (expr2))
+   gfc_add_modify (, tmp,
+   gfc_class_len_get (TREE_OPERAND (desc2, 0)));
  else
gfc_add_modify (, tmp,
build_int_cst (TREE_TYPE (tmp), 0));
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 2b2dceb8d0f..5946aa81391 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -11668,6 +11668,19 @@ trans_class_assignment (stmtblock_t *block, gfc_expr 
*lhs, gfc_expr *rhs,
old_vptr = build_int_cst (TREE_TYPE (vptr), 0);
 
   size = gfc_vptr_size_get (rhs_vptr);
+
+  /* Take into account _len of unlimited polymorphic entities.
+TODO: handle class(*) allocatable function results on rhs.  */
+  if (UNLIMITED_POLY (rhs) && rhs->expr_type == EXPR_VARIABLE)
+   {
+ tree len = trans_get_upoly_len (block, rhs);
+ len = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
+fold_convert (size_type_node, len),
+size_one_node);
+ size = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (size),
+ size, fold_convert (TREE_TYPE (size), len));
+   }
+
   tmp = lse->expr;
   class_han = GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
  ? gfc_class_data_get (tmp) : tmp;
diff --git a/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90 
b/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90
new file mode 100644
index 000..c69158a1b55
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90
@@ -0,0 +1,135 @@
+! { dg-do run }
+! PR fortran/114827 - issues with class(*) assignment found by valgrind
+!
+! Contributed by Neil Carlson 
+
+program main
+  implicit none
+  call run
+  call run1
+  call run2
+contains
+  ! Scalar tests
+  subroutine run ()
+character(*),parameter :: c = 'fubarfubarfubarfubarfubarfu'
+character(*,kind=4), parameter :: d = 4_"abcdef"
+complex, parameter :: z = (1.,2.)
+class(*),  allocatable :: y
+
+call foo (c, y)
+select type (y)
+type is (character(*))
+!  print *, y(5:6)  ! ICE (-> pr114874)
+   if (y /= c) stop 1
+class default
+   stop 2
+end select
+
+call foo (z, y)
+select type (y)
+type is (complex)
+   if (y /

[gcc r13-8793] Fortran: fix reallocation on assignment of polymorphic variables [PR110415]

2024-05-22 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:2ebf3af1f84d54fbda172eff105a8842c685d11d

commit r13-8793-g2ebf3af1f84d54fbda172eff105a8842c685d11d
Author: Andrew Jenner 
Date:   Tue Nov 28 15:27:05 2023 +

Fortran: fix reallocation on assignment of polymorphic variables [PR110415]

This patch fixes two bugs related to polymorphic class assignment in the
Fortran front-end. One (described in PR110415) is an issue with the malloc
and realloc calls using the size from the old vptr rather than the new one.
The other is caused by the return value from the realloc call being ignored.
Testcases are added for these issues.

2023-11-28  Andrew Jenner  

gcc/fortran/
PR fortran/110415
* trans-expr.cc (trans_class_vptr_len_assignment): Add
from_vptrp parameter. Populate it. Don't check for DECL_P
when deciding whether to create temporary.
(trans_class_pointer_fcn, gfc_trans_pointer_assignment): Add
NULL argument to trans_class_vptr_len_assignment calls.
(trans_class_assignment): Get rhs_vptr from
trans_class_vptr_len_assignment and use it for determining size
for allocation/reallocation. Use return value from realloc.

gcc/testsuite/
PR fortran/110415
* gfortran.dg/pr110415.f90: New test.
* gfortran.dg/asan/pr110415-2.f90: New test.
* gfortran.dg/asan/pr110415-3.f90: New test.

Co-Authored-By: Tobias Burnus  
(cherry picked from commit b247e917ff13328298c1eecf8563b12edd7ade04)

Diff:
---
 gcc/fortran/trans-expr.cc | 39 +
 gcc/testsuite/gfortran.dg/asan/pr110415-2.f90 | 45 
 gcc/testsuite/gfortran.dg/asan/pr110415-3.f90 | 49 +++
 gcc/testsuite/gfortran.dg/pr110415.f90| 20 +++
 4 files changed, 139 insertions(+), 14 deletions(-)

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index cfe03252582..2b2dceb8d0f 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -9748,7 +9748,8 @@ trans_get_upoly_len (stmtblock_t *block, gfc_expr *expr)
 static tree
 trans_class_vptr_len_assignment (stmtblock_t *block, gfc_expr * le,
 gfc_expr * re, gfc_se *rse,
-tree * to_lenp, tree * from_lenp)
+tree * to_lenp, tree * from_lenp,
+tree * from_vptrp)
 {
   gfc_se se;
   gfc_expr * vptr_expr;
@@ -9756,10 +9757,11 @@ trans_class_vptr_len_assignment (stmtblock_t *block, 
gfc_expr * le,
   bool set_vptr = false, temp_rhs = false;
   stmtblock_t *pre = block;
   tree class_expr = NULL_TREE;
+  tree from_vptr = NULL_TREE;
 
   /* Create a temporary for complicated expressions.  */
   if (re->expr_type != EXPR_VARIABLE && re->expr_type != EXPR_NULL
-  && rse->expr != NULL_TREE && !DECL_P (rse->expr))
+  && rse->expr != NULL_TREE)
 {
   if (re->ts.type == BT_CLASS && !GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr)))
class_expr = gfc_get_class_from_expr (rse->expr);
@@ -9856,6 +9858,7 @@ trans_class_vptr_len_assignment (stmtblock_t *block, 
gfc_expr * le,
tmp = rse->expr;
 
  se.expr = gfc_class_vptr_get (tmp);
+ from_vptr = se.expr;
  if (UNLIMITED_POLY (re))
from_len = gfc_class_len_get (tmp);
 
@@ -9877,6 +9880,7 @@ trans_class_vptr_len_assignment (stmtblock_t *block, 
gfc_expr * le,
  gfc_free_expr (vptr_expr);
  gfc_add_block_to_block (block, );
  gcc_assert (se.post.head == NULL_TREE);
+ from_vptr = se.expr;
}
   gfc_add_modify (pre, lhs_vptr, fold_convert (TREE_TYPE (lhs_vptr),
se.expr));
@@ -9905,11 +9909,13 @@ trans_class_vptr_len_assignment (stmtblock_t *block, 
gfc_expr * le,
}
 }
 
-  /* Return the _len trees only, when requested.  */
+  /* Return the _len and _vptr trees only, when requested.  */
   if (to_lenp)
 *to_lenp = to_len;
   if (from_lenp)
 *from_lenp = from_len;
+  if (from_vptrp)
+*from_vptrp = from_vptr;
   return lhs_vptr;
 }
 
@@ -9978,7 +9984,7 @@ trans_class_pointer_fcn (stmtblock_t *block, gfc_se *lse, 
gfc_se *rse,
 {
   expr1_vptr = trans_class_vptr_len_assignment (block, expr1,
expr2, rse,
-   NULL, NULL);
+   NULL, NULL, NULL);
   gfc_add_block_to_block (block, >pre);
   tmp = gfc_create_var (TREE_TYPE (rse->expr), "ptrtemp");
   gfc_add_modify (>pre, tmp, rse->expr);
@@ -10054,7 +10060,7 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, 
gfc_expr * expr2)
   if (non_proc_ptr_assign && expr1->ts.type == BT_CLASS)
{
  trans_class_vptr_len_assignment (, expr1, expr2, , 

[gcc r13-8786] Fortran: fix dependency checks for inquiry refs [PR115039]

2024-05-21 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:5ed32d00a7b408baa48d85e841740e73c8504d7a

commit r13-8786-g5ed32d00a7b408baa48d85e841740e73c8504d7a
Author: Harald Anlauf 
Date:   Fri May 10 21:18:03 2024 +0200

Fortran: fix dependency checks for inquiry refs [PR115039]

gcc/fortran/ChangeLog:

PR fortran/115039
* expr.cc (gfc_traverse_expr): An inquiry ref does not constitute
a dependency and cannot collide with a symbol.

gcc/testsuite/ChangeLog:

PR fortran/115039
* gfortran.dg/statement_function_5.f90: New test.

(cherry picked from commit d4974fd22730014e337fd7ec2471945ba8afb00e)

Diff:
---
 gcc/fortran/expr.cc|  2 +-
 gcc/testsuite/gfortran.dg/statement_function_5.f90 | 20 
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc
index a6c4dccb125..4a9b29c7e9d 100644
--- a/gcc/fortran/expr.cc
+++ b/gcc/fortran/expr.cc
@@ -5483,7 +5483,7 @@ gfc_traverse_expr (gfc_expr *expr, gfc_symbol *sym,
  break;
 
case REF_INQUIRY:
- return true;
+ return false;
 
default:
  gcc_unreachable ();
diff --git a/gcc/testsuite/gfortran.dg/statement_function_5.f90 
b/gcc/testsuite/gfortran.dg/statement_function_5.f90
new file mode 100644
index 000..bc5a5dba7a0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/statement_function_5.f90
@@ -0,0 +1,20 @@
+! { dg-do compile }
+! PR fortran/115039
+!
+! Check that inquiry refs work with statement functions
+!
+! { dg-additional-options "-std=legacy -fdump-tree-optimized" }
+! { dg-prune-output " Obsolescent feature" }
+! { dg-final { scan-tree-dump-not "_gfortran_stop_numeric" "optimized" } }
+
+program testit
+  implicit none
+  complex :: x
+  real:: im
+  integer :: slen
+  character(5) :: s
+  im(x)   = x%im + x%re + x%kind
+  slen(s) = s%len
+  if (im((1.0,3.0) + (2.0,4.0)) /= 14.) stop 1
+  if (slen('abcdef') /= 5)  stop 2
+end program testit


[gcc r14-10225] Fortran: fix dependency checks for inquiry refs [PR115039]

2024-05-21 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:edde60a53c7d4ee5a58c9835c8e1e1758ba636f7

commit r14-10225-gedde60a53c7d4ee5a58c9835c8e1e1758ba636f7
Author: Harald Anlauf 
Date:   Fri May 10 21:18:03 2024 +0200

Fortran: fix dependency checks for inquiry refs [PR115039]

gcc/fortran/ChangeLog:

PR fortran/115039
* expr.cc (gfc_traverse_expr): An inquiry ref does not constitute
a dependency and cannot collide with a symbol.

gcc/testsuite/ChangeLog:

PR fortran/115039
* gfortran.dg/statement_function_5.f90: New test.

(cherry picked from commit d4974fd22730014e337fd7ec2471945ba8afb00e)

Diff:
---
 gcc/fortran/expr.cc|  2 +-
 gcc/testsuite/gfortran.dg/statement_function_5.f90 | 20 
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc
index 09d1ebd95d2..50e32a7a3b7 100644
--- a/gcc/fortran/expr.cc
+++ b/gcc/fortran/expr.cc
@@ -5491,7 +5491,7 @@ gfc_traverse_expr (gfc_expr *expr, gfc_symbol *sym,
  break;
 
case REF_INQUIRY:
- return true;
+ return false;
 
default:
  gcc_unreachable ();
diff --git a/gcc/testsuite/gfortran.dg/statement_function_5.f90 
b/gcc/testsuite/gfortran.dg/statement_function_5.f90
new file mode 100644
index 000..bc5a5dba7a0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/statement_function_5.f90
@@ -0,0 +1,20 @@
+! { dg-do compile }
+! PR fortran/115039
+!
+! Check that inquiry refs work with statement functions
+!
+! { dg-additional-options "-std=legacy -fdump-tree-optimized" }
+! { dg-prune-output " Obsolescent feature" }
+! { dg-final { scan-tree-dump-not "_gfortran_stop_numeric" "optimized" } }
+
+program testit
+  implicit none
+  complex :: x
+  real:: im
+  integer :: slen
+  character(5) :: s
+  im(x)   = x%im + x%re + x%kind
+  slen(s) = s%len
+  if (im((1.0,3.0) + (2.0,4.0)) /= 14.) stop 1
+  if (slen('abcdef') /= 5)  stop 2
+end program testit


Re: [Patch, fortran] PR103312 - [11/12/13/14/15 Regression] ICE in gfc_find_component since r9-1098-g3cf89a7b992d483e

2024-05-21 Thread Harald Anlauf

Hi Paul,

Am 20.05.24 um 11:06 schrieb Paul Richard Thomas:

Hi All,

I don't think that this PR is really a regression although the fact that it
is marked as such brought it to my attention :-)

The fix turned out to be remarkably simple. It was found after going down a
silly number of rabbit holes, though!

The chunk in dependency.cc is probably more elaborate than it needs to be.
Returning -2 is sufficient for the testcase to work. Otherwise, the
comments in the patch say it all.


this part looks OK, but can you elaborate on this change to expr.cc:

diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc
index c883966646c..4ee2ad55915 100644
--- a/gcc/fortran/expr.cc
+++ b/gcc/fortran/expr.cc
@@ -3210,6 +3210,11 @@ gfc_reduce_init_expr (gfc_expr *expr)
 {
   bool t;

+  /* It is far too early to resolve a class compcall. Punt to
resolution.  */
+  if (expr && expr->expr_type == EXPR_COMPCALL
+  && expr->symtree->n.sym->ts.type == BT_CLASS)
+return true;
+

I would have expected to return 'false' here, as we do not
have an expression that reduces to a constant.  What am I
missing?

(The testcase compiles and works here also when using 'false'.)


OK for mainline? I will delay for a month before backporting.


OK if can you show me wrong...

Thanks,
Harald


Regards

Paul





[PING] [PATCH] Fortran: fix bounds check for assignment, class component [PR86100]

2024-05-21 Thread Harald Anlauf

Am 13.05.24 um 22:27 schrieb Harald Anlauf:

Dear all,

the attached patch does two things:

- it fixes a bogus array bounds check when deep-copying a class component
   of a derived type and the class component has rank > 1, the reason being
   that the previous code compared the full size of one side with the size
   of the first dimension of the other

- the bounds-check error message that was generated e.g. by an allocate
   statement with conflicting sizes in the allocation and the source-expr
   will now use an improved abbreviated name pointing to the component
   involved, which was introduced in 14-development.

What I could not resolve: a deep copy may still create no useful array
name in the error message (which I am now unable to trigger).  If someone
sees how to extract it reliably from the tree, please let me know.

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

I would like to backport this to 14-branch after a decent delay.

Thanks,
Harald





Re: [Patch, fortran] PR114874 - [14/15 Regression] ICE with select type, type is (character(*)), and substring

2024-05-16 Thread Harald Anlauf

Hi Paul!

Am 15.05.24 um 19:07 schrieb Paul Richard Thomas:

Hi All,

I have been around several circuits with a patch for this regression. I
posted one in Bugzilla but rejected it because it was not direct enough.
This one, however, is more to my liking and fixes another bug lurking in
the shadows.

The way in which select type has been implemented is a bit weird in that
the select type temporaries don't get their assoc set until resolution.
Therefore, if the selector is of inferred type, the namespace is tagged by
setting 'assoc_name_inferred'. This narrows down the range of select type
temporaries that are picked out by the chunk in primary.cc, thereby fixing
the problem.


I think that is a most reasonable approach.  I like it!

What I find hard to read is the logic in match.cc that sets
gfc_current_ns->assoc_name_inferred.  I wonder if reordering the
outer if-conditions and adding a comment might be a good thing:

@@ -6721,6 +6721,20 @@ gfc_match_select_type (void)
   goto cleanup;
 }

+  if (expr2 && expr2->expr_type == EXPR_VARIABLE
+  && expr2->symtree->n.sym->assoc)
+{
+  if (expr2->symtree->n.sym->assoc->inferred_type)
+   gfc_current_ns->assoc_name_inferred = 1;
+  else if (expr2->symtree->n.sym->assoc->target
+  && expr2->symtree->n.sym->assoc->target->ts.type ==
BT_UNKNOWN)
+   gfc_current_ns->assoc_name_inferred = 1;
+}
+  else if (!expr2
+  && expr1->symtree->n.sym->assoc
+  && expr1->symtree->n.sym->assoc->inferred_type)
+gfc_current_ns->assoc_name_inferred = 1;

As the second part refers to the case there is only a selector
and no associate-name, i.e. the simple case, have it first?

Otherwise it looks very good.


The chunks in resolve.cc fix a problem found on the way, where invalid
array references, either cause an ICE or were silently absorbed.

OK for mainline and 14-branch?


Yes.

Thanks for the patch!

Harald



Paul

Fortran: Fix select type regression due to r14-9489 [PR114874]

2024-05-15  Paul Thomas  

gcc/fortran
PR fortran/114874
* gfortran.h: Add 'assoc_name_inferred' to gfc_namespace.
* match.cc (gfc_match_select_type) : Set 'assoc_name_inferred'
in select type namespace if the selector has inferred type.
* primary.cc (gfc_match_varspec): If a select type temporary
is apparently scalar and '(' has been detected, check to see if
the current name space has 'assoc_name_inferred' set. If so,
set inferred_type.
* resolve.cc (resolve_variable): If the namespace of a select
type temporary is marked with 'assoc_name_inferred' call
gfc_fixup_inferred_type_refs to ensure references are OK.
(gfc_fixup_inferred_type_refs): Catch invalid array refs..

gcc/testsuite/
PR fortran/114874
* gfortran.dg/pr114874_1.f90: New test for valid code.
* gfortran.dg/pr114874_2.f90: New test for invalid code.





[PATCH] Fortran: fix bounds check for assignment, class component [PR86100]

2024-05-13 Thread Harald Anlauf
Dear all,

the attached patch does two things:

- it fixes a bogus array bounds check when deep-copying a class component
  of a derived type and the class component has rank > 1, the reason being
  that the previous code compared the full size of one side with the size
  of the first dimension of the other

- the bounds-check error message that was generated e.g. by an allocate
  statement with conflicting sizes in the allocation and the source-expr
  will now use an improved abbreviated name pointing to the component
  involved, which was introduced in 14-development.

What I could not resolve: a deep copy may still create no useful array
name in the error message (which I am now unable to trigger).  If someone
sees how to extract it reliably from the tree, please let me know.

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

I would like to backport this to 14-branch after a decent delay.

Thanks,
Harald

From e187285dfd83da2f69cfd50854c701744dc8acc5 Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Mon, 13 May 2024 22:06:33 +0200
Subject: [PATCH] Fortran: fix bounds check for assignment, class component
 [PR86100]

gcc/fortran/ChangeLog:

	PR fortran/86100
	* trans-array.cc (gfc_conv_ss_startstride): Use abridged_ref_name
	to generate a more user-friendly name for bounds-check messages.
	* trans-expr.cc (gfc_copy_class_to_class): Fix bounds check for
	rank>1 by looping over the dimensions.

gcc/testsuite/ChangeLog:

	PR fortran/86100
	* gfortran.dg/bounds_check_25.f90: New test.
---
 gcc/fortran/trans-array.cc|  7 +++-
 gcc/fortran/trans-expr.cc | 40 ++-
 gcc/testsuite/gfortran.dg/bounds_check_25.f90 | 32 +++
 3 files changed, 60 insertions(+), 19 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/bounds_check_25.f90

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index c5b56f4e273..eec62c296ff 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -4911,6 +4911,7 @@ done:
 	  gfc_expr *expr;
 	  locus *expr_loc;
 	  const char *expr_name;
+	  char *ref_name = NULL;

 	  ss_info = ss->info;
 	  if (ss_info->type != GFC_SS_SECTION)
@@ -4922,7 +4923,10 @@ done:

 	  expr = ss_info->expr;
 	  expr_loc = >where;
-	  expr_name = expr->symtree->name;
+	  if (expr->ref)
+	expr_name = ref_name = abridged_ref_name (expr, NULL);
+	  else
+	expr_name = expr->symtree->name;

 	  gfc_start_block ();

@@ -5134,6 +5138,7 @@ done:

 	  gfc_add_expr_to_block (, tmp);

+	  free (ref_name);
 	}

   tmp = gfc_finish_block ();
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index e315e2d3370..dfc5b8e9b4a 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -1520,7 +1520,6 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited)
   stmtblock_t body;
   stmtblock_t ifbody;
   gfc_loopinfo loop;
-  tree orig_nelems = nelems; /* Needed for bounds check.  */

   gfc_init_block ();
   tmp = fold_build2_loc (input_location, MINUS_EXPR,
@@ -1552,27 +1551,32 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited)
   /* Add bounds check.  */
   if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) > 0 && is_from_desc)
 	{
-	  char *msg;
 	  const char *name = "<>";
-	  tree from_len;
+	  int dim, rank;

 	  if (DECL_P (to))
-	name = (const char *)(DECL_NAME (to)->identifier.id.str);
-
-	  from_len = gfc_conv_descriptor_size (from_data, 1);
-	  from_len = fold_convert (TREE_TYPE (orig_nelems), from_len);
-	  tmp = fold_build2_loc (input_location, NE_EXPR,
-  logical_type_node, from_len, orig_nelems);
-	  msg = xasprintf ("Array bound mismatch for dimension %d "
-			   "of array '%s' (%%ld/%%ld)",
-			   1, name);
-
-	  gfc_trans_runtime_check (true, false, tmp, ,
-   _current_locus, msg,
-			 fold_convert (long_integer_type_node, orig_nelems),
-			   fold_convert (long_integer_type_node, from_len));
+	name = IDENTIFIER_POINTER (DECL_NAME (to));

-	  free (msg);
+	  rank = GFC_TYPE_ARRAY_RANK (TREE_TYPE (from_data));
+	  for (dim = 1; dim <= rank; dim++)
+	{
+	  tree from_len, to_len, cond;
+	  char *msg;
+
+	  from_len = gfc_conv_descriptor_size (from_data, dim);
+	  from_len = fold_convert (long_integer_type_node, from_len);
+	  to_len = gfc_conv_descriptor_size (to_data, dim);
+	  to_len = fold_convert (long_integer_type_node, to_len);
+	  msg = xasprintf ("Array bound mismatch for dimension %d "
+			   "of array '%s' (%%ld/%%ld)",
+			   dim, name);
+	  cond = fold_build2_loc (input_location, NE_EXPR,
+  logical_type_node, from_len, to_len);
+	  gfc_trans_runtime_check (true, false, cond, ,
+   _current_locus, msg,
+   to_len, from_len);
+	  free (msg);
+	}
 	}

   tmp = bu

Re: [Patch, fortran] PR113363 - ICE on ASSOCIATE and unlimited polymorphic function

2024-05-12 Thread Harald Anlauf

Hi Paul,

this looks all good now, and is OK for mainline as well as backporting!

***

While playing with the testcase, I found 3 remaining smaller issues that
are pre-existing, so they should not delay your present work.  To make
it clear: these are not regressions.

When "maliciously" perturbing the testcase by adding parentheses in the
right places, I see the following:

Replacing

  associate (var => foo ()) ! OK after r14-9489-g3fd46d859cda10

by

  associate (var => (foo ()))

gives an ICE here with 14-branch and 15-mainline.

Similarly replacing

  allocate (y, source = x(1))   ! Gave zero length here

by

  allocate (y, source = (x(1)))

Furthermore, replacing

  allocate(x, source = foo ())
by

  allocate(x, source = (foo ()))

gives a runtime segfault with both 14-branch and 15-mainline.
So this is something for another day...

Thanks for the patch!

Harald


Am 12.05.24 um 13:27 schrieb Paul Richard Thomas:

Hi Harald,

Please find attached my resubmission for pr113363. The changes are as
follows:
(i) The chunk in gfc_conv_procedure_call is new. This was the source of one
of the memory leaks;
(ii) The incorporation of the _len field in trans_class_assignment was done
for the pr84006 patch;
(iii) The source of all the invalid memory accesses and so on was down to
the use of realloc. I tried all sorts of workarounds such as testing the
vptrs and the sizes but only free followed by malloc worked. I have no idea
at all why this is the case; and
(iv) I took account of your remarks about the chunk in trans-array.cc by
removing it and that the chunk in trans-stmt.cc would leak frontend memory.

OK for mainline (and -14 branch after a few-weeks)?

Regards

Paul

Fortran: Fix wrong code in unlimited polymorphic assignment [PR113363]

2024-05-12  Paul Thomas  

gcc/fortran
PR fortran/113363
* trans-array.cc (gfc_array_init_size): Use the expr3 dtype so
that the correct element size is used.
* trans-expr.cc (gfc_conv_procedure_call): Remove restriction
that ss and ss->loop be present for the finalization of class
array function results.
(trans_class_assignment): Use free and malloc, rather than
realloc, for character expressions assigned to unlimited poly
entities.
* trans-stmt.cc (gfc_trans_allocate): Build a correct rhs for
the assignment of an unlimited polymorphic 'source'.

gcc/testsuite/
PR fortran/113363
* gfortran.dg/pr113363.f90: New test.



The first chunk in trans-array.cc ensures that the array dtype is set to
the source dtype. The second chunk ensures that the lhs _len field does

not

default to zero and so is specific to dynamic types of character.



Why the two gfc_copy_ref?  valgrind pointed my to the tail
of gfc_copy_ref which already has:

dest->next = gfc_copy_ref (src->next);

so this looks redundant and leaks frontend memory?

***

Playing with the testcase, I find several invalid writes with
valgrind, or a heap buffer overflow with -fsanitize=address .










[PATCH, committed] Fortran: fix frontend memleak

2024-05-12 Thread Harald Anlauf
Dear all,

the attached obvious patch fixes a frontend memleak that was introduced
recently, and which shows up when checking for inquiry references.
I came across it when working on pr115039.

Committed after regtesting as r15-391-g13b6ac4ebd04f0.

Thanks,
Harald

From 13b6ac4ebd04f0703d92828c9268b0b216890b0d Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Sun, 12 May 2024 21:48:03 +0200
Subject: [PATCH] Fortran: fix frontend memleak

gcc/fortran/ChangeLog:

	* primary.cc (gfc_match_varspec): Replace 'ref' argument to
	is_inquiry_ref() by NULL when the result is not needed to avoid
	a memleak.
---
 gcc/fortran/primary.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/fortran/primary.cc b/gcc/fortran/primary.cc
index 606e84432be..8e7833769a8 100644
--- a/gcc/fortran/primary.cc
+++ b/gcc/fortran/primary.cc
@@ -2250,7 +2250,7 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag,
 	 can be found.  If this was an inquiry reference with the same name
 	 as a derived component and the associate-name type is not derived
 	 or class, this is fixed up in 'gfc_fixup_inferred_type_refs'.  */
-  if (mm == MATCH_YES && is_inquiry_ref (name, )
+  if (mm == MATCH_YES && is_inquiry_ref (name, NULL)
 	  && !(sym->ts.type == BT_UNKNOWN
 		&& gfc_find_derived_types (sym, gfc_current_ns, name)))
 	inquiry = true;
--
2.35.3



[gcc r15-391] Fortran: fix frontend memleak

2024-05-12 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:13b6ac4ebd04f0703d92828c9268b0b216890b0d

commit r15-391-g13b6ac4ebd04f0703d92828c9268b0b216890b0d
Author: Harald Anlauf 
Date:   Sun May 12 21:48:03 2024 +0200

Fortran: fix frontend memleak

gcc/fortran/ChangeLog:

* primary.cc (gfc_match_varspec): Replace 'ref' argument to
is_inquiry_ref() by NULL when the result is not needed to avoid
a memleak.

Diff:
---
 gcc/fortran/primary.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/fortran/primary.cc b/gcc/fortran/primary.cc
index 606e84432be6..8e7833769a8f 100644
--- a/gcc/fortran/primary.cc
+++ b/gcc/fortran/primary.cc
@@ -2250,7 +2250,7 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, 
bool sub_flag,
 can be found.  If this was an inquiry reference with the same name
 as a derived component and the associate-name type is not derived
 or class, this is fixed up in 'gfc_fixup_inferred_type_refs'.  */
-  if (mm == MATCH_YES && is_inquiry_ref (name, )
+  if (mm == MATCH_YES && is_inquiry_ref (name, NULL)
  && !(sym->ts.type == BT_UNKNOWN
&& gfc_find_derived_types (sym, gfc_current_ns, name)))
inquiry = true;


Re: [Patch, fortran] PR84006 [11/12/13/14/15 Regression] ICE in storage_size() with CLASS entity

2024-05-11 Thread Harald Anlauf

Hi Paul,

Am 11.05.24 um 08:20 schrieb Paul Richard Thomas:

Hi Harald,

Thanks for the review. The attached resubmission fixes all the invalid
accesses, memory leaks and puts right the incorrect result.

In the course of fixing the fix, I found that deferred character length
MOLDs gave an ICE because reallocation on assign was using 'dest_word_len'
before it was defined. This is fixed by not fixing 'dest_word_len' for
these MOLDs. Unfortunately, the same did not work for unlimited polymorphic
MOLD expressions and so I added a TODO error in iresolve.cc since it
results in all manner of memory errors in runtime. I will return to this
another day.

A resubmission of the patch for PR113363 will follow since it depends on
this one to fix all the memory problems.

OK for mainline?


this is OK from my side.

One minor nit: the updated testcase transfer_class_4.f90 has

  if (sz /= storage_size (real32)/8) stop 1

I think you meant either  storage_size (r)  or  storage_size (1._real32)
instead of checking the storage size of the integer real32 here...

Thanks for the patch!

Harald


Regards

Paul

On Thu, 9 May 2024 at 08:52, Paul Richard Thomas <
paul.richard.tho...@gmail.com> wrote:


Hi Harald,

The Linaro people caught that as well. Thanks.

Interestingly, I was about to re-submit the patch for PR113363, in which
all the invalid accesses and memory leaks are fixed but requires this patch
to do so. The final transfer was thrown in because it seemed to be working
out of the box but should be checked anyway.

Inserting your print statements, my test shows the difference in
size(chr_a) but prints chr_a as "abcdefgjj" no matter what I do. Needless
to say, the latter was the only check that I did. The problem, I suspect,
lies somewhere in the murky depths of
trans-array.cc(gfc_alloc_allocatable_for_assignment) or in the array part
of intrinsic_transfer, untouched by either patch, and is present in 13- and
14-branches.

I am onto it.

Cheers

Paul


On Wed, 8 May 2024 at 22:06, Harald Anlauf  wrote:


Hi Paul,

this looks mostly good, but the new testcase transfer_class_4.f90
does exhibit a problem with your patch.  Run it with valgrind,
or with -fcheck=bounds, or with -fsanitize=address, or add the
following around the final transfer:

print *, storage_size (star_a), storage_size (chr_a), size (chr_a), len
(chr_a)
chr_a = transfer (star_a, chr_a)
print *, storage_size (star_a), storage_size (chr_a), size (chr_a), len
(chr_a)
print *, ">", chr_a, "<"

This prints for me:

40  40   2   5$
40  40   4   5$
   >abcdefghij^@^@^@^@^@^@^@^@^@^@<$

So since the physical representation of chr_a is sufficient
to hold star_a (F2023:16.9.212), no reallocation with a wrong
calculated size should happen.  (Intel and NAG get this right.)

Can you check again?

Thanks,
Harald









[gcc r15-385] Fortran: fix dependency checks for inquiry refs [PR115039]

2024-05-11 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:d4974fd22730014e337fd7ec2471945ba8afb00e

commit r15-385-gd4974fd22730014e337fd7ec2471945ba8afb00e
Author: Harald Anlauf 
Date:   Fri May 10 21:18:03 2024 +0200

Fortran: fix dependency checks for inquiry refs [PR115039]

gcc/fortran/ChangeLog:

PR fortran/115039
* expr.cc (gfc_traverse_expr): An inquiry ref does not constitute
a dependency and cannot collide with a symbol.

gcc/testsuite/ChangeLog:

PR fortran/115039
* gfortran.dg/statement_function_5.f90: New test.

Diff:
---
 gcc/fortran/expr.cc|  2 +-
 gcc/testsuite/gfortran.dg/statement_function_5.f90 | 20 
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc
index 66edad58278a..c883966646cb 100644
--- a/gcc/fortran/expr.cc
+++ b/gcc/fortran/expr.cc
@@ -5500,7 +5500,7 @@ gfc_traverse_expr (gfc_expr *expr, gfc_symbol *sym,
  break;
 
case REF_INQUIRY:
- return true;
+ return false;
 
default:
  gcc_unreachable ();
diff --git a/gcc/testsuite/gfortran.dg/statement_function_5.f90 
b/gcc/testsuite/gfortran.dg/statement_function_5.f90
new file mode 100644
index ..bc5a5dba7a0f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/statement_function_5.f90
@@ -0,0 +1,20 @@
+! { dg-do compile }
+! PR fortran/115039
+!
+! Check that inquiry refs work with statement functions
+!
+! { dg-additional-options "-std=legacy -fdump-tree-optimized" }
+! { dg-prune-output " Obsolescent feature" }
+! { dg-final { scan-tree-dump-not "_gfortran_stop_numeric" "optimized" } }
+
+program testit
+  implicit none
+  complex :: x
+  real:: im
+  integer :: slen
+  character(5) :: s
+  im(x)   = x%im + x%re + x%kind
+  slen(s) = s%len
+  if (im((1.0,3.0) + (2.0,4.0)) /= 14.) stop 1
+  if (slen('abcdef') /= 5)  stop 2
+end program testit


Re: [PATCH] Fortran: improve attribute conflict checking [PR93635]

2024-05-10 Thread Harald Anlauf

Am 10.05.24 um 21:48 schrieb Harald Anlauf:

Hi Mikael,

Am 10.05.24 um 11:45 schrieb Mikael Morin:

Le 09/05/2024 à 22:30, Harald Anlauf a écrit :

I'll stop here...


Thanks. Go figure, I have no problem reproducing today.
It's PR99798 (and there is even a patch for it).


this patch has rotten a bit: the type of gfc_reluease_symbol
has changed to bool, this can be fixed.

Unfortunately, applying the patch does not remove the ICEs here...


Oops, I take that back!  There was an error on my side applying the
patch; and now it does fix the ICEs after correcting that hickup




We currently do not recover well from errors, and the prevention
of corrupted namespaces is apparently a goal we aim at.


Yes, and we are not there yet. But at least there is a sensible error
message before the crash.


True.  But having a sensible error before ICEing does not improve
user experience either.

Are you planning to work again on PR99798?

Cheers,
Harald


Cheers,
Harald


The patch therefore does not require any testsuite update and
should not give any other surprises, so it should be very safe.
The plan is also to leave the PR open for the time being.

Regtesting on x86_64-pc-linux-gnu.  OK for mainline?

Thanks,
Harald
















Re: [PATCH] Fortran: improve attribute conflict checking [PR93635]

2024-05-10 Thread Harald Anlauf

Hi Mikael,

Am 10.05.24 um 11:45 schrieb Mikael Morin:

Le 09/05/2024 à 22:30, Harald Anlauf a écrit :

I'll stop here...


Thanks. Go figure, I have no problem reproducing today.
It's PR99798 (and there is even a patch for it).


this patch has rotten a bit: the type of gfc_reluease_symbol
has changed to bool, this can be fixed.

Unfortunately, applying the patch does not remove the ICEs here...


We currently do not recover well from errors, and the prevention
of corrupted namespaces is apparently a goal we aim at.


Yes, and we are not there yet. But at least there is a sensible error
message before the crash.


True.  But having a sensible error before ICEing does not improve
user experience either.

Are you planning to work again on PR99798?

Cheers,
Harald


Cheers,
Harald


The patch therefore does not require any testsuite update and
should not give any other surprises, so it should be very safe.
The plan is also to leave the PR open for the time being.

Regtesting on x86_64-pc-linux-gnu.  OK for mainline?

Thanks,
Harald













[PATCH] Fortran: fix dependency checks for inquiry refs [PR115039]

2024-05-10 Thread Harald Anlauf
Dear all,

the attached simple and obvious patch fixes a bogus recursion error
with inquiry refs used statement functions.  The commit message
says all there is to say...

Regtested on x86_64-pc-linux-gnu.

I intend to commit to mainline within the next 24 hours unless someone
screams...  Will also backport to 14-branch after a decent delay.

Thanks,
Harald

From 8bb31eb3d7f8ea6d21066380c36abf53f7b64156 Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Fri, 10 May 2024 21:18:03 +0200
Subject: [PATCH] Fortran: fix dependency checks for inquiry refs [PR115039]

gcc/fortran/ChangeLog:

	PR fortran/115039
	* expr.cc (gfc_traverse_expr): An inquiry ref does not constitute
	a dependency and cannot collide with a symbol.

gcc/testsuite/ChangeLog:

	PR fortran/115039
	* gfortran.dg/statement_function_5.f90: New test.
---
 gcc/fortran/expr.cc   |  3 ++-
 .../gfortran.dg/statement_function_5.f90  | 20 +++
 2 files changed, 22 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gfortran.dg/statement_function_5.f90

diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc
index 66edad58278..8e29535b0f7 100644
--- a/gcc/fortran/expr.cc
+++ b/gcc/fortran/expr.cc
@@ -5500,7 +5500,8 @@ gfc_traverse_expr (gfc_expr *expr, gfc_symbol *sym,
 	  break;

 	case REF_INQUIRY:
-	  return true;
+	  /* An inquiry_ref does not collide with a symbol.  */
+	  return false;

 	default:
 	  gcc_unreachable ();
diff --git a/gcc/testsuite/gfortran.dg/statement_function_5.f90 b/gcc/testsuite/gfortran.dg/statement_function_5.f90
new file mode 100644
index 000..bc5a5dba7a0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/statement_function_5.f90
@@ -0,0 +1,20 @@
+! { dg-do compile }
+! PR fortran/115039
+!
+! Check that inquiry refs work with statement functions
+!
+! { dg-additional-options "-std=legacy -fdump-tree-optimized" }
+! { dg-prune-output " Obsolescent feature" }
+! { dg-final { scan-tree-dump-not "_gfortran_stop_numeric" "optimized" } }
+
+program testit
+  implicit none
+  complex :: x
+  real:: im
+  integer :: slen
+  character(5) :: s
+  im(x)   = x%im + x%re + x%kind
+  slen(s) = s%len
+  if (im((1.0,3.0) + (2.0,4.0)) /= 14.) stop 1
+  if (slen('abcdef') /= 5)  stop 2
+end program testit
--
2.35.3



Re: [PATCH] Fortran: improve attribute conflict checking [PR93635]

2024-05-09 Thread Harald Anlauf

Hi Mikael,

Am 09.05.24 um 21:51 schrieb Mikael Morin:

Hello,

Le 06/05/2024 à 21:33, Harald Anlauf a écrit :

Dear all,

I've been contemplating whether to submit the attached patch.
It addresses an ICE-on-invalid as reported in the PR, and also
fixes an accepts-invalid (see testcase), plus maybe some more,
related due to incomplete checking of symbol attribute conflicts.

The fix does not fully address the general issue, which is
analyzed by Steve: some of the checks do depend on the selected
Fortran standard, and under circumstances such as in the testcase
the checking of other, standard-version-independent conflicts
simply does not occur.

Steve's solution would fix that, but unfortunately leads to issues
with error recovery in notoriously fragile parts of the FE: e.g.
testcase pr87907.f90 needs adjusting, and minor variations
of it will lead to various other horrendous ICEs that remind
of existing PRs where parsing or resolution goes sideways.

I therefore propose a much simpler approach: move - if possible -
selected of the standard-version-dependent checks after the
version-independent ones.  I think this could help in getting more
consistent error reporting and recovery.  However, I did *not*
move those checks that are critical when processing interfaces.
(-> pr87907.f90 / (sub)modules)


Your patch looks clean, but I'm concerned that the order of the checks
should be the important ones first, regardless of their standard
version.  I'm trying to look at the ICE caused by your other tentative
patch at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93635#c6 but I
can't reproduce the problem.  Do you by any chance have around some of
the variations causing "horrendous" ICEs?


Oh, that's easy.  Just move the block

  conf_std (allocatable, dummy, GFC_STD_F2003);
  conf_std (allocatable, function, GFC_STD_F2003);
  conf_std (allocatable, result, GFC_STD_F2003);

towards the end of the gfc_check_conflict before the return true.

While the error messages for the original gfortran.dg/pr87907.f90
look harmless, commenting out the main program p I get:

pr87907.f90:15:18:

   15 |   subroutine g(x)   ! { dg-error "mismatch in argument" }
  |  1
Error: FUNCTION attribute conflicts with SUBROUTINE attribute in 'g' at (1)
f951: internal compiler error: Segmentation fault
0x13b8ec2 crash_signal
../../gcc-trunk/gcc/toplev.cc:319
0xba530e free_sym_tree
../../gcc-trunk/gcc/fortran/symbol.cc:4026
0xba5319 free_sym_tree
../../gcc-trunk/gcc/fortran/symbol.cc:4026
0xba5319 free_sym_tree
../../gcc-trunk/gcc/fortran/symbol.cc:4026
0xba5319 free_sym_tree
../../gcc-trunk/gcc/fortran/symbol.cc:4026
0xba5609 gfc_free_namespace(gfc_namespace*&)
../../gcc-trunk/gcc/fortran/symbol.cc:4168
0xba39c1 gfc_free_symbol(gfc_symbol*&)
../../gcc-trunk/gcc/fortran/symbol.cc:3173
0xba3b89 gfc_release_symbol(gfc_symbol*&)
../../gcc-trunk/gcc/fortran/symbol.cc:3216
0xba5339 free_sym_tree
../../gcc-trunk/gcc/fortran/symbol.cc:4029
0xba5609 gfc_free_namespace(gfc_namespace*&)
../../gcc-trunk/gcc/fortran/symbol.cc:4168
0xba58ef gfc_symbol_done_2()
../../gcc-trunk/gcc/fortran/symbol.cc:4236
0xb12ec8 gfc_done_2()
../../gcc-trunk/gcc/fortran/misc.cc:387
0xb4ac7f clean_up_modules
../../gcc-trunk/gcc/fortran/parse.cc:7057
0xb4af02 translate_all_program_units
../../gcc-trunk/gcc/fortran/parse.cc:7122
0xb4b735 gfc_parse_file()
../../gcc-trunk/gcc/fortran/parse.cc:7413
0xbb626f gfc_be_parse_file
../../gcc-trunk/gcc/fortran/f95-lang.cc:241


Restoring the main program but simply adding "end subroutine g"
where it is naively expected gives:

pr87907.f90:15:18:

   15 |   subroutine g(x)   ! { dg-error "mismatch in argument" }
  |  1
Error: FUNCTION attribute conflicts with SUBROUTINE attribute in 'g' at (1)
pr87907.f90:16:9:

   16 |   end subroutine g
  | 1
Error: Expecting END SUBMODULE statement at (1)
pr87907.f90:20:7:

   20 |use m! { dg-error "has a type" }
  |   1
   21 |integer :: x = 3
   22 |call g(x)! { dg-error "which is not consistent
with" }
  |
2
Error: 'g' at (1) has a type, which is not consistent with the CALL at (2)
f951: internal compiler error: in gfc_free_namespace, at
fortran/symbol.cc:4164
0xba55e1 gfc_free_namespace(gfc_namespace*&)
../../gcc-trunk/gcc/fortran/symbol.cc:4164
0xba39c1 gfc_free_symbol(gfc_symbol*&)
../../gcc-trunk/gcc/fortran/symbol.cc:3173
0xba3b89 gfc_release_symbol(gfc_symbol*&)
../../gcc-trunk/gcc/fortran/symbol.cc:3216
0xba5339 free_sym_tree
../../gcc-trunk/gcc/fortran/symbol.cc:4029
0xba5609 gfc_free_namespace(gfc_namespace*&)
../../gcc-trunk/gcc/fortran/symbol.cc:4168
0xba58ef gfc_symbol_done_2()
../../gcc-trunk/g

[gcc r14-10191] Fortran: fix issues with class(*) assignment [PR114827]

2024-05-09 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:a5046235509caa10a4dc309ca0a8e67892b27750

commit r14-10191-ga5046235509caa10a4dc309ca0a8e67892b27750
Author: Harald Anlauf 
Date:   Mon Apr 29 19:52:52 2024 +0200

Fortran: fix issues with class(*) assignment [PR114827]

gcc/fortran/ChangeLog:

PR fortran/114827
* trans-array.cc (gfc_alloc_allocatable_for_assignment): Take into
account _len of unlimited polymorphic entities when calculating
the effective element size for allocation size and array span.
Set _len of lhs to _len of rhs.
* trans-expr.cc (trans_class_assignment): Take into account _len
of unlimited polymorphic entities for allocation size.

gcc/testsuite/ChangeLog:

PR fortran/114827
* gfortran.dg/asan/unlimited_polymorphic_34.f90: New test.

(cherry picked from commit 21e7aa5f3ea44ca2fef8deb8788edffc04901b5c)

Diff:
---
 gcc/fortran/trans-array.cc |  16 +++
 gcc/fortran/trans-expr.cc  |  13 ++
 .../gfortran.dg/asan/unlimited_polymorphic_34.f90  | 135 +
 3 files changed, 164 insertions(+)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 30b84762346d..7ec33fb15986 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -11278,6 +11278,19 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo 
*loop,
gfc_add_modify (, linfo->delta[dim], tmp);
 }
 
+  /* Take into account _len of unlimited polymorphic entities, so that span
+ for array descriptors and allocation sizes are computed correctly.  */
+  if (UNLIMITED_POLY (expr2))
+{
+  tree len = gfc_class_len_get (TREE_OPERAND (desc2, 0));
+  len = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
+fold_convert (size_type_node, len),
+size_one_node);
+  elemsize2 = fold_build2_loc (input_location, MULT_EXPR,
+  gfc_array_index_type, elemsize2,
+  fold_convert (gfc_array_index_type, len));
+}
+
   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
 gfc_conv_descriptor_span_set (, desc, elemsize2);
 
@@ -11324,6 +11337,9 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo 
*loop,
gfc_add_modify (, tmp,
fold_convert (TREE_TYPE (tmp),
  TYPE_SIZE_UNIT (type)));
+ else if (UNLIMITED_POLY (expr2))
+   gfc_add_modify (, tmp,
+   gfc_class_len_get (TREE_OPERAND (desc2, 0)));
  else
gfc_add_modify (, tmp,
build_int_cst (TREE_TYPE (tmp), 0));
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 0280c441ced3..bc8eb419cffe 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -11991,6 +11991,19 @@ trans_class_assignment (stmtblock_t *block, gfc_expr 
*lhs, gfc_expr *rhs,
old_vptr = build_int_cst (TREE_TYPE (vptr), 0);
 
   size = gfc_vptr_size_get (rhs_vptr);
+
+  /* Take into account _len of unlimited polymorphic entities.
+TODO: handle class(*) allocatable function results on rhs.  */
+  if (UNLIMITED_POLY (rhs) && rhs->expr_type == EXPR_VARIABLE)
+   {
+ tree len = trans_get_upoly_len (block, rhs);
+ len = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
+fold_convert (size_type_node, len),
+size_one_node);
+ size = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (size),
+ size, fold_convert (TREE_TYPE (size), len));
+   }
+
   tmp = lse->expr;
   class_han = GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
  ? gfc_class_data_get (tmp) : tmp;
diff --git a/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90 
b/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90
new file mode 100644
index ..c69158a1b55f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90
@@ -0,0 +1,135 @@
+! { dg-do run }
+! PR fortran/114827 - issues with class(*) assignment found by valgrind
+!
+! Contributed by Neil Carlson 
+
+program main
+  implicit none
+  call run
+  call run1
+  call run2
+contains
+  ! Scalar tests
+  subroutine run ()
+character(*),parameter :: c = 'fubarfubarfubarfubarfubarfu'
+character(*,kind=4), parameter :: d = 4_"abcdef"
+complex, parameter :: z = (1.,2.)
+class(*),  allocatable :: y
+
+call foo (c, y)
+select type (y)
+type is (character(*))
+!  print *, y(5:6)  ! ICE (-> pr114874)
+   if (y /= c) stop 1
+class default
+   stop 2
+end select
+
+call foo (z, y)
+select type (y)
+type is (complex)
+   if (y /

Re: [Patch, fortran] PR84006 [11/12/13/14/15 Regression] ICE in storage_size() with CLASS entity

2024-05-09 Thread Harald Anlauf

Hi Paul,

Am 09.05.24 um 09:52 schrieb Paul Richard Thomas:

Hi Harald,
Inserting your print statements, my test shows the difference in
size(chr_a) but prints chr_a as "abcdefgjj" no matter what I do.


have you tried

 ./a.out | cat -ev

?  Or some terminal that shows control characters?

Cheers,
Harald

Needless

to say, the latter was the only check that I did. The problem, I suspect,
lies somewhere in the murky depths of
trans-array.cc(gfc_alloc_allocatable_for_assignment) or in the array part
of intrinsic_transfer, untouched by either patch, and is present in 13- and
14-branches.

I am onto it.

Cheers

Paul


On Wed, 8 May 2024 at 22:06, Harald Anlauf  wrote:


Hi Paul,

this looks mostly good, but the new testcase transfer_class_4.f90
does exhibit a problem with your patch.  Run it with valgrind,
or with -fcheck=bounds, or with -fsanitize=address, or add the
following around the final transfer:

print *, storage_size (star_a), storage_size (chr_a), size (chr_a), len
(chr_a)
chr_a = transfer (star_a, chr_a)
print *, storage_size (star_a), storage_size (chr_a), size (chr_a), len
(chr_a)
print *, ">", chr_a, "<"

This prints for me:

40  40   2   5$
40  40   4   5$
   >abcdefghij^@^@^@^@^@^@^@^@^@^@<$

So since the physical representation of chr_a is sufficient
to hold star_a (F2023:16.9.212), no reallocation with a wrong
calculated size should happen.  (Intel and NAG get this right.)

Can you check again?

Thanks,
Harald


Am 08.05.24 um 17:01 schrieb Paul Richard Thomas:

This fix is straightforward and described by the ChangeLog. Jose Rui
Faustino de Sousa posted the same fix for the ICE on the fortran list
slightly more than three years ago. Thinking that he had commit rights, I
deferred but, regrettably, the patch was never applied. The attached

patch

also fixes storage_size and transfer for unlimited polymorphic arguments
with character payloads.

OK for mainline and backporting after a reasonable interval?

Paul

Fortran: Unlimited polymorphic intrinsic function arguments [PR84006]

2024-05-08  Paul Thomas  

gcc/fortran
PR fortran/84006
PR fortran/100027
PR fortran/98534
* trans-expr.cc (gfc_resize_class_size_with_len): Use the fold
even if a block is not available in which to fix the result.
(trans_class_assignment): Enable correct assignment of
character expressions to unlimited polymorphic variables using
lhs _len field and rse string_length.
* trans-intrinsic.cc (gfc_conv_intrinsic_storage_size): Extract
the class expression so that the unlimited polymorphic class
expression can be used in gfc_resize_class_size_with_len to
obtain the storage size for character payloads. Guard the use
of GFC_DECL_SAVED_DESCRIPTOR by testing for DECL_LANG_SPECIFIC
to prevent the ICE. Also, invert the order to use the class
expression extracted from the argument.
(gfc_conv_intrinsic_transfer): In same way as 'storage_size',
use the _len field to obtaining the correct length for arg 1.

gcc/testsuite/
PR fortran/84006
PR fortran/100027
* gfortran.dg/storage_size_7.f90: New test.

PR fortran/98534
* gfortran.dg/transfer_class_4.f90: New test.










Re: [Patch, fortran] PR84006 [11/12/13/14/15 Regression] ICE in storage_size() with CLASS entity

2024-05-08 Thread Harald Anlauf

Hi Paul,

this looks mostly good, but the new testcase transfer_class_4.f90
does exhibit a problem with your patch.  Run it with valgrind,
or with -fcheck=bounds, or with -fsanitize=address, or add the
following around the final transfer:

print *, storage_size (star_a), storage_size (chr_a), size (chr_a), len 
(chr_a)

  chr_a = transfer (star_a, chr_a)
print *, storage_size (star_a), storage_size (chr_a), size (chr_a), len 
(chr_a)

print *, ">", chr_a, "<"

This prints for me:

  40  40   2   5$
  40  40   4   5$
 >abcdefghij^@^@^@^@^@^@^@^@^@^@<$

So since the physical representation of chr_a is sufficient
to hold star_a (F2023:16.9.212), no reallocation with a wrong
calculated size should happen.  (Intel and NAG get this right.)

Can you check again?

Thanks,
Harald


Am 08.05.24 um 17:01 schrieb Paul Richard Thomas:

This fix is straightforward and described by the ChangeLog. Jose Rui
Faustino de Sousa posted the same fix for the ICE on the fortran list
slightly more than three years ago. Thinking that he had commit rights, I
deferred but, regrettably, the patch was never applied. The attached patch
also fixes storage_size and transfer for unlimited polymorphic arguments
with character payloads.

OK for mainline and backporting after a reasonable interval?

Paul

Fortran: Unlimited polymorphic intrinsic function arguments [PR84006]

2024-05-08  Paul Thomas  

gcc/fortran
PR fortran/84006
PR fortran/100027
PR fortran/98534
* trans-expr.cc (gfc_resize_class_size_with_len): Use the fold
even if a block is not available in which to fix the result.
(trans_class_assignment): Enable correct assignment of
character expressions to unlimited polymorphic variables using
lhs _len field and rse string_length.
* trans-intrinsic.cc (gfc_conv_intrinsic_storage_size): Extract
the class expression so that the unlimited polymorphic class
expression can be used in gfc_resize_class_size_with_len to
obtain the storage size for character payloads. Guard the use
of GFC_DECL_SAVED_DESCRIPTOR by testing for DECL_LANG_SPECIFIC
to prevent the ICE. Also, invert the order to use the class
expression extracted from the argument.
(gfc_conv_intrinsic_transfer): In same way as 'storage_size',
use the _len field to obtaining the correct length for arg 1.

gcc/testsuite/
PR fortran/84006
PR fortran/100027
* gfortran.dg/storage_size_7.f90: New test.

PR fortran/98534
* gfortran.dg/transfer_class_4.f90: New test.






[PATCH] Fortran: improve attribute conflict checking [PR93635]

2024-05-06 Thread Harald Anlauf
Dear all,

I've been contemplating whether to submit the attached patch.
It addresses an ICE-on-invalid as reported in the PR, and also
fixes an accepts-invalid (see testcase), plus maybe some more,
related due to incomplete checking of symbol attribute conflicts.

The fix does not fully address the general issue, which is
analyzed by Steve: some of the checks do depend on the selected
Fortran standard, and under circumstances such as in the testcase
the checking of other, standard-version-independent conflicts
simply does not occur.

Steve's solution would fix that, but unfortunately leads to issues
with error recovery in notoriously fragile parts of the FE: e.g.
testcase pr87907.f90 needs adjusting, and minor variations
of it will lead to various other horrendous ICEs that remind
of existing PRs where parsing or resolution goes sideways.

I therefore propose a much simpler approach: move - if possible -
selected of the standard-version-dependent checks after the
version-independent ones.  I think this could help in getting more
consistent error reporting and recovery.  However, I did *not*
move those checks that are critical when processing interfaces.
(-> pr87907.f90 / (sub)modules)

The patch therefore does not require any testsuite update and
should not give any other surprises, so it should be very safe.
The plan is also to leave the PR open for the time being.

Regtesting on x86_64-pc-linux-gnu.  OK for mainline?

Thanks,
Harald

From c55cb36a6ad00996b5efb33c0c5357fc5fa9919c Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Mon, 6 May 2024 20:57:29 +0200
Subject: [PATCH] Fortran: improve attribute conflict checking [PR93635]

gcc/fortran/ChangeLog:

	PR fortran/93635
	* symbol.cc (gfc_check_conflict): Move some attribute conflict
	checks that depend on the selected version of the Fortran standard
	so that error reporting gets more consistent.

gcc/testsuite/ChangeLog:

	PR fortran/93635
	* gfortran.dg/pr93635.f90: New test.
---
 gcc/fortran/symbol.cc | 30 ---
 gcc/testsuite/gfortran.dg/pr93635.f90 | 19 +
 2 files changed, 32 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/pr93635.f90

diff --git a/gcc/fortran/symbol.cc b/gcc/fortran/symbol.cc
index 8f7deac1d1e..ed17291c53e 100644
--- a/gcc/fortran/symbol.cc
+++ b/gcc/fortran/symbol.cc
@@ -459,22 +459,6 @@ gfc_check_conflict (symbol_attribute *attr, const char *name, locus *where)
   if (where == NULL)
 where = _current_locus;

-  if (attr->pointer && attr->intent != INTENT_UNKNOWN)
-{
-  a1 = pointer;
-  a2 = intent;
-  standard = GFC_STD_F2003;
-  goto conflict_std;
-}
-
-  if (attr->in_namelist && (attr->allocatable || attr->pointer))
-{
-  a1 = in_namelist;
-  a2 = attr->allocatable ? allocatable : pointer;
-  standard = GFC_STD_F2003;
-  goto conflict_std;
-}
-
   /* Check for attributes not allowed in a BLOCK DATA.  */
   if (gfc_current_state () == COMP_BLOCK_DATA)
 {
@@ -579,10 +563,12 @@ gfc_check_conflict (symbol_attribute *attr, const char *name, locus *where)
 return false;

   conf (allocatable, pointer);
+
+  /* Moving these checks past the function/subroutine conflict check may
+ cause trouble with minor variations of testcase pr87907.f90.  */
   conf_std (allocatable, dummy, GFC_STD_F2003);
   conf_std (allocatable, function, GFC_STD_F2003);
   conf_std (allocatable, result, GFC_STD_F2003);
-  conf_std (elemental, recursive, GFC_STD_F2018);

   conf (in_common, dummy);
   conf (in_common, allocatable);
@@ -911,6 +897,16 @@ gfc_check_conflict (symbol_attribute *attr, const char *name, locus *where)
   break;
 }

+  /* Conflict checks depending on the selected version of the Fortran
+ standard are preferably applied after standard-independent ones, so
+ that one gets more consistent error reporting and recovery.  */
+  if (attr->pointer && attr->intent != INTENT_UNKNOWN)
+conf_std (pointer, intent, GFC_STD_F2003);
+
+  conf_std (in_namelist, allocatable, GFC_STD_F2003);
+  conf_std (in_namelist, pointer, GFC_STD_F2003);
+  conf_std (elemental, recursive, GFC_STD_F2018);
+
   return true;

 conflict:
diff --git a/gcc/testsuite/gfortran.dg/pr93635.f90 b/gcc/testsuite/gfortran.dg/pr93635.f90
new file mode 100644
index 000..4ef33fecf2b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr93635.f90
@@ -0,0 +1,19 @@
+! { dg-do compile }
+! PR fortran/93635
+!
+! Test that some attribute conflicts are properly diagnosed
+
+program p
+  implicit none
+  character(len=:),allocatable :: r,s
+  namelist /args/ r,s
+  equivalence(r,s) ! { dg-error "EQUIVALENCE attribute conflicts with ALLOCATABLE" }
+  allocate(character(len=1024) :: r)
+end
+
+subroutine sub (p, q)
+  implicit none
+  real, pointer, intent(inout) :: p(:), q(:)
+  namelist /nml/ p,q
+  equivalence(p,q) ! { dg-error "EQUIVALENCE attribute conflicts with DUMMY" }
+end
--
2.35.3



Re: [PATCH] Fortran: fix issues with class(*) assignment [PR114827]

2024-05-05 Thread Harald Anlauf

Hi Paul,

Am 05.05.24 um 18:48 schrieb Paul Richard Thomas:

Hi Harald,

Please do commit, with or without the extra bit for the function result.


I've committed the attached variant that excludes the case of a scalar
class(*) allocatable function result on the rhs, and added a TODO.


As well as having to get back to pr113363, I have patches in a complete
state for pr84006 and 98534. However they clash with yours. You arrived at
the head of the queue first and so after you :-)


Well, thanks for volunteering to clean up after me... ;-)

Cheers,
Harald


Regards

Paul

From 21e7aa5f3ea44ca2fef8deb8788edffc04901b5c Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Mon, 29 Apr 2024 19:52:52 +0200
Subject: [PATCH] Fortran: fix issues with class(*) assignment [PR114827]

gcc/fortran/ChangeLog:

	PR fortran/114827
	* trans-array.cc (gfc_alloc_allocatable_for_assignment): Take into
	account _len of unlimited polymorphic entities when calculating
	the effective element size for allocation size and array span.
	Set _len of lhs to _len of rhs.
	* trans-expr.cc (trans_class_assignment): Take into account _len
	of unlimited polymorphic entities for allocation size.

gcc/testsuite/ChangeLog:

	PR fortran/114827
	* gfortran.dg/asan/unlimited_polymorphic_34.f90: New test.
---
 gcc/fortran/trans-array.cc|  16 +++
 gcc/fortran/trans-expr.cc |  13 ++
 .../asan/unlimited_polymorphic_34.f90 | 135 ++
 3 files changed, 164 insertions(+)
 create mode 100644 gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 30b84762346..7ec33fb1598 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -11278,6 +11278,19 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
 	gfc_add_modify (, linfo->delta[dim], tmp);
 }
 
+  /* Take into account _len of unlimited polymorphic entities, so that span
+ for array descriptors and allocation sizes are computed correctly.  */
+  if (UNLIMITED_POLY (expr2))
+{
+  tree len = gfc_class_len_get (TREE_OPERAND (desc2, 0));
+  len = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
+			 fold_convert (size_type_node, len),
+			 size_one_node);
+  elemsize2 = fold_build2_loc (input_location, MULT_EXPR,
+   gfc_array_index_type, elemsize2,
+   fold_convert (gfc_array_index_type, len));
+}
+
   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
 gfc_conv_descriptor_span_set (, desc, elemsize2);
 
@@ -11324,6 +11337,9 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
 	gfc_add_modify (, tmp,
 			fold_convert (TREE_TYPE (tmp),
 	  TYPE_SIZE_UNIT (type)));
+	  else if (UNLIMITED_POLY (expr2))
+	gfc_add_modify (, tmp,
+			gfc_class_len_get (TREE_OPERAND (desc2, 0)));
 	  else
 	gfc_add_modify (, tmp,
 			build_int_cst (TREE_TYPE (tmp), 0));
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 0280c441ced..bc8eb419cff 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -11991,6 +11991,19 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs,
 	old_vptr = build_int_cst (TREE_TYPE (vptr), 0);
 
   size = gfc_vptr_size_get (rhs_vptr);
+
+  /* Take into account _len of unlimited polymorphic entities.
+	 TODO: handle class(*) allocatable function results on rhs.  */
+  if (UNLIMITED_POLY (rhs) && rhs->expr_type == EXPR_VARIABLE)
+	{
+	  tree len = trans_get_upoly_len (block, rhs);
+	  len = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
+ fold_convert (size_type_node, len),
+ size_one_node);
+	  size = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (size),
+  size, fold_convert (TREE_TYPE (size), len));
+	}
+
   tmp = lse->expr;
   class_han = GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
 	  ? gfc_class_data_get (tmp) : tmp;
diff --git a/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90 b/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90
new file mode 100644
index 000..c69158a1b55
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90
@@ -0,0 +1,135 @@
+! { dg-do run }
+! PR fortran/114827 - issues with class(*) assignment found by valgrind
+!
+! Contributed by Neil Carlson 
+
+program main
+  implicit none
+  call run
+  call run1
+  call run2
+contains
+  ! Scalar tests
+  subroutine run ()
+character(*),parameter :: c = 'fubarfubarfubarfubarfubarfu'
+character(*,kind=4), parameter :: d = 4_"abcdef"
+complex, parameter :: z = (1.,2.)
+class(*),  allocatable :: y
+
+call foo (c, y)
+select type (y)
+type is (character(*))
+!  print *, y(5:6)  ! ICE (-> pr114874)
+   if (y /= c) stop 1
+class default
+   stop 2
+end select
+
+call foo (z, y)
+select type (y)
+type i

[gcc r15-168] Fortran: fix issues with class(*) assignment [PR114827]

2024-05-05 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:21e7aa5f3ea44ca2fef8deb8788edffc04901b5c

commit r15-168-g21e7aa5f3ea44ca2fef8deb8788edffc04901b5c
Author: Harald Anlauf 
Date:   Mon Apr 29 19:52:52 2024 +0200

Fortran: fix issues with class(*) assignment [PR114827]

gcc/fortran/ChangeLog:

PR fortran/114827
* trans-array.cc (gfc_alloc_allocatable_for_assignment): Take into
account _len of unlimited polymorphic entities when calculating
the effective element size for allocation size and array span.
Set _len of lhs to _len of rhs.
* trans-expr.cc (trans_class_assignment): Take into account _len
of unlimited polymorphic entities for allocation size.

gcc/testsuite/ChangeLog:

PR fortran/114827
* gfortran.dg/asan/unlimited_polymorphic_34.f90: New test.

Diff:
---
 gcc/fortran/trans-array.cc |  16 +++
 gcc/fortran/trans-expr.cc  |  13 ++
 .../gfortran.dg/asan/unlimited_polymorphic_34.f90  | 135 +
 3 files changed, 164 insertions(+)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 30b84762346..7ec33fb1598 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -11278,6 +11278,19 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo 
*loop,
gfc_add_modify (, linfo->delta[dim], tmp);
 }
 
+  /* Take into account _len of unlimited polymorphic entities, so that span
+ for array descriptors and allocation sizes are computed correctly.  */
+  if (UNLIMITED_POLY (expr2))
+{
+  tree len = gfc_class_len_get (TREE_OPERAND (desc2, 0));
+  len = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
+fold_convert (size_type_node, len),
+size_one_node);
+  elemsize2 = fold_build2_loc (input_location, MULT_EXPR,
+  gfc_array_index_type, elemsize2,
+  fold_convert (gfc_array_index_type, len));
+}
+
   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
 gfc_conv_descriptor_span_set (, desc, elemsize2);
 
@@ -11324,6 +11337,9 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo 
*loop,
gfc_add_modify (, tmp,
fold_convert (TREE_TYPE (tmp),
  TYPE_SIZE_UNIT (type)));
+ else if (UNLIMITED_POLY (expr2))
+   gfc_add_modify (, tmp,
+   gfc_class_len_get (TREE_OPERAND (desc2, 0)));
  else
gfc_add_modify (, tmp,
build_int_cst (TREE_TYPE (tmp), 0));
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 0280c441ced..bc8eb419cff 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -11991,6 +11991,19 @@ trans_class_assignment (stmtblock_t *block, gfc_expr 
*lhs, gfc_expr *rhs,
old_vptr = build_int_cst (TREE_TYPE (vptr), 0);
 
   size = gfc_vptr_size_get (rhs_vptr);
+
+  /* Take into account _len of unlimited polymorphic entities.
+TODO: handle class(*) allocatable function results on rhs.  */
+  if (UNLIMITED_POLY (rhs) && rhs->expr_type == EXPR_VARIABLE)
+   {
+ tree len = trans_get_upoly_len (block, rhs);
+ len = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
+fold_convert (size_type_node, len),
+size_one_node);
+ size = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (size),
+ size, fold_convert (TREE_TYPE (size), len));
+   }
+
   tmp = lse->expr;
   class_han = GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
  ? gfc_class_data_get (tmp) : tmp;
diff --git a/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90 
b/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90
new file mode 100644
index 000..c69158a1b55
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90
@@ -0,0 +1,135 @@
+! { dg-do run }
+! PR fortran/114827 - issues with class(*) assignment found by valgrind
+!
+! Contributed by Neil Carlson 
+
+program main
+  implicit none
+  call run
+  call run1
+  call run2
+contains
+  ! Scalar tests
+  subroutine run ()
+character(*),parameter :: c = 'fubarfubarfubarfubarfubarfu'
+character(*,kind=4), parameter :: d = 4_"abcdef"
+complex, parameter :: z = (1.,2.)
+class(*),  allocatable :: y
+
+call foo (c, y)
+select type (y)
+type is (character(*))
+!  print *, y(5:6)  ! ICE (-> pr114874)
+   if (y /= c) stop 1
+class default
+   stop 2
+end select
+
+call foo (z, y)
+select type (y)
+type is (complex)
+   if (y /= z) stop 3
+class default
+   stop 4
+end select
+
+call foo (d, y)

Re: [PATCH] Fortran: fix issues with class(*) assignment [PR114827]

2024-04-30 Thread Harald Anlauf

Hi Paul,

On 4/30/24 07:50, Paul Richard Thomas wrote:

Hi Harald,

This patch is verging on 'obvious', . once one sees it :-)

Yes, it's good for mainline and all active branches, when available.


thanks for your quick review.

I haven't committed it yet, because I forgot to check what happens with
a class(*) allocatable function result on the r.h.s. of the assignment.
One now gets an ICE with the testcase in your submission

  https://gcc.gnu.org/pipermail/fortran/2024-April/060426.html

on the simple scalar assignment

  y = bar ()

instead of wrong code.  Not very helpful.

I tried the following change on top of the submitted patch:

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 4ba40bfdbd3..cacf3c0dda1 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -11995,7 +11996,11 @@ trans_class_assignment (stmtblock_t *block,
gfc_expr *lhs, gfc_expr *rhs,
   /* Take into account _len of unlimited polymorphic entities.  */
   if (UNLIMITED_POLY (rhs))
{
- tree len = trans_get_upoly_len (block, rhs);
+ tree len;
+ if (rhs->expr_type == EXPR_VARIABLE)
+   len = trans_get_upoly_len (block, rhs);
+ else
+   len = gfc_class_len_get (gfc_get_class_from_expr (tmp));
  len = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
 fold_convert (size_type_node, len),
 size_one_node);

This avoids the ICE, but depending on details of bar() this leads
to different wrong code from before, and

  function bar() result(res)
class(*), allocatable :: res
res = sca
  end function bar

behaves differently from

  function bar()
class(*), allocatable :: bar
bar = sca
  end function bar

The minimal and sort of "safe" fix to avoid a new ICE while keeping
the fix for simple assignments is to replace in the above snippet

   if (UNLIMITED_POLY (rhs))

by

   if (UNLIMITED_POLY (rhs) && rhs->expr_type == EXPR_VARIABLE)

omit the other changes above, and defer a fix for assignment of
function results, as looking at the dump-tree suggests that this
will be a bigger piece of work.  (The .span looks suspicious all
over the place...)

The good thing is: a simple test with array-valued function results
did not immediately break the submitted patch...  ;-)

What do you think?

Thanks,
Harald


Thanks

Paul

PS The fall-out pr114874 is so peculiar that I am dropping everything to
find the source.


On Mon, 29 Apr 2024 at 19:39, Harald Anlauf  wrote:


Dear all,

the attached patch fixes issues with assignments of unlimited polymorphic
entities that were found with the help of valgrind or asan, see PR.
Looking
further into it, it turns out that allocation sizes as well as array spans
could be set incorrectly, leading to wrong results or heap corruption.

The fix is rather straightforward: take into the _len of unlimited
polymorphic entities when it is non-zero to get the correct allocation
sizes and array spans.

The patch has been tested by the reporter, see PR.

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

I would like to backport this to active branches where appropriate,
starting with 14 after it reopens after release.  Is this OK?

Thanks,
Harald








[PATCH] Fortran: fix issues with class(*) assignment [PR114827]

2024-04-29 Thread Harald Anlauf
Dear all,

the attached patch fixes issues with assignments of unlimited polymorphic
entities that were found with the help of valgrind or asan, see PR.  Looking
further into it, it turns out that allocation sizes as well as array spans
could be set incorrectly, leading to wrong results or heap corruption.

The fix is rather straightforward: take into the _len of unlimited
polymorphic entities when it is non-zero to get the correct allocation
sizes and array spans.

The patch has been tested by the reporter, see PR.

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

I would like to backport this to active branches where appropriate,
starting with 14 after it reopens after release.  Is this OK?

Thanks,
Harald

From 3b73471b570898e5a5085422da48d5bf118edff1 Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Mon, 29 Apr 2024 19:52:52 +0200
Subject: [PATCH] Fortran: fix issues with class(*) assignment [PR114827]

gcc/fortran/ChangeLog:

	PR fortran/114827
	* trans-array.cc (gfc_alloc_allocatable_for_assignment): Take into
	account _len of unlimited polymorphic entities when calculating
	the effective element size for allocation size and array span.
	Set _len of lhs to _len of rhs.
	* trans-expr.cc (trans_class_assignment): Take into account _len
	of unlimited polymorphic entities for allocation size.

gcc/testsuite/ChangeLog:

	PR fortran/114827
	* gfortran.dg/asan/unlimited_polymorphic_34.f90: New test.
---
 gcc/fortran/trans-array.cc|  16 +++
 gcc/fortran/trans-expr.cc |  12 ++
 .../asan/unlimited_polymorphic_34.f90 | 135 ++
 3 files changed, 163 insertions(+)
 create mode 100644 gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 30b84762346..7ec33fb1598 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -11278,6 +11278,19 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
 	gfc_add_modify (, linfo->delta[dim], tmp);
 }

+  /* Take into account _len of unlimited polymorphic entities, so that span
+ for array descriptors and allocation sizes are computed correctly.  */
+  if (UNLIMITED_POLY (expr2))
+{
+  tree len = gfc_class_len_get (TREE_OPERAND (desc2, 0));
+  len = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
+			 fold_convert (size_type_node, len),
+			 size_one_node);
+  elemsize2 = fold_build2_loc (input_location, MULT_EXPR,
+   gfc_array_index_type, elemsize2,
+   fold_convert (gfc_array_index_type, len));
+}
+
   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
 gfc_conv_descriptor_span_set (, desc, elemsize2);

@@ -11324,6 +11337,9 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
 	gfc_add_modify (, tmp,
 			fold_convert (TREE_TYPE (tmp),
 	  TYPE_SIZE_UNIT (type)));
+	  else if (UNLIMITED_POLY (expr2))
+	gfc_add_modify (, tmp,
+			gfc_class_len_get (TREE_OPERAND (desc2, 0)));
 	  else
 	gfc_add_modify (, tmp,
 			build_int_cst (TREE_TYPE (tmp), 0));
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 0280c441ced..4ba40bfdbd3 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -11991,6 +11991,18 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs,
 	old_vptr = build_int_cst (TREE_TYPE (vptr), 0);

   size = gfc_vptr_size_get (rhs_vptr);
+
+  /* Take into account _len of unlimited polymorphic entities.  */
+  if (UNLIMITED_POLY (rhs))
+	{
+	  tree len = trans_get_upoly_len (block, rhs);
+	  len = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
+ fold_convert (size_type_node, len),
+ size_one_node);
+	  size = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (size),
+  size, fold_convert (TREE_TYPE (size), len));
+	}
+
   tmp = lse->expr;
   class_han = GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
 	  ? gfc_class_data_get (tmp) : tmp;
diff --git a/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90 b/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90
new file mode 100644
index 000..c69158a1b55
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90
@@ -0,0 +1,135 @@
+! { dg-do run }
+! PR fortran/114827 - issues with class(*) assignment found by valgrind
+!
+! Contributed by Neil Carlson 
+
+program main
+  implicit none
+  call run
+  call run1
+  call run2
+contains
+  ! Scalar tests
+  subroutine run ()
+character(*),parameter :: c = 'fubarfubarfubarfubarfubarfu'
+character(*,kind=4), parameter :: d = 4_"abcdef"
+complex, parameter :: z = (1.,2.)
+class(*),  allocatable :: y
+
+call foo (c, y)
+select type (y)
+type is (character(*))
+!  print *, y(5:6)  ! ICE (-> pr114874)
+   if (y /= c) stop 1
+class default
+   stop 2
+end select
+
+call foo

[gcc r12-10398] Fortran: Fix assumed length chars and len inquiry [PR103716]

2024-04-26 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:b482968801158116dd8ba3b15a4c29143b2a423a

commit r12-10398-gb482968801158116dd8ba3b15a4c29143b2a423a
Author: Paul Thomas 
Date:   Tue May 23 06:46:37 2023 +0100

Fortran: Fix assumed length chars and len inquiry [PR103716]

2023-05-23  Paul Thomas  

gcc/fortran
PR fortran/103716
* resolve.cc (gfc_resolve_ref): Conversion of array_ref into an
element should be done for all characters without a len expr,
not just deferred lens, and for integer expressions.
* trans-expr.cc (conv_inquiry): For len and kind inquiry refs,
set the se string_length to NULL_TREE.

gcc/testsuite/
PR fortran/103716
* gfortran.dg/pr103716.f90 : New test.

(cherry picked from commit 842a432b02238361ecc601d301ac400a7f30f4fa)

Diff:
---
 gcc/fortran/resolve.cc |  4 +++-
 gcc/fortran/trans-expr.cc  |  2 ++
 gcc/testsuite/gfortran.dg/pr103716.f90 | 15 +++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index 9264322f671..6a7325e15e7 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -5461,7 +5461,9 @@ gfc_resolve_ref (gfc_expr *expr)
case REF_INQUIRY:
  /* Implement requirement in note 9.7 of F2018 that the result of the
 LEN inquiry be a scalar.  */
- if (ref->u.i == INQUIRY_LEN && array_ref && expr->ts.deferred)
+ if (ref->u.i == INQUIRY_LEN && array_ref
+ && ((expr->ts.type == BT_CHARACTER && !expr->ts.u.cl->length)
+ || expr->ts.type == BT_INTEGER))
{
  array_ref->u.ar.type = AR_ELEMENT;
  expr->rank = 0;
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 11ee1931b8e..e78a01003c9 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -2854,11 +2854,13 @@ conv_inquiry (gfc_se * se, gfc_ref * ref, gfc_expr 
*expr, gfc_typespec *ts)
 case INQUIRY_KIND:
   res = build_int_cst (gfc_typenode_for_spec (>ts),
   ts->kind);
+  se->string_length = NULL_TREE;
   break;
 
 case INQUIRY_LEN:
   res = fold_convert (gfc_typenode_for_spec (>ts),
  se->string_length);
+  se->string_length = NULL_TREE;
   break;
 
 default:
diff --git a/gcc/testsuite/gfortran.dg/pr103716.f90 
b/gcc/testsuite/gfortran.dg/pr103716.f90
new file mode 100644
index 000..4f78900839e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr103716.f90
@@ -0,0 +1,15 @@
+! { dg-do compile }
+!
+! The gimplifier used to throw a fit on thes two functions.
+!
+! Contributed by Gerhard Steinmetz  
+!
+function f1(x)
+   character(*) :: x(*)
+   print *, g(x%len)
+end
+
+function f2(x)
+   character(*) :: x(3)
+   print *, g(x%len)
+end


[gcc r12-10396] gfortran: Allow ref'ing PDT's len() in parameter-initializer.

2024-04-26 Thread Harald Anlauf via Gcc-cvs
mtree->n.sym
-  && e->symtree->n.sym->ts.type != BT_DERIVED
-  && e->symtree->n.sym->assoc && e->symtree->n.sym->assoc->target
-  && e->symtree->n.sym->assoc->target->ts.type == BT_DERIVED
-  && e->symtree->n.sym->assoc->target->symtree->n.sym
-  && UNLIMITED_POLY (e->symtree->n.sym->assoc->target->symtree->n.sym))
-
-/* The expression in assoc->target points to a ref to the _data component
-   of the unlimited polymorphic entity.  To get the _len component the last
-   _data ref needs to be stripped and a ref to the _len component added.  
*/
-return gfc_get_len_component (e->symtree->n.sym->assoc->target, k);
-  else
-return NULL;
+  && e->symtree->n.sym)
+{
+  if (e->symtree->n.sym->ts.type != BT_DERIVED
+ && e->symtree->n.sym->assoc && e->symtree->n.sym->assoc->target
+ && e->symtree->n.sym->assoc->target->ts.type == BT_DERIVED
+ && e->symtree->n.sym->assoc->target->symtree->n.sym
+ && UNLIMITED_POLY (e->symtree->n.sym->assoc->target->symtree->n.sym))
+   /* The expression in assoc->target points to a ref to the _data
+  component of the unlimited polymorphic entity.  To get the _len
+  component the last _data ref needs to be stripped and a ref to the
+  _len component added.  */
+   return gfc_get_len_component (e->symtree->n.sym->assoc->target, k);
+  else if (e->symtree->n.sym->ts.type == BT_DERIVED
+  && e->ref && e->ref->type == REF_COMPONENT
+  && e->ref->u.c.component->attr.pdt_string
+  && e->ref->u.c.component->ts.type == BT_CHARACTER
+  && e->ref->u.c.component->ts.u.cl->length)
+   {
+ if (gfc_init_expr_flag)
+   {
+ gfc_expr* tmp;
+ tmp = gfc_pdt_find_component_copy_initializer (e->symtree->n.sym,
+e->ref->u.c
+.component->ts.u.cl
+->length->symtree
+->name);
+ if (tmp)
+   return tmp;
+   }
+ else
+   {
+ gfc_expr *len_expr = gfc_copy_expr (e);
+ gfc_free_ref_list (len_expr->ref);
+ len_expr->ref = NULL;
+ gfc_find_component (len_expr->symtree->n.sym->ts.u.derived, e->ref
+ ->u.c.component->ts.u.cl->length->symtree
+ ->name,
+ false, true, _expr->ref);
+ len_expr->ts = len_expr->ref->u.c.component->ts;
+ return len_expr;
+   }
+   }
+}
+  return NULL;
 }
 
 
diff --git a/gcc/testsuite/gfortran.dg/pdt_33.f03 
b/gcc/testsuite/gfortran.dg/pdt_33.f03
new file mode 100644
index 000..3b2fe72431d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pdt_33.f03
@@ -0,0 +1,21 @@
+! { dg-do run }
+!
+! Test the fix for PR102003, where len parameters where not returned as 
constants.
+!
+! Contributed by Harald Anlauf  
+!
+program pr102003
+  type pdt(n)
+ integer, len :: n = 8
+ character(len=n) :: c
+  end type pdt
+  type(pdt(42)) :: p
+  integer, parameter :: m = len (p% c)
+  integer, parameter :: lm = p% c% len
+
+  if (m /= 42) stop 1
+  if (len (p% c) /= 42) stop 2
+  if (lm /= 42) stop 3
+  if (p% c% len /= 42) stop 4
+end
+


[gcc r13-8651] gfortran: Allow ref'ing PDT's len() in parameter-initializer.

2024-04-26 Thread Harald Anlauf via Gcc-cvs
mtree->n.sym
-  && e->symtree->n.sym->ts.type != BT_DERIVED
-  && e->symtree->n.sym->assoc && e->symtree->n.sym->assoc->target
-  && e->symtree->n.sym->assoc->target->ts.type == BT_DERIVED
-  && e->symtree->n.sym->assoc->target->symtree->n.sym
-  && UNLIMITED_POLY (e->symtree->n.sym->assoc->target->symtree->n.sym))
-
-/* The expression in assoc->target points to a ref to the _data component
-   of the unlimited polymorphic entity.  To get the _len component the last
-   _data ref needs to be stripped and a ref to the _len component added.  
*/
-return gfc_get_len_component (e->symtree->n.sym->assoc->target, k);
-  else
-return NULL;
+  && e->symtree->n.sym)
+{
+  if (e->symtree->n.sym->ts.type != BT_DERIVED
+ && e->symtree->n.sym->assoc && e->symtree->n.sym->assoc->target
+ && e->symtree->n.sym->assoc->target->ts.type == BT_DERIVED
+ && e->symtree->n.sym->assoc->target->symtree->n.sym
+ && UNLIMITED_POLY (e->symtree->n.sym->assoc->target->symtree->n.sym))
+   /* The expression in assoc->target points to a ref to the _data
+  component of the unlimited polymorphic entity.  To get the _len
+  component the last _data ref needs to be stripped and a ref to the
+  _len component added.  */
+   return gfc_get_len_component (e->symtree->n.sym->assoc->target, k);
+  else if (e->symtree->n.sym->ts.type == BT_DERIVED
+  && e->ref && e->ref->type == REF_COMPONENT
+  && e->ref->u.c.component->attr.pdt_string
+  && e->ref->u.c.component->ts.type == BT_CHARACTER
+  && e->ref->u.c.component->ts.u.cl->length)
+   {
+ if (gfc_init_expr_flag)
+   {
+ gfc_expr* tmp;
+ tmp = gfc_pdt_find_component_copy_initializer (e->symtree->n.sym,
+e->ref->u.c
+.component->ts.u.cl
+->length->symtree
+->name);
+ if (tmp)
+   return tmp;
+   }
+ else
+   {
+ gfc_expr *len_expr = gfc_copy_expr (e);
+ gfc_free_ref_list (len_expr->ref);
+ len_expr->ref = NULL;
+ gfc_find_component (len_expr->symtree->n.sym->ts.u.derived, e->ref
+ ->u.c.component->ts.u.cl->length->symtree
+ ->name,
+ false, true, _expr->ref);
+ len_expr->ts = len_expr->ref->u.c.component->ts;
+ return len_expr;
+   }
+   }
+}
+  return NULL;
 }
 
 
diff --git a/gcc/testsuite/gfortran.dg/pdt_33.f03 
b/gcc/testsuite/gfortran.dg/pdt_33.f03
new file mode 100644
index 000..3b2fe72431d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pdt_33.f03
@@ -0,0 +1,21 @@
+! { dg-do run }
+!
+! Test the fix for PR102003, where len parameters where not returned as 
constants.
+!
+! Contributed by Harald Anlauf  
+!
+program pr102003
+  type pdt(n)
+ integer, len :: n = 8
+ character(len=n) :: c
+  end type pdt
+  type(pdt(42)) :: p
+  integer, parameter :: m = len (p% c)
+  integer, parameter :: lm = p% c% len
+
+  if (m /= 42) stop 1
+  if (len (p% c) /= 42) stop 2
+  if (lm /= 42) stop 3
+  if (p% c% len /= 42) stop 4
+end
+


Re: [Patch, fortran] PR93678 - [11/12/13/14 Regression] ICE with TRANSFER and typebound procedures

2024-04-24 Thread Harald Anlauf

Hi Paul,

On 4/24/24 18:26, Paul Richard Thomas wrote:

Hi there,

This regression turned out to be low hanging fruit, although it has taken
four years to reach it :-(

The ChangeLog says it all. OK for mainline and backporting after a suitable
delay?


yes to both.

Thanks for "picking" this fruit!

Harald


Paul

Fortran: Fix ICE in gfc_trans_create_temp_array from bad type [PR93678]

2024-04-24  Paul Thomas  

gcc/fortran
PR fortran/93678
* trans-expr.cc (gfc_conv_procedure_call): Use the interface,
where possible, to obtain the type of character procedure
pointers of class entities.

gcc/testsuite/
PR fortran/93678
* gfortran.dg/pr93678.f90: New test.





[gcc r14-10097] Fortran: check C_SIZEOF on additions from TS29113/F2018 [PR103496]

2024-04-23 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:0bf94da59feab2c72a02c91df310a36d33dfd1f7

commit r14-10097-g0bf94da59feab2c72a02c91df310a36d33dfd1f7
Author: Harald Anlauf 
Date:   Tue Apr 23 20:21:43 2024 +0200

Fortran: check C_SIZEOF on additions from TS29113/F2018 [PR103496]

gcc/testsuite/ChangeLog:

PR fortran/103496
* gfortran.dg/c_sizeof_8.f90: New test.

Diff:
---
 gcc/testsuite/gfortran.dg/c_sizeof_8.f90 | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/gcc/testsuite/gfortran.dg/c_sizeof_8.f90 
b/gcc/testsuite/gfortran.dg/c_sizeof_8.f90
new file mode 100644
index 000..0ae284436d0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c_sizeof_8.f90
@@ -0,0 +1,23 @@
+! { dg-do run }
+!
+! PR fortran/103496
+!
+! Test that C_SIZEOF returns the expected results
+
+program pr103496
+  use iso_c_binding
+  implicit none
+  integer :: a(6)
+  integer, pointer :: p(:)
+
+  if (c_sizeof(a)   /= 6*4) stop 1
+  if (c_sizeof(a(1))/=   4) stop 2
+  if (c_sizeof(a(:))/= 6*4) stop 3
+  if (c_sizeof(a(2::2)) /= 3*4) stop 4
+
+  allocate(p(5))
+  if (c_sizeof(p)   /= 5*4) stop 5
+  if (c_sizeof(p(1))/=   4) stop 6
+  if (c_sizeof(p(:))/= 5*4) stop 7
+  if (c_sizeof(p(2::2)) /= 2*4) stop 8
+end


Re: [Patch, fortran] PR103471 - [11/12/13/14 Regression] ICE in gfc_typenode_for_spec, at fortran/trans-types.c:1114

2024-04-20 Thread Harald Anlauf

Hi Paul!

On 4/20/24 09:54, Paul Richard Thomas wrote:

subroutine sub
implicit none
real, external :: x
real   :: y(10)
integer :: kk
print *, [real(x(k))]
!  print *, [real(y(k))]
end



This is another problem, somewhere upstream from resolve.cc, which I have
just spent an hour failing to find. In the presence of both print
statements, in no matter which order, it is the error in trans-decl.cc that
applies.


Indeed, the gfc_fatal_error always wins.

(I had tried to replace it with gfc_error()/return NULL_TREE, but then
I hit an ICE later on.  When trying to find out who added the said
code, guess whom I found :)




Thus I have the impression that the testcase tests something different
on the one hand, and on the other I wonder if we would want to change
the error message and replace "no default type" to "no IMPLICIT type".
It still would not hit the fuzzy check, but that is something that
might not be important now.



The fuzzy check was intended to ensure that the error was being detected in
the "right" place. I want to keep the "no default type" message for the
time being at least so as to identify exactly where it comes from. Getting
to trans-decl.cc with an unknown type is just wrong.


True.


I'll come back to you on this.


This PR is marked as a regression.  Depending on your progress,
it might be worth to consider fixing what you think is needed
to get rid of the regression marker and defer the improvement
of the diagnostics to a second patch.

Harald


Thanks for the report.

Paul





Re: [Patch, fortran] PR103471 - [11/12/13/14 Regression] ICE in gfc_typenode_for_spec, at fortran/trans-types.c:1114

2024-04-19 Thread Harald Anlauf

Hi Paul,

the patch is OK, but I had to manually fix it.  I wonder how you managed
to produce:

diff --git a/gcc/testsuite/gfortran.dg/pr93484.f90
b/gcc/testsuite/gfortran.dg/pr93484.f90
new file mode 100644
index 000..4dcad47e8da
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr103471.f90
@@ -0,0 +1,13 @@

A minor comment on the error message and the testcase.
Take for example:

subroutine sub
  implicit none
  real, external :: x
  real   :: y(10)
  integer :: kk
  print *, [real(x(k))]
!  print *, [real(y(k))]
end

The original testcase in the PR would - without implicit none -
resemble the function invocation x(k) here and emit the error:

Fatal Error: k at (1) has no default type
compilation terminated.

while commenting the first print and uncommenting the second
would emit the message

Error: Symbol 'k' at (1) has no IMPLICIT type; did you mean 'kk'?

Thus I have the impression that the testcase tests something different
on the one hand, and on the other I wonder if we would want to change
the error message and replace "no default type" to "no IMPLICIT type".
It still would not hit the fuzzy check, but that is something that
might not be important now.

Thanks,
Harald


On 4/19/24 18:52, Paul Richard Thomas wrote:

Hi All,

This is a more or less obvious patch. The action is in resolve.cc. The
chunk in symbol.cc is a tidy up of a diagnostic marker to distinguish where
the 'no IMPLICIT type' error was coming from and the chunk in trans-decl.cc
follows from discussion with Harald on the PR.

Regtests fine. OK for mainline and backporting in a couple of weeks?

Paul

Fortran: Detect 'no implicit type' error in right place [PR103471]

2024-04-19  Paul Thomas  

gcc/fortran
PR fortran/103471
* resolve.cc (gfc_resolve_index_1): Block index expressions of
unknown type from being converted to default integer, avoiding
the fatal error in trans-decl.cc.
* symbol.cc (gfc_set_default_type): Remove '(symbol)' from the
'no IMPLICIT type' error message.
* trans-decl.cc (gfc_get_symbol_decl): Change fatal error locus
to that of the symbol declaration.
(gfc_trans_deferred_vars): Remove two trailing tabs.

gcc/testsuite/
PR fortran/103471
* gfortran.dg/pr103471.f90: New test.





[gcc r14-9996] Fortran: ALLOCATE of fixed-length CHARACTER with SOURCE/MOLD [PR113793]

2024-04-16 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:48024a99e3c2ae522d0026eedd591390506b68ca

commit r14-9996-g48024a99e3c2ae522d0026eedd591390506b68ca
Author: Harald Anlauf 
Date:   Sat Apr 13 19:09:24 2024 +0200

Fortran: ALLOCATE of fixed-length CHARACTER with SOURCE/MOLD [PR113793]

F2008 requires for ALLOCATE with SOURCE= or MOLD= specifier that the kind
type parameters of allocate-object and source-expr have the same values.
Add compile-time diagnostics for different character length and a runtime
check (under -fcheck=bounds).  Use length from allocate-object to prevent
heap corruption and to allow string padding or truncation on assignment.

gcc/fortran/ChangeLog:

PR fortran/113793
* resolve.cc (resolve_allocate_expr): Reject ALLOCATE with SOURCE=
or MOLD= specifier for unequal length.
* trans-stmt.cc (gfc_trans_allocate): If an allocatable character
variable has fixed length, use it and do not use the source length.
With bounds-checking enabled, add a runtime check for same length.

gcc/testsuite/ChangeLog:

PR fortran/113793
* gfortran.dg/allocate_with_source_29.f90: New test.
* gfortran.dg/allocate_with_source_30.f90: New test.
* gfortran.dg/allocate_with_source_31.f90: New test.

Diff:
---
 gcc/fortran/resolve.cc | 10 +
 gcc/fortran/trans-stmt.cc  | 36 +--
 .../gfortran.dg/allocate_with_source_29.f90| 48 
 .../gfortran.dg/allocate_with_source_30.f90| 51 ++
 .../gfortran.dg/allocate_with_source_31.f90| 38 
 5 files changed, 179 insertions(+), 4 deletions(-)

diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index 4cbf7186119..6b3e5ba4fcb 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -8278,6 +8278,16 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code, bool 
*array_alloc_wo_spec)
  goto failure;
}
 
+  /* Check F2008:C639: "Corresponding kind type parameters of
+allocate-object and source-expr shall have the same values."  */
+  if (e->ts.type == BT_CHARACTER
+ && !e->ts.deferred
+ && e->ts.u.cl->length
+ && code->expr3->ts.type == BT_CHARACTER
+ && !gfc_check_same_strlen (e, code->expr3, "ALLOCATE with "
+"SOURCE= or MOLD= specifier"))
+   goto failure;
+
   /* Check TS18508, C702/C703.  */
   if (code->expr3->ts.type == BT_DERIVED
  && ((codimension && gfc_expr_attr (code->expr3).event_comp)
diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 7997c167bae..c34e0b4c0cd 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -6829,10 +6829,26 @@ gfc_trans_allocate (gfc_code * code, gfc_omp_namelist 
*omp_allocate)
 in the array is needed, which is the product of the len and
 esize for char arrays.  For unlimited polymorphics len can be
 zero, therefore take the maximum of len and one.  */
+ tree lhs_len;
+
+ /* If an allocatable character variable has fixed length, use it.
+Otherwise use source length.  As different lengths are not
+allowed by the standard, generate a runtime check.  */
+ if (expr->ts.type == BT_CHARACTER && !expr->ts.deferred)
+   {
+ gfc_trans_same_strlen_check ("ALLOCATE with SOURCE= or MOLD=",
+  >expr3->where,
+  se.string_length, expr3_len,
+  );
+ lhs_len = fold_convert (TREE_TYPE (expr3_len), se.string_length);
+   }
+ else
+   lhs_len = expr3_len;
+
  tmp = fold_build2_loc (input_location, MAX_EXPR,
 TREE_TYPE (expr3_len),
-expr3_len, fold_convert (TREE_TYPE (expr3_len),
- integer_one_node));
+lhs_len, fold_convert (TREE_TYPE (expr3_len),
+   integer_one_node));
  tmp = fold_build2_loc (input_location, MULT_EXPR,
 TREE_TYPE (expr3_esize), expr3_esize,
 fold_convert (TREE_TYPE (expr3_esize), tmp));
@@ -6877,10 +6893,22 @@ gfc_trans_allocate (gfc_code * code, gfc_omp_namelist 
*omp_allocate)
 allocate.
 
 expr3_len is set when expr3 is an unlimited polymorphic
-object or a deferred length string.  */
+object or a deferred length string.
+
+If an allocatable

[PATCH] Fortran: ALLOCATE of fixed-length CHARACTER with SOURCE/MOLD [PR113793]

2024-04-13 Thread Harald Anlauf
Dear all,

the attached patch adds the following:

- diagnostics of different string length of allocate-object and of the
  source-expr (SOURCE/MOLD) as hard error when it can be determined at
  compile-time

- a runtime-diagnostics und -fcheck=bounds (reuse of existing checks)

- a fallback solution (GNU extension) to use the length of allocate-object
  if the length mismatch is not diagnosed at compile-time or runtime.
  This avoids heap corruption and leads to string truncation or padding
  during assignment.

F2008 demands same values of the kind type parameters, and this is
diagnosed by NAG.  It also always gives a hard error, even at runtime.

Some brands (NVidia, AMD flang) tolerate a length mismatch silently
and perform string truncation or padding, without crashing.

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

Thanks,
Harald

From b9ece695a178319e35cd9f36cc731855302dd57f Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Sat, 13 Apr 2024 19:09:24 +0200
Subject: [PATCH] Fortran: ALLOCATE of fixed-length CHARACTER with SOURCE/MOLD
 [PR113793]

F2008 requires for ALLOCATE with SOURCE= or MOLD= specifier that the kind
type parameters of allocate-object and source-expr have the same values.
Add compile-time diagnostics for different character length and a runtime
check (under -fcheck=bounds).  Use length from allocate-object to prevent
heap corruption and to allow string padding or truncation on assignment.

gcc/fortran/ChangeLog:

	PR fortran/113793
	* resolve.cc (resolve_allocate_expr): Reject ALLOCATE with SOURCE=
	or MOLD= specifier for unequal length.
	* trans-stmt.cc (gfc_trans_allocate): If an allocatable character
	variable has fixed length, use it and do not use the source length.
	With bounds-checking enabled, add a runtime check for same length.

gcc/testsuite/ChangeLog:

	PR fortran/113793
	* gfortran.dg/allocate_with_source_29.f90: New test.
	* gfortran.dg/allocate_with_source_30.f90: New test.
	* gfortran.dg/allocate_with_source_31.f90: New test.
---
 gcc/fortran/resolve.cc| 10 
 gcc/fortran/trans-stmt.cc | 36 +++--
 .../gfortran.dg/allocate_with_source_29.f90   | 48 +
 .../gfortran.dg/allocate_with_source_30.f90   | 51 +++
 .../gfortran.dg/allocate_with_source_31.f90   | 38 ++
 5 files changed, 179 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/allocate_with_source_29.f90
 create mode 100644 gcc/testsuite/gfortran.dg/allocate_with_source_30.f90
 create mode 100644 gcc/testsuite/gfortran.dg/allocate_with_source_31.f90

diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index 4cbf7186119..6b3e5ba4fcb 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -8278,6 +8278,16 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code, bool *array_alloc_wo_spec)
 	  goto failure;
 	}

+  /* Check F2008:C639: "Corresponding kind type parameters of
+	 allocate-object and source-expr shall have the same values."  */
+  if (e->ts.type == BT_CHARACTER
+	  && !e->ts.deferred
+	  && e->ts.u.cl->length
+	  && code->expr3->ts.type == BT_CHARACTER
+	  && !gfc_check_same_strlen (e, code->expr3, "ALLOCATE with "
+ "SOURCE= or MOLD= specifier"))
+	goto failure;
+
   /* Check TS18508, C702/C703.  */
   if (code->expr3->ts.type == BT_DERIVED
 	  && ((codimension && gfc_expr_attr (code->expr3).event_comp)
diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 7997c167bae..c34e0b4c0cd 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -6829,10 +6829,26 @@ gfc_trans_allocate (gfc_code * code, gfc_omp_namelist *omp_allocate)
 	 in the array is needed, which is the product of the len and
 	 esize for char arrays.  For unlimited polymorphics len can be
 	 zero, therefore take the maximum of len and one.  */
+	  tree lhs_len;
+
+	  /* If an allocatable character variable has fixed length, use it.
+	 Otherwise use source length.  As different lengths are not
+	 allowed by the standard, generate a runtime check.  */
+	  if (expr->ts.type == BT_CHARACTER && !expr->ts.deferred)
+	{
+	  gfc_trans_same_strlen_check ("ALLOCATE with SOURCE= or MOLD=",
+	   >expr3->where,
+	   se.string_length, expr3_len,
+	   );
+	  lhs_len = fold_convert (TREE_TYPE (expr3_len), se.string_length);
+	}
+	  else
+	lhs_len = expr3_len;
+
 	  tmp = fold_build2_loc (input_location, MAX_EXPR,
  TREE_TYPE (expr3_len),
- expr3_len, fold_convert (TREE_TYPE (expr3_len),
-			  integer_one_node));
+ lhs_len, fold_convert (TREE_TYPE (expr3_len),
+			integer_one_node));
 	  tmp = fold_build2_loc (input_location, MULT_EXPR,
  TREE_TYPE (expr3_esize), expr3_esize,
  fold_convert (TREE_TYPE (expr3_esize), tmp));
@@ -687

Re: [Patch, fortran] PR113363 - ICE on ASSOCIATE and unlimited polymorphic function

2024-04-10 Thread Harald Anlauf

Hi Paul!

On 4/10/24 10:25, Paul Richard Thomas wrote:

Hi All,

This patch corrects incorrect results from assignment of unlimited
polymorphic function results both in assignment statements and allocation
with source.

The first chunk in trans-array.cc ensures that the array dtype is set to
the source dtype. The second chunk ensures that the lhs _len field does not
default to zero and so is specific to dynamic types of character.

The addition to trans-stmt.cc transforms the source expression, aka expr3,
from a derived type of type "STAR" into a proper unlimited polymorphic
expression ready for assignment to the newly allocated entity.


I am wondering about the following snippet in trans-stmt.cc:

+ /* Copy over the lhs _data component ref followed by the
+full array reference for source expressions with rank.
+Otherwise, just copy the _data component ref.  */
+ if (code->expr3->rank
+ && ref && ref->next && !ref->next->next)
+   {
+ rhs->ref = gfc_copy_ref (ref);
+ rhs->ref->next = gfc_copy_ref (ref->next);
+ break;
+   }

Why the two gfc_copy_ref?  valgrind pointed my to the tail
of gfc_copy_ref which already has:

  dest->next = gfc_copy_ref (src->next);

so this looks redundant and leaks frontend memory?

***

Playing with the testcase, I find several invalid writes with
valgrind, or a heap buffer overflow with -fsanitize=address .

It is sufficient to look at a mini-test where the class(*) function
result is assigned to the class(*), allocatable in the main:

  x = foo ()
  deallocate (x)

The dump tree suggests that array bounds in foo() are read before
they are properly set.

These invalid writes do not occur with 13-branch, so this might
be a regression.

Can you have a look yourself?

Thanks,
Harald


OK for mainline?

Paul

Fortran: Fix wrong code in unlimited polymorphic assignment [PR113363]

2024-04-10  Paul Thomas  

gcc/fortran
PR fortran/113363
* trans-array.cc (gfc_array_init_size): Use the expr3 dtype so
that the correct element size is used.
(gfc_alloc_allocatable_for_assignment): Set the _len field for
unlimited polymorphic assignments.
* trans-stmt.cc (gfc_trans_allocate): Build a correct rhs for
the assignment of an unlimited polymorphic 'source'.

gcc/testsuite/
PR fortran/113363
* gfortran.dg/pr113363.f90: New test.






[gcc r14-9893] Fortran: fix argument checking of intrinsics C_SIZEOF, C_F_POINTER [PR106500]

2024-04-10 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:ded646c91d2c0fb908faf6fa8fe1df0d7df49d16

commit r14-9893-gded646c91d2c0fb908faf6fa8fe1df0d7df49d16
Author: Harald Anlauf 
Date:   Tue Apr 9 23:07:59 2024 +0200

Fortran: fix argument checking of intrinsics C_SIZEOF, C_F_POINTER 
[PR106500]

The interpretation of the F2018 standard regarding valid arguments to the
intrinsic C_SIZEOF(X) was clarified in an edit to 18-007r1:

  https://j3-fortran.org/doc/year/22/22-101r1.txt

loosening restrictions and giving examples.  The F2023 text has:

! F2023:18.2.3.8  C_SIZEOF (X)
!
!   X shall be a data entity with interoperable type and type parameters,
!   and shall not be an assumed-size array, an assumed-rank array that
!   is associated with an assumed-size array, an unallocated allocatable
!   variable, or a pointer that is not associated.

where

! 3.41 data entity
!   data object, result of the evaluation of an expression, or the
!   result of the execution of a function reference

Update the checking code for interoperable arguments accordingly, and extend
to reject functions returning pointer as FPTR argument to C_F_POINTER.

gcc/fortran/ChangeLog:

PR fortran/106500
* check.cc (is_c_interoperable): Fix checks for C_SIZEOF.
(gfc_check_c_f_pointer): Reject function returning a pointer as 
FPTR,
and improve an error message.

gcc/testsuite/ChangeLog:

PR fortran/106500
* gfortran.dg/c_sizeof_6.f90: Remove wrong dg-error.
* gfortran.dg/sizeof_2.f90: Adjust pattern.
* gfortran.dg/c_f_pointer_tests_9.f90: New test.
* gfortran.dg/c_sizeof_7.f90: New test.

Diff:
---
 gcc/fortran/check.cc  | 26 --
 gcc/testsuite/gfortran.dg/c_f_pointer_tests_9.f90 | 37 
 gcc/testsuite/gfortran.dg/c_sizeof_6.f90  |  2 +-
 gcc/testsuite/gfortran.dg/c_sizeof_7.f90  | 42 +++
 gcc/testsuite/gfortran.dg/sizeof_2.f90|  2 +-
 5 files changed, 96 insertions(+), 13 deletions(-)

diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc
index db74dcf3f40..2f50d84b876 100644
--- a/gcc/fortran/check.cc
+++ b/gcc/fortran/check.cc
@@ -5299,18 +5299,14 @@ is_c_interoperable (gfc_expr *expr, const char **msg, 
bool c_loc, bool c_f_ptr)
   return false;
 }
 
-  if (!c_loc && expr->rank > 0 && expr->expr_type != EXPR_ARRAY)
+  /* Checks for C_SIZEOF need to take into account edits to 18-007r1, see
+ https://j3-fortran.org/doc/year/22/22-101r1.txt .  */
+  if (!c_loc && !c_f_ptr && expr->rank > 0 && expr->expr_type == EXPR_VARIABLE)
 {
   gfc_array_ref *ar = gfc_find_array_ref (expr);
-  if (ar->type != AR_FULL)
+  if (ar->type == AR_FULL && ar->as->type == AS_ASSUMED_SIZE)
{
- *msg = "Only whole-arrays are interoperable";
- return false;
-   }
-  if (!c_f_ptr && ar->as->type != AS_EXPLICIT
- && ar->as->type != AS_ASSUMED_SIZE)
-   {
- *msg = "Only explicit-size and assumed-size arrays are interoperable";
+ *msg = "Assumed-size arrays are not interoperable";
  return false;
}
 }
@@ -5475,9 +5471,17 @@ gfc_check_c_f_pointer (gfc_expr *cptr, gfc_expr *fptr, 
gfc_expr *shape)
   return false;
 }
 
+  if (fptr->ts.type == BT_PROCEDURE && attr.function)
+{
+  gfc_error ("FPTR argument to C_F_POINTER at %L is a function "
+"returning a pointer", >where);
+  return false;
+}
+
   if (fptr->rank > 0 && !is_c_interoperable (fptr, , false, true))
-return gfc_notify_std (GFC_STD_F2018, "Noninteroperable array FPTR "
-  "at %L to C_F_POINTER: %s", >where, msg);
+return gfc_notify_std (GFC_STD_F2018,
+  "Noninteroperable array FPTR argument to "
+  "C_F_POINTER at %L: %s", >where, msg);
 
   return true;
 }
diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_tests_9.f90 
b/gcc/testsuite/gfortran.dg/c_f_pointer_tests_9.f90
new file mode 100644
index 000..8c8b4a713a4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c_f_pointer_tests_9.f90
@@ -0,0 +1,37 @@
+! { dg-do compile }
+!
+! A function returning a pointer cannot be interoperable
+! and cannot be used as FPTR argument to C_F_POINTER.
+
+subroutine s ()
+  use, intrinsic :: iso_c_binding
+  implicit none
+  type(c_ptr) :: cPtr
+  call c_f_pointer (cPtr, p0)! { dg-error "function returning a 
pointer" }
+  call c_f_pointer (cPtr, p1, shape=[2]) ! { dg-error "function returning a 
pointer" }
+contains
+  function p0 ()
+

[PATCH, v2] Fortran: fix argument checking of intrinsics C_SIZEOF, C_F_POINTER [PR106500]

2024-04-09 Thread Harald Anlauf

Hi FX!

On 4/9/24 09:32, FX Coudert wrote:

Hi Harald,

Thanks for the patch.



+  if (attr.function)
+{
+  gfc_error ("FPTR at %L to C_F_POINTER is a function returning a pointer",
+ >where);
+  return false;
+}
+
if (fptr->rank > 0 && !is_c_interoperable (fptr, , false, true))
  return gfc_notify_std (GFC_STD_F2018, "Noninteroperable array FPTR "
 "at %L to C_F_POINTER: %s", >where, msg);



In both of these gfc_error(), could we change our error message to say "FPTR 
argument” instead of “FPTR”? “FPTR to C_F_POINTER” does not really make sense to me.

This would be more in line with what the generally do:


Error: 'x' argument of 'sqrt' intrinsic at (1) must be REAL or COMPLEX


So maybe “FPTR argument to C_F_POINTER at %L” ? That’s much more readable to me.


Good point!  I did indeed feel a little uncomfortable with the text
and adjusted both messages accordingly to your suggestion.

I also forgot to add one update of a pattern, and found a cornercase
where the tightening of checks for C_F_POINTER was too strong.
Corrected and now covered in an extension of the corresponding testcase.


Otherwise, OK.

FX


Thanks for the review!

If there are no further comments, I will commit tomorrow.

Thanks,
Harald
From 5983a07f11c88d920241141732fa742735cdb8ea Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Tue, 9 Apr 2024 23:07:59 +0200
Subject: [PATCH] Fortran: fix argument checking of intrinsics C_SIZEOF,
 C_F_POINTER [PR106500]

The interpretation of the F2018 standard regarding valid arguments to the
intrinsic C_SIZEOF(X) was clarified in an edit to 18-007r1:

  https://j3-fortran.org/doc/year/22/22-101r1.txt

loosening restrictions and giving examples.  The F2023 text has:

! F2023:18.2.3.8  C_SIZEOF (X)
!
!   X shall be a data entity with interoperable type and type parameters,
!   and shall not be an assumed-size array, an assumed-rank array that
!   is associated with an assumed-size array, an unallocated allocatable
!   variable, or a pointer that is not associated.

where

! 3.41 data entity
!   data object, result of the evaluation of an expression, or the
!   result of the execution of a function reference

Update the checking code for interoperable arguments accordingly, and extend
to reject functions returning pointer as FPTR argument to C_F_POINTER.

gcc/fortran/ChangeLog:

	PR fortran/106500
	* check.cc (is_c_interoperable): Fix checks for C_SIZEOF.
	(gfc_check_c_f_pointer): Reject function returning a pointer as FPTR,
	and improve an error message.

gcc/testsuite/ChangeLog:

	PR fortran/106500
	* gfortran.dg/c_sizeof_6.f90: Remove wrong dg-error.
	* gfortran.dg/sizeof_2.f90: Adjust pattern.
	* gfortran.dg/c_f_pointer_tests_9.f90: New test.
	* gfortran.dg/c_sizeof_7.f90: New test.
---
 gcc/fortran/check.cc  | 26 +++-
 .../gfortran.dg/c_f_pointer_tests_9.f90   | 37 
 gcc/testsuite/gfortran.dg/c_sizeof_6.f90  |  2 +-
 gcc/testsuite/gfortran.dg/c_sizeof_7.f90  | 42 +++
 gcc/testsuite/gfortran.dg/sizeof_2.f90|  2 +-
 5 files changed, 96 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/c_f_pointer_tests_9.f90
 create mode 100644 gcc/testsuite/gfortran.dg/c_sizeof_7.f90

diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc
index db74dcf3f40..2f50d84b876 100644
--- a/gcc/fortran/check.cc
+++ b/gcc/fortran/check.cc
@@ -5299,18 +5299,14 @@ is_c_interoperable (gfc_expr *expr, const char **msg, bool c_loc, bool c_f_ptr)
   return false;
 }
 
-  if (!c_loc && expr->rank > 0 && expr->expr_type != EXPR_ARRAY)
+  /* Checks for C_SIZEOF need to take into account edits to 18-007r1, see
+ https://j3-fortran.org/doc/year/22/22-101r1.txt .  */
+  if (!c_loc && !c_f_ptr && expr->rank > 0 && expr->expr_type == EXPR_VARIABLE)
 {
   gfc_array_ref *ar = gfc_find_array_ref (expr);
-  if (ar->type != AR_FULL)
+  if (ar->type == AR_FULL && ar->as->type == AS_ASSUMED_SIZE)
 	{
-	  *msg = "Only whole-arrays are interoperable";
-	  return false;
-	}
-  if (!c_f_ptr && ar->as->type != AS_EXPLICIT
-	  && ar->as->type != AS_ASSUMED_SIZE)
-	{
-	  *msg = "Only explicit-size and assumed-size arrays are interoperable";
+	  *msg = "Assumed-size arrays are not interoperable";
 	  return false;
 	}
 }
@@ -5475,9 +5471,17 @@ gfc_check_c_f_pointer (gfc_expr *cptr, gfc_expr *fptr, gfc_expr *shape)
   return false;
 }
 
+  if (fptr->ts.type == BT_PROCEDURE && attr.function)
+{
+  gfc_error ("FPTR argument to C_F_POINTER at %L is a function "
+		 "returning a pointer", >where);
+  return false;
+}
+
   if (fptr->rank > 0 && !is_c_interoperable (fptr, , false, true))
-return gfc_notify_std (GFC_ST

[PATCH] Fortran: fix argument checking of intrinsics C_SIZEOF, C_F_POINTER [PR106500]

2024-04-08 Thread Harald Anlauf
Dear all,

the attached patch fixes argument checking of:

- C_SIZEOF - rejects-valid (see below) and ICE-on-valid
- C_F_POINTER - ICE-on-invalid

The interesting part is that C_SIZEOF was not well specified until
after F2018, where an interp request lead to an edit that actually
loosened restrictions and makes the checking much more straightforward,
since expressions and function results are now allowed.

I've added references to the relevant text and interp in the commit message.

While updating the checking code shared between C_SIZEOF and C_F_POINTER,
I figured that the latter missed a check preventing an ICE-on-invalid
when a function returning a pointer was passed.

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

Thanks,
Harald

From 6f412a6399a7e125db835584d3d2489a52150c27 Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Mon, 8 Apr 2024 21:43:24 +0200
Subject: [PATCH] Fortran: fix argument checking of intrinsics C_SIZEOF,
 C_F_POINTER [PR106500]

The interpretation of the F2018 standard regarding valid arguments to the
intrinsic C_SIZEOF(X) was clarified in an edit to 18-007r1:

  https://j3-fortran.org/doc/year/22/22-101r1.txt

loosening restrictions and giving examples.  The F2023 text has:

! F2023:18.2.3.8  C_SIZEOF (X)
!
!   X shall be a data entity with interoperable type and type parameters,
!   and shall not be an assumed-size array, an assumed-rank array that
!   is associated with an assumed-size array, an unallocated allocatable
!   variable, or a pointer that is not associated.

where

! 3.41 data entity
!   data object, result of the evaluation of an expression, or the
!   result of the execution of a function reference

Update the checking code for interoperable arguments accordingly, and extend
to reject functions returning pointer as FPTR argument to C_F_POINTER.

gcc/fortran/ChangeLog:

	PR fortran/106500
	* check.cc (is_c_interoperable): Fix checks for C_SIZEOF.
	(gfc_check_c_f_pointer): Reject function returning a pointer as FPTR.

gcc/testsuite/ChangeLog:

	PR fortran/106500
	* gfortran.dg/c_sizeof_6.f90: Remove wrong dg-error.
	* gfortran.dg/c_f_pointer_tests_9.f90: New test.
	* gfortran.dg/c_sizeof_7.f90: New test.
---
 gcc/fortran/check.cc  | 21 ++
 .../gfortran.dg/c_f_pointer_tests_9.f90   | 21 ++
 gcc/testsuite/gfortran.dg/c_sizeof_6.f90  |  2 +-
 gcc/testsuite/gfortran.dg/c_sizeof_7.f90  | 42 +++
 4 files changed, 76 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/c_f_pointer_tests_9.f90
 create mode 100644 gcc/testsuite/gfortran.dg/c_sizeof_7.f90

diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc
index db74dcf3f40..b7f60575c67 100644
--- a/gcc/fortran/check.cc
+++ b/gcc/fortran/check.cc
@@ -5299,18 +5299,14 @@ is_c_interoperable (gfc_expr *expr, const char **msg, bool c_loc, bool c_f_ptr)
   return false;
 }

-  if (!c_loc && expr->rank > 0 && expr->expr_type != EXPR_ARRAY)
+  /* Checks for C_SIZEOF need to take into account edits to 18-007r1, see
+ https://j3-fortran.org/doc/year/22/22-101r1.txt .  */
+  if (!c_loc && !c_f_ptr && expr->rank > 0 && expr->expr_type == EXPR_VARIABLE)
 {
   gfc_array_ref *ar = gfc_find_array_ref (expr);
-  if (ar->type != AR_FULL)
+  if (ar->type == AR_FULL && ar->as->type == AS_ASSUMED_SIZE)
 	{
-	  *msg = "Only whole-arrays are interoperable";
-	  return false;
-	}
-  if (!c_f_ptr && ar->as->type != AS_EXPLICIT
-	  && ar->as->type != AS_ASSUMED_SIZE)
-	{
-	  *msg = "Only explicit-size and assumed-size arrays are interoperable";
+	  *msg = "Assumed-size arrays are not interoperable";
 	  return false;
 	}
 }
@@ -5475,6 +5471,13 @@ gfc_check_c_f_pointer (gfc_expr *cptr, gfc_expr *fptr, gfc_expr *shape)
   return false;
 }

+  if (attr.function)
+{
+  gfc_error ("FPTR at %L to C_F_POINTER is a function returning a pointer",
+		 >where);
+  return false;
+}
+
   if (fptr->rank > 0 && !is_c_interoperable (fptr, , false, true))
 return gfc_notify_std (GFC_STD_F2018, "Noninteroperable array FPTR "
 			   "at %L to C_F_POINTER: %s", >where, msg);
diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_tests_9.f90 b/gcc/testsuite/gfortran.dg/c_f_pointer_tests_9.f90
new file mode 100644
index 000..bb6d3281b02
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c_f_pointer_tests_9.f90
@@ -0,0 +1,21 @@
+! { dg-do compile }
+!
+! A function returning a pointer cannot be interoperable
+! and cannot be used as FPTR argument to C_F_POINTER.
+
+subroutine s ()
+  use, intrinsic :: iso_c_binding
+  implicit none
+  type(c_ptr) :: cPtr
+  call c_f_pointer (cPtr, p0)! { dg-error "function returning a pointer" }
+  call c_f_pointer (cPtr, p1, shape=[2]) ! { dg-error "functio

[gcc r11-11311] Fortran: fix DATA and derived types with pointer components [PR114474]

2024-04-07 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:619fc13043c86d616ef57cb31f8ac5d29b059ade

commit r11-11311-g619fc13043c86d616ef57cb31f8ac5d29b059ade
Author: Harald Anlauf 
Date:   Wed Mar 27 21:18:04 2024 +0100

Fortran: fix DATA and derived types with pointer components [PR114474]

When matching actual arguments in match_actual_arg, these are initially
treated as a possible dummy procedure, assuming that the correct type is
determined later.  This resolution could fail when the procedure is a
derived type constructor with a pointer component and appears in a DATA
statement, where the pointer shall be associated with an initial data
target.  Check for those cases where the type obviously has not been
resolved yet, and which were missed because there was no component
reference.

gcc/fortran/ChangeLog:

PR fortran/114474
* primary.c (gfc_variable_attr): Catch variables used in structure
constructors within DATA statements that are still tagged with a
temporary type BT_PROCEDURE from match_actual_arg and which have the
target attribute, and fix their typespec.

gcc/testsuite/ChangeLog:

PR fortran/114474
* gfortran.dg/data_pointer_3.f90: New test.

(cherry picked from commit bbb7c513dddc5c9b2d5e9b78bc1c2f85a0cfe07e)

Diff:
---
 gcc/fortran/primary.c| 12 +
 gcc/testsuite/gfortran.dg/data_pointer_3.f90 | 77 
 2 files changed, 89 insertions(+)

diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index 5cad2d2682b..79a2201c812 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -2663,6 +2663,18 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts)
   if (ts != NULL && expr->ts.type == BT_UNKNOWN)
 *ts = sym->ts;
 
+  /* Catch left-overs from match_actual_arg, where an actual argument of a
+ procedure is given a temporary ts.type == BT_PROCEDURE.  The fixup is
+ needed for structure constructors in DATA statements, where a pointer
+ is associated with a data target, and the argument has not been fully
+ resolved yet.  Components references are dealt with further below.  */
+  if (ts != NULL
+  && expr->ts.type == BT_PROCEDURE
+  && expr->ref == NULL
+  && attr.flavor != FL_PROCEDURE
+  && attr.target)
+*ts = sym->ts;
+
   has_inquiry_part = false;
   for (ref = expr->ref; ref; ref = ref->next)
 if (ref->type == REF_INQUIRY)
diff --git a/gcc/testsuite/gfortran.dg/data_pointer_3.f90 
b/gcc/testsuite/gfortran.dg/data_pointer_3.f90
new file mode 100644
index 000..49c288e93b9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/data_pointer_3.f90
@@ -0,0 +1,77 @@
+! { dg-do compile }
+! PR fortran/114474 - DATA and derived types with pointer components
+
+program pr114474
+  implicit none
+  integer, target :: ii = 42! initial data target
+
+  integer, target :: jj = 24
+  integer, pointer:: qq => jj
+  ! ii and jj resolve slightly differently when the data statement below
+  ! is reached, as jj is resolved outside the structure constructor first
+
+  type t
+ integer, pointer :: h
+  end type t
+
+  integer, target :: kk(7) =  23
+  integer, pointer:: ll(:) => kk
+
+  type t1
+ integer  :: m(7)
+  end type t1
+
+  type(t) :: x1, x2, x3, x4, x5
+  type(t), parameter  :: z1 = t(null())
+
+  type(t1), target:: tt = t1([1,2,3,4,5,6,7])
+  type(t1), parameter :: vv = t1(22)
+  type(t1):: w1, w2
+  integer,  pointer   :: p1(:) => tt% m
+
+  data x1 / t(null())  /
+  data x2 / t(ii)  / ! ii is initial data target
+  data x3 / t(jj)  / ! jj is resolved differently...
+  data x4 / t(tt%m(3)) / ! pointer association with 3rd element
+
+  data w1 / t1(12) /
+  data w2 / t1(vv%m)   /
+
+  if (  associated (x1% h)) stop 1
+  if (.not. associated (x2% h)) stop 2
+  if (.not. associated (x3% h)) stop 3
+  if (.not. associated (x4% h)) stop 4
+  if (x2% h /= 42) stop 5
+  if (x3% h /= 24) stop 6
+  if (x4% h /=  3) stop 7
+ 
+  if (any (w1%m /= 12  )) stop 8
+  if (any (w2%m /= vv%m)) stop 9
+end
+
+
+subroutine sub
+  implicit none
+
+  interface
+ real function myfun (x)
+   real, intent(in) :: x
+ end function myfun
+  end interface
+
+  type u
+ procedure(myfun), pointer, nopass :: p
+  end type u
+
+  type(u):: u3 = u(null())
+  type(u), parameter :: u4 = u(null())
+  type(u):: u1, u2
+
+  data u1 / u(null()) /
+  data u2 / u(myfun)  /
+end
+
+real function myfun (x)
+  real, intent(in) :: x
+  myfun = x
+end function myfun


[gcc r12-10314] Fortran: fix DATA and derived types with pointer components [PR114474]

2024-04-07 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:88abe04de2f16f773126f3908632a27568330cc9

commit r12-10314-g88abe04de2f16f773126f3908632a27568330cc9
Author: Harald Anlauf 
Date:   Wed Mar 27 21:18:04 2024 +0100

Fortran: fix DATA and derived types with pointer components [PR114474]

When matching actual arguments in match_actual_arg, these are initially
treated as a possible dummy procedure, assuming that the correct type is
determined later.  This resolution could fail when the procedure is a
derived type constructor with a pointer component and appears in a DATA
statement, where the pointer shall be associated with an initial data
target.  Check for those cases where the type obviously has not been
resolved yet, and which were missed because there was no component
reference.

gcc/fortran/ChangeLog:

PR fortran/114474
* primary.cc (gfc_variable_attr): Catch variables used in structure
constructors within DATA statements that are still tagged with a
temporary type BT_PROCEDURE from match_actual_arg and which have the
target attribute, and fix their typespec.

gcc/testsuite/ChangeLog:

PR fortran/114474
* gfortran.dg/data_pointer_3.f90: New test.

(cherry picked from commit bbb7c513dddc5c9b2d5e9b78bc1c2f85a0cfe07e)

Diff:
---
 gcc/fortran/primary.cc   | 12 +
 gcc/testsuite/gfortran.dg/data_pointer_3.f90 | 77 
 2 files changed, 89 insertions(+)

diff --git a/gcc/fortran/primary.cc b/gcc/fortran/primary.cc
index 1ae6a12e0b7..78295c54b6c 100644
--- a/gcc/fortran/primary.cc
+++ b/gcc/fortran/primary.cc
@@ -2664,6 +2664,18 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts)
   if (ts != NULL && expr->ts.type == BT_UNKNOWN)
 *ts = sym->ts;
 
+  /* Catch left-overs from match_actual_arg, where an actual argument of a
+ procedure is given a temporary ts.type == BT_PROCEDURE.  The fixup is
+ needed for structure constructors in DATA statements, where a pointer
+ is associated with a data target, and the argument has not been fully
+ resolved yet.  Components references are dealt with further below.  */
+  if (ts != NULL
+  && expr->ts.type == BT_PROCEDURE
+  && expr->ref == NULL
+  && attr.flavor != FL_PROCEDURE
+  && attr.target)
+*ts = sym->ts;
+
   has_inquiry_part = false;
   for (ref = expr->ref; ref; ref = ref->next)
 if (ref->type == REF_INQUIRY)
diff --git a/gcc/testsuite/gfortran.dg/data_pointer_3.f90 
b/gcc/testsuite/gfortran.dg/data_pointer_3.f90
new file mode 100644
index 000..49c288e93b9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/data_pointer_3.f90
@@ -0,0 +1,77 @@
+! { dg-do compile }
+! PR fortran/114474 - DATA and derived types with pointer components
+
+program pr114474
+  implicit none
+  integer, target :: ii = 42! initial data target
+
+  integer, target :: jj = 24
+  integer, pointer:: qq => jj
+  ! ii and jj resolve slightly differently when the data statement below
+  ! is reached, as jj is resolved outside the structure constructor first
+
+  type t
+ integer, pointer :: h
+  end type t
+
+  integer, target :: kk(7) =  23
+  integer, pointer:: ll(:) => kk
+
+  type t1
+ integer  :: m(7)
+  end type t1
+
+  type(t) :: x1, x2, x3, x4, x5
+  type(t), parameter  :: z1 = t(null())
+
+  type(t1), target:: tt = t1([1,2,3,4,5,6,7])
+  type(t1), parameter :: vv = t1(22)
+  type(t1):: w1, w2
+  integer,  pointer   :: p1(:) => tt% m
+
+  data x1 / t(null())  /
+  data x2 / t(ii)  / ! ii is initial data target
+  data x3 / t(jj)  / ! jj is resolved differently...
+  data x4 / t(tt%m(3)) / ! pointer association with 3rd element
+
+  data w1 / t1(12) /
+  data w2 / t1(vv%m)   /
+
+  if (  associated (x1% h)) stop 1
+  if (.not. associated (x2% h)) stop 2
+  if (.not. associated (x3% h)) stop 3
+  if (.not. associated (x4% h)) stop 4
+  if (x2% h /= 42) stop 5
+  if (x3% h /= 24) stop 6
+  if (x4% h /=  3) stop 7
+ 
+  if (any (w1%m /= 12  )) stop 8
+  if (any (w2%m /= vv%m)) stop 9
+end
+
+
+subroutine sub
+  implicit none
+
+  interface
+ real function myfun (x)
+   real, intent(in) :: x
+ end function myfun
+  end interface
+
+  type u
+ procedure(myfun), pointer, nopass :: p
+  end type u
+
+  type(u):: u3 = u(null())
+  type(u), parameter :: u4 = u(null())
+  type(u):: u1, u2
+
+  data u1 / u(null()) /
+  data u2 / u(myfun)  /
+end
+
+real function myfun (x)
+  real, intent(in) :: x
+  myfun = x
+end function myfun


[gcc r13-8592] Fortran: fix DATA and derived types with pointer components [PR114474]

2024-04-07 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:0d4862691d2b58f7bd2d58de0e78bc574c313d39

commit r13-8592-g0d4862691d2b58f7bd2d58de0e78bc574c313d39
Author: Harald Anlauf 
Date:   Wed Mar 27 21:18:04 2024 +0100

Fortran: fix DATA and derived types with pointer components [PR114474]

When matching actual arguments in match_actual_arg, these are initially
treated as a possible dummy procedure, assuming that the correct type is
determined later.  This resolution could fail when the procedure is a
derived type constructor with a pointer component and appears in a DATA
statement, where the pointer shall be associated with an initial data
target.  Check for those cases where the type obviously has not been
resolved yet, and which were missed because there was no component
reference.

gcc/fortran/ChangeLog:

PR fortran/114474
* primary.cc (gfc_variable_attr): Catch variables used in structure
constructors within DATA statements that are still tagged with a
temporary type BT_PROCEDURE from match_actual_arg and which have the
target attribute, and fix their typespec.

gcc/testsuite/ChangeLog:

PR fortran/114474
* gfortran.dg/data_pointer_3.f90: New test.

(cherry picked from commit bbb7c513dddc5c9b2d5e9b78bc1c2f85a0cfe07e)

Diff:
---
 gcc/fortran/primary.cc   | 12 +
 gcc/testsuite/gfortran.dg/data_pointer_3.f90 | 77 
 2 files changed, 89 insertions(+)

diff --git a/gcc/fortran/primary.cc b/gcc/fortran/primary.cc
index c6a119c73cb..edbd162ed13 100644
--- a/gcc/fortran/primary.cc
+++ b/gcc/fortran/primary.cc
@@ -2672,6 +2672,18 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts)
   if (ts != NULL && expr->ts.type == BT_UNKNOWN)
 *ts = sym->ts;
 
+  /* Catch left-overs from match_actual_arg, where an actual argument of a
+ procedure is given a temporary ts.type == BT_PROCEDURE.  The fixup is
+ needed for structure constructors in DATA statements, where a pointer
+ is associated with a data target, and the argument has not been fully
+ resolved yet.  Components references are dealt with further below.  */
+  if (ts != NULL
+  && expr->ts.type == BT_PROCEDURE
+  && expr->ref == NULL
+  && attr.flavor != FL_PROCEDURE
+  && attr.target)
+*ts = sym->ts;
+
   has_inquiry_part = false;
   for (ref = expr->ref; ref; ref = ref->next)
 if (ref->type == REF_INQUIRY)
diff --git a/gcc/testsuite/gfortran.dg/data_pointer_3.f90 
b/gcc/testsuite/gfortran.dg/data_pointer_3.f90
new file mode 100644
index 000..49c288e93b9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/data_pointer_3.f90
@@ -0,0 +1,77 @@
+! { dg-do compile }
+! PR fortran/114474 - DATA and derived types with pointer components
+
+program pr114474
+  implicit none
+  integer, target :: ii = 42! initial data target
+
+  integer, target :: jj = 24
+  integer, pointer:: qq => jj
+  ! ii and jj resolve slightly differently when the data statement below
+  ! is reached, as jj is resolved outside the structure constructor first
+
+  type t
+ integer, pointer :: h
+  end type t
+
+  integer, target :: kk(7) =  23
+  integer, pointer:: ll(:) => kk
+
+  type t1
+ integer  :: m(7)
+  end type t1
+
+  type(t) :: x1, x2, x3, x4, x5
+  type(t), parameter  :: z1 = t(null())
+
+  type(t1), target:: tt = t1([1,2,3,4,5,6,7])
+  type(t1), parameter :: vv = t1(22)
+  type(t1):: w1, w2
+  integer,  pointer   :: p1(:) => tt% m
+
+  data x1 / t(null())  /
+  data x2 / t(ii)  / ! ii is initial data target
+  data x3 / t(jj)  / ! jj is resolved differently...
+  data x4 / t(tt%m(3)) / ! pointer association with 3rd element
+
+  data w1 / t1(12) /
+  data w2 / t1(vv%m)   /
+
+  if (  associated (x1% h)) stop 1
+  if (.not. associated (x2% h)) stop 2
+  if (.not. associated (x3% h)) stop 3
+  if (.not. associated (x4% h)) stop 4
+  if (x2% h /= 42) stop 5
+  if (x3% h /= 24) stop 6
+  if (x4% h /=  3) stop 7
+ 
+  if (any (w1%m /= 12  )) stop 8
+  if (any (w2%m /= vv%m)) stop 9
+end
+
+
+subroutine sub
+  implicit none
+
+  interface
+ real function myfun (x)
+   real, intent(in) :: x
+ end function myfun
+  end interface
+
+  type u
+ procedure(myfun), pointer, nopass :: p
+  end type u
+
+  type(u):: u3 = u(null())
+  type(u), parameter :: u4 = u(null())
+  type(u):: u1, u2
+
+  data u1 / u(null()) /
+  data u2 / u(myfun)  /
+end
+
+real function myfun (x)
+  real, intent(in) :: x
+  myfun = x
+end function myfun


[gcc r11-11310] fortran: Fix setting of array lower bound for named arrays

2024-04-06 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:b755a7af1f2ef1f5348d04db20f751e898abcd9d

commit r11-11310-gb755a7af1f2ef1f5348d04db20f751e898abcd9d
Author: Chung-Lin Tang 
Date:   Fri Dec 3 17:27:17 2021 +0800

fortran: Fix setting of array lower bound for named arrays

This patch fixes a case of setting array low-bounds, found for particular 
uses
of SOURCE=/MOLD=. This adjusts the relevant part in gfc_trans_allocate() to
set e3_has_nodescriptor only for non-named arrays.

2021-12-03  Tobias Burnus  

gcc/fortran/ChangeLog:

* trans-stmt.c (gfc_trans_allocate): Set e3_has_nodescriptor to true
only for non-named arrays.

gcc/testsuite/ChangeLog:

* gfortran.dg/allocate_with_source_26.f90: Adjust testcase.
* gfortran.dg/allocate_with_mold_4.f90: New testcase.

(cherry picked from commit 6262e3a22b3d86afc116480bc59a7bb30b0cfd40)

Diff:
---
 gcc/fortran/trans-stmt.c   | 17 +++
 gcc/testsuite/gfortran.dg/allocate_with_mold_4.f90 | 24 ++
 .../gfortran.dg/allocate_with_source_26.f90|  8 
 3 files changed, 35 insertions(+), 14 deletions(-)

diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 0e387bbb4e6..0f920c496a0 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -6661,16 +6661,13 @@ gfc_trans_allocate (gfc_code * code)
   else
e3rhs = gfc_copy_expr (code->expr3);
 
-  // We need to propagate the bounds of the expr3 for source=/mold=;
-  // however, for nondescriptor arrays, we use internally a lower bound
-  // of zero instead of one, which needs to be corrected for the allocate 
obj
-  if (e3_is == E3_DESC)
-   {
- symbol_attribute attr = gfc_expr_attr (code->expr3);
- if (code->expr3->expr_type == EXPR_ARRAY ||
- (!attr.allocatable && !attr.pointer))
-   e3_has_nodescriptor = true;
-   }
+  // We need to propagate the bounds of the expr3 for source=/mold=.
+  // However, for non-named arrays, the lbound has to be 1 and neither the
+  // bound used inside the called function even when returning an
+  // allocatable/pointer nor the zero used internally.
+  if (e3_is == E3_DESC
+ && code->expr3->expr_type != EXPR_VARIABLE)
+   e3_has_nodescriptor = true;
 }
 
   /* Loop over all objects to allocate.  */
diff --git a/gcc/testsuite/gfortran.dg/allocate_with_mold_4.f90 
b/gcc/testsuite/gfortran.dg/allocate_with_mold_4.f90
new file mode 100644
index 000..d545fe1249f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/allocate_with_mold_4.f90
@@ -0,0 +1,24 @@
+program A_M
+  implicit none
+  real, parameter :: C(5:10) = 5.0
+  real, dimension (:), allocatable :: A, B
+  allocate (A(6))
+  call Init (A)
+contains
+  subroutine Init ( A )
+real, dimension ( -1 : ), intent ( in ) :: A
+integer, dimension ( 1 ) :: lb_B
+
+allocate (B, mold = A)
+if (any (lbound (B) /= lbound (A))) stop 1
+if (any (ubound (B) /= ubound (A))) stop 2
+if (any (shape (B) /= shape (A))) stop 3
+if (size (B) /= size (A)) stop 4
+deallocate (B)
+allocate (B, mold = C)
+if (any (lbound (B) /= lbound (C))) stop 5
+if (any (ubound (B) /= ubound (C))) stop 6
+if (any (shape (B) /= shape (C))) stop 7
+if (size (B) /= size (C)) stop 8
+end
+end 
diff --git a/gcc/testsuite/gfortran.dg/allocate_with_source_26.f90 
b/gcc/testsuite/gfortran.dg/allocate_with_source_26.f90
index 28f24fc1e10..323c8a30b9e 100644
--- a/gcc/testsuite/gfortran.dg/allocate_with_source_26.f90
+++ b/gcc/testsuite/gfortran.dg/allocate_with_source_26.f90
@@ -34,23 +34,23 @@ program p
  if (lbound(p1, 1) /= 3 .or. ubound(p1, 1) /= 4 &
  .or. lbound(p2, 1) /= 3 .or. ubound(p2, 1) /= 4 &
  .or. lbound(p3, 1) /= 1 .or. ubound(p3, 1) /= 2 &
- .or. lbound(p4, 1) /= 7 .or. ubound(p4, 1) /= 8 &
+ .or. lbound(p4, 1) /= 1 .or. ubound(p4, 1) /= 2 &
  .or. p1(3)%i /= 43 .or. p1(4)%i /= 56 &
  .or. p2(3)%i /= 43 .or. p2(4)%i /= 56 &
  .or. p3(1)%i /= 43 .or. p3(2)%i /= 56 &
- .or. p4(7)%i /= 11 .or. p4(8)%i /= 12) then
+ .or. p4(1)%i /= 11 .or. p4(2)%i /= 12) then
call abort()
  endif
 
  !write(*,*) lbound(a,1), ubound(a,1) ! prints 1 3
  !write(*,*) lbound(b,1), ubound(b,1) ! prints 1 3
- !write(*,*) lbound(c,1), ubound(c,1) ! prints 3 5
+ !write(*,*) lbound(c,1), ubound(c,1) ! prints 1 3
  !write(*,*) lbound(d,1), ubound(d,1) ! prints 1 5
  !write(*,*) lbound(e,1), ubound(e,1) ! prints 1 6
 
  if (lbound(a,1) /= 1 .or. ubound(a,1) /= 3 &
  .or. lbound(b,1) /= 1 .or. ubound(b,1) /= 3 &
- .or. lbound(c,1) /= 3 .or. ubound(c,1) /= 5 &
+ .or. lbound(c,1) /= 1 .or. ubound(c,1) /= 3 & 
  .or. lbound(d,1) /= 1 .or. ubound(d,1) /= 5 &
  .or. lbound(e,1) /= 1 .or. ubound(e,1) /= 6) then
call abort()


[gcc r13-8559] Fortran: error recovery while simplifying expressions [PR103707, PR106987]

2024-04-02 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:2808797fc4da7cc455803e2b69368b52db857b4c

commit r13-8559-g2808797fc4da7cc455803e2b69368b52db857b4c
Author: Harald Anlauf 
Date:   Tue Mar 5 21:54:26 2024 +0100

Fortran: error recovery while simplifying expressions [PR103707,PR106987]

When an exception is encountered during simplification of arithmetic
expressions, the result may depend on whether range-checking is active
(-frange-check) or not.  However, the code path in the front-end should
stay the same for "soft" errors for which the exception is triggered by the
check, while "hard" errors should always terminate the simplification, so
that error recovery is independent of the flag.  Separation of arithmetic
error codes into "hard" and "soft" errors shall be done consistently via
is_hard_arith_error().

PR fortran/103707
PR fortran/106987

gcc/fortran/ChangeLog:

* arith.cc (is_hard_arith_error): New helper function to determine
whether an arithmetic error is "hard" or not.
(check_result): Use it.
(gfc_arith_divide): Set "Division by zero" only for regular
numerators of real and complex divisions.
(reduce_unary): Use is_hard_arith_error to determine whether a hard
or (recoverable) soft error was encountered.  Terminate immediately
on hard error, otherwise remember code of first soft error.
(reduce_binary_ac): Likewise.
(reduce_binary_ca): Likewise.
(reduce_binary_aa): Likewise.

gcc/testsuite/ChangeLog:

* gfortran.dg/arithmetic_overflow_3.f90: New test.

(cherry picked from commit 93e1d4d24ed014387da97e2ce11556d68fe98e66)

Diff:
---
 gcc/fortran/arith.cc   | 134 +++--
 .../gfortran.dg/arithmetic_overflow_3.f90  |  48 
 2 files changed, 142 insertions(+), 40 deletions(-)

diff --git a/gcc/fortran/arith.cc b/gcc/fortran/arith.cc
index 5673c76823a..fade085450c 100644
--- a/gcc/fortran/arith.cc
+++ b/gcc/fortran/arith.cc
@@ -130,6 +130,30 @@ gfc_arith_error (arith code)
 }
 
 
+/* Check if a certain arithmetic error code is severe enough to prevent
+   further simplification, as opposed to errors thrown by the range check
+   (e.g. overflow) or arithmetic exceptions that are tolerated with
+   -fno-range-check.  */
+
+static bool
+is_hard_arith_error (arith code)
+{
+  switch (code)
+{
+case ARITH_OK:
+case ARITH_OVERFLOW:
+case ARITH_UNDERFLOW:
+case ARITH_NAN:
+case ARITH_DIV0:
+case ARITH_ASYMMETRIC:
+  return false;
+
+default:
+  return true;
+}
+}
+
+
 /* Get things ready to do math.  */
 
 void
@@ -579,10 +603,10 @@ check_result (arith rc, gfc_expr *x, gfc_expr *r, 
gfc_expr **rp)
   val = ARITH_OK;
 }
 
-  if (val == ARITH_OK || val == ARITH_OVERFLOW)
-*rp = r;
-  else
+  if (is_hard_arith_error (val))
 gfc_free_expr (r);
+  else
+*rp = r;
 
   return val;
 }
@@ -792,23 +816,26 @@ gfc_arith_divide (gfc_expr *op1, gfc_expr *op2, gfc_expr 
**resultp)
   break;
 
 case BT_REAL:
-  if (mpfr_sgn (op2->value.real) == 0 && flag_range_check == 1)
-   {
- rc = ARITH_DIV0;
- break;
-   }
+  /* Set "Division by zero" only for regular numerator.  */
+  if (flag_range_check == 1
+ && mpfr_zero_p (op2->value.real)
+ && mpfr_regular_p (op1->value.real))
+   rc = ARITH_DIV0;
 
   mpfr_div (result->value.real, op1->value.real, op2->value.real,
   GFC_RND_MODE);
   break;
 
 case BT_COMPLEX:
-  if (mpc_cmp_si_si (op2->value.complex, 0, 0) == 0
- && flag_range_check == 1)
-   {
- rc = ARITH_DIV0;
- break;
-   }
+  /* Set "Division by zero" only for regular numerator.  */
+  if (flag_range_check == 1
+ && mpfr_zero_p (mpc_realref (op2->value.complex))
+ && mpfr_zero_p (mpc_imagref (op2->value.complex))
+ && ((mpfr_regular_p (mpc_realref (op1->value.complex))
+  && mpfr_number_p (mpc_imagref (op1->value.complex)))
+ || (mpfr_regular_p (mpc_imagref (op1->value.complex))
+ && mpfr_number_p (mpc_realref (op1->value.complex)
+   rc = ARITH_DIV0;
 
   gfc_set_model (mpc_realref (op1->value.complex));
   if (mpc_cmp_si_si (op2->value.complex, 0, 0) == 0)
@@ -1323,7 +1350,6 @@ reduce_unary (arith (*eval) (gfc_expr *, gfc_expr **), 
gfc_expr *op,
   gfc_constructor *c;
   gfc_expr *r;
   arith rc;
-  bool ov = false;
 
   if (op->expr_type == EXPR_CONSTANT)
 return eval (op, result);
@@ -1335,19 +1361,22 @@ reduce_unary (arith (*eval) (gfc_expr *, gfc_expr **), 
gfc_expr *op,
 

[gcc r13-8558] Fortran: error recovery on arithmetic overflow on unary operations [PR113799]

2024-04-02 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:ec8303dea72ed4f9ae9fdf3c996a0deef6809351

commit r13-8558-gec8303dea72ed4f9ae9fdf3c996a0deef6809351
Author: Harald Anlauf 
Date:   Thu Feb 8 21:51:38 2024 +0100

Fortran: error recovery on arithmetic overflow on unary operations 
[PR113799]

PR fortran/113799

gcc/fortran/ChangeLog:

* arith.cc (reduce_unary): Remember any overflow encountered during
reduction of unary arithmetic operations on array constructors and
continue, and return error status, but terminate on serious errors.

gcc/testsuite/ChangeLog:

* gfortran.dg/arithmetic_overflow_2.f90: New test.

(cherry picked from commit b3d622d70ba209b63471fc1b0970870046e55745)

Diff:
---
 gcc/fortran/arith.cc| 11 ---
 gcc/testsuite/gfortran.dg/arithmetic_overflow_2.f90 | 12 
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/gcc/fortran/arith.cc b/gcc/fortran/arith.cc
index fcf37d48bfc..5673c76823a 100644
--- a/gcc/fortran/arith.cc
+++ b/gcc/fortran/arith.cc
@@ -1323,6 +1323,7 @@ reduce_unary (arith (*eval) (gfc_expr *, gfc_expr **), 
gfc_expr *op,
   gfc_constructor *c;
   gfc_expr *r;
   arith rc;
+  bool ov = false;
 
   if (op->expr_type == EXPR_CONSTANT)
 return eval (op, result);
@@ -1336,13 +1337,17 @@ reduce_unary (arith (*eval) (gfc_expr *, gfc_expr **), 
gfc_expr *op,
 {
   rc = reduce_unary (eval, c->expr, );
 
-  if (rc != ARITH_OK)
+  /* Remember any overflow encountered during reduction and continue,
+but terminate on serious errors.  */
+  if (rc == ARITH_OVERFLOW)
+   ov = true;
+  else if (rc != ARITH_OK)
break;
 
   gfc_replace_expr (c->expr, r);
 }
 
-  if (rc != ARITH_OK)
+  if (rc != ARITH_OK && rc != ARITH_OVERFLOW)
 gfc_constructor_free (head);
   else
 {
@@ -1363,7 +1368,7 @@ reduce_unary (arith (*eval) (gfc_expr *, gfc_expr **), 
gfc_expr *op,
   *result = r;
 }
 
-  return rc;
+  return ov ? ARITH_OVERFLOW : rc;
 }
 
 
diff --git a/gcc/testsuite/gfortran.dg/arithmetic_overflow_2.f90 
b/gcc/testsuite/gfortran.dg/arithmetic_overflow_2.f90
new file mode 100644
index 000..6ca27f74215
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/arithmetic_overflow_2.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! { dg-additional-options "-frange-check" }
+!
+! PR fortran/113799 - handle arithmetic overflow on unary minus
+
+program p
+  implicit none
+  real, parameter :: inf = real(z'7F80')
+  real, parameter :: someInf(*) = [inf, 0.]
+  print *, -someInf ! { dg-error "Arithmetic overflow" }
+  print *, minval(-someInf) ! { dg-error "Arithmetic overflow" }
+end


[gcc r13-8557] Fortran: set shape of initializers of zero-sized arrays [PR95374, PR104352]

2024-04-02 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:0dd82c0fba660775ff76ae27077a67f2f1358920

commit r13-8557-g0dd82c0fba660775ff76ae27077a67f2f1358920
Author: Harald Anlauf 
Date:   Wed May 17 20:39:18 2023 +0200

Fortran: set shape of initializers of zero-sized arrays [PR95374,PR104352]

gcc/fortran/ChangeLog:

PR fortran/95374
PR fortran/104352
* decl.cc (add_init_expr_to_sym): Set shape of initializer also for
zero-sized arrays, so that bounds violations can be detected later.

gcc/testsuite/ChangeLog:

PR fortran/95374
PR fortran/104352
* gfortran.dg/zero_sized_13.f90: New test.

(cherry picked from commit 7bafe652dba9167b65e7b5ef24e77eceb49709ba)

Diff:
---
 gcc/fortran/decl.cc |  3 +--
 gcc/testsuite/gfortran.dg/zero_sized_13.f90 | 28 
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc
index 03e993eb0ff..527e84ad763 100644
--- a/gcc/fortran/decl.cc
+++ b/gcc/fortran/decl.cc
@@ -2248,8 +2248,7 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, 
locus *var_locus)
  && gfc_is_constant_expr (init)
  && (init->expr_type == EXPR_CONSTANT
  || init->expr_type == EXPR_STRUCTURE)
- && spec_size (sym->as, )
- && mpz_cmp_si (size, 0) > 0)
+ && spec_size (sym->as, ))
{
  array = gfc_get_array_expr (init->ts.type, init->ts.kind,
  >where);
diff --git a/gcc/testsuite/gfortran.dg/zero_sized_13.f90 
b/gcc/testsuite/gfortran.dg/zero_sized_13.f90
new file mode 100644
index 000..4035d458b32
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/zero_sized_13.f90
@@ -0,0 +1,28 @@
+! { dg-do compile }
+! { dg-options "-w" }
+!
+! PR fortran/95374
+! PR fortran/104352 - Various ICEs for bounds violation with zero-sized arrays
+!
+! Contributed by G. Steinmetz
+
+program p
+  implicit none
+  integer :: i
+  integer, parameter :: a(0)= 0
+  integer, parameter :: b(0:-5) = 0
+  integer, parameter :: c(*) = [(a(i:i), i=0,0)] ! { dg-error "out of bounds" }
+  integer, parameter :: d(*) = [(b(i:i), i=1,1)] ! { dg-error "out of bounds" }
+  integer, parameter :: e(1) = [(a(i)  , i=1,1)] ! { dg-error "out of bounds" }
+  integer, parameter :: f(1) = [(a(i:i), i=1,1)] ! { dg-error "out of bounds" }
+  integer:: g(1) = [(a(i:i), i=0,0)] ! { dg-error "out of bounds" }
+  integer:: h(1) = [(a(i:i), i=1,1)] ! { dg-error "out of bounds" }
+  print *, [(a(i:i), i=0,0)] ! { dg-error "out of bounds" }
+  print *, [(a(i:i), i=1,1)] ! { dg-error "out of bounds" }
+  print *, any (a(1:1) == 1) ! { dg-error "out of bounds" }
+  print *, all (a(0:0) == 1) ! { dg-error "out of bounds" }
+  print *, sum (a(1:1))  ! { dg-error "out of bounds" }
+  print *, iall (a(0:0)) ! { dg-error "out of bounds" }
+  print *, minloc (a(0:0),1) ! { dg-error "out of bounds" }
+  print *, dot_product(a(1:1),a(1:1)) ! { dg-error "out of bounds" }
+end


Re: [Patch, fortran] PR106999 [11/12/13/14 Regression] ICE tree check: expected record_type or union_type or qual_union_type, have function_type in gfc_class_data_get, at fortran/trans-expr.cc:233

2024-04-01 Thread Harald Anlauf

Hi Paul,

On 3/31/24 15:01, Paul Richard Thomas wrote:

This regression has a relatively simple fix. The passing of a subroutine
procedure pointer component to a dummy variable was being missed
completely. The error has been added. Conversely, an error was generated
for a procedure pointer variable but no use was being made of the
interface, if one was available. This has been corrected.

OK for mainline and backporting in a couple of weeks?


this is all OK.

Thanks for the patch!

Harald


Paul

Fortran: Add error for subroutine passed to a variable dummy [PR106999]

2024-03-31  Paul Thomas  

gcc/fortran
PR fortran/106999
*interface.cc (gfc_compare_interfaces): Add error for a
subroutine proc pointer passed to a variable formal.
(compare_parameter): If a procedure pointer is being passed to
a non-procedure formal arg, and there is an an interface, use
gfc_compare_interfaces to check and provide a more useful error
message.

gcc/testsuite/
PR fortran/106999
* gfortran.dg/pr106999.f90: New test.





Re: [Patch, fortran] PR112407 - [13/14 Regression] Fix for PR37336 triggers an ICE in gfc_format_decoder while constructing a vtab

2024-04-01 Thread Harald Anlauf

Hi Paul!

Am 31.03.24 um 14:08 schrieb Paul Richard Thomas:

Hi Harald,



I had only a quick glance at your patch.  I guess you unintentionally
forgot to remove those parts that you already committed for PR110987,
along with the finalize-testcases.



Guilty as charged. I guess I got out of the wrong side of the bed :-)



I am still trying to find the precise paragraph in the standard
you refer to regarding INTENT(OUT) and default initialization.



Page 114 of the draft F2023 standard:
"The INTENT (OUT) attribute for a nonpointer dummy argument specifies that
the dummy argument becomes undefined on invocation of the procedure, except
for any subcomponents that are default-initialized (7.5.4.6)."
With the fix, gfortran behaves in the same way as ifort and nagfor.

On rereading the patch, I think that s/"and use the passed value"/"and
leave undefined"/ or some such is in order.


Yes, something along this line is better.

I also did test with NAG and Intel, and was surprised (confused?) at how
the count of finalizer calls changes if component "i" gets a default
value or not.  Something one wouldn't do right after getting out of bed!

So the patch looks good to me - except for one philosophical question:

Fortran 2018 makes procedures recursive by default, but this is not
yet implemented as such, and NON_RECURSIVE is not yet implemented.

The new testcase pr112407b.f90 compiles with nagfor -f2018 without
any warnings, and gives an error with nagfor -f2008.  It appears
that it works in the testsuite after the patch and when adding
"-std=f2008" instead of using the default "-std=gnu".

Would you mind adding "-std=f2008" as dg-option to that testcase?
This would avoid one bogus regression when gfortran moves forward.

Thanks for the patch!

Harald




While at it, I think I found a minor nit in testcase pr112407a.f90:
component x%i appears undefined the first time it is printed.



Fixed - thanks for pointing it out.

A correct patch is attached.

Thanks for looking at the previous, overloaded version.

Paul






2024-03-30  Paul Thomas  

gcc/fortran
PR fortran/112407
*resolve.cc (resolve_procedure_expression): Change the test for
for recursion in the case of hidden procedures from modules.
(resolve_typebound_static): Add warning for possible recursive
calls to typebound procedures.
* trans-expr.cc (gfc_trans_class_init_assign): Do not apply
default initializer to class dummy where component initializers
are all null.

gcc/testsuite/
PR fortran/112407
* gfortran.dg/pr112407a.f90: New test.
* gfortran.dg/pr112407b.f90: New test.











Re: [Patch, fortran] PR112407 - [13/14 Regression] Fix for PR37336 triggers an ICE in gfc_format_decoder while constructing a vtab

2024-03-30 Thread Harald Anlauf

Hi Paul,

I had only a quick glance at your patch.  I guess you unintentionally
forgot to remove those parts that you already committed for PR110987,
along with the finalize-testcases.

I am still trying to find the precise paragraph in the standard
you refer to regarding INTENT(OUT) and default initialization.

While at it, I think I found a minor nit in testcase pr112407a.f90:
component x%i appears undefined the first time it is printed.
This can be verified by either adding an explicit

  x% i = -42

in the main after the allocate(x).  Alternatively, running the
code with Intel and using MALLOC_PERTURB_ shows a random arg1%i,
but is otherwise fine.  However, if by chance (random memory)

  x% i = +42

then the test would likely fail everywhere.

Cheers,
Harald


Am 30.03.24 um 10:06 schrieb Paul Richard Thomas:

Hi All,

This bug emerged in a large code and involves possible recursion with a
"hidden" module procedure; ie. where the symtree name starts with '@'. This
throws the format decoder. As the last message in the PR shows, I have
vacillated between silently passing on the possible recursion or adding an
alternative warning message. In the end, as a conservative choice I went
for emitting the message.

In the course of trying to develop a compact test case, I found that type
bound procedures were not being tested for recursion and that class
dummies, with intent out, were being incorrectly initialized with an empty
default initializer. Both of these have been fixed.

Unfortunately, the most compact reproducer that Tomas was able to come up
with required more than 100kbytes of module files. I tried from the bottom
up but failed. Both the tests check the fixes for the other bugs.

Regtests on x86_64 - OK for mainline and, in a couple of weeks, 13-branch?

Paul

Fortran: Fix wrong recursive errors and class initialization [PR112407]

2024-03-30  Paul Thomas  

gcc/fortran
PR fortran/112407
*resolve.cc (resolve_procedure_expression): Change the test for
for recursion in the case of hidden procedures from modules.
(resolve_typebound_static): Add warning for possible recursive
calls to typebound procedures.
* trans-expr.cc (gfc_trans_class_init_assign): Do not apply
default initializer to class dummy where component initializers
are all null.

gcc/testsuite/
PR fortran/112407
* gfortran.dg/pr112407a.f90: New test.
* gfortran.dg/pr112407b.f90: New test.





[gcc r11-11299] Fortran: fix NULL pointer dereference on overlapping initialization [PR50410]

2024-03-29 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:1611acc1f72cad30c7ecccb5c85246836c1d0299

commit r11-11299-g1611acc1f72cad30c7ecccb5c85246836c1d0299
Author: Harald Anlauf 
Date:   Thu Mar 28 22:34:40 2024 +0100

Fortran: fix NULL pointer dereference on overlapping initialization 
[PR50410]

gcc/fortran/ChangeLog:

PR fortran/50410
* trans-expr.c (gfc_conv_structure): Check for NULL pointer.

gcc/testsuite/ChangeLog:

PR fortran/50410
* gfortran.dg/data_initialized_4.f90: New test.

(cherry picked from commit 6fb253a25dff13253d63553f02e0fe72c5e3ab4e)

Diff:
---
 gcc/fortran/trans-expr.c |  2 +-
 gcc/testsuite/gfortran.dg/data_initialized_4.f90 | 16 
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 5adee114157..37f16f37e12 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -8879,7 +8879,7 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int 
init)
   cm = expr->ts.u.derived->components;
 
   for (c = gfc_constructor_first (expr->value.constructor);
-   c; c = gfc_constructor_next (c), cm = cm->next)
+   c && cm; c = gfc_constructor_next (c), cm = cm->next)
 {
   /* Skip absent members in default initializers and allocatable
 components.  Although the latter have a default initializer
diff --git a/gcc/testsuite/gfortran.dg/data_initialized_4.f90 
b/gcc/testsuite/gfortran.dg/data_initialized_4.f90
new file mode 100644
index 000..156b6607edf
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/data_initialized_4.f90
@@ -0,0 +1,16 @@
+! { dg-do compile }
+! { dg-additional-options "-std=legacy" }
+!
+! PR fortran/50410
+!
+! Silently allow overlapping initialization in legacy mode (used to ICE)
+
+program p
+  implicit none
+  type t
+ integer :: g = 1
+  end type t
+  type(t) :: u = t(2)
+  data u%g /3/
+  print *, u! this might print "2"
+end


[gcc r12-10299] Fortran: fix NULL pointer dereference on overlapping initialization [PR50410]

2024-03-29 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:cb72fbd49e1f0c1cbdf8a9e97860063b19b1f95e

commit r12-10299-gcb72fbd49e1f0c1cbdf8a9e97860063b19b1f95e
Author: Harald Anlauf 
Date:   Thu Mar 28 22:34:40 2024 +0100

Fortran: fix NULL pointer dereference on overlapping initialization 
[PR50410]

gcc/fortran/ChangeLog:

PR fortran/50410
* trans-expr.cc (gfc_conv_structure): Check for NULL pointer.

gcc/testsuite/ChangeLog:

PR fortran/50410
* gfortran.dg/data_initialized_4.f90: New test.

(cherry picked from commit 6fb253a25dff13253d63553f02e0fe72c5e3ab4e)

Diff:
---
 gcc/fortran/trans-expr.cc|  2 +-
 gcc/testsuite/gfortran.dg/data_initialized_4.f90 | 16 
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 27b34984705..11ee1931b8e 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -9298,7 +9298,7 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int 
init)
   cm = expr->ts.u.derived->components;
 
   for (c = gfc_constructor_first (expr->value.constructor);
-   c; c = gfc_constructor_next (c), cm = cm->next)
+   c && cm; c = gfc_constructor_next (c), cm = cm->next)
 {
   /* Skip absent members in default initializers and allocatable
 components.  Although the latter have a default initializer
diff --git a/gcc/testsuite/gfortran.dg/data_initialized_4.f90 
b/gcc/testsuite/gfortran.dg/data_initialized_4.f90
new file mode 100644
index 000..156b6607edf
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/data_initialized_4.f90
@@ -0,0 +1,16 @@
+! { dg-do compile }
+! { dg-additional-options "-std=legacy" }
+!
+! PR fortran/50410
+!
+! Silently allow overlapping initialization in legacy mode (used to ICE)
+
+program p
+  implicit none
+  type t
+ integer :: g = 1
+  end type t
+  type(t) :: u = t(2)
+  data u%g /3/
+  print *, u! this might print "2"
+end


[gcc r13-8506] Fortran: fix passing of optional dummies to bind(c) procedures [PR113866]

2024-03-29 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:5f9144021615f24d038890dab7db2a0b9e84f6d3

commit r13-8506-g5f9144021615f24d038890dab7db2a0b9e84f6d3
Author: Harald Anlauf 
Date:   Tue Feb 13 20:19:10 2024 +0100

Fortran: fix passing of optional dummies to bind(c) procedures [PR113866]

PR fortran/113866

gcc/fortran/ChangeLog:

* trans-expr.cc (gfc_conv_procedure_call): When passing an optional
dummy argument to an optional dummy argument of a bind(c) procedure
and the dummy argument is passed via a CFI descriptor, no special
presence check and passing of a default NULL pointer is needed.

gcc/testsuite/ChangeLog:

* gfortran.dg/bind_c_optional-2.f90: New test.

(cherry picked from commit f4935df217ad89f884f908f39086b322e80123d0)

Diff:
---
 gcc/fortran/trans-expr.cc   |   6 +-
 gcc/testsuite/gfortran.dg/bind_c_optional-2.f90 | 105 
 2 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index d9de93260a6..c3f02c83b3f 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -7052,8 +7052,10 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
 with an interface indicating an optional argument.  When we call
 an intrinsic subroutine, however, fsym is NULL, but we might still
 have an optional argument, so we proceed to the substitution
-just in case.  */
-  if (e && (fsym == NULL || fsym->attr.optional))
+just in case.  Arguments passed to bind(c) procedures via CFI
+descriptors are handled elsewhere.  */
+  if (e && (fsym == NULL || fsym->attr.optional)
+ && !(sym->attr.is_bind_c && is_CFI_desc (fsym, NULL)))
{
  /* If an optional argument is itself an optional dummy argument,
 check its presence and substitute a null if absent.  This is
diff --git a/gcc/testsuite/gfortran.dg/bind_c_optional-2.f90 
b/gcc/testsuite/gfortran.dg/bind_c_optional-2.f90
new file mode 100644
index 000..ceedef7f006
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind_c_optional-2.f90
@@ -0,0 +1,105 @@
+! { dg-do run }
+! PR fortran/113866
+!
+! Check interoperability of assumed-length character (optional and
+! non-optional) dummies between bind(c) and non-bind(c) procedures
+
+module bindcchar
+  implicit none
+  integer, parameter :: n = 100, l = 10
+contains
+  subroutine bindc_optional (c2, c4) bind(c)
+character(*), optional :: c2, c4(n)
+!   print *, c2(1:3)
+!   print *, c4(5)(1:3) 
+if (.not. present (c2) .or. .not. present (c4)) stop 8
+if (len (c2) /= l .or. len (c4) /= l) stop 81
+if (c2(1:3)/= "a23") stop 1
+if (c4(5)(1:3) /= "bcd") stop 2
+  end
+
+  subroutine bindc (c2, c4) bind(c)
+character(*) :: c2, c4(n)
+if (len (c2) /= l .or. len (c4) /= l) stop 82
+if (c2(1:3)/= "a23") stop 3
+if (c4(5)(1:3) /= "bcd") stop 4
+call bindc_optional (c2, c4)
+  end
+
+  subroutine not_bindc_optional (c1, c3)
+character(*), optional :: c1, c3(n)
+if (.not. present (c1) .or. .not. present (c3)) stop 5
+if (len (c1) /= l .or. len (c3) /= l) stop 83
+call bindc_optional (c1, c3)
+call bindc  (c1, c3)
+  end
+
+  subroutine not_bindc_optional_deferred (c5, c6)
+character(:), allocatable, optional :: c5, c6(:)
+if (.not. present (c5) .or. .not. present (c6)) stop 6
+if (len (c5) /= l .or. len (c6) /= l) stop 84
+call not_bindc_optional (c5, c6)
+call bindc_optional (c5, c6)
+call bindc  (c5, c6)
+  end
+
+  subroutine not_bindc_optional2 (c7, c8)
+character(*), optional :: c7, c8(:)
+if (.not. present (c7) .or. .not. present (c8)) stop 7
+if (len (c7) /= l .or. len (c8) /= l) stop 85
+call bindc_optional (c7, c8)
+call bindc  (c7, c8)
+  end
+
+  subroutine bindc_optional2 (c2, c4) bind(c)
+character(*), optional :: c2, c4(n)
+if (.not. present (c2) .or. .not. present (c4)) stop 8
+if (len (c2) /= l .or. len (c4) /= l) stop 86
+if (c2(1:3)/= "a23") stop 9
+if (c4(5)(1:3) /= "bcd") stop 10
+call bindc_optional (c2, c4)
+call not_bindc_optional (c2, c4)
+  end
+
+  subroutine bindc_optional_missing (c1, c2, c3, c4, c5) bind(c)
+character(*), optional :: c1, c2(n), c3(:), c4(..), c5(*)
+if (present (c1)) stop 11
+if (present (c2)) stop 12
+if (present (c3)) stop 13
+if (present (c4)) stop 14
+if (present (c5)) stop 15
+  end
+
+  subroutine non_bindc_optional_missing (c1, c2, c3, c4, c5)
+character(*), optional :: c1, c2(n), c3(:), c4(..), c5(*)
+if (present (c1)) stop 21
+if (present (c2)) stop 22
+if (present (c3)) stop 23
+if (present (c4)) stop 24
+if (present (c5)) stop 25
+  end
+end module
+
+progra

[gcc r13-8505] Fortran: fix NULL pointer dereference on overlapping initialization [PR50410]

2024-03-29 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:250990298fb792635d9895e7642ccedbc2dd39d4

commit r13-8505-g250990298fb792635d9895e7642ccedbc2dd39d4
Author: Harald Anlauf 
Date:   Thu Mar 28 22:34:40 2024 +0100

Fortran: fix NULL pointer dereference on overlapping initialization 
[PR50410]

gcc/fortran/ChangeLog:

PR fortran/50410
* trans-expr.cc (gfc_conv_structure): Check for NULL pointer.

gcc/testsuite/ChangeLog:

PR fortran/50410
* gfortran.dg/data_initialized_4.f90: New test.

(cherry picked from commit 6fb253a25dff13253d63553f02e0fe72c5e3ab4e)

Diff:
---
 gcc/fortran/trans-expr.cc|  2 +-
 gcc/testsuite/gfortran.dg/data_initialized_4.f90 | 16 
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 3f3f0123dc3..d9de93260a6 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -9364,7 +9364,7 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int 
init)
   cm = expr->ts.u.derived->components;
 
   for (c = gfc_constructor_first (expr->value.constructor);
-   c; c = gfc_constructor_next (c), cm = cm->next)
+   c && cm; c = gfc_constructor_next (c), cm = cm->next)
 {
   /* Skip absent members in default initializers and allocatable
 components.  Although the latter have a default initializer
diff --git a/gcc/testsuite/gfortran.dg/data_initialized_4.f90 
b/gcc/testsuite/gfortran.dg/data_initialized_4.f90
new file mode 100644
index 000..156b6607edf
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/data_initialized_4.f90
@@ -0,0 +1,16 @@
+! { dg-do compile }
+! { dg-additional-options "-std=legacy" }
+!
+! PR fortran/50410
+!
+! Silently allow overlapping initialization in legacy mode (used to ICE)
+
+program p
+  implicit none
+  type t
+ integer :: g = 1
+  end type t
+  type(t) :: u = t(2)
+  data u%g /3/
+  print *, u! this might print "2"
+end


[gcc r14-9720] Fortran: fix NULL pointer dereference on overlapping initialization [PR50410]

2024-03-29 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:6fb253a25dff13253d63553f02e0fe72c5e3ab4e

commit r14-9720-g6fb253a25dff13253d63553f02e0fe72c5e3ab4e
Author: Harald Anlauf 
Date:   Thu Mar 28 22:34:40 2024 +0100

Fortran: fix NULL pointer dereference on overlapping initialization 
[PR50410]

gcc/fortran/ChangeLog:

PR fortran/50410
* trans-expr.cc (gfc_conv_structure): Check for NULL pointer.

gcc/testsuite/ChangeLog:

PR fortran/50410
* gfortran.dg/data_initialized_4.f90: New test.

Diff:
---
 gcc/fortran/trans-expr.cc|  2 +-
 gcc/testsuite/gfortran.dg/data_initialized_4.f90 | 16 
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 079ac93aa8a..d21e3956d6e 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -9650,7 +9650,7 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int 
init)
   cm = expr->ts.u.derived->components;
 
   for (c = gfc_constructor_first (expr->value.constructor);
-   c; c = gfc_constructor_next (c), cm = cm->next)
+   c && cm; c = gfc_constructor_next (c), cm = cm->next)
 {
   /* Skip absent members in default initializers and allocatable
 components.  Although the latter have a default initializer
diff --git a/gcc/testsuite/gfortran.dg/data_initialized_4.f90 
b/gcc/testsuite/gfortran.dg/data_initialized_4.f90
new file mode 100644
index 000..156b6607edf
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/data_initialized_4.f90
@@ -0,0 +1,16 @@
+! { dg-do compile }
+! { dg-additional-options "-std=legacy" }
+!
+! PR fortran/50410
+!
+! Silently allow overlapping initialization in legacy mode (used to ICE)
+
+program p
+  implicit none
+  type t
+ integer :: g = 1
+  end type t
+  type(t) :: u = t(2)
+  data u%g /3/
+  print *, u! this might print "2"
+end


  1   2   3   4   5   6   7   8   9   10   >