[patch, fortran] Implement IANY, IALL and IPARITY for unsigned

2024-09-18 Thread Thomas Koenig

OK for trunk?

This is based on the previous submissions. Again, this does not
generate a new library version; rather it re-uses the signed
integer version already present in the library.

OK for trunk?

Previous submissions (without which this will not work):

https://gcc.gnu.org/pipermail/fortran/2024-September/060975.html
https://gcc.gnu.org/pipermail/fortran/2024-September/060987.html

gcc/fortran/ChangeLog:

* check.cc (gfc_check_transf_bit_intrins): Handle unsigned.
* gfortran.texi: Docment IANY, IALL and IPARITY for unsigned.
* iresolve.cc (gfc_resolve_iall): Set flag to use integer
if type is BT_UNSIGNED.
(gfc_resolve_iany): Likewise.
(gfc_resolve_iparity): Likewise.
* simplify.cc (do_bit_and): Adjust asserts for BT_UNSIGNED.
(do_bit_ior): Likewise.
(do_bit_xor): Likewise

gcc/testsuite/ChangeLog:

* gfortran.dg/unsigned_29.f90: New test.

 gcc/fortran/check.cc  | 14 ++-
 gcc/fortran/gfortran.texi |  1 +
 gcc/fortran/iresolve.cc   |  6 +--
 gcc/fortran/simplify.cc   | 51 +++
 gcc/testsuite/gfortran.dg/unsigned_29.f90 | 40 ++
 5 files changed, 99 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/unsigned_29.f90

diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc
index 7c630dd73f4..533c9d7d343 100644
--- a/gcc/fortran/check.cc
+++ b/gcc/fortran/check.cc
@@ -4430,7 +4430,19 @@ gfc_check_mask (gfc_expr *i, gfc_expr *kind)
 bool
 gfc_check_transf_bit_intrins (gfc_actual_arglist *ap)
 {
-  if (ap->expr->ts.type != BT_INTEGER)
+  bt type = ap->expr->ts.type;
+
+  if (flag_unsigned)
+{
+  if (type != BT_INTEGER && type != BT_UNSIGNED)
+   {
+ gfc_error ("%qs argument of %qs intrinsic at %L must be INTEGER "
+"or UNSIGNED", gfc_current_intrinsic_arg[0]->name,
+gfc_current_intrinsic, &ap->expr->where);
+ return false;
+   }
+}
+  else if (ap->expr->ts.type != BT_INTEGER)
 {
   gfc_error ("%qs argument of %qs intrinsic at %L must be INTEGER",
  gfc_current_intrinsic_arg[0]->name,
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index e5ffe67..3eb8039c09f 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -2789,6 +2789,7 @@ As of now, the following intrinsics take unsigned 
arguments:

 @item @code{RANGE}
 @item @code{TRANSFER}
 @item @code{SUM}, @code{PRODUCT}, @code{MATMUL} and @code{DOT_PRODUCT}
+@item @code{IANY}, @code{IALL} and @code{IPARITY}
 @end itemize
 This list will grow in the near future.
 @c -
diff --git a/gcc/fortran/iresolve.cc b/gcc/fortran/iresolve.cc
index 92a591cf6d7..58a1821ef10 100644
--- a/gcc/fortran/iresolve.cc
+++ b/gcc/fortran/iresolve.cc
@@ -1195,7 +1195,7 @@ gfc_resolve_hypot (gfc_expr *f, gfc_expr *x, 
gfc_expr *y ATTRIBUTE_UNUSED)

 void
 gfc_resolve_iall (gfc_expr *f, gfc_expr *array, gfc_expr *dim, 
gfc_expr *mask)

 {
-  resolve_transformational ("iall", f, array, dim, mask);
+  resolve_transformational ("iall", f, array, dim, mask, true);
 }


@@ -1223,7 +1223,7 @@ gfc_resolve_iand (gfc_expr *f, gfc_expr *i, 
gfc_expr *j)

 void
 gfc_resolve_iany (gfc_expr *f, gfc_expr *array, gfc_expr *dim, 
gfc_expr *mask)

 {
-  resolve_transformational ("iany", f, array, dim, mask);
+  resolve_transformational ("iany", f, array, dim, mask, true);
 }


@@ -1429,7 +1429,7 @@ gfc_resolve_long (gfc_expr *f, gfc_expr *a)
 void
 gfc_resolve_iparity (gfc_expr *f, gfc_expr *array, gfc_expr *dim, 
gfc_expr *mask)

 {
-  resolve_transformational ("iparity", f, array, dim, mask);
+  resolve_transformational ("iparity", f, array, dim, mask, true);
 }


diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc
index e5681c42a48..bd2f6485c95 100644
--- a/gcc/fortran/simplify.cc
+++ b/gcc/fortran/simplify.cc
@@ -3401,9 +3401,20 @@ gfc_simplify_iachar (gfc_expr *e, gfc_expr *kind)
 static gfc_expr *
 do_bit_and (gfc_expr *result, gfc_expr *e)
 {
-  gcc_assert (e->ts.type == BT_INTEGER && e->expr_type == EXPR_CONSTANT);
-  gcc_assert (result->ts.type == BT_INTEGER
- && result->expr_type == EXPR_CONSTANT);
+  if (flag_unsigned)
+{
+  gcc_assert ((e->ts.type == BT_INTEGER || e->ts.type == BT_UNSIGNED)
+ && e->expr_type == EXPR_CONSTANT);
+  gcc_assert ((result->ts.type == BT_INTEGER
+  || result->ts.type == BT_UNSIGNED)
+ && result->expr_type == EXPR_CONSTANT);
+}
+  else
+{
+  gcc_assert (e->ts.type == BT_INTEGER && e->expr_type == 
EXPR_CONSTANT);

+  gcc_assert (result->ts.type == BT_INTEGER
+ && result->expr_type == EXPR_CONSTANT);
+}

   mpz_and (result->value.integer, result->value.integer, 
e->value.integer);

   return result;
@@ -3420,9 +3431,20 @@ gfc_simplif

[patch, fortran] Add random numbers and fix some bugs.

2024-09-18 Thread Thomas Koenig

This patch adds random number support for UNSIGNED, plus fixes
two bugs, with array I/O where the type used to be set to BT_INTEGER,
and for division with the divisor being a constant.

Again, depends on prevous submissions.

OK for trunk?

gcc/fortran/ChangeLog:

* check.cc (gfc_check_random_number): Adjust for unsigned.
* iresolve.cc (gfc_resolve_random_number): Handle unsinged.
* trans-expr.cc (gfc_conv_expr_op): Handle BT_UNSIGNED for divide.
* trans-types.cc (gfc_get_dtype_rank_type): Handle BT_UNSIGNED.
* gfortran.texi: Add RANDOM_NUMBER for UNSIGNED.

libgfortran/ChangeLog:

* gfortran.map: Add _gfortran_random_m1, _gfortran_random_m2,
_gfortran_random_m4, _gfortran_random_m8 and _gfortran_random_m16.
* intrinsics/random.c (random_m1): New function.
(random_m2): New function.
(random_m4): New function.
(random_m8): New function.
(random_m16): New function.
(arandom_m1): New function.
(arandom_m2): New function.
(arandom_m4): New function.
(arandom_m8): New funciton.
(arandom_m16): New function.

gcc/testsuite/ChangeLog:

* gfortran.dg/unsigned_30.f90: New test.
---
 gcc/fortran/check.cc  |  10 +-
 gcc/fortran/gfortran.texi |   1 +
 gcc/fortran/iresolve.cc   |   6 +-
 gcc/fortran/trans-expr.cc |   4 +-
 gcc/fortran/trans-types.cc|   7 +-
 gcc/testsuite/gfortran.dg/unsigned_30.f90 |  63 
 libgfortran/gfortran.map  |  10 +
 libgfortran/intrinsics/random.c   | 440 ++
 8 files changed, 534 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/unsigned_30.f90

diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc
index 533c9d7d343..1851cfb8d4a 100644
--- a/gcc/fortran/check.cc
+++ b/gcc/fortran/check.cc
@@ -7007,8 +7007,14 @@ gfc_check_random_init (gfc_expr *repeatable, 
gfc_expr *image_distinct)

 bool
 gfc_check_random_number (gfc_expr *harvest)
 {
-  if (!type_check (harvest, 0, BT_REAL))
-return false;
+  if (flag_unsigned)
+{
+  if (!type_check2 (harvest, 0, BT_REAL, BT_UNSIGNED))
+   return false;
+}
+  else
+if (!type_check (harvest, 0, BT_REAL))
+  return false;

   if (!variable_check (harvest, 0, false))
 return false;
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 3eb8039c09f..a5ebadff3bb 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -2790,6 +2790,7 @@ As of now, the following intrinsics take unsigned 
arguments:

 @item @code{TRANSFER}
 @item @code{SUM}, @code{PRODUCT}, @code{MATMUL} and @code{DOT_PRODUCT}
 @item @code{IANY}, @code{IALL} and @code{IPARITY}
+@item @code{RANDOM_NUMBER}.
 @end itemize
 This list will grow in the near future.
 @c -
diff --git a/gcc/fortran/iresolve.cc b/gcc/fortran/iresolve.cc
index 58a1821ef10..a814c9279cf 100644
--- a/gcc/fortran/iresolve.cc
+++ b/gcc/fortran/iresolve.cc
@@ -3452,12 +3452,14 @@ gfc_resolve_random_number (gfc_code *c)
 {
   const char *name;
   int kind;
+  char type;

   kind = gfc_type_abi_kind (&c->ext.actual->expr->ts);
+  type = gfc_type_letter (c->ext.actual->expr->ts.type);
   if (c->ext.actual->expr->rank == 0)
-name = gfc_get_string (PREFIX ("random_r%d"), kind);
+name = gfc_get_string (PREFIX ("random_%c%d"), type, kind);
   else
-name = gfc_get_string (PREFIX ("arandom_r%d"), kind);
+name = gfc_get_string (PREFIX ("arandom_%c%d"), type, kind);

   c->resolved_sym = gfc_get_intrinsic_sub_symbol (name);
 }
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index f1dfac4a2be..b39b4450997 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -3982,9 +3982,9 @@ gfc_conv_expr_op (gfc_se * se, gfc_expr * expr)

 case INTRINSIC_DIVIDE:
   /* If expr is a real or complex expr, use an RDIV_EXPR. If op1 is
- an integer, we must round towards zero, so we use a
+an integer or unsigned, we must round towards zero, so we use a
  TRUNC_DIV_EXPR.  */
-  if (expr->ts.type == BT_INTEGER)
+  if (expr->ts.type == BT_INTEGER || expr->ts.type == BT_UNSIGNED)
code = TRUNC_DIV_EXPR;
   else
code = RDIV_EXPR;
diff --git a/gcc/fortran/trans-types.cc b/gcc/fortran/trans-types.cc
index 3a1ff98b33c..ce7d3027f1b 100644
--- a/gcc/fortran/trans-types.cc
+++ b/gcc/fortran/trans-types.cc
@@ -1651,7 +1651,12 @@ gfc_get_dtype_rank_type (int rank, tree etype)
  && TYPE_STRING_FLAG (ptype))
n = BT_CHARACTER;
   else
-   n = BT_INTEGER;
+   {
+ if (TYPE_UNSIGNED (etype))
+   n = BT_UNSIGNED;
+ else
+   n = BT_INTEGER;
+   }
   break;

 case BOOLEAN_TYPE:
diff --git a/gcc/testsuite/gfortran.dg/unsigned_30.f90 
b/gcc/testsuite/gfortran.dg/unsigned_3

Re: [Ping, Fortran, Patch, PR85002, v1] Fix deep-copy of alloc. comps. in coarrays ICEing and crashing w/ lib.

2024-09-18 Thread Thomas Koenig

Am 18.09.24 um 12:31 schrieb Andre Vehreschild:

Regtested ok on x86_64-pc-linux-gnu / F39. Ok for mainline?


OK.

Thanks for the patch!

Best regards

Thomas


Re: [Fortran, Patch, PR106606, v1] Fortran: Break recursion building recursive types. [PR106606]

2024-09-18 Thread Thomas Koenig

Hi Andre,


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


Extremely minor nit: In the commit message and ChangeLog entry,

Build a derived type component's type only, when it is not already being
build and the component uses pointer semantics.

I believe that should be "being built".

In the ChangeLog entry

derived types as component's types when they are not yet build.

s/build/built/

OK for trunk.

Thanks for the patch!

Best regards

Thomas




Re: [Ping*2, Patch, Fortran, 77871, v1] Allow for class typed coarray parameter as dummy [PR77871]

2024-09-18 Thread Andre Vehreschild
Hi all,

back from my holidays and still no review.  PING PING!

Rebased to current mainline.

Regtested ok on x86_64-pc-linux-gnu / F39. Ok for mainline?

Regards,
Andre

On Wed, 21 Aug 2024 13:43:52 +0200
Andre Vehreschild  wrote:

> Hi all,
>
> pinging this patch for the first time.
>
> Rebased and regtested ok on x86_64-pc-linux-gnu / Fedora 39. Ok for mainline?
>
> - Andre
>
> On Thu, 15 Aug 2024 14:39:25 +0200
> Andre Vehreschild  wrote:
>
> > Hi all,
> >
> > attached patch fixes another regression on coarrays. This time for class
> > typed coarrays as dummys.
> >
> > Regtested ok on x86_64-pc-linux-gnu / Fedora 39. Ok for mainline?
> >
> > Regards,
> > Andre
> > --
> > Andre Vehreschild * Email: vehre ad gmx dot de
>
>
> --
> Andre Vehreschild * Email: vehre ad gmx dot de


--
Andre Vehreschild * Email: vehre ad gmx dot de
From 0e5b1a132c250fd7d823aa8a16da80e850ae4350 Mon Sep 17 00:00:00 2001
From: Andre Vehreschild 
Date: Thu, 15 Aug 2024 13:49:49 +0200
Subject: [PATCH] [Fortran] Allow for class type coarray parameters. [PR77871]

gcc/fortran/ChangeLog:

	PR fortran/77871

	* trans-expr.cc (gfc_conv_derived_to_class): Assign token when
	converting a coarray to class.
	(gfc_get_tree_for_caf_expr): For classes get the caf decl from
	the saved descriptor.
	(gfc_get_caf_token_offset):Assert that coarray=lib is set and
	cover more cases where the tree having the coarray token can be.
	* trans-intrinsic.cc (gfc_conv_intrinsic_caf_get): Use unified
	test for pointers.

gcc/testsuite/ChangeLog:

	* gfortran.dg/coarray/dummy_3.f90: New test.
---
 gcc/fortran/trans-expr.cc | 36 ---
 gcc/fortran/trans-intrinsic.cc|  2 +-
 gcc/testsuite/gfortran.dg/coarray/dummy_3.f90 | 33 +
 3 files changed, 58 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/coarray/dummy_3.f90

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 07e28a9f7a8..d626d80ba51 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -810,6 +810,16 @@ gfc_conv_derived_to_class (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym,
   /* Now set the data field.  */
   ctree = gfc_class_data_get (var);

+  if (flag_coarray == GFC_FCOARRAY_LIB && CLASS_DATA (fsym)->attr.codimension)
+{
+  tree token;
+  tmp = gfc_get_tree_for_caf_expr (e);
+  if (POINTER_TYPE_P (TREE_TYPE (tmp)))
+	tmp = build_fold_indirect_ref (tmp);
+  gfc_get_caf_token_offset (parmse, &token, nullptr, tmp, NULL_TREE, e);
+  gfc_add_modify (&parmse->pre, gfc_conv_descriptor_token (ctree), token);
+}
+
   if (optional)
 cond_optional = gfc_conv_expr_present (e->symtree->n.sym);

@@ -2344,6 +2354,10 @@ gfc_get_tree_for_caf_expr (gfc_expr *expr)

   if (expr->symtree->n.sym->ts.type == BT_CLASS)
 {
+  if (DECL_P (caf_decl) && DECL_LANG_SPECIFIC (caf_decl)
+	  && GFC_DECL_SAVED_DESCRIPTOR (caf_decl))
+	caf_decl = GFC_DECL_SAVED_DESCRIPTOR (caf_decl);
+
   if (expr->ref && expr->ref->type == REF_ARRAY)
 	{
 	  caf_decl = gfc_class_data_get (caf_decl);
@@ -2408,16 +2422,12 @@ gfc_get_caf_token_offset (gfc_se *se, tree *token, tree *offset, tree caf_decl,
 {
   tree tmp;

+  gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
+
   /* Coarray token.  */
   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (caf_decl)))
-{
-  gcc_assert (GFC_TYPE_ARRAY_AKIND (TREE_TYPE (caf_decl))
-		== GFC_ARRAY_ALLOCATABLE
-		  || expr->symtree->n.sym->attr.select_type_temporary
-		  || expr->symtree->n.sym->assoc);
   *token = gfc_conv_descriptor_token (caf_decl);
-}
-  else if (DECL_LANG_SPECIFIC (caf_decl)
+  else if (DECL_P (caf_decl) && DECL_LANG_SPECIFIC (caf_decl)
 	   && GFC_DECL_TOKEN (caf_decl) != NULL_TREE)
 *token = GFC_DECL_TOKEN (caf_decl);
   else
@@ -2435,7 +2445,7 @@ gfc_get_caf_token_offset (gfc_se *se, tree *token, tree *offset, tree caf_decl,
   && (GFC_TYPE_ARRAY_AKIND (TREE_TYPE (caf_decl)) == GFC_ARRAY_ALLOCATABLE
 	  || GFC_TYPE_ARRAY_AKIND (TREE_TYPE (caf_decl)) == GFC_ARRAY_POINTER))
 *offset = build_int_cst (gfc_array_index_type, 0);
-  else if (DECL_LANG_SPECIFIC (caf_decl)
+  else if (DECL_P (caf_decl) && DECL_LANG_SPECIFIC (caf_decl)
 	   && GFC_DECL_CAF_OFFSET (caf_decl) != NULL_TREE)
 *offset = GFC_DECL_CAF_OFFSET (caf_decl);
   else if (GFC_TYPE_ARRAY_CAF_OFFSET (TREE_TYPE (caf_decl)) != NULL_TREE)
@@ -2502,11 +2512,13 @@ gfc_get_caf_token_offset (gfc_se *se, tree *token, tree *offset, tree caf_decl,
 }
   else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (caf_decl)))
 tmp = gfc_conv_descriptor_data_get (caf_decl);
+  else if (INDIRECT_REF_P (caf_decl))
+tmp = TREE_OPERAND (caf_decl, 0);
   else
-   {
- gcc_assert (POINTER_TYPE_P (TREE_TYPE (caf_decl)));
- tmp = caf_decl;
-   }
+{
+  gcc_assert (POINTER_TYPE_P (TREE_TYPE (caf_decl)));
+  tmp = caf_decl;
+}

   *offset = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
 			fold_c

Re: [Ping, Fortran, Patch, PR85002, v1] Fix deep-copy of alloc. comps. in coarrays ICEing and crashing w/ lib.

2024-09-18 Thread Andre Vehreschild
Hi all,

pinging this patch.

Regtested ok on x86_64-pc-linux-gnu / F39. Ok for mainline?

Regards,
Andre

On Fri, 23 Aug 2024 11:19:59 +0200
Andre Vehreschild  wrote:

> Hi all,
>
> attached patch fixes an ICE during trans-phase when allocatable components in
> derived typed coarrays were nested. I am nearly convinced, that the ICE is
> mostly fixed by pr86468, because I get a slightly different ICE. Nevertheless
> was the executable crashing with -fcoarray=lib because the deep copy was not
> inserted in the coarray case, which is fixed by this patch now. Furthermore
> did I correct a comment, that was describing the inverse of the code
> following.
>
> Regtests ok on x86_64-pc-linux-gnu / Fedora 39. Ok for mainline?
>
> Regards,
>   Andre
> --
> Andre Vehreschild * Email: vehre ad gmx dot de


--
Andre Vehreschild * Email: vehre ad gmx dot de
From eb81bce1c905f52643454e3b663e458a94a1bb75 Mon Sep 17 00:00:00 2001
From: Andre Vehreschild 
Date: Fri, 23 Aug 2024 09:07:09 +0200
Subject: [PATCH] [Fortran] Fix deep copy allocatable components in coarrays.
 [PR85002]

Fix code for deep copy of allocatable components in derived type nested
structures generated, but not inserted when the copy had to be done in
a coarray.  Additionally fix a comment.

gcc/fortran/ChangeLog:

	PR fortran/85002
	* trans-array.cc (duplicate_allocatable_coarray): Allow adding
	of deep copy code in the when-allocated case.  Add bounds
	computation before condition, because coarrays need the bounds
	also when not allocated.
	(structure_alloc_comps): Duplication in the coarray case is done
	already, omit it.  Add the deep-code when duplication a coarray.
	* trans-expr.cc (gfc_trans_structure_assign): Fix comment.

gcc/testsuite/ChangeLog:

	* gfortran.dg/coarray/alloc_comp_9.f90: New test.
---
 gcc/fortran/trans-array.cc| 16 ++---
 gcc/fortran/trans-expr.cc |  2 +-
 .../gfortran.dg/coarray/alloc_comp_9.f90  | 23 +++
 3 files changed, 32 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/coarray/alloc_comp_9.f90

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 8c35926436d..838b6d3da80 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -9417,10 +9417,9 @@ gfc_duplicate_allocatable_nocopy (tree dest, tree src, tree type, int rank)
 NULL_TREE, NULL_TREE);
 }

-
 static tree
-duplicate_allocatable_coarray (tree dest, tree dest_tok, tree src,
-			   tree type, int rank)
+duplicate_allocatable_coarray (tree dest, tree dest_tok, tree src, tree type,
+			   int rank, tree add_when_allocated)
 {
   tree tmp;
   tree size;
@@ -9474,7 +9473,7 @@ duplicate_allocatable_coarray (tree dest, tree dest_tok, tree src,
   gfc_add_modify (&globalblock, tmp, build_int_cst (TREE_TYPE (tmp), rank));

   if (rank)
-	nelems = gfc_full_array_size (&block, src, rank);
+	nelems = gfc_full_array_size (&globalblock, src, rank);
   else
 	nelems = integer_one_node;

@@ -9505,7 +9504,7 @@ duplicate_allocatable_coarray (tree dest, tree dest_tok, tree src,
  fold_convert (size_type_node, size));
   gfc_add_expr_to_block (&block, tmp);
 }
-
+  gfc_add_expr_to_block (&block, add_when_allocated);
   tmp = gfc_finish_block (&block);

   /* Null the destination if the source is null; otherwise do
@@ -9684,7 +9683,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, tree dest,
 	 gfc_duplicate_allocatable (), where the deep copy code is just added
 	 into the if's body, by adding tmp (the deep copy code) as last
 	 argument to gfc_duplicate_allocatable ().  */
-  if (purpose == COPY_ALLOC_COMP
+  if (purpose == COPY_ALLOC_COMP && caf_mode == 0
 	  && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
 	tmp = gfc_duplicate_allocatable (dest, decl, decl_type, rank,
 	 tmp);
@@ -10414,8 +10413,9 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, tree dest,
 		 c->caf_token,
 		 NULL_TREE);
 		}
-		  tmp = duplicate_allocatable_coarray (dcmp, dst_tok, comp,
-		   ctype, rank);
+		  tmp
+		= duplicate_allocatable_coarray (dcmp, dst_tok, comp, ctype,
+		 rank, add_when_allocated);
 		}
 	  else
 		tmp = gfc_duplicate_allocatable (dcmp, comp, ctype, rank,
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index d626d80ba51..54901c33139 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -9657,7 +9657,7 @@ gfc_trans_structure_assign (tree dest, gfc_expr * expr, bool init, bool coarray)

   /* Register the component with the caf-lib before it is initialized.
 	 Register only allocatable components, that are not coarray'ed
-	 components (%comp[*]).  Only register when the constructor is not the
+	 components (%comp[*]).  Only register when the constructor is the
 	 null-expression.  */
   if (coarray && !cm->attr.codimension
 	  && (cm->attr.allocatable || cm->attr.pointer)
diff --git a/gcc/testsu

[Fortran, Patch, PR106606, v1] Fortran: Break recursion building recursive types. [PR106606]

2024-09-18 Thread Andre Vehreschild
Hi all,

Paul asked me to have a look at his approach for pr106606. Now here is my
solution. I needed to break the endless recursion of a derived type referencing
itself in a component (like in a linked list). I accomplished this by checking,
if a type is in the build (i.e. if its size has not been computed; checking if
no FIELD_DECLs are present, lead to errors when in the middle of constructing a
type). So, when now a derived type uses itself (directly or implicitly) using
a pointer style component (pointer, allocatable...) then it is not build again,
but only the address to the incomplete type is used (a POINTER_TYPE tree is
created). This is sufficient to layout the type and later on the RECORD_TYPE
will be completed and everything is fine.

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

Regards,
Andre
--
Andre Vehreschild * Email: vehre ad gmx dot de
From 3ed3a61ea37d5e6d3a5aba64d8176ac8bbdb3f92 Mon Sep 17 00:00:00 2001
From: Andre Vehreschild 
Date: Fri, 23 Aug 2024 16:28:38 +0200
Subject: [PATCH] Fortran: Break recursion building recursive types. [PR106606]

Build a derived type component's type only, when it is not already being
build and the component uses pointer semantics.

gcc/fortran/ChangeLog:

	PR fortran/106606

	* trans-types.cc (gfc_get_derived_type): Only build non-pointer
	derived types as component's types when they are not yet build.

gcc/testsuite/ChangeLog:

	* gfortran.dg/recursive_alloc_comp_5.f90: New test.
---
 gcc/fortran/trans-types.cc| 20 +++---
 .../gfortran.dg/recursive_alloc_comp_5.f90| 37 +++
 2 files changed, 51 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/recursive_alloc_comp_5.f90

diff --git a/gcc/fortran/trans-types.cc b/gcc/fortran/trans-types.cc
index 3a1ff98b33c..96ef8b49fbe 100644
--- a/gcc/fortran/trans-types.cc
+++ b/gcc/fortran/trans-types.cc
@@ -2905,18 +2905,26 @@ gfc_get_derived_type (gfc_symbol * derived, int codimen)
  will be built and so we can return the type.  */
   for (c = derived->components; c; c = c->next)
 {
-  bool same_alloc_type = c->attr.allocatable
-			 && derived == c->ts.u.derived;
-
   if (c->ts.type == BT_UNION && c->ts.u.derived->backend_decl == NULL)
 c->ts.u.derived->backend_decl = gfc_get_union_type (c->ts.u.derived);

   if (c->ts.type != BT_DERIVED && c->ts.type != BT_CLASS)
 	continue;

-  if ((!c->attr.pointer && !c->attr.proc_pointer
-	  && !same_alloc_type)
-	  || c->ts.u.derived->backend_decl == NULL)
+  const bool incomplete_type
+	= c->ts.u.derived->backend_decl
+	  && TREE_CODE (c->ts.u.derived->backend_decl) == RECORD_TYPE
+	  && !(TYPE_LANG_SPECIFIC (c->ts.u.derived->backend_decl)
+	   && TYPE_LANG_SPECIFIC (c->ts.u.derived->backend_decl)->size);
+  const bool pointer_component
+	= c->attr.pointer || c->attr.allocatable || c->attr.proc_pointer;
+
+  /* Prevent endless recursion on recursive types (i.e. types that reference
+	 themself in a component.  Break the recursion by not building pointers
+	 to incomplete types again, aka types that are already in the build.  */
+  if (c->ts.u.derived->backend_decl == NULL
+	  || (c->attr.codimension && c->as->corank != codimen)
+	  || !(incomplete_type && pointer_component))
 	{
 	  int local_codim = c->attr.codimension ? c->as->corank: codimen;
 	  c->ts.u.derived->backend_decl = gfc_get_derived_type (c->ts.u.derived,
diff --git a/gcc/testsuite/gfortran.dg/recursive_alloc_comp_5.f90 b/gcc/testsuite/gfortran.dg/recursive_alloc_comp_5.f90
new file mode 100644
index 000..f26d6a8da38
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/recursive_alloc_comp_5.f90
@@ -0,0 +1,37 @@
+!{ dg-do run }
+
+! Check that PR106606 is fixed.
+
+! Contributed by Ron Shepard  
+
+module bst_base_mod
+
+  ! Binary Search Tree Module
+
+  implicit none
+
+  public
+
+  type, abstract :: bst_base_node_type
+class(bst_base_node_type), allocatable :: left
+class(bst_base_node_type), allocatable :: right
+  end type bst_base_node_type
+
+  type, extends (bst_base_node_type) :: bst_base
+integer :: bst_base_value
+  end type bst_base
+
+end module bst_base_mod
+
+  use bst_base_mod
+
+  class (bst_base), allocatable :: root
+
+  allocate (root, source = bst_base (NULL(), NULL(), 0))
+  root%left = bst_base (NULL(), NULL(), 1)
+  root%right = bst_base (NULL(), NULL(), 2)
+
+  if (.not. allocated(root%left)) stop 1
+  if (.not. allocated(root%right)) stop 2
+end
+
--
2.46.0