https://gcc.gnu.org/g:68700cafd15691802325340d9cf9c1e31ff5abe4

commit r16-3423-g68700cafd15691802325340d9cf9c1e31ff5abe4
Author: Paul Thomas <pa...@gcc.gnu.org>
Date:   Thu Aug 28 08:10:04 2025 +0100

    Fortran: Implement correct form of PDT constructors [PR82205]
    
    2025-08-28  Paul Thomas  <pa...@gcc.gnu.org>
    
    gcc/fortran
            PR fortran/82205
            * decl.cc (gfc_get_pdt_instance): Copy the default initializer
            for components that are not PDT parameters or parameterized. If
            any component is a pointer or allocatable set the attributes
            'pointer_comp' or 'alloc_comp' of the new PDT instance.
            * primary.cc (gfc_match_rvalue): Implement the correct form of
            PDT constructors with 'name (type parms)(component values)'.
            * trans-array.cc (structure_alloc_comps): Apply scalar default
            initializers. Array initializers await the coming change in PDT
            representation.
            * trans-io.cc (transfer_expr): Do not output the type parms of
            a PDT in list directed output.
    
    gcc/testsuite/
            PR fortran/82205
            * gfortran.dg/pdt_22.f03: Use the correct for PDT constructors.
            * gfortran.dg/pdt_23.f03: Likewise.
            * gfortran.dg/pdt_3.f03: Likewise.

Diff:
---
 gcc/fortran/decl.cc                  | 17 ++++++++++
 gcc/fortran/primary.cc               | 61 ++++++++++++++++++++++++++++++++++++
 gcc/fortran/trans-array.cc           | 10 ++++++
 gcc/fortran/trans-io.cc              |  3 +-
 gcc/testsuite/gfortran.dg/pdt_22.f03 | 11 +++++--
 gcc/testsuite/gfortran.dg/pdt_23.f03 | 14 ++++-----
 gcc/testsuite/gfortran.dg/pdt_3.f03  | 12 +++----
 7 files changed, 111 insertions(+), 17 deletions(-)

diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc
index 5146731d454e..1e91b57aa96d 100644
--- a/gcc/fortran/decl.cc
+++ b/gcc/fortran/decl.cc
@@ -3870,6 +3870,8 @@ gfc_get_pdt_instance (gfc_actual_arglist *param_list, 
gfc_symbol **sym,
   bool assumed_seen = false;
   bool deferred_seen = false;
   bool spec_error = false;
+  bool alloc_seen = false;
+  bool ptr_seen = false;
   int kind_value, i;
   gfc_expr *kind_expr;
   gfc_component *c1, *c2;
@@ -4201,6 +4203,12 @@ gfc_get_pdt_instance (gfc_actual_arglist *param_list, 
gfc_symbol **sym,
       if (c1->ts.type == BT_CLASS)
        CLASS_DATA (c2)->as = gfc_copy_array_spec (CLASS_DATA (c1)->as);
 
+      if (c1->attr.allocatable)
+       alloc_seen = true;
+
+      if (c1->attr.pointer)
+       ptr_seen = true;
+
       /* Determine if an array spec is parameterized. If so, substitute
         in the parameter expressions for the bounds and set the pdt_array
         attribute. Notice that this attribute must be unconditionally set
@@ -4271,8 +4279,17 @@ gfc_get_pdt_instance (gfc_actual_arglist *param_list, 
gfc_symbol **sym,
          if (c2->attr.allocatable)
            instance->attr.alloc_comp = 1;
        }
+      else if (!(c2->attr.pdt_kind || c2->attr.pdt_len || c2->attr.pdt_string
+                || c2->attr.pdt_array) && c1->initializer)
+       c2->initializer = gfc_copy_expr (c1->initializer);
     }
 
+  if (alloc_seen)
+    instance->attr.alloc_comp = 1;
+  if (ptr_seen)
+    instance->attr.pointer_comp = 1;
+
+
   gfc_commit_symbol (instance);
   if (ext_param_list)
     *ext_param_list = type_param_spec_list;
diff --git a/gcc/fortran/primary.cc b/gcc/fortran/primary.cc
index f0e1fef6812e..6df95558bb15 100644
--- a/gcc/fortran/primary.cc
+++ b/gcc/fortran/primary.cc
@@ -4055,6 +4055,67 @@ gfc_match_rvalue (gfc_expr **result)
          break;
        }
 
+      /* Check to see if this is a PDT constructor.  The format of these
+        constructors is rather unusual:
+               name (type_params)(component_values)
+        where, component_values excludes the type_params. With the present
+        gfortran representation this is rather awkward because the two are not
+        distinguished, other than by their attributes.  */
+      if (sym->attr.generic)
+       {
+         gfc_symtree *pdt_st;
+         gfc_symbol *pdt_sym;
+         gfc_actual_arglist *ctr_arglist, *tmp;
+         gfc_component *c;
+
+         /* Obtain the template.  */
+         gfc_find_sym_tree (gfc_dt_upper_string (name), NULL, 1, &pdt_st);
+         if (pdt_st && pdt_st->n.sym && pdt_st->n.sym->attr.pdt_template)
+           {
+             pdt_sym = pdt_st->n.sym;
+
+             /* Generate this instance using the type parameters from the
+                first argument list and return the parameter list in
+                ctr_arglist.  */
+             m = gfc_get_pdt_instance (actual_arglist, &pdt_sym, &ctr_arglist);
+             if (m != MATCH_YES)
+               {
+                 m = MATCH_ERROR;
+                 break;
+               }
+             /* Now match the component_values.  */
+             m = gfc_match_actual_arglist (0, &actual_arglist);
+             if (m != MATCH_YES)
+               {
+                 m = MATCH_ERROR;
+                 break;
+               }
+
+             /* Make sure that the component names are in place so that this
+                list can be safely appended to the type parameters.  */
+             tmp = actual_arglist;
+             for (c = pdt_sym->components; c && tmp; c = c->next)
+               {
+                 if (c->attr.pdt_kind || c->attr.pdt_len)
+                   continue;
+                 tmp->name = c->name;
+                 tmp = tmp->next;
+               }
+
+             gfc_get_ha_sym_tree (gfc_dt_lower_string (pdt_sym->name) ,
+                                  &symtree);
+             symtree->n.sym = pdt_sym;
+             symtree->n.sym->ts.u.derived = pdt_sym;
+             symtree->n.sym->ts.type = BT_DERIVED;
+
+             /* Do the appending.  */
+             for (tmp = ctr_arglist; tmp && tmp->next;)
+               tmp = tmp->next;
+             tmp->next = actual_arglist;
+             actual_arglist = ctr_arglist;
+           }
+       }
+
       gfc_get_ha_sym_tree (name, &symtree);    /* Can't fail */
       sym = symtree->n.sym;
 
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 7e6437bbdf7e..193bac512402 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -10896,6 +10896,16 @@ structure_alloc_comps (gfc_symbol * der_type, tree 
decl, tree dest,
                  gfc_add_modify (&fnblock, comp, tse.expr);
                }
            }
+         else if (c->initializer && !c->attr.pdt_string && !c->attr.pdt_array
+                  && !c->as && !(c->ts.type == BT_DERIVED
+                                 && c->ts.u.derived->attr.pdt_type))   /* Take 
care of arrays.  */
+           {
+             gfc_se tse;
+             gfc_expr *c_expr;
+             c_expr = c->initializer;
+             gfc_conv_expr_type (&tse, c_expr, TREE_TYPE (comp));
+             gfc_add_modify (&fnblock, comp, tse.expr);
+           }
 
          if (c->attr.pdt_string)
            {
diff --git a/gcc/fortran/trans-io.cc b/gcc/fortran/trans-io.cc
index 824f232988c2..df2fef70172a 100644
--- a/gcc/fortran/trans-io.cc
+++ b/gcc/fortran/trans-io.cc
@@ -2499,7 +2499,8 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree 
addr_expr,
              for (c = ts->u.derived->components; c; c = c->next)
                {
                  /* Ignore hidden string lengths.  */
-                 if (c->name[0] == '_')
+                 if (c->name[0] == '_'
+                     || c->attr.pdt_kind || c->attr.pdt_len)
                    continue;
 
                  field = c->backend_decl;
diff --git a/gcc/testsuite/gfortran.dg/pdt_22.f03 
b/gcc/testsuite/gfortran.dg/pdt_22.f03
index 929f398635d8..23feb8c84c70 100644
--- a/gcc/testsuite/gfortran.dg/pdt_22.f03
+++ b/gcc/testsuite/gfortran.dg/pdt_22.f03
@@ -8,9 +8,10 @@
 !
 program p
    character(120) :: buffer
-   integer :: i(4)
+   integer :: i(3)
    type t(a)
       integer, len :: a
+      integer :: z = 4
    end type
    type t2(b)
       integer, len :: b
@@ -18,6 +19,10 @@ program p
    end type
    type(t2(3)) :: x
    write (buffer,*) x
-   read (buffer,*) i
-   if (any (i .ne. [3,1,1,1])) STOP 1
+   read (buffer, *) i
+   if (any (i .ne. [4,4,4])) stop 1
+   x%r = [t(1)(3),t(1)(2),t(1)(1)]
+   write (buffer,*) x
+   read (buffer, *) i
+   if (any (i .ne. [3,2,1])) stop 2
 end
diff --git a/gcc/testsuite/gfortran.dg/pdt_23.f03 
b/gcc/testsuite/gfortran.dg/pdt_23.f03
index b2156b9ce6ee..c0cec9afe0fe 100644
--- a/gcc/testsuite/gfortran.dg/pdt_23.f03
+++ b/gcc/testsuite/gfortran.dg/pdt_23.f03
@@ -15,19 +15,19 @@ program p
    type(t(:)), allocatable :: x
    allocate (t(2) :: x)
 
-   x = t(2,'ab')
+   x = t(2)('ab')
    write (buffer, *) x%c ! Tests the fix for PR82720
    read (buffer, *) chr
    if (trim (chr) .ne. 'ab') STOP 1
 
-   x = t(3,'xyz')
+   x = t(3)('xyz')
    if (len (x%c) .ne. 3) STOP 2
-   write (buffer, *) x   ! Tests the fix for PR82719
-   read (buffer, *) i, chr
-   if (i .ne. 3) STOP 3
+   write (buffer, *) x   ! Tests the fix for PR82719. PDT IO was incorrect 
(PRs 84143/84432).
+   read (buffer, *) chr
+!   if (i .ne. 3) STOP 3
    if (chr .ne. 'xyz') STOP 4
 
-   buffer = " 3  lmn"
-   read (buffer, *) x   ! Some thought will be needed for PDT reads.
+   buffer = "lmn"
+   read (buffer, *) x    ! PDT IO was incorrect (PRs 84143/84432).
    if (x%c .ne. 'lmn') STOP 5
 end
diff --git a/gcc/testsuite/gfortran.dg/pdt_3.f03 
b/gcc/testsuite/gfortran.dg/pdt_3.f03
index e364eeae6dfc..cd48364b1534 100644
--- a/gcc/testsuite/gfortran.dg/pdt_3.f03
+++ b/gcc/testsuite/gfortran.dg/pdt_3.f03
@@ -5,7 +5,7 @@
 module vars
   integer :: d_dim = 4
   integer :: mat_dim = 256
-  integer, parameter :: ftype = kind(0.0d0)
+  integer, parameter :: ftype = kind(0.0)
 end module
 
   use vars
@@ -34,7 +34,7 @@ end module
 
   real, allocatable :: matrix (:,:)
   type(thytype(ftype, 4, 4)) :: w
-  type(x(8,4,256)) :: q
+  type(x(ftype,ftype,256)) :: q
   class(mytype(ftype, :)), allocatable :: cz
 
   w%d = reshape ([(real(i), i = 1, d_dim*d_dim)],[d_dim,d_dim])
@@ -57,21 +57,21 @@ end module
   matrix = w%d
 
 ! TODO - for some reason, using w%d directly in the source causes a seg fault.
-  allocate (cz, source = mytype(ftype, d_dim, 0, matrix))
+  allocate (cz, source = mytype(ftype, d_dim)( 0, matrix))
   select type (cz)
     type is (mytype(ftype, *))
       if (int (sum (cz%d)) .ne. 136) STOP 11
-    type is (thytype(ftype, *, 8))
+    type is (thytype(ftype, *, ftype))
       STOP 12
   end select
   deallocate (cz)
 
-  allocate (thytype(ftype, d_dim*2, 8) :: cz)
+  allocate (thytype(ftype, d_dim*2, ftype) :: cz)
   cz%d = reshape ([(i*10, i = 1, cz%b**2)], [cz%b,cz%b])
   select type (cz)
     type is (mytype(ftype, *))
       STOP 13
-    type is (thytype(ftype, *, 8))
+    type is (thytype(ftype, *, ftype))
       if (int (sum (cz%d)) .ne. 20800) STOP 14
   end select

Reply via email to