Hi Jerry,

The attached patch fixes both pr84122 and pr85942. Beyond the more
elaborate chunk in parse.cc, a new chunk was required in
simplify.cc(get_kind) to convert KIND expressions involving PDT kind
parameters into viable initialization expressions. Both are straight
forward.

The patch regtests on FC42/x86_64. OK for mainline?

The next PDT patch, to be posted tomorrow, corrects the invalid PDT
constructors present in pft_22/23.f03. The change is from my_pdt (all
components) to my_pdt (type parms)(the rest of the components). Following
this will be a patch to fix list directed IO of a PDT object so that the
type parameters do not appear. A few more parse errors will be fixed before
I hit the representation of PDTs(pr82649).

Cheers

Paul

On Tue, 19 Aug 2025 at 17:23, Paul Richard Thomas <
paul.richard.tho...@gmail.com> wrote:

> Hi Jerry,
>
> Thanks for taking a look at it but I have to withdraw this patch for a
> short while. It suppresses legal declarations like(pr85942):
>   type, public :: mat_t(k,c,r)
>      !.. type parameters
>      integer, kind :: k = r4
>      integer, len :: c = 1
>      integer, len :: r = 1
>      private
>      !.. private by default
>      !.. type data
>      real(kind=k) :: m_a(c,r)
>   end type mat_t
>
> Sorry about that.
>
> Thanks again
>
> Paul
>

Attachment: Change.Logs
Description: Binary data

diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index 300a7a36fbd..b29f6900841 100644
--- a/gcc/fortran/parse.cc
+++ b/gcc/fortran/parse.cc
@@ -3938,6 +3938,7 @@ parse_derived (void)
   gfc_state_data s;
   gfc_symbol *sym;
   gfc_component *c, *lock_comp = NULL, *event_comp = NULL;
+  bool pdt_parameters;
 
   accept_statement (ST_DERIVED_DECL);
   push_state (&s, COMP_DERIVED, gfc_new_block);
@@ -3946,9 +3947,11 @@ parse_derived (void)
   seen_private = 0;
   seen_sequence = 0;
   seen_component = 0;
+  pdt_parameters = false;
 
   compiling_type = 1;
 
+
   while (compiling_type)
     {
       st = next_statement ();
@@ -3961,6 +3964,31 @@ parse_derived (void)
 	case ST_PROCEDURE:
 	  accept_statement (st);
 	  seen_component = 1;
+	  /* Type parameters must not have an explicit access specification
+	     and must be placed before a PRIVATE statement. If a PRIVATE
+	     statement is encountered after type parameters, mark the remaining
+	     components as PRIVATE. */
+	  for (c = gfc_current_block ()->components; c; c = c->next)
+	    if (!c->next && (c->attr.pdt_kind || c->attr.pdt_len))
+	      {
+		pdt_parameters = true;
+		if (c->attr.access != ACCESS_UNKNOWN)
+		  {
+		    gfc_error ("Access specification of a type parameter at "
+			       "%C is not allowed");
+		    c->attr.access = ACCESS_PUBLIC;
+		    break;
+		  }
+		if (seen_private)
+		  {
+		    gfc_error ("The type parameter at %C must come before a "
+			       "PRIVATE statement");
+		    break;
+		  }
+	      }
+	    else if (pdt_parameters && seen_private
+		     && !(c->attr.pdt_kind || c->attr.pdt_len))
+	      c->attr.access = ACCESS_PRIVATE;
 	  break;
 
 	case ST_FINAL:
@@ -3986,7 +4014,7 @@ endType:
 	      break;
 	    }
 
-	  if (seen_component)
+	  if (seen_component && !pdt_parameters)
 	    {
 	      gfc_error ("PRIVATE statement at %C must precede "
 			 "structure components");
@@ -3996,7 +4024,10 @@ endType:
 	  if (seen_private)
 	    gfc_error ("Duplicate PRIVATE statement at %C");
 
-	  s.sym->component_access = ACCESS_PRIVATE;
+	  if (pdt_parameters)
+	    s.sym->component_access = ACCESS_PUBLIC;
+	  else
+	    s.sym->component_access = ACCESS_PRIVATE;
 
 	  accept_statement (ST_PRIVATE);
 	  seen_private = 1;
diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc
index b25cd2c2388..00b02f34120 100644
--- a/gcc/fortran/simplify.cc
+++ b/gcc/fortran/simplify.cc
@@ -120,10 +120,26 @@ static int
 get_kind (bt type, gfc_expr *k, const char *name, int default_kind)
 {
   int kind;
+  gfc_expr *tmp;
 
   if (k == NULL)
     return default_kind;
 
+  if (k->expr_type == EXPR_VARIABLE
+      && k->symtree->n.sym->ts.type == BT_DERIVED
+      && k->symtree->n.sym->ts.u.derived->attr.pdt_type)
+    {
+      gfc_ref *ref;
+      for (ref = k->ref; ref; ref = ref->next)
+	if (!ref->next && ref->type == REF_COMPONENT
+	    && ref->u.c.component->attr.pdt_kind
+	    && ref->u.c.component->initializer)
+	  {
+	    tmp = gfc_copy_expr (ref->u.c.component->initializer);
+	    gfc_replace_expr (k, tmp);
+	  }
+    }
+
   if (k->expr_type != EXPR_CONSTANT)
     {
       gfc_error ("KIND parameter of %s at %L must be an initialization "
diff --git a/gcc/testsuite/gfortran.dg/pdt_38.f03 b/gcc/testsuite/gfortran.dg/pdt_38.f03
new file mode 100644
index 00000000000..4eb8a411c57
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pdt_38.f03
@@ -0,0 +1,21 @@
+! { dg-do compile )
+!
+! Test the fix for pr84122
+!
+! Contributed by Neil Carlson  <neil.n.carl...@gmail.com>
+!
+module mod
+type foo(idim)
+  integer, len, PUBLIC :: idim ! { dg-error "is not allowed" }
+  private
+  integer :: array(idim)
+end type
+end module
+
+module bar
+type foo(idim)
+  private
+  integer,len :: idim         ! { dg-error "must come before a PRIVATE statement" }
+  integer :: array(idim)
+end type
+end module
diff --git a/gcc/testsuite/gfortran.dg/pdt_39.f03 b/gcc/testsuite/gfortran.dg/pdt_39.f03
new file mode 100644
index 00000000000..7378cf50983
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pdt_39.f03
@@ -0,0 +1,123 @@
+! { dg-do run }
+!
+! Test the fix for pr95541.
+!
+! Contributed by Juergen Reuter  <juergen.reu...@desy.de>
+!
+module mykinds 
+  use, intrinsic :: iso_fortran_env, only : i4 => int32, r4 => real32, r8 => real64 
+  implicit none
+  private
+  public :: i4, r4, r8
+end module mykinds
+ 
+module matrix
+  use mykinds, only : r4, r8
+  implicit none
+  private
+ 
+  type, public :: mat_t(k,c,r)
+     !.. type parameters
+     integer, kind :: k = r4
+     integer, len :: c = 1
+     integer, len :: r = 1
+     private
+     !.. private by default
+     !.. type data
+     real(kind=k) :: m_a(c,r)
+  end type mat_t
+ 
+  interface assignment(=)
+     module procedure geta_r4
+     module procedure seta_r4
+     module procedure geta_r8
+     module procedure seta_r8
+     !.. additional bindings elided
+  end interface assignment(=)
+  
+  public :: assignment(=)
+  
+contains
+  
+  subroutine geta_r4(a_lhs, t_rhs)   
+    real(r4), allocatable, intent(out) :: a_lhs(:,:)
+    class(mat_t(k=r4,c=*,r=*)), intent(in) :: t_rhs   
+    a_lhs = t_rhs%m_a
+    return
+  end subroutine geta_r4
+ 
+  subroutine geta_r8(a_lhs, t_rhs)
+    real(r8), allocatable, intent(out) :: a_lhs(:,:)
+    class(mat_t(k=r8,c=*,r=*)), intent(in) :: t_rhs
+    a_lhs = t_rhs%m_a
+    return 
+  end subroutine geta_r8
+ 
+  subroutine seta_r4(t_lhs, a_rhs) 
+    class(mat_t(k=r4,c=*,r=*)), intent(inout) :: t_lhs
+    real(r4), intent(in) :: a_rhs(:,:)
+    !.. checks on size elided
+    t_lhs%m_a = a_rhs
+    return 
+  end subroutine seta_r4
+ 
+  subroutine seta_r8(t_lhs, a_rhs) 
+    class(mat_t(k=r8,c=*,r=*)), intent(inout) :: t_lhs
+    real(r8), intent(in) :: a_rhs(:,:)
+    !.. checks on size elided
+    t_lhs%m_a = a_rhs
+    return 
+  end subroutine seta_r8
+ 
+end module matrix
+
+program p  
+  use mykinds, only : r4, r8
+  use matrix, only : mat_t, assignment(=)  
+  implicit none
+  type(mat_t(k=r4,c=:,r=:)), allocatable :: mat_r4
+  type(mat_t(k=r8,c=:,r=:)), allocatable :: mat_r8
+  real(r4), allocatable :: a_r4(:,:)
+  real(r8), allocatable :: a_r8(:,:)
+  integer :: N
+  integer :: M
+  integer :: i
+  integer :: istat
+  N = 2
+  M = 3
+  allocate( mat_t(k=r4,c=N,r=M) :: mat_r4, stat=istat )
+  if ( istat /= 0 ) then
+     print *, " error allocating mat_r4: stat = ", istat
+     stop
+  end if
+  if (mat_r4%k /= r4) stop 1
+  if (mat_r4%c /= N) stop 2
+  if (mat_r4%r /= M) stop 3
+  mat_r4 = reshape( [ (real(i, kind=mat_r4%k), i=1,N*M) ], [ N, M ] )
+  a_r4 = mat_r4
+  if (int (sum (a_r4)) /= 21) stop 4
+  N = 4
+  M = 4
+  allocate( mat_t(k=r8,c=N,r=M) :: mat_r8, stat=istat )
+  if ( istat /= 0 ) then
+     print *, " error allocating mat_r4: stat = ", istat
+     stop
+  end if
+  if (mat_r8%k /= r8) stop 5
+  if (mat_r8%c /= N) stop 6
+  if (mat_r8%r /= M) stop 7
+  mat_r8 = reshape( [ (real(i, kind=mat_r8%k), i=1,N*M) ], [ N, M ] )
+  a_r8 = mat_r8
+  if (int (sum (a_r8)) /= 136) stop 8
+  deallocate( mat_r4, stat=istat )
+  if ( istat /= 0 ) then
+     print *, " error deallocating mat_r4: stat = ", istat
+     stop
+  end if
+  deallocate( mat_r8, stat=istat )
+  if ( istat /= 0 ) then
+     print *, " error deallocating mat_r4: stat = ", istat
+     stop
+  end if
+  stop
+end program p

Reply via email to